BC: Add scenario support.

scenarios
Pierre-Antoine Rouby 2024-09-16 16:25:47 +02:00
parent e73f76024e
commit a5ecc2383c
6 changed files with 221 additions and 86 deletions

View File

@ -38,9 +38,12 @@ class Data(SQLSubModel):
def __init__(self, data0, data1, def __init__(self, data0, data1,
id: int = -1, id: int = -1,
types=[float, float], types=[float, float],
status=None): status=None,
super(Data, self).__init__(id) owner_scenario=-1):
self._status = status super(Data, self).__init__(
id=id, status=status,
owner_scenario=owner_scenario
)
self._types = types self._types = types
self._data = [data0, data1] self._data = [data0, data1]
@ -50,6 +53,7 @@ class Data(SQLSubModel):
execute(f""" execute(f"""
CREATE TABLE boundary_condition_data{ext}( CREATE TABLE boundary_condition_data{ext}(
{cls.create_db_add_pamhyr_id()}, {cls.create_db_add_pamhyr_id()},
deleted BOOLEAN NOT NULL DEFAULT FALSE,
ind INTEGER NOT NULL, ind INTEGER NOT NULL,
data0 TEXT NOT NULL, data0 TEXT NOT NULL,
data1 TEXT NOT NULL, data1 TEXT NOT NULL,
@ -70,6 +74,13 @@ class Data(SQLSubModel):
if major == "0" and int(minor) < 1: if major == "0" and int(minor) < 1:
cls._db_update_to_0_1_0(execute, data) cls._db_update_to_0_1_0(execute, data)
if major == "0" and minor == "1":
if release < 2:
execute(
"ALTER TABLE boundary_condition_data " +
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
@classmethod @classmethod
@ -117,11 +128,19 @@ class Data(SQLSubModel):
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = [] new = []
bc = data["bc"] bc = data["bc"]
scenario = data["scenario"]
loaded = data['loaded_pid']
if scenario is None:
return new
values = execute( values = execute(
"SELECT pamhyr_id, ind, data0, data1 " + "SELECT pamhyr_id, deleted, ind, " +
"data0, data1, scenario " +
"FROM boundary_condition_data " + "FROM boundary_condition_data " +
f"WHERE bc = {bc._pamhyr_id} " + f"WHERE bc = {bc._pamhyr_id} " +
f"AND scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " +
"ORDER BY ind ASC" "ORDER BY ind ASC"
) )
@ -129,19 +148,29 @@ class Data(SQLSubModel):
it = iter(v) it = iter(v)
pid = next(it) pid = next(it)
deleted = (next(it) == 1)
ind = next(it) ind = next(it)
data0 = bc._types[0](next(it)) data0 = bc._types[0](next(it))
data1 = bc._types[1](next(it)) data1 = bc._types[1](next(it))
owner_scenario = next(it)
nd = cls( nd = cls(
data0, data1, data0, data1,
id=pid, id=pid,
types=bc._types, types=bc._types,
status=data['status'] status=data['status'],
owner_scenario=owner_scenario
) )
if deleted:
nd.set_as_deleted()
loaded.add(pid)
new.append(nd) new.append(nd)
data["scenario"] = scenario.parent
new += cls._db_load(execute, data)
data["scenario"] = scenario
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
@ -153,10 +182,17 @@ class Data(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"boundary_condition_data(pamhyr_id, ind, data0, data1, bc) " + "boundary_condition_data(pamhyr_id, deleted, ind, " +
f"VALUES ({pid}, {ind}, '{data0}', {data1}, {bc._pamhyr_id})" "data0, data1, bc, scenario) " +
f"VALUES (" +
f"{pid}, {self._db_format(self.is_deleted())}, " +
f"{ind}, '{self._db_format(data0)}', {self._db_format(data1)}, " +
f"{bc._pamhyr_id}, {self._status.scenario_id}" +
")"
) )
return True
def __getitem__(self, key): def __getitem__(self, key):
return self._types[key](self._data[key]) return self._types[key](self._data[key])
@ -168,10 +204,13 @@ class BoundaryCondition(SQLSubModel):
_sub_classes = [Data] _sub_classes = [Data]
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
name: str = "", status=None): name: str = "",
super(BoundaryCondition, self).__init__(id) status=None,
owner_scenario=-1):
self._status = status super(BoundaryCondition, self).__init__(
id=id, status=status,
owner_scenario=owner_scenario
)
self._name = name self._name = name
self._type = "" self._type = ""
@ -185,6 +224,7 @@ class BoundaryCondition(SQLSubModel):
execute(f""" execute(f"""
CREATE TABLE boundary_condition{ext}( CREATE TABLE boundary_condition{ext}(
{cls.create_db_add_pamhyr_id()}, {cls.create_db_add_pamhyr_id()},
deleted BOOLEAN NOT NULL DEFAULT FALSE,
name TEXT NOT NULL, name TEXT NOT NULL,
type TEXT NOT NULL, type TEXT NOT NULL,
tab TEXT NOT NULL, tab TEXT NOT NULL,
@ -208,6 +248,13 @@ class BoundaryCondition(SQLSubModel):
if major == minor == "0": if major == minor == "0":
cls._db_update_to_0_1_0(execute, data) cls._db_update_to_0_1_0(execute, data)
if major == "0" and minor == "1":
if release < 2:
execute(
"ALTER TABLE friction " +
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
@classmethod @classmethod
@ -258,43 +305,67 @@ class BoundaryCondition(SQLSubModel):
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = [] new = []
tab = data["tab"] tab = data["tab"]
nodes = data["nodes"]
scenario = data["scenario"]
loaded = data['loaded_pid']
if scenario is None:
return new
table = execute( table = execute(
"SELECT pamhyr_id, name, type, node " + "SELECT pamhyr_id, deleted, name, type, node, scenario " +
"FROM boundary_condition " + "FROM boundary_condition " +
f"WHERE tab = '{tab}'" f"WHERE tab = '{tab}' " +
f"AND scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) "
) )
for row in table: for row in table:
t = row[2] it = iter(row)
pid = next(it)
deleted = (next(it) == 1)
name = next(it)
t = next(it)
node = next(it)
owner_scenario = next(it)
ctor = cls._get_ctor_from_type(t) ctor = cls._get_ctor_from_type(t)
bc = ctor( bc = ctor(
id=row[0], id=pid, name=name,
name=row[1], status=data['status'],
status=data['status'] owner_scenario=owner_scenario
) )
if deleted:
f.set_as_deleted()
bc.node = None bc.node = None
if row[3] != -1: if node != -1:
bc.node = next(filter(lambda n: n.id == row[3], data["nodes"])) bc.node = next(filter(lambda n: n.id == node, nodes))
data["bc"] = bc data["bc"] = bc
bc._data = Data._db_load(execute, data=data) bc._data = Data._db_load(execute, data=data)
loaded.add(pid)
new.append(bc) new.append(bc)
data["scenario"] = scenario.parent
new += cls._db_load(execute, data)
data["scenario"] = scenario
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
tab = data["tab"] tab = data["tab"]
execute(
"DELETE FROM boundary_condition " +
f"WHERE pamhyr_id = {self._pamhyr_id}"
)
execute( execute(
"DELETE FROM boundary_condition_data " + "DELETE FROM boundary_condition_data " +
f"WHERE bc = {self._pamhyr_id}" f"WHERE bc = {self._pamhyr_id} " +
f"AND scenario = {self._status.scenario_id}"
) )
node = -1 node = -1
@ -303,10 +374,14 @@ class BoundaryCondition(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"boundary_condition(pamhyr_id, name, type, tab, node) " + "boundary_condition(" +
"pamhyr_id, deleted, name, type, tab, node, scenario" +
") " +
"VALUES (" + "VALUES (" +
f"{self._pamhyr_id}, '{self._db_format(self._name)}', " + f"{self._pamhyr_id}, {self._db_format(self.is_deleted())}, " +
f"'{self._db_format(self._type)}', '{tab}', {node}" + f"'{self._db_format(self._name)}', " +
f"'{self._db_format(self._type)}', '{tab}', {node}, " +
f"{self._status.scenario_id}" +
")" ")"
) )
@ -323,7 +398,14 @@ class BoundaryCondition(SQLSubModel):
return True return True
def __len__(self): def __len__(self):
return len(self._data) return len(
list(
filter(
lambda el: not el.is_deleted(),
self._data
)
)
)
@classmethod @classmethod
def compatibility(cls): def compatibility(cls):
@ -355,7 +437,7 @@ class BoundaryCondition(SQLSubModel):
@name.setter @name.setter
def name(self, name): def name(self, name):
self._name = name self._name = name
self._status.modified() self.modified()
@property @property
def bctype(self): def bctype(self):
@ -368,7 +450,7 @@ class BoundaryCondition(SQLSubModel):
@node.setter @node.setter
def node(self, node): def node(self, node):
self._node = node self._node = node
self._status.modified() self.modified()
def has_node(self): def has_node(self):
return self._node is not None return self._node is not None
@ -379,7 +461,12 @@ class BoundaryCondition(SQLSubModel):
@property @property
def data(self): def data(self):
return self._data.copy() return list(
filter(
lambda el: not el.is_deleted(),
self._data
)
)
def get_type_column(self, column): def get_type_column(self, column):
if 0 <= column < 2: if 0 <= column < 2:
@ -418,40 +505,53 @@ class BoundaryCondition(SQLSubModel):
def add(self, index: int): def add(self, index: int):
value = Data(self._default_0, self._default_1) value = Data(self._default_0, self._default_1)
self._data.insert(index, value) self._data.insert(index, value)
self._status.modified() self.modified()
return value return value
def insert(self, index: int, value): def insert(self, index: int, value):
self._data.insert(index, value) if value in self._data:
self._status.modified() value.set_as_not_deleted()
else:
self._data.insert(index, value)
def delete_i(self, indexes): self.modified()
def hard_delete_i(self, indexes):
self._data = list( self._data = list(
map( map(
lambda e: e[1], lambda e: e[1],
filter( filter(
lambda e: e[0] not in indexes, lambda e: e[0] not in indexes,
enumerate(self._data)
)
)
)
self.modified()
def delete_i(self, indexes):
list(
map(
lambda e: e[1].set_as_deleted(),
filter(
lambda e: e[0] in indexes,
enumerate(self.data) enumerate(self.data)
) )
) )
) )
self._status.modified() self.modified()
def delete(self, els): def delete(self, els):
self._data = list( for el in els:
filter( el.set_as_deleted()
lambda e: e not in els,
self.data self.modified()
)
)
self._status.modified()
def sort(self, _reverse=False, key=None): def sort(self, _reverse=False, key=None):
if key is None: if key is None:
self._data.sort(reverse=_reverse) self._data.sort(reverse=_reverse)
else: else:
self._data.sort(reverse=_reverse, key=key) self._data.sort(reverse=_reverse, key=key)
self._status.modified() self.modified()
def index(self, bc): def index(self, bc):
self._data.index(bc) self._data.index(bc)
@ -469,7 +569,7 @@ class BoundaryCondition(SQLSubModel):
v = self._data[index] v = self._data[index]
v[column] = self._types[column](value) v[column] = self._types[column](value)
self._data[index] = v self._data[index] = v
self._status.modified() self.modified()
def set_i_0(self, index: int, value): def set_i_0(self, index: int, value):
self._set_i_c_v(index, 0, value) self._set_i_c_v(index, 0, value)
@ -501,14 +601,14 @@ class BoundaryCondition(SQLSubModel):
next = index - 1 next = index - 1
d = self._data d = self._data
d[index], d[next] = d[next], d[index] d[index], d[next] = d[next], d[index]
self._status.modified() self.modified()
def move_down(self, index): def move_down(self, index):
if index >= 0: if index >= 0:
prev = index + 1 prev = index + 1
d = self._data d = self._data
d[index], d[prev] = d[prev], d[index] d[index], d[prev] = d[prev], d[index]
self._status.modified() self.modified()
def reach(self, river): def reach(self, river):
r = [] r = []

View File

@ -19,7 +19,7 @@
from copy import copy from copy import copy
from tools import trace, timer from tools import trace, timer
from Model.Tools.PamhyrList import PamhyrModelListWithTab from Model.Tools.PamhyrListExt import PamhyrModelListWithTab
from Model.Except import NotImplementedMethodeError from Model.Except import NotImplementedMethodeError
from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition
@ -50,7 +50,10 @@ class BoundaryConditionList(PamhyrModelListWithTab):
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
execute("DELETE FROM boundary_condition") execute(
"DELETE FROM boundary_condition "
f"WHERE scenario = {self._status.scenario_id}"
)
for tab in self._tabs: for tab in self._tabs:
data["tab"] = tab data["tab"] = tab

View File

@ -22,8 +22,12 @@ from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition
class NotDefined(BoundaryCondition): class NotDefined(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
super(NotDefined, self).__init__(id=id, name=name, status=status) status=None, owner_scenario=-1):
super(NotDefined, self).__init__(
id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self._type = "ND" self._type = "ND"
self._header = ["x", "y"] self._header = ["x", "y"]
@ -34,9 +38,12 @@ class NotDefined(BoundaryCondition):
class PonctualContribution(BoundaryCondition): class PonctualContribution(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
status=None, owner_scenario=-1):
super(PonctualContribution, self).__init__( super(PonctualContribution, self).__init__(
id=id, name=name, status=status) id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self._type = "PC" self._type = "PC"
self._header = ["time", "discharge"] self._header = ["time", "discharge"]
@ -48,8 +55,12 @@ class PonctualContribution(BoundaryCondition):
class TimeOverZ(BoundaryCondition): class TimeOverZ(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
super(TimeOverZ, self).__init__(id=id, name=name, status=status) status=None, owner_scenario=-1):
super(TimeOverZ, self).__init__(
id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self._type = "TZ" self._type = "TZ"
self._header = ["time", "z"] self._header = ["time", "z"]
@ -61,9 +72,12 @@ class TimeOverZ(BoundaryCondition):
class TimeOverDischarge(BoundaryCondition): class TimeOverDischarge(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
status=None, owner_scenario=-1):
super(TimeOverDischarge, self).__init__( super(TimeOverDischarge, self).__init__(
id=id, name=name, status=status) id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self._type = "TD" self._type = "TD"
self._header = ["time", "discharge"] self._header = ["time", "discharge"]
@ -75,8 +89,12 @@ class TimeOverDischarge(BoundaryCondition):
class ZOverDischarge(BoundaryCondition): class ZOverDischarge(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
super(ZOverDischarge, self).__init__(id=id, name=name, status=status) status=None, owner_scenario=-1):
super(ZOverDischarge, self).__init__(
id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self._type = "ZD" self._type = "ZD"
self._header = ["z", "discharge"] self._header = ["z", "discharge"]
@ -92,8 +110,12 @@ class ZOverDischarge(BoundaryCondition):
class Solid(BoundaryCondition): class Solid(BoundaryCondition):
def __init__(self, id: int = -1, name: str = "", status=None): def __init__(self, id: int = -1, name: str = "",
super(Solid, self).__init__(id=id, name=name, status=status) status=None, owner_scenario=-1):
super(Solid, self).__init__(
id=id, name=name, status=status,
owner_scenario=owner_scenario
)
self.d50 = 0.002 self.d50 = 0.002
self.sigma = 1 self.sigma = 1

View File

@ -30,7 +30,8 @@ logger = logging.getLogger()
class Friction(SQLSubModel): class Friction(SQLSubModel):
def __init__(self, id: int = -1, def __init__(self, id: int = -1,
status=None, owner_scenario=-1): status=None,
owner_scenario=-1):
super(Friction, self).__init__( super(Friction, self).__init__(
id=id, status=status, id=id, status=status,
owner_scenario=owner_scenario owner_scenario=owner_scenario
@ -149,7 +150,7 @@ class Friction(SQLSubModel):
table = execute( table = execute(
"SELECT pamhyr_id, deleted, begin_rk, end_rk, " + "SELECT pamhyr_id, deleted, begin_rk, end_rk, " +
"begin_strickler, end_strickler, scenario " + "begin_strickler, end_strickler, scenario " +
f"FROM friction " + "FROM friction " +
f"WHERE reach = {reach.pamhyr_id} " + f"WHERE reach = {reach.pamhyr_id} " +
f"AND scenario = {scenario.id} " + f"AND scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " +

View File

@ -222,7 +222,7 @@ class PamhyrModelListWithTab(SQLSubModel):
Returns: Returns:
The size of the tab list The size of the tab list
""" """
return len(self._tabs[lst]) return len(self.get_tab(lst))
def get_tab(self, lst): def get_tab(self, lst):
"""Get tab list (copy) from name """Get tab list (copy) from name
@ -233,14 +233,16 @@ class PamhyrModelListWithTab(SQLSubModel):
Returns: Returns:
Nothing Nothing
""" """
return self._tabs[lst].copy() # return self._tabs[lst].copy()
return list(
filter(
lambda el: not el.is_deleted(),
self._tabs[lst]
)
)
def get(self, lst, index): def get(self, lst, index):
return self._tabs[lst][index] return self.get_tab(lst)[index]
def set(self, lst, index, new):
self._tabs[lst][index] = new
self._status.modified()
def new(self, lst, index): def new(self, lst, index):
"""Create new elements and add it to list """Create new elements and add it to list
@ -255,32 +257,38 @@ class PamhyrModelListWithTab(SQLSubModel):
raise NotImplementedMethodeError(self, self.new) raise NotImplementedMethodeError(self, self.new)
def insert(self, lst, index, new): def insert(self, lst, index, new):
"""Insert element in tab if new in self._tabs[lst]:
new.set_as_not_deleted()
else:
self._tabs[lst].insert(index, new)
Args:
lst: The tab name
index: The index of new element
new: The new elements
Returns:
Nothing
"""
self._tabs[lst].insert(index, new)
self._status.modified() self._status.modified()
def delete(self, lst, els): def undelete(self, lst, els):
"""Delete elements from specific tab """Delete a list of elements
Args: Args:
lst: The tab name lst: The tab name
els: The elements list els: The list of elements
Returns: Returns:
Nothing Nothing
""" """
for el in els: for el in els:
self._tabs[lst].remove(el) el.set_as_not_deleted()
self._status.modified()
def delete(self, lst, els):
"""Delete a list of elements
Args:
lst: The tab name
els: The list of elements
Returns:
Nothing
"""
for el in els:
el.set_as_deleted()
def delete_i(self, lst, indexes): def delete_i(self, lst, indexes):
"""Delete elements from specific tab """Delete elements from specific tab

View File

@ -94,10 +94,11 @@ class AddCommand(QUndoCommand):
self._bcs = bcs self._bcs = bcs
self._tab = tab self._tab = tab
self._index = index self._index = index
self._old = self._bcs.get(self._tab, self._index)
self._new = None self._new = None
def undo(self): def undo(self):
self._bcs.delete_i(self._tab, [self._index]) self._bcs.delete(self._tab, self._old)
def redo(self): def redo(self):
if self._new is None: if self._new is None: