diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index 91be5f81..924c7280 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -75,7 +75,7 @@ class Data(SQLSubModel): cls._db_update_to_0_1_0(execute, data) if major == "0" and minor == "1": - if release < 2: + if int(release) < 2: execute( "ALTER TABLE boundary_condition_data " + "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" @@ -174,6 +174,9 @@ class Data(SQLSubModel): return new def _db_save(self, execute, data=None): + if not self.must_be_saved(): + return True + pid = self._pamhyr_id ind = data["ind"] data0 = self._db_format(str(self[0])) diff --git a/src/Model/InitialConditions/InitialConditions.py b/src/Model/InitialConditions/InitialConditions.py index 55db5f9d..a56b9e31 100644 --- a/src/Model/InitialConditions/InitialConditions.py +++ b/src/Model/InitialConditions/InitialConditions.py @@ -34,13 +34,13 @@ class Data(SQLSubModel): reach=None, section=None, discharge: float = 0.0, height: float = 0.0, - status=None): - super(Data, self).__init__(id) - - self._status = status - + status=None, + owner_scenario=-1): + super(Data, self).__init__( + id=id, status=status, + owner_scenario=owner_scenario + ) self._reach = reach - self._name = name self._comment = comment @@ -62,6 +62,7 @@ class Data(SQLSubModel): execute(f""" CREATE TABLE initial_conditions{ext} ( {cls.create_db_add_pamhyr_id()}, + deleted BOOLEAN NOT NULL DEFAULT FALSE, ind INTEGER NOT NULL, name TEXT NOT NULL, comment TEXT NOT NULL, @@ -93,6 +94,11 @@ class Data(SQLSubModel): if int(release) < 1: cls._db_update_to_0_1_1(execute, data) + if int(release) < 2: + execute( + "ALTER TABLE initial_conditions " + + "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" + ) return cls._update_submodel(execute, version, data) @classmethod @@ -137,29 +143,38 @@ class Data(SQLSubModel): @classmethod def _db_load(cls, execute, data=None): + new = [] reach = data["reach"] + scenario = data["scenario"] + loaded = data['loaded_pid'] + + if scenario is None: + return new + id = reach.pamhyr_id table = execute( - "SELECT pamhyr_id, ind, name, comment, " + - "section, discharge, height " + + "SELECT pamhyr_id, deleted, ind, name, comment, " + + "section, discharge, height, scenario " + "FROM initial_conditions " + f"WHERE reach = {id} " + + f"AND scenario = {scenario.id} " + + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " + "ORDER BY ind ASC" ) - new = [] ok = True - for row in table: it = iter(row) pid = next(it) + deleted = (next(it) == 1) ind = next(it) name = next(it) comment = next(it) section_id = next(it) discharge = next(it) height = next(it) + owner_scenario = next(it) section = reduce( lambda acc, s: ( @@ -186,8 +201,12 @@ class Data(SQLSubModel): section=section, discharge=discharge, height=height, + owner_scenario=owner_scenario ) + if deleted: + nd.set_as_deleted() + loaded.add(pid) new.append(d) if not ok: @@ -196,6 +215,12 @@ class Data(SQLSubModel): f"for reach {reach.name} ({reach.pamhyr_id})" ) + # Recution only if no data found + if len(new) == 0: + data["scenario"] = scenario.parent + new += cls._db_load(execute, data) + data["scenario"] = scenario + return new def _db_save(self, execute, data=None): @@ -203,14 +228,14 @@ class Data(SQLSubModel): execute( "INSERT INTO " + - "initial_conditions(pamhyr_id, ind, name, comment, section, " + - "discharge, height, reach) " + + "initial_conditions(pamhyr_id, deleted, ind, name, comment, " + + "section, discharge, height, reach, scenario) " + "VALUES (" + - f"{self.pamhyr_id}, " + + f"{self.pamhyr_id}, {self._db_format(self.is_deleted())}, " + f"{ind}, '{self._db_format(self.name)}', " + f"'{self._db_format(self._comment)}', " + f"{self._section.id}, {self._discharge}, {self._height}, " + - f"{self._reach.id}" + + f"{self._reach.id}, {self._status.scenario_id}" + ")" ) @@ -239,7 +264,7 @@ class Data(SQLSubModel): val = self._name elif key == "comment": val = self._comment - elif key == "rk": + elif key == "rk" or key == "section": val = self._section elif key == "speed": val = self._speed @@ -282,7 +307,7 @@ class Data(SQLSubModel): self._name = str(value) elif key == "comment": self._comment = str(value) - elif key == "rk": + elif key == "rk" or key == "section": self._section = value self._update_from_rk() elif key == "speed": @@ -298,7 +323,7 @@ class Data(SQLSubModel): self._height = float(value) self._update_from_height() - self._status.modified() + self.modified() class InitialConditions(SQLSubModel): @@ -361,11 +386,16 @@ class InitialConditions(SQLSubModel): @reach.setter def reach(self, new): self._reach = reach - self._status.modified() + self.modified() @property def data(self): - return self._data.copy() + return list( + filter( + lambda el: not el.is_deleted(), + self._data + ) + ) @data.setter def data(self, data): @@ -376,34 +406,46 @@ class InitialConditions(SQLSubModel): def set(self, index, data): self._data.insert(index, data) - self._status.modified() + self.modified() def new(self, index): n = Data(reach=self._reach, status=self._status) self._data.insert(index, n) - self._status.modified() + self.modified() def new_from_data(self, rk, discharge, elevation): n = Data(reach=self._reach, status=self._status) - n['rk'] = rk + section = reduce( + lambda acc, s: ( + s if s.rk == rk else acc + ), + self._reach.reach.profiles, + None + ) + + n['section'] = section n['discharge'] = discharge n['elevation'] = elevation return n def insert(self, index, data): - self._data.insert(index, data) - self._status.modified() + if data in self._data: + data.set_as_not_deleted() + else: + self._data.insert(index, data) + + self.modified() def delete(self, data): - self._data = list( + list( filter( - lambda x: x not in data, + lambda x: x.set_as_deleted(), self._data ) ) - self._status.modified() + self.modified() def delete_i(self, indexes): data = list( @@ -419,7 +461,7 @@ class InitialConditions(SQLSubModel): def sort(self, reverse=False, key=None): self._data.sort(reverse=reverse, key=key) - self._status.modified() + self.modified() def _data_get(self, key): return list( @@ -443,27 +485,9 @@ class InitialConditions(SQLSubModel): def get_discharge(self): return self._data_get("discharge") - def _sort_by_z_and_rk(self, profiles): - profiles.sort( - reverse=False, - key=lambda p: p.rk - ) - - first_z = profiles[0].z() - last_z = profiles[-1].z() - - if first_z > last_z: - profiles.sort( - reverse=True, - key=lambda p: p.rk - ) - def generate_growing_constante_height(self, height: float, compute_discharge: bool): - profiles = self._reach.reach.profiles.copy() - self._sort_by_z_and_rk(profiles) - previous_elevation = -99999.99 data_discharge = {} @@ -478,7 +502,7 @@ class InitialConditions(SQLSubModel): incline = self._reach.reach.get_incline_median_mean() logger.debug(f"incline = {incline}") self._data = [] - for profile in profiles: + for profile in reversed(profiles): width = profile.wet_width(profile.z_min() + height) frictions = self._reach.frictions.frictions strickler = None @@ -509,20 +533,17 @@ class InitialConditions(SQLSubModel): logger.debug(f" discharge = {discharge}") new = Data(reach=self._reach, status=self._status) - new["rk"] = profile.rk + new["rk"] = profile new["discharge"] = discharge new["elevation"] = elevation previous_elevation = elevation self._data.append(new) - self._generate_resort_data(profiles) + self._data.reverse() def generate_discharge(self, discharge: float, compute_height: bool): - profiles = self._reach.reach.profiles.copy() - self._sort_by_z_and_rk(profiles) - previous_elevation = -99999.99 data_height = {} @@ -537,7 +558,7 @@ class InitialConditions(SQLSubModel): incline = self._reach.reach.get_incline_median_mean() logger.debug(f"incline = {incline}") self._data = [] - for profile in profiles: + for profile in reversed(profiles): width = profile.width_approximation() frictions = self._reach.frictions.frictions strickler = None @@ -567,21 +588,11 @@ class InitialConditions(SQLSubModel): logger.debug(f" height = {height}") new = Data(reach=self._reach, status=self._status) - new["rk"] = profile.rk + new["section"] = profile new["discharge"] = discharge new["elevation"] = elevation previous_elevation = elevation self._data.append(new) - self._generate_resort_data(profiles) - - def _generate_resort_data(self, profiles): - is_reverse = False - if profiles[0].rk > profiles[-1].rk: - is_reverse = True - - self._data.sort( - reverse=not is_reverse, - key=lambda d: d['rk'] - ) + self._data.reverse() diff --git a/src/Model/InitialConditions/InitialConditionsDict.py b/src/Model/InitialConditions/InitialConditionsDict.py index 92d013a2..7ef81a12 100644 --- a/src/Model/InitialConditions/InitialConditionsDict.py +++ b/src/Model/InitialConditions/InitialConditionsDict.py @@ -64,7 +64,8 @@ class InitialConditionsDict(PamhyrModelDict): execute( "DELETE FROM initial_conditions " + - f"WHERE reach = '{reach.id}'" + f"WHERE reach = '{reach.id}' " + + f"AND scenario = {self._status.scenario_id}" ) ok &= self._dict[reach]._db_save(execute, data) diff --git a/src/Model/Tools/PamhyrDict.py b/src/Model/Tools/PamhyrDict.py index 1e81dc2b..519093c2 100644 --- a/src/Model/Tools/PamhyrDict.py +++ b/src/Model/Tools/PamhyrDict.py @@ -32,9 +32,9 @@ class PamhyrModelDict(SQLSubModel): _sub_classes = [] def __init__(self, status=None): - super(PamhyrModelDict, self).__init__() - - self._status = status + super(PamhyrModelDict, self).__init__( + status=status + ) self._dict = {}