diff --git a/src/Model/Pollutants/Pollutants.py b/src/Model/Pollutants/Pollutants.py index a321978f..3b2b117e 100644 --- a/src/Model/Pollutants/Pollutants.py +++ b/src/Model/Pollutants/Pollutants.py @@ -32,60 +32,82 @@ from Model.Scenario import Scenario logger = logging.getLogger() -class Pollutants(SQLSubModel): +class PollutantCharacteristics(SQLSubModel): _sub_classes = [] - def __init__(self, id: int = -1, name: str = "", - status=None, owner_scenario=-1): - super(Pollutants, self).__init__( + def __init__(self, id: int = -1, type=-1, + diametre=-1, rho=-1, + porosity=-1, + cdc_riv=-1, cdc_cas=-1, + apd=-1, ac=-1, bc=-1, + pollutant=None, + status=None, + owner_scenario=-1): + super(PollutantCharacteristics, self).__init__( id=id, status=status, owner_scenario=owner_scenario ) self._status = status - if name is None or name == "": - self.name = f"pol{self.id}" - else: - self._name = str(name) - self._enabled = True + self._type = type + self._diametre = diametre + self._rho = rho + self._porosity = porosity + self._cdc_riv = cdc_riv + self._cdc_cas = cdc_cas + self._apd = apd + self._ac = ac + self._bc = bc + self._pollutant = pollutant - self._data = [] + # FIXME: This four next method is dirty work, just an hack to keep + # the View API working... Must be refactoring + def to_list(self): + return [ + self._type, + self._diametre, + self._rho, + self._porosity, + self._cdc_riv, + self._cdc_cas, + self._apd, + self._ac, + self._bc, + ] - @property - def name(self): - return self._name + def __len__(self): + return len(self.to_list()) - @name.setter - def name(self, name): - self._name = name - self._status.modified() + def __getitem__(self, key): + return self.to_list()[key] - @property - def data(self): - return self._data.copy() + def __setitem__(self, key, value): + if key == 0: + self._type = value + elif key == 1: + self._diametre = value + elif key == 2: + self._rho = value + elif key == 3: + self._porosity = value + elif key == 4: + self._cdc_riv = value + elif key == 5: + self._cdc_cas = value + elif key == 6: + self._apd = value + elif key == 7: + self._ac = value + elif key == 8: + self._bc = value @classmethod def _db_create(cls, execute, ext=""): - cls._db_create_pol(execute, ext=ext) - cls._db_create_pol_char(execute, ext=ext) - - @classmethod - def _db_create_pol(cls, execute, ext=""): - execute(f""" - CREATE TABLE pollutants{ext}( - {cls.create_db_add_pamhyr_id()}, - name TEXT NOT NULL UNIQUE, - {Scenario.create_db_add_scenario()}, - {Scenario.create_db_add_scenario_fk()} - ) - """) - - @classmethod - def _db_create_pol_char(cls, execute, ext=""): execute(f""" CREATE TABLE pollutants_characteristics{ext}( {cls.create_db_add_pamhyr_id()}, + deleted BOOLEAN NOT NULL DEFAULT FALSE, type INTEGER NOT NULL, diametre REAL NOT NULL, rho REAL NOT NULL, @@ -102,7 +124,7 @@ class Pollutants(SQLSubModel): ) """) - return cls._create_submodel(execute) + return True @classmethod def _db_update(cls, execute, version, data=None): @@ -117,39 +139,18 @@ class Pollutants(SQLSubModel): if major == "0" and int(minor) < 2: if not created: cls._db_update_to_0_2_0(execute, data) - cls._db_update_to_0_2_0_char(execute, data) - return True + return cls._update_submodel(execute, version, data) @classmethod def _db_update_to_0_2_0(cls, execute, data): - table = "Pollutants" - table_new = "pollutants" - - cls.update_db_add_pamhyr_id(execute, table, data) - Scenario.update_db_add_scenario(execute, table) - - cls._db_create_pol(execute, ext="_tmp") - - execute( - f"INSERT INTO {table_new}_tmp " + - "(pamhyr_id, name, scenario) " + - "SELECT pamhyr_id, name, scenario " + - f"FROM {table}" - ) - - execute(f"DROP TABLE {table}") - execute(f"ALTER TABLE {table_new}_tmp RENAME TO {table_new}") - - @classmethod - def _db_update_to_0_2_0_char(cls, execute, data): table = "Pollutants_characteristics" table_new = "pollutants_characteristics" cls.update_db_add_pamhyr_id(execute, table, data) Scenario.update_db_add_scenario(execute, table) - cls._db_create_pol_char(execute, ext="_tmp") + cls._db_create(execute, ext="_tmp") execute( f"INSERT INTO {table_new}_tmp " + @@ -194,12 +195,181 @@ class Pollutants(SQLSubModel): status = data["status"] scenario = data["scenario"] loaded = data['loaded_pid'] + pollutant = data['pollutant'] if scenario is None: return new table = execute( - "SELECT pamhyr_id, name FROM pollutants " + + "SELECT pamhyr_id, deleted, type, diametre, rho, porosity, " + + "cdc_riv, cdc_cas, apd, ac, bc, scenario " + + "FROM pollutants_characteristics " + + f"WHERE pollutant = {pollutant.id} " + + f"AND scenario = {scenario.id} " + + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})" + ) + + if table is not None: + for row in table: + it = iter(row) + + pid = next(it) + deleted = (next(it) == 1) + type = next(it) + diametre = next(it) + rho = next(it) + porosity = next(it) + cdc_riv = next(it) + cdc_cas = next(it) + apd = next(it) + ac = next(it) + bc = next(it) + owner_scenario = next(it) + + pc = cls( + id=pid, type=type, + diametre=diametre, + rho=rho, + porosity=porosity, + cdc_riv=cdc_riv, cdc_cas=cdc_cas, + apd=apd, ac=ac, bc=bc, + pollutant=pollutant, + status=status, + owner_scenario=owner_scenario + ) + if deleted: + pc.set_as_deleted() + + loaded.add(pid) + new.append(pc) + + data["scenario"] = scenario.parent + new += cls._db_load(execute, data) + data["scenario"] = scenario + + return new + + def _db_save(self, execute, data=None): + if not self.must_be_saved(): + return True + + execute( + "INSERT INTO " + + "pollutants_characteristics(pamhyr_id, deleted, " + + "type, diametre, rho, porosity, " + + "cdc_riv, cdc_cas, apd, ac, bc, " + + "pollutant, scenario) " + + "VALUES (" + + f"{self.id}, {self._db_format(self.is_deleted())}, " + + f"{self._type}, " + + f"{self._diametre}, {self._rho}, " + + f"{self._porosity}, " + + f"{self._cdc_riv}, {self._cdc_cas}, " + + f"{self._apd}, {self._ac}, {self._bc}, " + + f"{self._pollutant.id}, " + + f"{self._status.scenario_id}" + + ")" + ) + + return True + + +class Pollutants(SQLSubModel): + _sub_classes = [PollutantCharacteristics] + + def __init__(self, id: int = -1, name: str = "", + status=None, owner_scenario=-1): + super(Pollutants, self).__init__( + id=id, status=status, + owner_scenario=owner_scenario + ) + + self._status = status + + if name is None or name == "": + self.name = f"pol{self.id}" + else: + self._name = str(name) + self._enabled = True + + self._data = [] + + @property + def name(self): + return self._name + + @name.setter + def name(self, name): + self._name = name + self._status.modified() + + @property + def data(self): + return self._data + + @classmethod + def _db_create(cls, execute, ext=""): + execute(f""" + CREATE TABLE pollutants{ext}( + {cls.create_db_add_pamhyr_id()}, + deleted BOOLEAN NOT NULL DEFAULT FALSE, + name TEXT NOT NULL UNIQUE, + {Scenario.create_db_add_scenario()}, + {Scenario.create_db_add_scenario_fk()} + ) + """) + + return True + + @classmethod + def _db_update(cls, execute, version, data=None): + major, minor, release = version.strip().split(".") + created = False + + if major == "0" and int(minor) <= 1: + if int(release) < 7: + cls._db_create(execute) + created = True + + if major == "0" and int(minor) < 2: + if not created: + cls._db_update_to_0_2_0(execute, data) + + return cls._update_submodel(execute, version, data) + + @classmethod + def _db_update_to_0_2_0(cls, execute, data): + table = "Pollutants" + table_new = "pollutants" + + cls.update_db_add_pamhyr_id(execute, table, data) + Scenario.update_db_add_scenario(execute, table) + + cls._db_create(execute, ext="_tmp") + + execute( + f"INSERT INTO {table_new}_tmp " + + "(pamhyr_id, name, scenario) " + + "SELECT pamhyr_id, name, scenario " + + f"FROM {table}" + ) + + execute(f"DROP TABLE {table}") + execute(f"ALTER TABLE {table_new}_tmp RENAME TO {table_new}") + + @classmethod + def _db_load(cls, execute, data=None): + new = [] + + status = data["status"] + scenario = data["scenario"] + loaded = data['loaded_pid'] + + if scenario is None: + return new + + table = execute( + "SELECT pamhyr_id, deleted, name FROM pollutants " + f"WHERE scenario = {scenario.id} " + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})" @@ -207,29 +377,24 @@ class Pollutants(SQLSubModel): if table is not None: for row in table: - pid = row[0] - name = row[1] + it = iter(row) + + pid = next(it) + deleted = (next(it) == 1) + name = next(it) new_pollutant = cls( id=pid, name=name, status=status ) + if deleted: + new_pollutant.set_as_deleted() - new_data = [] - table = execute( - "SELECT * " + - "FROM pollutants_characteristics " + - f"WHERE pollutant = {pid} " + - f"AND scenario = {scenario.id} " + - f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})" + data["pollutant"] = new_pollutant + new_pollutant._data = PollutantCharacteristics._db_load( + execute, data.copy() ) - if table is not None: - for t in table: - new_data = t[1:-2] - - new_pollutant._data.append(new_data) - loaded.add(pid) new.append(new_pollutant) @@ -243,6 +408,8 @@ class Pollutants(SQLSubModel): if not self.must_be_saved(): return True + ok = True + execute( "DELETE FROM pollutants " + f"WHERE pamhyr_id = {self.id} " + @@ -256,25 +423,18 @@ class Pollutants(SQLSubModel): execute( "INSERT INTO " + - "pollutants(id, name, scenario) " + + "pollutants(pamhyr_id, deleted, name, scenario) " + "VALUES (" + - f"{self.id}, " + + f"{self.id}, {self._db_format(self.is_deleted())}, " + f"'{self._db_format(self._name)}', " + f"{self._status.scenario_id}" + ")" ) for d in self._data: - execute( - "INSERT INTO " + - "pollutants_characteristics(type, diametre, rho, porosity, " + - "cdc_riv, cdc_cas, apd, ac, bc, pollutant, scenario) " + - f"VALUES ({d[0]}, {d[1]}, {d[2]},{d[3]}, {d[4]}, " - f"{d[5]}, {d[6]}, {d[7]}, {d[8]}, {self.id}, " + - f"{self._status.scenario_id})" - ) + ok &= d._db_save(execute, data) - return True + return ok @property def enabled(self): @@ -289,7 +449,6 @@ class Pollutants(SQLSubModel): return len(self._data) != 0 def new_from_data(self, data): - try: new = [int(data[0])] new += [float(d) for d in data[1:]]