InitialConditions.py 5.56 KiB
# -*- coding: utf-8 -*-

from copy import copy
from tools import trace, timer
from functools import reduce

class Data(object):
    def __init__(self, reach = None, status = None):
        super(Data, self).__init__()

        self._status = status

        self._reach = reach

        self._name = ""
        self._comment = ""

        self._kp = 0.0
        self._flow = 0.0
        self._speed = 0.0
        self._elevation = 0.0
        self._draft = 0.0

    @property
    def name(self):
        return self._name

    def __getitem__(self, key):
        val = None

        if key == "name":
            val = self._name
        elif key == "comment":
            val = self._comment
        elif key == "kp":
            val = self._kp
        elif key == "speed":
            val = self._speed
        elif key == "flow":
            val = self._flow
        elif key == "elevation":
            val = self._elevation
        elif key == "draft":
            val = self._draft

        return val

    def _update_get_min(self):
        profile = self._reach.reach.get_profiles_from_kp(self._kp)
        if len(profile) > 0:
            min = profile[0].z_min()
        else:
            min = 0.0

        return min

    def _update_from_kp(self):
        min = self._update_get_min()
        self._elevation = min - self._draft

    def _update_from_elevation(self):
        min = self._update_get_min()
        self._draft = self._elevation - min

    def _update_from_draft(self):
        min = self._update_get_min()
        self._elevation = self._draft + min

    def _update_from_flow(self):
        min = self._update_get_min()
        print("TODO")

    def __setitem__(self, key, value):
        if key == "name":
            self._name = str(value)
        elif key == "comment":
            self._comment = str(value)
        elif key == "kp":
            self._kp = float(value)
            self._update_from_kp()
        elif key == "speed":
            self._speed = float(value)
            # Not supposed to be modified
        elif key == "flow":
            self._flow = float(value)
            self._update_from_flow()
        elif key == "elevation":
            self._elevation = float(value)
            self._update_from_elevation()
        elif key == "draft":
            self._draft = float(value)
            self._update_from_draft()

        self._status.modified()

class InitialConditions(object):
    def __init__(self, reach = None, status = None):
        super(InitialConditions, self).__init__()

        self._status = status

        self._reach = reach
        self._data = []

    def __len__(self):
        return len(self._data)

    @property
    def reach(self):
        return self._reach

    @reach.setter
    def reach(self, new):
        self._reach = reach
        self._status.modified()

    @property
    def data(self):
        return self._data.copy()

    @data.setter
    def data(self, data):
        self._data = data

    def get(self, index):
        return self._data[index]

    def set(self, index, data):
        self._data.insert(index, data)
        self._status.modified()

    def new(self, index):
        n = Data(reach = self._reach, status = self._status)
        self._data.insert(index, n)
        self._status.modified()

    def insert(self, index, data):
        self._data.insert(index, data)
        self._status.modified()

    def delete(self, data):
        self._data = list(
            filter(
                lambda x: x not in data,
                self._data
            )
        )
        self._status.modified()

    def delete_i(self, indexes):
        data = list(
            map(
                lambda x: x[1],
                filter(
                    lambda x: x[0] in indexes,
                    enumerate(self._data)
                )
            )
        )
        self.delete(data)

    def sort(self, reverse=False, key=None):
        self._data.sort(reverse=reverse, key=key)
        self._status.modified()


    def _data_get(self, key):
        return list(
            map(
                lambda d: d[key],
                self._data
            )
        )

    def get_kp(self):
        return self._data_get("kp")

    def get_elevation(self):
        return self._data_get("elevation")

    def get_flow(self):
        return self._data_get("flow")

    def _sort_by_z_and_kp(self, profiles):
        profiles.sort(
            reverse = False,
            key = lambda p: p.kp
        )

        first_z = profiles[0].z()
        last_z = profiles[-1].z()

        if first_z > last_z:
            profiles.sort(
                reverse = True,
                key = lambda p: p.kp
            )

    def generate_growing_constante_draft(self, draft:float):
        self._data = []

        profiles = self._reach.reach.profiles
        self._sort_by_z_and_kp(profiles)

        prev = None
        for profile in profiles:
            new = Data(reach = self._reach, status = self._status)
            new["kp"] = profile.kp

            if prev is None:
                new["elevation"] = profile.z_min() + draft
            else:
                new["elevation"] = max(
                    profile.z_min() + draft,
                    prev["elevation"]
                )

            self._data.append(new)
            prev = new

        is_reverse = False
        if profiles[0].kp > profiles[-1].kp:
            is_reverse = True

        self._data.sort(
            reverse = not is_reverse,
            key = lambda d: d['kp']
        )

    def generate_discharge(self, discharge:float):
        for d in self._data:
            d['flow'] = discharge