mirror of https://gitlab.com/pamhyr/pamhyr2
Network: Add scenario support.
parent
4199eb6ac5
commit
48c389a27c
|
|
@ -24,10 +24,8 @@ class Edge(PamhyrID):
|
|||
def __init__(self, id: int, name: str,
|
||||
node1: Node = None,
|
||||
node2: Node = None,
|
||||
status=None):
|
||||
super(Edge, self).__init__(id)
|
||||
|
||||
self._status = status
|
||||
status=None, **kwargs):
|
||||
super(Edge, self).__init__(id=id, status=status, **kwargs)
|
||||
|
||||
self._name = name
|
||||
self.node1 = node1
|
||||
|
|
@ -63,7 +61,7 @@ class Edge(PamhyrID):
|
|||
elif name == "enable":
|
||||
self._enable = value
|
||||
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
|
|
@ -79,16 +77,19 @@ class Edge(PamhyrID):
|
|||
def is_enable(self):
|
||||
return self._enable
|
||||
|
||||
def is_deleted(self):
|
||||
return False
|
||||
|
||||
def enable(self, enable=True):
|
||||
self._enable = enable
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
def disable(self):
|
||||
self._enable = False
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
def reverse(self):
|
||||
tmp = self.node1
|
||||
self.node1 = self.node2
|
||||
self.node2 = tmp
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@ from Model.Network.Edge import Edge
|
|||
|
||||
|
||||
class Graph(object):
|
||||
def __init__(self, status=None):
|
||||
super(Graph, self).__init__()
|
||||
|
||||
self._status = status
|
||||
def __init__(self, **kwargs):
|
||||
super(Graph, self).__init__(**kwargs)
|
||||
|
||||
self._node_ctor = Node
|
||||
self._edge_ctor = Edge
|
||||
|
|
@ -38,13 +36,13 @@ class Graph(object):
|
|||
return f"Graph {{nodes: {self._nodes}, edges: {self._edges}}}"
|
||||
|
||||
def nodes(self):
|
||||
return self._nodes
|
||||
return list(filter(lambda n: not n.is_deleted(), self._nodes))
|
||||
|
||||
def nodes_names(self):
|
||||
return list(map(lambda n: n.name, self._nodes))
|
||||
return list(map(lambda n: n.name, self.nodes()))
|
||||
|
||||
def edges(self):
|
||||
return self._edges
|
||||
return list(filter(lambda e: not e.is_deleted(), self._edges))
|
||||
|
||||
def enable_edges(self):
|
||||
return list(
|
||||
|
|
@ -55,43 +53,43 @@ class Graph(object):
|
|||
"""Return a generator"""
|
||||
return filter(
|
||||
lambda e: e.is_enable(),
|
||||
self._edges
|
||||
self.edges()
|
||||
)
|
||||
|
||||
def edges_names(self):
|
||||
return list(map(lambda e: e.name, self._edges))
|
||||
return list(map(lambda e: e.name, self.edges()))
|
||||
|
||||
def nodes_counts(self):
|
||||
return len(self._nodes)
|
||||
return len(self.nodes())
|
||||
|
||||
def edges_counts(self):
|
||||
return len(self._edges)
|
||||
return len(self.edges())
|
||||
|
||||
def enable_nodes_counts(self):
|
||||
return reduce(
|
||||
lambda acc, n: acc + 1 if self.is_enable_node(n) else acc,
|
||||
self._nodes,
|
||||
self.nodes(),
|
||||
0
|
||||
)
|
||||
|
||||
def enable_edges_counts(self):
|
||||
return reduce(
|
||||
lambda acc, e: acc + 1 if e.is_enable() else acc,
|
||||
self._edges,
|
||||
self.edges(),
|
||||
0
|
||||
)
|
||||
|
||||
def is_node_exists(self, node_name):
|
||||
return reduce(
|
||||
lambda acc, n: (acc or (n.name == node_name)),
|
||||
self._nodes,
|
||||
self.nodes(),
|
||||
False
|
||||
)
|
||||
|
||||
def is_edge_exists(self, edge_name):
|
||||
return reduce(
|
||||
lambda acc, e: (acc or (e.name == edge_name)),
|
||||
self._edges,
|
||||
self.edges(),
|
||||
False
|
||||
)
|
||||
|
||||
|
|
@ -99,7 +97,7 @@ class Graph(object):
|
|||
node = list(
|
||||
filter(
|
||||
lambda n: n.name == node_name,
|
||||
self._nodes
|
||||
self.nodes()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -112,7 +110,7 @@ class Graph(object):
|
|||
edge = list(
|
||||
filter(
|
||||
lambda e: e.name == edge_name,
|
||||
self._edges
|
||||
self.edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -123,16 +121,18 @@ class Graph(object):
|
|||
|
||||
def _create_node(self, x: float, y: float):
|
||||
node = self._node_ctor(
|
||||
-1,
|
||||
"",
|
||||
x=x, y=y,
|
||||
id=-1, name="", x=x, y=y,
|
||||
status=self._status
|
||||
)
|
||||
return node
|
||||
|
||||
def _add_node(self, node):
|
||||
self._nodes.append(node)
|
||||
self._status.modified()
|
||||
if node in self._nodes:
|
||||
node.set_as_not_deleted()
|
||||
else:
|
||||
self._nodes.append(node)
|
||||
|
||||
self.modified()
|
||||
return node
|
||||
|
||||
def add_node(self, x: float = 0.0, y: float = 0.0):
|
||||
|
|
@ -143,9 +143,9 @@ class Graph(object):
|
|||
return self._add_node(node)
|
||||
|
||||
def remove_node(self, node):
|
||||
self._nodes.remove(node)
|
||||
node.set_as_deleted()
|
||||
self._remove_associated_edge(node)
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
def _remove_associated_edge(self, node: str):
|
||||
edges = list(
|
||||
|
|
@ -176,10 +176,12 @@ class Graph(object):
|
|||
# e.node2 == edge.node2),
|
||||
# self._edges)):
|
||||
# return None
|
||||
if edge in self._edges:
|
||||
edge.set_as_not_deleted()
|
||||
else:
|
||||
self._edges.append(edge)
|
||||
|
||||
self._edges.append(edge)
|
||||
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
return edge
|
||||
|
||||
def add_edge(self, n1: Node, n2: Node):
|
||||
|
|
@ -193,8 +195,8 @@ class Graph(object):
|
|||
return self._create_edge(n1, n2)
|
||||
|
||||
def remove_edge(self, edge):
|
||||
self._edges.remove(edge)
|
||||
self._status.modified()
|
||||
edge.set_as_deleted()
|
||||
self.modified()
|
||||
|
||||
def is_upstream_node(self, node):
|
||||
return reduce(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from Model.Network.Point import Point
|
|||
class Node(PamhyrID):
|
||||
def __init__(self, id: int, name: str,
|
||||
x: float = 0.0, y: float = 0.0,
|
||||
status=None):
|
||||
status=None, **kwargs):
|
||||
super(Node, self).__init__(id)
|
||||
|
||||
self._status = status
|
||||
|
|
@ -55,6 +55,9 @@ class Node(PamhyrID):
|
|||
|
||||
self._status.modified()
|
||||
|
||||
def is_deleted(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
|
|
|||
|
|
@ -54,15 +54,13 @@ logger = logging.getLogger()
|
|||
class RiverNode(Node, SQLSubModel):
|
||||
_sub_classes = []
|
||||
|
||||
def __init__(self, id: int, name: str,
|
||||
x: float, y: float,
|
||||
status=None):
|
||||
self._pamhyr_id = self.get_new_pamhyr_id(id)
|
||||
|
||||
def __init__(self, id: int = -1, name: str = "",
|
||||
x: float = 0.0, y: float = 0.0,
|
||||
status=None, owner_scenario=-1):
|
||||
super(RiverNode, self).__init__(
|
||||
id, name,
|
||||
x, y,
|
||||
status=status
|
||||
id, name, x, y,
|
||||
status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
|
||||
self._locker = None
|
||||
|
|
@ -72,6 +70,7 @@ class RiverNode(Node, SQLSubModel):
|
|||
execute(f"""
|
||||
CREATE TABLE river_node{ext}(
|
||||
{cls.create_db_add_pamhyr_id()},
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
name TEXT NOT NULL,
|
||||
x REAL NOT NULL,
|
||||
y REAL NOT NULL,
|
||||
|
|
@ -93,6 +92,13 @@ class RiverNode(Node, SQLSubModel):
|
|||
if major == minor == "0":
|
||||
cls._db_update_to_0_1_0(execute, data=data)
|
||||
|
||||
if major == "0" and minor == "1":
|
||||
if int(release) < 2:
|
||||
execute(
|
||||
"ALTER TABLE river_node " +
|
||||
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
|
||||
)
|
||||
|
||||
return cls._update_submodel(execute, version, data)
|
||||
|
||||
@classmethod
|
||||
|
|
@ -118,27 +124,65 @@ class RiverNode(Node, SQLSubModel):
|
|||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
nodes = []
|
||||
scenario = data["scenario"]
|
||||
loaded = data['loaded_pid']
|
||||
|
||||
if scenario is None:
|
||||
return nodes
|
||||
|
||||
table = execute(
|
||||
"SELECT pamhyr_id, deleted, name, x, y, scenario " +
|
||||
"FROM river_node " +
|
||||
f"WHERE scenario = {scenario.id} " +
|
||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) "
|
||||
)
|
||||
|
||||
table = execute("SELECT pamhyr_id, name, x, y FROM river_node")
|
||||
for row in table:
|
||||
nodes.append(
|
||||
cls(*row, status=data["status"])
|
||||
it = iter(row)
|
||||
|
||||
pid = next(it)
|
||||
deleted = (next(it) == 1)
|
||||
name = next(it)
|
||||
x = next(it)
|
||||
y = next(it)
|
||||
owner_scenario = next(it)
|
||||
|
||||
|
||||
node = cls(
|
||||
id=pid,
|
||||
name=name, x=x, y=y,
|
||||
status=data["status"],
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
if deleted:
|
||||
node.set_as_deleted()
|
||||
|
||||
loaded.add(pid)
|
||||
nodes.append(node)
|
||||
|
||||
data["scenario"] = scenario.parent
|
||||
nodes += cls._db_load(execute, data)
|
||||
data["scenario"] = scenario
|
||||
|
||||
return nodes
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
execute(
|
||||
"INSERT OR REPLACE INTO river_node(pamhyr_id, name, x, y) " +
|
||||
"INSERT OR REPLACE INTO river_node(" +
|
||||
"pamhyr_id, deleted, name, x, y, scenario" +
|
||||
") " +
|
||||
"VALUES (" +
|
||||
f"{self._pamhyr_id}, " +
|
||||
f"{self._pamhyr_id}, {self._db_format(self.is_deleted())}, " +
|
||||
f"'{self._db_format(self.name)}', " +
|
||||
f"{self.x}, {self.y}" +
|
||||
f"{self.x}, {self.y}, {self._status.scenario_id}" +
|
||||
")"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def is_deleted(self):
|
||||
return self._deleted
|
||||
|
||||
@property
|
||||
def locker(self):
|
||||
return self._locker
|
||||
|
|
@ -154,16 +198,15 @@ class RiverReach(Edge, SQLSubModel):
|
|||
FrictionList,
|
||||
]
|
||||
|
||||
def __init__(self, id: str, name: str,
|
||||
def __init__(self, id: str = -1, name: str = "",
|
||||
node1: RiverNode = None,
|
||||
node2: RiverNode = None,
|
||||
status=None):
|
||||
# self._pamhyr_id = self.get_new_pamhyr_id(id)
|
||||
|
||||
status=None, owner_scenario=-1):
|
||||
super(RiverReach, self).__init__(
|
||||
id, name,
|
||||
node1, node2,
|
||||
status=status
|
||||
status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
|
||||
self._reach = Reach(status=self._status, parent=self)
|
||||
|
|
@ -174,6 +217,7 @@ class RiverReach(Edge, SQLSubModel):
|
|||
execute(f"""
|
||||
CREATE TABLE river_reach{ext} (
|
||||
{cls.create_db_add_pamhyr_id()},
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
name TEXT NOT NULL,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
node1 INTEGER,
|
||||
|
|
@ -198,6 +242,13 @@ class RiverReach(Edge, SQLSubModel):
|
|||
if major == minor == "0":
|
||||
cls._db_update_to_0_1_0(execute, data)
|
||||
|
||||
if major == "0" and minor == "1":
|
||||
if int(release) < 2:
|
||||
execute(
|
||||
"ALTER TABLE river_reach " +
|
||||
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
|
||||
)
|
||||
|
||||
return cls._update_submodel(execute, version, data)
|
||||
|
||||
@classmethod
|
||||
|
|
@ -246,20 +297,30 @@ class RiverReach(Edge, SQLSubModel):
|
|||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
reachs = []
|
||||
scenario = data["scenario"]
|
||||
loaded = data['loaded_pid']
|
||||
|
||||
if scenario is None:
|
||||
return reachs
|
||||
|
||||
table = execute(
|
||||
"SELECT pamhyr_id, name, enabled, node1, node2 FROM river_reach"
|
||||
"SELECT pamhyr_id, deleted, name, enabled, " +
|
||||
"node1, node2, scenario " +
|
||||
"FROM river_reach " +
|
||||
f"WHERE scenario = {scenario.id} " +
|
||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
|
||||
)
|
||||
|
||||
for row in table:
|
||||
it = iter(row)
|
||||
|
||||
# Create new reach
|
||||
pid = next(it)
|
||||
deleted = (next(it) == 1)
|
||||
name = next(it)
|
||||
enabled = (next(it) == 1)
|
||||
node1_pid = next(it)
|
||||
node2_pid = next(it)
|
||||
owner_scenario = next(it)
|
||||
|
||||
# Get nodes corresponding to db foreign key id
|
||||
node1 = next(
|
||||
|
|
@ -273,26 +334,41 @@ class RiverReach(Edge, SQLSubModel):
|
|||
)
|
||||
)
|
||||
|
||||
new = cls(pid, name, node1, node2, status=data["status"])
|
||||
new = cls(
|
||||
id=pid, name=name, node1=node1, node2=node2,
|
||||
status=data["status"],
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
new.enable(enable=enabled)
|
||||
if deleted:
|
||||
nd.set_as_deleted()
|
||||
|
||||
data["reach"] = new
|
||||
|
||||
new._reach = Reach._db_load(execute, data)
|
||||
new._frictions = FrictionList._db_load(execute, data)
|
||||
|
||||
loaded.add(pid)
|
||||
reachs.append(new)
|
||||
|
||||
data["scenario"] = scenario.parent
|
||||
reachs += cls._db_load(execute, data)
|
||||
data["scenario"] = scenario
|
||||
|
||||
return reachs
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
execute(
|
||||
"INSERT OR REPLACE INTO " +
|
||||
"river_reach(pamhyr_id, name, enabled, node1, node2) " +
|
||||
"river_reach(" +
|
||||
"pamhyr_id, deleted, name, enabled, " +
|
||||
"node1, node2, scenario" +
|
||||
") " +
|
||||
"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._name)}', " +
|
||||
f"{self._db_format(self.is_enable())},"
|
||||
f"{self.node1.pamhyr_id}, {self.node2.pamhyr_id}" +
|
||||
f"{self.node1.pamhyr_id}, {self.node2.pamhyr_id}, " +
|
||||
f"{self._status.scenario_id}" +
|
||||
")"
|
||||
)
|
||||
|
||||
|
|
@ -301,6 +377,9 @@ class RiverReach(Edge, SQLSubModel):
|
|||
objs = [self._reach, self._frictions]
|
||||
return self._save_submodel(execute, objs, data)
|
||||
|
||||
def is_deleted(self):
|
||||
return self._deleted
|
||||
|
||||
@property
|
||||
def reach(self):
|
||||
return self._reach
|
||||
|
|
@ -327,7 +406,9 @@ class River(Graph, SQLSubModel):
|
|||
]
|
||||
|
||||
def __init__(self, status=None):
|
||||
super(River, self).__init__(status=status)
|
||||
super(River, self).__init__(
|
||||
status=status
|
||||
)
|
||||
|
||||
# Replace Node and Edge ctor by custom ctor
|
||||
self._node_ctor = RiverNode
|
||||
|
|
@ -359,7 +440,7 @@ class River(Graph, SQLSubModel):
|
|||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = cls(data["status"])
|
||||
new = cls(status=data["status"])
|
||||
|
||||
# Stricklers (Stricklers is load in first because it's needed
|
||||
# for reachs)
|
||||
|
|
@ -462,12 +543,13 @@ class River(Graph, SQLSubModel):
|
|||
execute(
|
||||
f"DELETE FROM {table} " +
|
||||
"WHERE " +
|
||||
f"scenario = {self._status.scenario_id} AND (" +
|
||||
" OR ".join(
|
||||
map(
|
||||
lambda n: f"( pamhyr_id <> {n.pamhyr_id} )",
|
||||
els
|
||||
)
|
||||
)
|
||||
) + ")"
|
||||
)
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
|
|
|
|||
Loading…
Reference in New Issue