Accept Merge Request #37: (api -> master)
Merge Request: Big api refactor Created By: @王琼钰 Accepted By: @王琼钰 URL: https://tjwater.coding.net/p/tjwatercloud/d/TJWaterServer/git/merge/37
This commit is contained in:
@@ -5,10 +5,8 @@ from .project import copy_project
|
||||
from .change_set import ChangeSet
|
||||
|
||||
from .operation import get_current_operation
|
||||
from .operation import execute_undo as undo
|
||||
from .operation import execute_redo as redo
|
||||
from .operation import have_snapshot, take_snapshot, pick_snapshot
|
||||
from .operation import have_transaction, start_transaction, commit_transaction, abort_transaction
|
||||
from .operation import execute_undo, execute_redo
|
||||
from .operation import have_snapshot, take_snapshot, pick_snapshot, sync_with_server
|
||||
|
||||
from .s0_base import JUNCTION, RESERVOIR, TANK, PIPE, PUMP, VALVE
|
||||
from .s0_base import is_node, is_junction, is_reservoir, is_tank
|
||||
@@ -20,31 +18,19 @@ from .s0_base import get_node_links
|
||||
|
||||
from .s1_title import set_title, get_title
|
||||
|
||||
from .s2_junctions import add_junction, delete_junction
|
||||
from .s2_junctions import set_junction_elevation, set_junction_demand, set_junction_pattern, set_junction_coord
|
||||
from .s2_junctions import get_junction_property_names, get_junction_properties
|
||||
from .s2_junctions import get_junction_schema, add_junction, get_junction, set_junction, delete_junction
|
||||
|
||||
from .s3_reservoirs import add_reservoir, delete_reservoir
|
||||
from .s3_reservoirs import set_reservoir_head, set_reservoir_pattern, set_reservoir_coord
|
||||
from .s3_reservoirs import get_reservoir_property_names, get_reservoir_properties
|
||||
from .s3_reservoirs import get_reservoir_schema, add_reservoir, get_reservoir, set_reservoir, delete_reservoir
|
||||
|
||||
from .s4_tanks import OVERFLOW_YES, OVERFLOW_NO
|
||||
from .s4_tanks import add_tank, delete_tank
|
||||
from .s4_tanks import set_tank_elevation, set_tank_init_level, set_tank_min_level, set_tank_max_level, set_tank_diameter, set_tank_min_vol, set_tank_vol_curve, set_tank_overflow, set_tank_coord
|
||||
from .s4_tanks import get_tank_property_names, get_tank_properties
|
||||
from .s4_tanks import get_tank_schema, add_tank, get_tank, set_tank, delete_tank
|
||||
|
||||
from .s5_pipes import PIPE_STATUS_OPEN, PIPE_STATUS_CLOSED, PIPE_STATUS_CV
|
||||
from .s5_pipes import add_pipe, delete_pipe
|
||||
from .s5_pipes import set_pipe_node1, set_pipe_node2, set_pipe_length, set_pipe_diameter, set_pipe_roughness, set_pipe_minor_loss, set_pipe_status
|
||||
from .s5_pipes import get_pipe_property_names, get_pipe_properties
|
||||
from .s5_pipes import get_pipe_schema, add_pipe, get_pipe, set_pipe, delete_pipe
|
||||
|
||||
from .s6_pumps import add_pump, delete_pump
|
||||
from .s6_pumps import set_pump_node1, set_pump_node2
|
||||
from .s6_pumps import get_pump_property_names, get_pump_properties
|
||||
from .s6_pumps import get_pump_schema, add_pump, get_pump, set_pump, delete_pump
|
||||
|
||||
from .s7_valves import VALVES_TYPE_PRV, VALVES_TYPE_PSV, VALVES_TYPE_PBV, VALVES_TYPE_FCV, VALVES_TYPE_TCV, VALVES_TYPE_GPV
|
||||
from .s7_valves import add_valve, delete_valve
|
||||
from .s7_valves import set_valve_node1, set_valve_node2, set_valve_diameter, set_valve_type, set_valve_setting, set_valve_minor_loss
|
||||
from .s7_valves import get_valve_property_names, get_valve_properties
|
||||
from .s7_valves import get_valve_schema, add_valve, get_valve, set_valve, delete_valve
|
||||
|
||||
# from .s24_coordinates import get_node_coord, set_node_coord
|
||||
@@ -1,12 +1,22 @@
|
||||
class ChangeSet:
|
||||
def __init__(self) -> None:
|
||||
def __init__(self):
|
||||
self.operations : list[dict[str, str]] = []
|
||||
|
||||
def add(self, type: str, id: str) -> None:
|
||||
def add(self, type: str, id: str):
|
||||
self.operations.append({ 'operation': 'add', 'type': type, 'id': id })
|
||||
return self
|
||||
|
||||
def delete(self, type: str, id: str) -> None:
|
||||
def delete(self, type: str, id: str):
|
||||
self.operations.append({ 'operation': 'delete', 'type': type, 'id': id })
|
||||
return self
|
||||
|
||||
def update(self, type: str, id: str, property: str) -> None:
|
||||
self.operations.append({ 'operation': 'update', 'type': type, 'id': id, 'property': property })
|
||||
def update(self, type: str, id: str, properties: list[str]):
|
||||
self.operations.append({ 'operation': 'update', 'type': type, 'id': id, 'properties': properties })
|
||||
return self
|
||||
|
||||
def append(self, other) -> None:
|
||||
self.operations += other.operations
|
||||
return self
|
||||
|
||||
def compress(self) -> None:
|
||||
return self
|
||||
|
||||
319
api/operation.py
319
api/operation.py
@@ -1,111 +1,129 @@
|
||||
from psycopg.rows import dict_row, Row
|
||||
from .connection import g_conn_dict as conn
|
||||
from .utility import *
|
||||
from .change_set import *
|
||||
|
||||
def _get_current_transaction(name: str) -> Row | None:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select * from transaction_operation")
|
||||
return cur.fetchone()
|
||||
|
||||
def _get_current_transaction_id(name: str) -> int:
|
||||
row = _get_current_transaction(name)
|
||||
return int(row['id'])
|
||||
API_ADD = 'add'
|
||||
API_DELETE = 'delete'
|
||||
API_UPDATE = 'update'
|
||||
|
||||
def _remove_transaction(name: str) -> None:
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(f"delete from transaction_operation")
|
||||
|
||||
def _remove_operation(name: str, id: int) -> None:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
# can not be >= to cascade delete since there is a tree !
|
||||
cur.execute(f"delete from transaction_operation where id = {id}") # this should not happen
|
||||
cur.execute(f"delete from snapshot_operation where id = {id}") # this may happen
|
||||
cur.execute(f"delete from operation where id = {id}")
|
||||
row = read(name, f'select * from operation where parent = {id}')
|
||||
if row != None:
|
||||
raise Exception('Disallow to remove parent operation !')
|
||||
|
||||
sql += f'delete from snapshot_operation where id = {id};'
|
||||
sql += f'delete from operation where id = {id}'
|
||||
write(name, sql)
|
||||
|
||||
|
||||
def _get_parents(name: str, id: int) -> list[int]:
|
||||
ids = [id]
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
while ids[-1] != 0:
|
||||
cur.execute(f"select parent from operation where id = {ids[-1]}")
|
||||
ids.append(int(cur.fetchone()['parent']))
|
||||
while ids[-1] != 0:
|
||||
row = read(name, f'select parent from operation where id = {ids[-1]}')
|
||||
ids.append(int(row['parent']))
|
||||
return ids
|
||||
|
||||
|
||||
def get_current_operation(name: str) -> int:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select id from current_operation")
|
||||
return int(cur.fetchone()['id'])
|
||||
row = read(name, f'select id from current_operation')
|
||||
return int(row['id'])
|
||||
|
||||
|
||||
def _update_current_operation(name: str, old_id: int, id: int) -> None:
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(f"update current_operation set id = {id} where id = {old_id}")
|
||||
return write(name, f'update current_operation set id = {id} where id = {old_id}')
|
||||
|
||||
def _add_redo_undo(name: str, redo: str, undo: str) -> int:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
parent = get_current_operation(name)
|
||||
cur.execute(f"insert into operation (id, redo, undo, parent) values (default, '{redo}', '{undo}', {parent})")
|
||||
cur.execute("select max(id) from operation")
|
||||
return int(cur.fetchone()['max'])
|
||||
|
||||
# execute curr undo
|
||||
def _query_undo(name: str, id: str) -> dict[str, str]:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select undo, parent from operation where id = {id}")
|
||||
return cur.fetchone()
|
||||
def _add_redo_undo(name: str, redo: str, undo: str, api_id: str, api_op: str, api_object_type: str, api_object_id: str, api_object_properties: list[str]) -> int:
|
||||
parent = get_current_operation(name)
|
||||
ps = []
|
||||
for p in api_object_properties:
|
||||
ps.append(f'"{p}"')
|
||||
if len(ps) > 0:
|
||||
ps = ','.join(ps)
|
||||
ps = '{' + ps + '}'
|
||||
sql = f"insert into operation (id, redo, undo, parent, api_id, api_op, api_object_type, api_object_id, api_object_properties) values (default, '{redo}', '{undo}', {parent}, '{api_id}', '{api_op}', '{api_object_type}', '{api_object_id}', '{ps}')"
|
||||
else:
|
||||
sql = f"insert into operation (id, redo, undo, parent, api_id, api_op, api_object_type, api_object_id) values (default, '{redo}', '{undo}', {parent}, '{api_id}', '{api_op}', '{api_object_type}', '{api_object_id}')"
|
||||
write(name, sql)
|
||||
|
||||
return int(read(name, 'select max(id) from operation')['max'])
|
||||
|
||||
|
||||
def _query_operation(name: str, id: str) -> dict[str, str]:
|
||||
return read(name, f'select * from operation where id = {id}')
|
||||
|
||||
|
||||
# execute next redo
|
||||
def _query_redo_child(name: str, id: str) -> str:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select redo_child from operation where id = {id}")
|
||||
return cur.fetchone()['redo_child']
|
||||
row = read(name, f'select redo_child from operation where id = {id}')
|
||||
return row['redo_child']
|
||||
|
||||
def _query_redo(name: str, id: str) -> dict[str, str]:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select redo from operation where id = {id}")
|
||||
return cur.fetchone()['redo']
|
||||
|
||||
def _set_redo_child(name: str, id: int, child: int | str) -> None:
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(f"update operation set redo_child = {child} where id = {id}")
|
||||
return write(name, f'update operation set redo_child = {child} where id = {id}')
|
||||
|
||||
def _execute(name: str, sql: str) -> None:
|
||||
with conn[name].cursor() as cur:
|
||||
sql = sql.replace("\"", "\'")
|
||||
cur.execute(sql)
|
||||
|
||||
def add_operation(name: str, redo: str, undo: str) -> None:
|
||||
curr = _add_redo_undo(name, redo, undo)
|
||||
def add_operation(name: str, redo: str, undo: str, api_id: str, api_op: str, api_object_type: str, api_object_id: str, api_object_properties: list[str] = []) -> None:
|
||||
curr = _add_redo_undo(name, redo, undo, api_id, api_op, api_object_type, api_object_id, api_object_properties)
|
||||
old = get_current_operation(name)
|
||||
_update_current_operation(name, old, curr)
|
||||
|
||||
def execute_undo(name: str, discard: bool = False) -> None:
|
||||
|
||||
def _reverser_op(op: str) -> str:
|
||||
if op == API_ADD:
|
||||
return API_DELETE
|
||||
elif op == API_DELETE:
|
||||
return API_ADD
|
||||
else:
|
||||
return op
|
||||
|
||||
|
||||
def _get_change_set(row: dict[str, str], undo: bool) -> ChangeSet:
|
||||
op = row['api_op']
|
||||
if undo:
|
||||
op = _reverser_op(op)
|
||||
|
||||
type = row['api_object_type']
|
||||
id = row['api_object_id']
|
||||
|
||||
change = ChangeSet()
|
||||
|
||||
if op == API_ADD:
|
||||
change.add(type, id)
|
||||
elif op == API_DELETE:
|
||||
change.delete(type, id)
|
||||
elif op == API_UPDATE:
|
||||
change.update(type, id, row['api_object_properties'])
|
||||
|
||||
return change
|
||||
|
||||
|
||||
def execute_undo(name: str, discard: bool) -> ChangeSet:
|
||||
curr = get_current_operation(name)
|
||||
|
||||
# transaction control
|
||||
if have_transaction(name):
|
||||
tran = _get_current_transaction(name)
|
||||
if tran != None and int(tran['id']) >= 0:
|
||||
if bool(tran['strict']): # strict mode disallow undo
|
||||
print("Do not allow to undo in strict transaction mode!")
|
||||
return
|
||||
elif int(tran['id']) >= curr: # normal mode disallow undo start point, and there is foreign key constraint
|
||||
print("Do not allow to undo transaction start point!")
|
||||
return
|
||||
|
||||
row = _query_undo(name, curr)
|
||||
row = _query_operation(name, curr)
|
||||
undo = row['undo']
|
||||
if undo == '':
|
||||
print("nothing to undo!")
|
||||
return
|
||||
|
||||
parent = int(row['parent'])
|
||||
_set_redo_child(name, parent, 'NULL' if discard else curr)
|
||||
change = _get_change_set(row, True)
|
||||
|
||||
_execute(name, undo)
|
||||
parent = int(row['parent'])
|
||||
_set_redo_child(name, parent, 'null' if discard else curr)
|
||||
|
||||
write(name, undo)
|
||||
_update_current_operation(name, curr, parent)
|
||||
|
||||
if discard:
|
||||
_remove_operation(name, curr)
|
||||
|
||||
def execute_redo(name: str) -> None:
|
||||
return change
|
||||
|
||||
|
||||
def execute_redo(name: str) -> ChangeSet:
|
||||
curr = get_current_operation(name)
|
||||
redoChild = _query_redo_child(name, curr)
|
||||
if redoChild == None:
|
||||
@@ -113,108 +131,127 @@ def execute_redo(name: str) -> None:
|
||||
return
|
||||
|
||||
child = int(redoChild)
|
||||
redo = _query_redo(name, child)
|
||||
row = _query_operation(name, child)
|
||||
redo = row['redo']
|
||||
|
||||
_execute(name, redo)
|
||||
change = _get_change_set(row, False)
|
||||
|
||||
write(name, redo)
|
||||
_update_current_operation(name, curr, child)
|
||||
|
||||
# snapshot support to checkout between different version of database
|
||||
# snapshot is persistent
|
||||
# since redo always remember the recently undo path
|
||||
return change
|
||||
|
||||
|
||||
def _get_operation_by_tag(name: str, tag: str) -> int | None:
|
||||
row = read(name, f"select id from snapshot_operation where tag = '{tag}'")
|
||||
return int(row['id']) if row != None else None
|
||||
|
||||
|
||||
def have_snapshot(name: str, tag: str) -> bool:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select id from snapshot_operation where tag = '{tag}'")
|
||||
return cur.rowcount > 0
|
||||
return _get_operation_by_tag(name, tag) != None
|
||||
|
||||
def take_snapshot(name: str, tag: str) -> None:
|
||||
|
||||
def take_snapshot(name: str, tag: str) -> int | None:
|
||||
if tag == None or tag == '':
|
||||
print('Non empty tag is expected!')
|
||||
return
|
||||
return None
|
||||
|
||||
curr = get_current_operation(name)
|
||||
write(name, f"insert into snapshot_operation (id, tag) values ({curr}, '{tag}')")
|
||||
return curr
|
||||
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(f"insert into snapshot_operation (id, tag) values ({curr}, '{tag}')")
|
||||
|
||||
def pick_snapshot(name: str, tag: str) -> None:
|
||||
def pick_snapshot(name: str, tag: str, discard: bool) -> ChangeSet:
|
||||
if tag == None or tag == '':
|
||||
print('Non empty tag is expected!')
|
||||
return
|
||||
return ChangeSet()
|
||||
|
||||
if not have_snapshot(name, tag):
|
||||
target = _get_operation_by_tag(name, tag)
|
||||
if target == None:
|
||||
print('No such snapshot!')
|
||||
return
|
||||
return ChangeSet()
|
||||
|
||||
curr = get_current_operation(name)
|
||||
|
||||
curr_parents = _get_parents(name, curr)
|
||||
target_parents = _get_parents(name, target)
|
||||
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select id from snapshot_operation where tag = '{tag}'")
|
||||
target = int(cur.fetchone()['id'])
|
||||
if target in curr_parents: # target -> curr
|
||||
for i in range(curr_parents.index(target)):
|
||||
execute_undo(name)
|
||||
else:
|
||||
target_parents = _get_parents(name, target)
|
||||
if curr in target_parents: # curr -> target
|
||||
for i in range(target_parents.index(curr)):
|
||||
execute_redo(name)
|
||||
else:
|
||||
ancestor_index = -1
|
||||
while curr_parents[ancestor_index] == target_parents[ancestor_index]:
|
||||
ancestor_index -= 1
|
||||
change = ChangeSet()
|
||||
|
||||
# ancestor -> curr
|
||||
ancestor = curr_parents[ancestor_index + 1] # ancestor_index + 1 is common parent
|
||||
for i in range(curr_parents.index(ancestor)):
|
||||
execute_undo(name)
|
||||
# ancestor -> redo, need assign redo_child
|
||||
while target_parents[ancestor_index] != target:
|
||||
cur.execute(f"update operation set redo_child = '{target_parents[ancestor_index]}' where id = '{target_parents[ancestor_index + 1]}'")
|
||||
execute_redo(name)
|
||||
ancestor_index -= 1
|
||||
cur.execute(f"update operation set redo_child = '{target}' where id = '{target_parents[1]}'")
|
||||
execute_redo(name)
|
||||
if target in curr_parents:
|
||||
for _ in range(curr_parents.index(target)):
|
||||
change.append(execute_undo(name, discard))
|
||||
|
||||
# transaction is volatile, commit/abort will destroy transaction.
|
||||
# can not redo an aborted transaction.
|
||||
# but can undo a committed transaction... inconsistent...
|
||||
# it may remove snapshot if it is in aborted transaction
|
||||
elif curr in target_parents:
|
||||
target_parents.reverse()
|
||||
curr_index = target_parents.index(curr)
|
||||
for i in range(curr_index, len(target_parents) - 1):
|
||||
write(name, f"update operation set redo_child = '{target_parents[i + 1]}' where id = '{target_parents[i]}'")
|
||||
change.append(execute_redo(name))
|
||||
|
||||
def have_transaction(name: str) -> bool:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(f"select * from transaction_operation")
|
||||
return cur.rowcount > 0
|
||||
else:
|
||||
ancestor_index = -1
|
||||
while curr_parents[ancestor_index] == target_parents[ancestor_index]:
|
||||
ancestor_index -= 1
|
||||
ancestor = curr_parents[ancestor_index + 1]
|
||||
|
||||
def start_transaction(name: str, strict: bool = False) -> None:
|
||||
if have_transaction(name):
|
||||
print("Only support single transaction now, please commit/abort current transaction!")
|
||||
return
|
||||
for _ in range(curr_parents.index(ancestor)):
|
||||
change.append(execute_undo(name, discard))
|
||||
|
||||
curr = get_current_operation(name)
|
||||
target_parents.reverse()
|
||||
curr_index = target_parents.index(ancestor)
|
||||
for i in range(curr_index, len(target_parents) - 1):
|
||||
write(name, f"update operation set redo_child = '{target_parents[i + 1]}' where id = '{target_parents[i]}'")
|
||||
change.append(execute_redo(name))
|
||||
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(f"insert into transaction_operation (id, strict) values ({curr}, {strict});")
|
||||
return change.compress()
|
||||
|
||||
def commit_transaction(name: str) -> None:
|
||||
if not have_transaction(name):
|
||||
print("No active transaction!")
|
||||
return
|
||||
|
||||
_remove_transaction(name)
|
||||
def get_change_set(name: str, operation: int, undo: bool) -> ChangeSet:
|
||||
row = read(name, f'select api_id, api_op, api_object_type, api_object_id, api_object_properties from operation where id = {operation}')
|
||||
return _get_change_set(row, undo)
|
||||
|
||||
def abort_transaction(name: str) -> None:
|
||||
if not have_transaction(name):
|
||||
print("No active transaction!")
|
||||
return
|
||||
|
||||
tran = _get_current_transaction_id(name)
|
||||
def get_current_change_set(name: str) -> ChangeSet:
|
||||
return get_change_set(name, get_current_operation(name), False)
|
||||
|
||||
curr = get_current_operation(name)
|
||||
curr_parents = _get_parents(name, curr)
|
||||
|
||||
for i in range(curr_parents.index(tran)):
|
||||
execute_undo(name, True)
|
||||
|
||||
_remove_transaction(name)
|
||||
def sync_with_server(name: str, operation: int) -> ChangeSet:
|
||||
fr = operation
|
||||
to = get_current_operation(name)
|
||||
|
||||
fr_parents = _get_parents(name, fr)
|
||||
to_parents = _get_parents(name, to)
|
||||
|
||||
change = ChangeSet()
|
||||
|
||||
if fr in to_parents:
|
||||
index = to_parents.index(fr) - 1
|
||||
while index >= 0:
|
||||
change.append(get_change_set(name, to_parents[index], False))
|
||||
index -= 1
|
||||
|
||||
elif to in fr_parents:
|
||||
index = 0
|
||||
while index <= fr_parents.index(to) - 1:
|
||||
change.append(get_change_set(name, fr_parents[index], True))
|
||||
index += 1
|
||||
|
||||
else:
|
||||
ancestor_index = -1
|
||||
while fr_parents[ancestor_index] == to_parents[ancestor_index]:
|
||||
ancestor_index -= 1
|
||||
|
||||
ancestor = fr_parents[ancestor_index + 1]
|
||||
|
||||
index = 0
|
||||
while index <= fr_parents.index(ancestor) - 1:
|
||||
change.append(get_change_set(name, fr_parents[index], True))
|
||||
index += 1
|
||||
|
||||
index = to_parents.index(ancestor) - 1
|
||||
while index >= 0:
|
||||
change.append(get_change_set(name, to_parents[index], False))
|
||||
index -= 1
|
||||
|
||||
return change.compress()
|
||||
|
||||
@@ -99,15 +99,15 @@ def add_node(name: str, node_type: str, id: str, x: float, y: float, table_sql:
|
||||
return ChangeSet()
|
||||
|
||||
with conn[name].cursor() as cur:
|
||||
sql = f"insert into _node (id, type) values ('{id}', '{node_type}'); "
|
||||
sql = f"insert into _node (id, type) values ('{id}', '{node_type}');"
|
||||
sql += table_sql
|
||||
sql += f" insert into coordinates (node, coord) values ('{id}', '({x}, {y})');"
|
||||
sql += f"insert into coordinates (node, coord) values ('{id}', '({x}, {y})');"
|
||||
cur.execute(sql)
|
||||
|
||||
redo = sql.replace("'", '"')
|
||||
undo = f'delete from coordinates where node = "{id}"; '
|
||||
undo = f'delete from coordinates where node = "{id}";'
|
||||
undo += table_undo_sql
|
||||
undo += f' delete from _node where id = "{id}";'
|
||||
undo += f'delete from _node where id = "{id}";'
|
||||
add_operation(name, redo, undo)
|
||||
|
||||
change = ChangeSet()
|
||||
@@ -133,9 +133,9 @@ def delete_node(name: str, node_type: str, id: str, table_sql: str, table_undo_s
|
||||
cur.execute(sql)
|
||||
|
||||
redo = sql.replace("'", '"')
|
||||
undo = f'insert into _node (id, type) values ("{id}", "{node_type}"); '
|
||||
undo = f'insert into _node (id, type) values ("{id}", "{node_type}");'
|
||||
undo += table_undo_sql
|
||||
undo += f' insert into coordinates (node, coord) values ("{id}", "{coord}");'
|
||||
undo += f'insert into coordinates (node, coord) values ("{id}", "{coord}");'
|
||||
add_operation(name, redo, undo)
|
||||
|
||||
change = ChangeSet()
|
||||
@@ -148,13 +148,13 @@ def add_link(name: str, link_type: str, id: str, table_sql: str, table_undo_sql:
|
||||
return ChangeSet()
|
||||
|
||||
with conn[name].cursor() as cur:
|
||||
sql = f"insert into _link (id, type) values ('{id}', '{link_type}'); "
|
||||
sql = f"insert into _link (id, type) values ('{id}', '{link_type}');"
|
||||
sql += table_sql
|
||||
cur.execute(sql)
|
||||
|
||||
redo = sql.replace("'", '"')
|
||||
undo = table_undo_sql
|
||||
undo += f' delete from _link where id = "{id}";'
|
||||
undo += f'delete from _link where id = "{id}";'
|
||||
add_operation(name, redo, undo)
|
||||
|
||||
change = ChangeSet()
|
||||
|
||||
@@ -11,14 +11,8 @@ def get_title(name: str) -> str:
|
||||
def set_title(name: str, value: str) -> ChangeSet:
|
||||
old = get_title(name)
|
||||
|
||||
with conn[name].cursor() as cur:
|
||||
sql = f"update title set value = '{value}'"
|
||||
cur.execute(sql)
|
||||
|
||||
redo = sql.replace("'", '"')
|
||||
undo = f'update title set value = "{old}"'
|
||||
add_operation(name, redo, undo)
|
||||
|
||||
change = ChangeSet()
|
||||
change.update('title', 'null', 'value')
|
||||
return change
|
||||
sql = f"update title set value = '{value}'"
|
||||
undo = f"update title set value = ''{old}''"
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_title', API_UPDATE, 'title', '')
|
||||
return get_current_change_set(name)
|
||||
|
||||
@@ -5,10 +5,8 @@ from .operation import *
|
||||
from .change_set import ChangeSet
|
||||
|
||||
|
||||
def _to_point(coord: str) -> dict[str, float]:
|
||||
coord = coord.removeprefix('(')
|
||||
coord = coord.removesuffix(')')
|
||||
coord = coord.split(',')
|
||||
def _to_client_point(coord: str) -> dict[str, float]:
|
||||
coord = coord.removeprefix('(').removesuffix(')').split(',')
|
||||
return { 'x': float(coord[0]), 'y': float(coord[1]) }
|
||||
|
||||
|
||||
@@ -20,7 +18,7 @@ def get_node_coord(name: str, id: str) -> dict[str, float] | None:
|
||||
return None
|
||||
|
||||
coord = str(row['coord'])
|
||||
return _to_point(coord)
|
||||
return _to_client_point(coord)
|
||||
|
||||
|
||||
def set_node_coord(name: str, node_type: str, id: str, x: float, y: float) -> ChangeSet:
|
||||
|
||||
@@ -4,82 +4,102 @@ from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'elevation' : define_property(float_type), \
|
||||
'demand' : define_property(float_type, True), \
|
||||
'pattern' : define_property(str_type, True), \
|
||||
'coord' : define_property(client_point_type), \
|
||||
'links' : define_property(str_list_type, False, True)}
|
||||
|
||||
|
||||
def get_junction_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_junction(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from junctions where id = '{id}'")
|
||||
|
||||
|
||||
def add_junction(name: str, id: str, x: float, y: float, elevation: float) -> ChangeSet:
|
||||
sql = f"insert into junctions (id, elevation) values ('{id}', {elevation});"
|
||||
undo_sql = f'delete from junctions where id = "{id}";'
|
||||
return add_node(name, JUNCTION, id, x, y, sql, undo_sql)
|
||||
|
||||
|
||||
def _get_junction(name: str, id: str) -> Row | None:
|
||||
return query(name, f"select elevation, demand, pattern from junctions where id = '{id}'")
|
||||
|
||||
|
||||
def delete_junction(name: str, id: str) -> ChangeSet:
|
||||
if not is_junction(name, id):
|
||||
if is_junction(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_junction(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
sql = f"insert into _node (id, type) values ('{id}', '{JUNCTION}');"
|
||||
sql += f"\ninsert into junctions (id, elevation) values ('{id}', {elevation});"
|
||||
sql += f"\ninsert into coordinates (node, coord) values ('{id}', '({x}, {y})');"
|
||||
|
||||
elevation = row['elevation']
|
||||
demand = decorate(row['demand'], 'float', True)
|
||||
pattern = decorate(row['pattern'], 'str', True)
|
||||
undo = f"delete from coordinates where node = ''{id}'';"
|
||||
undo += f"\ndelete from junctions where id = ''{id}'';"
|
||||
undo += f"\ndelete from _node where id = ''{id}'';"
|
||||
|
||||
sql = f"delete from junctions where id = '{id}';"
|
||||
undo_sql = f'insert into junctions (id, elevation, demand, pattern) values ("{id}", {elevation}, {demand}, {pattern});'
|
||||
|
||||
return delete_node(name, JUNCTION, id, sql, undo_sql)
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_junction', API_ADD, JUNCTION, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def _set_junction(name: str, id: str, key: str, key_type: str, value: str, optional: bool = False) -> ChangeSet:
|
||||
if not is_junction(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_junction(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
return update(name, JUNCTION, 'junctions', 'id', id, key, key_type, row[key], value, optional)
|
||||
|
||||
|
||||
def set_junction_elevation(name: str, id: str, elevation: float) -> ChangeSet:
|
||||
return _set_junction(name, id, 'elevation', 'float', str(elevation))
|
||||
|
||||
|
||||
def set_junction_demand(name: str, id: str, demand: float) -> ChangeSet:
|
||||
return _set_junction(name, id, 'demand', 'float', str(demand), True)
|
||||
|
||||
|
||||
def set_junction_pattern(name: str, id: str, pattern: str) -> ChangeSet:
|
||||
if not is_pattern(name, pattern):
|
||||
return ChangeSet()
|
||||
|
||||
return _set_junction(name, id, 'pattern', 'str', pattern, True)
|
||||
|
||||
|
||||
def set_junction_coord(name: str, id: str, x: float, y: float) -> ChangeSet:
|
||||
if not is_junction(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
return set_node_coord(name, JUNCTION, id, x, y)
|
||||
|
||||
|
||||
def get_junction_property_names(name: str) -> list[str]:
|
||||
return ['elevation', 'demand', 'pattern', 'coord', 'links']
|
||||
|
||||
|
||||
def get_junction_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _get_junction(name, id)
|
||||
def get_junction(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_junction(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['id'] = id
|
||||
ps['elevation'] = float(row['elevation'])
|
||||
ps['demand'] = float(row['demand']) if row != None and row['demand'] != None else None
|
||||
ps['pattern'] = row['pattern'] if row != None and row['pattern'] != None else None
|
||||
ps['demand'] = float(row['demand']) if row['demand'] != None else None
|
||||
ps['pattern'] = row['pattern']
|
||||
ps['coord'] = get_node_coord(name, id)
|
||||
ps['links'] = get_node_links(name, id)
|
||||
return ps
|
||||
|
||||
|
||||
def set_junction(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_junction(name, id):
|
||||
return ChangeSet()
|
||||
if 'pattern' in properties:
|
||||
if not is_pattern(properties['pattern']):
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_junction(name, id), schema).to_storage()
|
||||
|
||||
new = get_junction(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update junctions set elevation = {new['elevation']}, demand = {new['demand']}, pattern = {new['pattern']} where id = '{id}';"
|
||||
undo = ""
|
||||
if 'coord' in ps:
|
||||
sql += f"\nupdate coordinates set coord = {new['coord']} where node = '{id}';"
|
||||
undo = f"update coordinates set coord = {old['coord']} where node = ''{id}'';"
|
||||
undo += f"\nupdate junctions set elevation = {old['elevation']}, demand = {old['demand']}, pattern = {old['pattern']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_junction', API_UPDATE, JUNCTION, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_junction(name: str, id: str) -> ChangeSet:
|
||||
row = get_junction(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_junction(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from coordinates where node = '{id}';"
|
||||
sql += f"\ndelete from junctions where id = '{id}';"
|
||||
sql += f"\ndelete from _node where id = '{id}';"
|
||||
|
||||
undo = f"insert into _node (id, type) values (''{id}'', ''{JUNCTION}'');"
|
||||
undo += f"\ninsert into junctions (id, elevation, demand, pattern) values (''{id}'', {old['elevation']}, {old['demand']}, {old['pattern']});"
|
||||
undo += f"\ninsert into coordinates (node, coord) values (''{id}'', {old['coord']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_junction', API_DELETE, JUNCTION, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
@@ -4,76 +4,100 @@ from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'head' : define_property(float_type), \
|
||||
'pattern' : define_property(str_type, True), \
|
||||
'coord' : define_property(client_point_type), \
|
||||
'links' : define_property(str_list_type, False, True)}
|
||||
|
||||
|
||||
def get_reservoir_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_reservoir(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from reservoirs where id = '{id}'")
|
||||
|
||||
|
||||
def add_reservoir(name: str, id: str, x: float, y: float, head: float) -> ChangeSet:
|
||||
sql = f"insert into reservoirs (id, head) values ('{id}', {head});"
|
||||
undo_sql = f'delete from reservoirs where id = "{id}";'
|
||||
return add_node(name, RESERVOIR, id, x, y, sql, undo_sql)
|
||||
|
||||
|
||||
def _get_reservoir(name: str, id: str) -> Row | None:
|
||||
return query(name, f"select head, pattern from reservoirs where id = '{id}'")
|
||||
|
||||
|
||||
def delete_reservoir(name: str, id: str) -> ChangeSet:
|
||||
if not is_reservoir(name, id):
|
||||
if is_reservoir(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_reservoir(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
sql = f"insert into _node (id, type) values ('{id}', '{RESERVOIR}');"
|
||||
sql += f"\ninsert into reservoirs (id, head) values ('{id}', {head});"
|
||||
sql += f"\ninsert into coordinates (node, coord) values ('{id}', '({x}, {y})');"
|
||||
|
||||
head = row['head']
|
||||
pattern = decorate(row['pattern'], 'str', True)
|
||||
undo = f"delete from coordinates where node = ''{id}'';"
|
||||
undo += f"\ndelete from reservoirs where id = ''{id}'';"
|
||||
undo += f"\ndelete from _node where id = ''{id}'';"
|
||||
|
||||
sql = f"delete from reservoirs where id = '{id}';"
|
||||
undo_sql = f'insert into reservoirs (id, head, pattern) values ("{id}", {head}, {pattern});'
|
||||
|
||||
return delete_node(name, RESERVOIR, id, sql, undo_sql)
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_reservoir', API_ADD, RESERVOIR, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def _set_reservoir(name: str, id: str, key: str, key_type: str, value: str, optional: bool = False) -> ChangeSet:
|
||||
if not is_reservoir(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_reservoir(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
return update(name, RESERVOIR, 'reservoirs', 'id', id, key, key_type, row[key], value, optional)
|
||||
|
||||
|
||||
def set_reservoir_head(name: str, id: str, head: float) -> ChangeSet:
|
||||
return _set_reservoir(name, id, 'head', 'float', str(head))
|
||||
|
||||
|
||||
def set_reservoir_pattern(name: str, id: str, pattern: str) -> ChangeSet:
|
||||
if not is_pattern(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
return _set_reservoir(name, id, 'pattern', 'str', pattern, True)
|
||||
|
||||
|
||||
def set_reservoir_coord(name: str, id: str, x: float, y: float) -> ChangeSet:
|
||||
if not is_reservoir(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
return set_node_coord(name, RESERVOIR, id, x, y)
|
||||
|
||||
|
||||
def get_reservoir_property_names(name: str) -> list[str]:
|
||||
return ['head', 'pattern', 'coord', 'links']
|
||||
|
||||
|
||||
def get_reservoir_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _get_reservoir(name, id)
|
||||
def get_reservoir(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_reservoir(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['head'] = float(row['head']) if row != None else None
|
||||
ps['pattern'] = row['pattern'] if row != None and row['pattern'] != None else None
|
||||
ps['id'] = id
|
||||
ps['head'] = float(row['head'])
|
||||
ps['pattern'] = row['pattern']
|
||||
ps['coord'] = get_node_coord(name, id)
|
||||
ps['links'] = get_node_links(name, id)
|
||||
return ps
|
||||
|
||||
|
||||
def set_reservoir(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_reservoir(name, id):
|
||||
return ChangeSet()
|
||||
if 'pattern' in properties:
|
||||
if not is_pattern(properties['pattern']):
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_reservoir(name, id), schema).to_storage()
|
||||
|
||||
new = get_reservoir(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update reservoirs set head = {new['head']}, pattern = {new['pattern']} where id = '{id}';"
|
||||
undo = ""
|
||||
if 'coord' in ps:
|
||||
sql += f"\nupdate coordinates set coord = {new['coord']} where node = '{id}';"
|
||||
undo = f"update coordinates set coord = {old['coord']} where node = ''{id}'';"
|
||||
undo += f"\nupdate reservoirs set head = {old['head']}, pattern = {old['pattern']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_reservoir', API_UPDATE, RESERVOIR, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_reservoir(name: str, id: str) -> ChangeSet:
|
||||
row = get_reservoir(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_reservoir(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from coordinates where node = '{id}';"
|
||||
sql += f"\ndelete from reservoirs where id = '{id}';"
|
||||
sql += f"\ndelete from _node where id = '{id}';"
|
||||
|
||||
undo = f"insert into _node (id, type) values (''{id}'', ''{RESERVOIR}'');"
|
||||
undo += f"\ninsert into reservoirs (id, head, pattern) values (''{id}'', {old['head']}, {old['pattern']});"
|
||||
undo += f"\ninsert into coordinates (node, coord) values (''{id}'', {old['coord']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_reservoir', API_DELETE, RESERVOIR, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
197
api/s4_tanks.py
197
api/s4_tanks.py
@@ -4,119 +4,124 @@ from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
OVERFLOW_YES = 'yes'
|
||||
OVERFLOW_NO = 'no'
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'elevation' : define_property(float_type), \
|
||||
'init_level': define_property(float_type), \
|
||||
'min_level' : define_property(float_type), \
|
||||
'max_level' : define_property(float_type), \
|
||||
'diameter' : define_property(float_type), \
|
||||
'min_vol' : define_property(float_type), \
|
||||
'vol_curve' : define_property(str_type, True), \
|
||||
'overflow' : define_property(str_type, True), \
|
||||
'coord' : define_property(client_point_type), \
|
||||
'links' : define_property(str_list_type, False, True)}
|
||||
|
||||
|
||||
def get_tank_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_tank(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from tanks where id = '{id}'")
|
||||
|
||||
|
||||
def add_tank(name: str, id: str, x: float, y: float, elevation: float, init_level: float = 0, min_level: float = 0, max_level: float = 0, diameter: float = 0, min_vol: float = 0) -> ChangeSet:
|
||||
sql = f"insert into tanks (id, elevation, init_level, min_level, max_level, diameter, min_vol) values ('{id}', {elevation}, {init_level}, {min_level}, {max_level}, {diameter}, {min_vol});"
|
||||
undo_sql = f'delete from tanks where id = "{id}";'
|
||||
return add_node(name, TANK, id, x, y, sql, undo_sql)
|
||||
|
||||
|
||||
def _get_tank(name: str, id: str) -> Row | None:
|
||||
return query(name, f"select elevation, init_level, min_level, max_level, diameter, min_vol, vol_curve, overflow from tanks where id = '{id}'")
|
||||
|
||||
|
||||
def delete_tank(name: str, id: str) -> ChangeSet:
|
||||
if not is_tank(name, id):
|
||||
if is_tank(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_tank(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
sql = f"insert into _node (id, type) values ('{id}', '{TANK}');"
|
||||
sql += f"\ninsert into tanks (id, elevation, init_level, min_level, max_level, diameter, min_vol) values ('{id}', {elevation}, {init_level}, {min_level}, {max_level}, {diameter}, {min_vol});"
|
||||
sql += f"\ninsert into coordinates (node, coord) values ('{id}', '({x}, {y})');"
|
||||
|
||||
elevation = row['elevation']
|
||||
init_level = row['init_level']
|
||||
min_level = row['min_level']
|
||||
max_level = row['max_level']
|
||||
diameter = row['diameter']
|
||||
min_vol = row['min_vol']
|
||||
vol_curve = decorate(row['vol_curve'], 'str', True)
|
||||
overflow = decorate(row['overflow'], 'str', True)
|
||||
undo = f"delete from coordinates where node = ''{id}'';"
|
||||
undo += f"\ndelete from tanks where id = ''{id}'';"
|
||||
undo += f"\ndelete from _node where id = ''{id}'';"
|
||||
|
||||
sql = f"delete from tanks where id = '{id}';"
|
||||
undo_sql = f'insert into tanks (id, elevation, init_level, min_level, max_level, diameter, min_vol, vol_curve, overflow) values ("{id}", {elevation}, {init_level}, {min_level}, {max_level}, {diameter}, {min_vol}, {vol_curve}, {overflow});'
|
||||
|
||||
return delete_node(name, TANK, id, sql, undo_sql)
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_tank', API_ADD, TANK, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def _set_tank(name: str, id: str, key: str, key_type: str, value: str, optional: bool = False) -> ChangeSet:
|
||||
if not is_tank(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_tank(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
return update(name, TANK, 'tanks', 'id', id, key, key_type, row[key], value, optional)
|
||||
|
||||
|
||||
def set_tank_elevation(name: str, id: str, elevation: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'elevation', 'float', elevation)
|
||||
|
||||
|
||||
def set_tank_init_level(name: str, id: str, init_level: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'init_level', 'float', init_level)
|
||||
|
||||
|
||||
def set_tank_min_level(name: str, id: str, min_level: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'min_level', 'float', min_level)
|
||||
|
||||
|
||||
def set_tank_max_level(name: str, id: str, max_level: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'max_level', 'float', max_level)
|
||||
|
||||
|
||||
def set_tank_diameter(name: str, id: str, diameter: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'diameter', 'float', diameter)
|
||||
|
||||
|
||||
def set_tank_min_vol(name: str, id: str, min_vol: float) -> ChangeSet:
|
||||
return _set_tank(name, id, 'min_vol', 'float', min_vol)
|
||||
|
||||
|
||||
def set_tank_vol_curve(name: str, id: str, vol_curve: str) -> ChangeSet:
|
||||
if not is_curve(name, vol_curve):
|
||||
return ChangeSet()
|
||||
|
||||
return _set_tank(name, id, 'vol_curve', 'str', vol_curve, True)
|
||||
|
||||
|
||||
def set_tank_overflow(name: str, id: str, overflow: str) -> ChangeSet:
|
||||
if overflow != OVERFLOW_YES and overflow != OVERFLOW_NO:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_tank(name, id, 'overflow', 'str', overflow)
|
||||
|
||||
|
||||
def set_tank_coord(name: str, id: str, x: float, y: float) -> ChangeSet:
|
||||
if not is_tank(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
return set_node_coord(name, TANK, id, x, y)
|
||||
|
||||
|
||||
def get_tank_property_names(name: str) -> list[str]:
|
||||
return ['elevation', 'init_level', 'min_level', 'max_level', 'diameter', 'min_vol', 'vol_curve', 'overflow', 'coord', 'links']
|
||||
|
||||
|
||||
def get_tank_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _get_tank(name, id)
|
||||
def get_tank(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_tank(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['elevation'] = float(row['elevation']) if row != None else None
|
||||
ps['init_level'] = float(row['init_level']) if row != None else None
|
||||
ps['min_level'] = float(row['min_level']) if row != None else None
|
||||
ps['max_level'] = float(row['max_level']) if row != None else None
|
||||
ps['diameter'] = float(row['diameter']) if row != None else None
|
||||
ps['min_vol'] = float(row['min_vol']) if row != None else None
|
||||
ps['vol_curve'] = row['vol_curve'] if row != None and row['vol_curve'] != None else None
|
||||
ps['overflow'] = row['overflow'] if row != None and row['overflow'] != None else None
|
||||
ps['id'] = id
|
||||
ps['elevation'] = float(row['elevation'])
|
||||
ps['init_level'] = float(row['init_level'])
|
||||
ps['min_level'] = float(row['min_level'])
|
||||
ps['max_level'] = float(row['max_level'])
|
||||
ps['diameter'] = float(row['diameter'])
|
||||
ps['min_vol'] = float(row['min_vol'])
|
||||
ps['vol_curve'] = row['vol_curve']
|
||||
ps['overflow'] = row['overflow']
|
||||
ps['coord'] = get_node_coord(name, id)
|
||||
ps['links'] = get_node_links(name, id)
|
||||
return ps
|
||||
|
||||
|
||||
def set_tank(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_tank(name, id):
|
||||
return ChangeSet()
|
||||
if 'vol_curve' in properties:
|
||||
if not is_curve(properties['vol_curve']):
|
||||
return ChangeSet()
|
||||
if 'overflow' in properties:
|
||||
if properties['overflow'] != OVERFLOW_YES and properties['overflow'] != OVERFLOW_NO:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_tank(name, id), schema).to_storage()
|
||||
|
||||
new = get_tank(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update tanks set elevation = {new['elevation']}, \
|
||||
init_level = {new['init_level']}, min_level = {new['min_level']}, max_level = {new['max_level']}, \
|
||||
diameter = {new['diameter']}, min_vol = {new['min_vol']}, vol_curve = {new['vol_curve']}, overflow = {new['overflow']} where id = '{id}';"
|
||||
undo = ""
|
||||
if 'coord' in ps:
|
||||
sql += f"\nupdate coordinates set coord = {new['coord']} where node = '{id}';"
|
||||
undo = f"update coordinates set coord = {old['coord']} where node = ''{id}'';"
|
||||
undo += f"\nupdate tanks set elevation = {old['elevation']}, \
|
||||
init_level = {old['init_level']}, min_level = {old['min_level']}, max_level = {old['max_level']}, \
|
||||
diameter = {old['diameter']}, min_vol = {old['min_vol']}, vol_curve = {old['vol_curve']}, overflow = {old['overflow']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_tank', API_UPDATE, TANK, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_tank(name: str, id: str) -> ChangeSet:
|
||||
row = get_tank(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_tank(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from coordinates where node = '{id}';"
|
||||
sql += f"\ndelete from tanks where id = '{id}';"
|
||||
sql += f"\ndelete from _node where id = '{id}';"
|
||||
|
||||
undo = f"insert into _node (id, type) values (''{id}'', ''{TANK}'');"
|
||||
undo += f"\ninsert into tanks (id, elevation, init_level, min_level, max_level, diameter, min_vol, vol_curve, overflow) \
|
||||
values (''{id}'', {old['elevation']}, {old['init_level']}, {old['min_level']}, {old['max_level']}, {old['diameter']}, {old['min_vol']}, {old['vol_curve']}, {old['overflow']});"
|
||||
undo += f"\ninsert into coordinates (node, coord) values (''{id}'', {old['coord']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_tank', API_DELETE, TANK, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
208
api/s5_pipes.py
208
api/s5_pipes.py
@@ -2,7 +2,9 @@ from typing import Any
|
||||
from psycopg.rows import Row
|
||||
from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
PIPE_STATUS_OPEN = 'open'
|
||||
@@ -10,119 +12,125 @@ PIPE_STATUS_CLOSED = 'closed'
|
||||
PIPE_STATUS_CV = 'cv'
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'node1' : define_property(str_type), \
|
||||
'node2' : define_property(str_type), \
|
||||
'length' : define_property(float_type), \
|
||||
'diameter' : define_property(float_type), \
|
||||
'roughness' : define_property(float_type), \
|
||||
'minor_loss': define_property(float_type), \
|
||||
'status' : define_property(str_type)}
|
||||
|
||||
|
||||
def get_pipe_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_pipe(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from pipes where id = '{id}'")
|
||||
|
||||
|
||||
def _get_pipe_node1(name: str, id: str) -> str | None:
|
||||
row = _query_pipe(name, id)
|
||||
return row['node1'] if row != None else None
|
||||
|
||||
|
||||
def _get_pipe_node2(name: str, id: str) -> str | None:
|
||||
row = _query_pipe(name, id)
|
||||
return row['node2'] if row != None else None
|
||||
|
||||
|
||||
def add_pipe(name: str, id: str, node1: str, node2: str, length: float = 0, diameter: float = 0, roughness: float = 0, minor_loss: float = 0, status: str = PIPE_STATUS_OPEN) -> ChangeSet:
|
||||
if is_pipe(name, id):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node2):
|
||||
return ChangeSet()
|
||||
if node1 == node2:
|
||||
return ChangeSet()
|
||||
|
||||
if status != PIPE_STATUS_OPEN and status != PIPE_STATUS_CLOSED and status != PIPE_STATUS_CV:
|
||||
return ChangeSet()
|
||||
|
||||
sql = f"insert into pipes (id, node1, node2, length, diameter, roughness, minor_loss, status) values ('{id}', '{node1}', '{node2}', {length}, {diameter}, {roughness}, {minor_loss}, '{status}');"
|
||||
undo_sql = f'delete from pipes where id = "{id}";'
|
||||
return add_link(name, PIPE, id, sql, undo_sql)
|
||||
sql = f"insert into _link (id, type) values ('{id}', '{PIPE}');"
|
||||
sql += f"\ninsert into pipes (id, node1, node2, length, diameter, roughness, minor_loss, status) values ('{id}', '{node1}', '{node2}', {length}, {diameter}, {roughness}, {minor_loss}, '{status}');"
|
||||
|
||||
undo = f"delete from pipes where id = ''{id}'';"
|
||||
undo += f"\ndelete from _link where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_pipe', API_ADD, PIPE, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def _get_pipe(name: str, id: str) -> Row | None:
|
||||
return query(name, f"select node1, node2, length, diameter, roughness, minor_loss, status from pipes where id = '{id}'")
|
||||
|
||||
|
||||
def delete_pipe(name: str, id: str) -> ChangeSet:
|
||||
if not is_pipe(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_pipe(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
node1, node2, length, diameter, roughness, minor_loss, status = row['node1'], row['node2'], row['length'], row['diameter'], row['roughness'], row['minor_loss'], row['status']
|
||||
|
||||
sql = f"delete from pipes where id = '{id}';"
|
||||
undo_sql = f'insert into pipes (id, node1, node2, length, diameter, roughness, minor_loss, status) values ("{id}", "{node1}", "{node2}", {length}, {diameter}, {roughness}, {minor_loss}, "{status}");'
|
||||
|
||||
return delete_link(name, PIPE, id, sql, undo_sql)
|
||||
|
||||
|
||||
def _get_pipe_node1(name: str, id: str) -> str | None:
|
||||
row = _get_pipe(name, id)
|
||||
return row['node1'] if row != None else None
|
||||
|
||||
|
||||
def _get_pipe_node2(name: str, id: str) -> str | None:
|
||||
row = _get_pipe(name, id)
|
||||
return row['node2'] if row != None else None
|
||||
|
||||
|
||||
def _set_pipe(name: str, id: str, key: str, key_type: str, value: str, optional: bool = False) -> ChangeSet:
|
||||
if not is_pipe(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_pipe(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
return update(name, PIPE, 'pipes', 'id', id, key, key_type, row[key], value, optional)
|
||||
|
||||
|
||||
def set_pipe_node1(name: str, id: str, node1: str) -> ChangeSet:
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
if _get_pipe_node2(name, id) == node1:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_pipe(name, id, 'node1', 'str', str(node1))
|
||||
|
||||
|
||||
def set_pipe_node2(name: str, id: str, node2: str) -> ChangeSet:
|
||||
if not is_node(name, node2):
|
||||
return ChangeSet()
|
||||
if _get_pipe_node1(name, id) == node2:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_pipe(name, id, 'node2', 'str', str(node2))
|
||||
|
||||
|
||||
def set_pipe_length(name: str, id: str, length: float) -> ChangeSet:
|
||||
return _set_pipe(name, id, 'length', 'float', str(length))
|
||||
|
||||
|
||||
def set_pipe_diameter(name: str, id: str, diameter: float) -> ChangeSet:
|
||||
return _set_pipe(name, id, 'diameter', 'float', str(diameter))
|
||||
|
||||
|
||||
def set_pipe_roughness(name: str, id: str, roughness: float) -> ChangeSet:
|
||||
return _set_pipe(name, id, 'roughness', 'float', str(roughness))
|
||||
|
||||
|
||||
def set_pipe_minor_loss(name: str, id: str, minor_loss: float) -> ChangeSet:
|
||||
return _set_pipe(name, id, 'minor_loss', 'float', str(minor_loss))
|
||||
|
||||
|
||||
def set_pipe_status(name: str, id: str, status: float) -> ChangeSet:
|
||||
if status != PIPE_STATUS_OPEN and status != PIPE_STATUS_CLOSED and status != PIPE_STATUS_CV:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_pipe(name, id, 'status', 'str', str(status))
|
||||
|
||||
|
||||
def get_pipe_property_names(name: str) -> list[str]:
|
||||
return ['node1', 'node2', 'length', 'diameter', 'roughness', 'minor_loss', 'status']
|
||||
|
||||
|
||||
def get_pipe_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _get_pipe(name, id)
|
||||
def get_pipe(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_pipe(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['node1'] = row['node1'] if row != None else None
|
||||
ps['node2'] = row['node2'] if row != None else None
|
||||
ps['length'] = float(row['length']) if row != None else None
|
||||
ps['diameter'] = float(row['diameter']) if row != None else None
|
||||
ps['roughness'] = float(row['roughness']) if row != None else None
|
||||
ps['minor_loss'] = float(row['minor_loss']) if row != None else None
|
||||
ps['status'] = row['status'] if row != None else None
|
||||
return ps
|
||||
ps['id'] = id
|
||||
ps['node1'] = row['node1']
|
||||
ps['node2'] = row['node2']
|
||||
ps['length'] = float(row['length'])
|
||||
ps['diameter'] = float(row['diameter'])
|
||||
ps['roughness'] = float(row['roughness'])
|
||||
ps['minor_loss'] = float(row['minor_loss'])
|
||||
ps['status'] = row['status']
|
||||
return ps
|
||||
|
||||
|
||||
def set_pipe(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_pipe(name, id):
|
||||
return ChangeSet()
|
||||
if 'node1' in properties:
|
||||
if not is_node(name, properties['node1']) or _get_pipe_node2(name, id) == properties['node1']:
|
||||
return ChangeSet()
|
||||
if 'node2' in properties:
|
||||
if not is_node(name, properties['node2']) or _get_pipe_node1(name, id) == properties['node2']:
|
||||
return ChangeSet()
|
||||
if 'node1' in properties and 'node2' in properties:
|
||||
if properties['node1'] == properties['node2']:
|
||||
return ChangeSet()
|
||||
if 'status' in properties:
|
||||
if properties['status'] != PIPE_STATUS_OPEN and properties['status'] != PIPE_STATUS_CLOSED and properties['status'] != PIPE_STATUS_CV:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_pipe(name, id), schema).to_storage()
|
||||
|
||||
new = get_pipe(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update pipes set node1 = {new['node1']}, node2 = {new['node2']}, \
|
||||
length = {new['length']}, diameter = {new['diameter']}, roughness = {new['roughness']}, minor_loss = {new['minor_loss']}, status = {new['status']} where id = '{id}';"
|
||||
undo = f"update pipes set node1 = {old['node1']}, node2 = {old['node2']}, \
|
||||
length = {old['length']}, diameter = {old['diameter']}, roughness = {old['roughness']}, minor_loss = {old['minor_loss']}, status = {old['status']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_pipe', API_UPDATE, PIPE, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_pipe(name: str, id: str) -> ChangeSet:
|
||||
row = get_pipe(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_pipe(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from pipes where id = '{id}';"
|
||||
sql += f"\ndelete from _link where id = '{id}';"
|
||||
|
||||
undo = f"insert into _link (id, type) values (''{id}'', ''{PIPE}'');"
|
||||
undo += f"\ninsert into pipes (id, node1, node2, length, diameter, roughness, minor_loss, status) \
|
||||
values (''{id}'', {old['node1']}, {old['node2']}, {old['length']}, {old['diameter']}, {old['roughness']}, {old['minor_loss']}, {old['status']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_pipe', API_DELETE, PIPE, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
167
api/s6_pumps.py
167
api/s6_pumps.py
@@ -2,10 +2,38 @@ from typing import Any
|
||||
from psycopg.rows import Row
|
||||
from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'node1' : define_property(str_type), \
|
||||
'node2' : define_property(str_type)}
|
||||
|
||||
|
||||
def get_pump_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_pump(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from pumps where id = '{id}'")
|
||||
|
||||
|
||||
def _get_pump_node1(name: str, id: str) -> str | None:
|
||||
row = _query_pump(name, id)
|
||||
return row['node1'] if row != None else None
|
||||
|
||||
|
||||
def _get_pump_node2(name: str, id: str) -> str | None:
|
||||
row = _query_pump(name, id)
|
||||
return row['node2'] if row != None else None
|
||||
|
||||
|
||||
def add_pump(name: str, id: str, node1: str, node2: str) -> ChangeSet:
|
||||
if is_pump(name, id):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node2):
|
||||
@@ -13,86 +41,73 @@ def add_pump(name: str, id: str, node1: str, node2: str) -> ChangeSet:
|
||||
if node1 == node2:
|
||||
return ChangeSet()
|
||||
|
||||
sql = f"insert into pumps (id, node1, node2) values ('{id}', '{node1}', '{node2}');"
|
||||
undo_sql = f'delete from pumps where id = "{id}";'
|
||||
return add_link(name, PUMP, id, sql, undo_sql)
|
||||
sql = f"insert into _link (id, type) values ('{id}', '{PUMP}');"
|
||||
sql += f"\ninsert into pumps (id, node1, node2) values ('{id}', '{node1}', '{node2}');"
|
||||
|
||||
undo = f"delete from pumps where id = ''{id}'';"
|
||||
undo += f"\ndelete from _link where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_pump', API_ADD, PUMP, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def _get_pump(name: str, id: str) -> Row | None:
|
||||
return query(name, f"select node1, node2 from pumps where id = '{id}'")
|
||||
|
||||
|
||||
def delete_pump(name: str, id: str) -> ChangeSet:
|
||||
if not is_pump(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_pump(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
node1, node2 = row['node1'], row['node2']
|
||||
|
||||
sql = f"delete from pumps where id = '{id}';"
|
||||
undo_sql = f'insert into pumps (id, node1, node2) values ("{id}", "{node1}", "{node2}");'
|
||||
|
||||
return delete_link(name, PUMP, id, sql, undo_sql)
|
||||
|
||||
|
||||
def _get_pump_node1(name: str, id: str) -> str | None:
|
||||
row = _get_pump(name, id)
|
||||
return row['node1'] if row != None else None
|
||||
|
||||
|
||||
def _get_pump_node2(name: str, id: str) -> str | None:
|
||||
row = _get_pump(name, id)
|
||||
return row['node2'] if row != None else None
|
||||
|
||||
|
||||
def _set_pump(name: str, id: str, key: str, key_type: str, value: str, optional: bool = False) -> ChangeSet:
|
||||
if not is_pump(name, id):
|
||||
return ChangeSet()
|
||||
|
||||
row = _get_pump(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
return update(name, PUMP, 'pumps', 'id', id, key, key_type, row[key], value, optional)
|
||||
|
||||
|
||||
def set_pump_node1(name: str, id: str, node1: str) -> ChangeSet:
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
if _get_pump_node2(name, id) == node1:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_pump(name, id, 'node1', 'str', str(node1))
|
||||
|
||||
|
||||
def set_pump_node2(name: str, id: str, node2: str) -> ChangeSet:
|
||||
if not is_node(name, node2):
|
||||
return ChangeSet()
|
||||
if _get_pump_node1(name, id) == node2:
|
||||
return ChangeSet()
|
||||
|
||||
return _set_pump(name, id, 'node2', 'str', str(node2))
|
||||
|
||||
|
||||
def set_pump_power(name: str, id: str) -> ChangeSet: pass
|
||||
def set_pump_speed(name: str, id: str) -> ChangeSet: pass
|
||||
def set_pump_head(name: str, id: str) -> ChangeSet: pass
|
||||
def set_pump_pattern(name: str, id: str) -> ChangeSet: pass
|
||||
|
||||
|
||||
def get_pump_property_names(name: str) -> list[str]:
|
||||
return ['node1', 'node2']
|
||||
|
||||
|
||||
def get_pump_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _get_pump(name, id)
|
||||
def get_pump(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_pump(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['node1'] = row['node1'] if row != None else None
|
||||
ps['node2'] = row['node2'] if row != None else None
|
||||
ps['id'] = id
|
||||
ps['node1'] = row['node1']
|
||||
ps['node2'] = row['node2']
|
||||
return ps
|
||||
|
||||
|
||||
def set_pump(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_pump(name, id):
|
||||
return ChangeSet()
|
||||
if 'node1' in properties:
|
||||
if not is_node(name, properties['node1']) or _get_pump_node2(name, id) == properties['node1']:
|
||||
return ChangeSet()
|
||||
if 'node2' in properties:
|
||||
if not is_node(name, properties['node2']) or _get_pump_node1(name, id) == properties['node2']:
|
||||
return ChangeSet()
|
||||
if 'node1' in properties and 'node2' in properties:
|
||||
if properties['node1'] == properties['node2']:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_pump(name, id), schema).to_storage()
|
||||
|
||||
new = get_pump(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update pumps set node1 = {new['node1']}, node2 = {new['node2']} where id = '{id}';"
|
||||
undo = f"update pumps set node1 = {old['node1']}, node2 = {old['node2']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_pump', API_UPDATE, PUMP, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_pump(name: str, id: str) -> ChangeSet:
|
||||
row = get_pump(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_pump(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from pumps where id = '{id}';"
|
||||
sql += f"\ndelete from _link where id = '{id}';"
|
||||
|
||||
undo = f"insert into _link (id, type) values (''{id}'', ''{PUMP}'');"
|
||||
undo += f"\ninsert into pumps (id, node1, node2) values (''{id}'', {old['node1']}, {old['node2']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_pump', API_DELETE, PUMP, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
126
api/s7_valves.py
126
api/s7_valves.py
@@ -2,7 +2,9 @@ from typing import Any
|
||||
from psycopg.rows import Row
|
||||
from .s0_base import *
|
||||
from .change_set import ChangeSet
|
||||
from .s24_coordinates import *
|
||||
from .utility import *
|
||||
from .schema import *
|
||||
|
||||
|
||||
VALVES_TYPE_PRV = 'prv'
|
||||
@@ -13,6 +15,129 @@ VALVES_TYPE_TCV = 'tcv'
|
||||
VALVES_TYPE_GPV = 'gpv'
|
||||
|
||||
|
||||
schema: dict[str, dict[str, Any]] = { \
|
||||
'id' : define_property(str_type, False, True), \
|
||||
'node1' : define_property(str_type), \
|
||||
'node2' : define_property(str_type), \
|
||||
'diameter' : define_property(float_type), \
|
||||
'type' : define_property(str_type), \
|
||||
'setting' : define_property(float_type), \
|
||||
'minor_loss': define_property(float_type)}
|
||||
|
||||
|
||||
def get_valve_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return schema
|
||||
|
||||
|
||||
def _query_valve(name: str, id: str) -> Row | None:
|
||||
return read(name, f"select * from valves where id = '{id}'")
|
||||
|
||||
|
||||
def _get_valve_node1(name: str, id: str) -> str | None:
|
||||
row = _query_valve(name, id)
|
||||
return row['node1'] if row != None else None
|
||||
|
||||
|
||||
def _get_valve_node2(name: str, id: str) -> str | None:
|
||||
row = _query_valve(name, id)
|
||||
return row['node2'] if row != None else None
|
||||
|
||||
|
||||
def add_valve(name: str, id: str, node1: str, node2: str, diameter: float = 0, type: str = VALVES_TYPE_PRV, setting: float = 0, minor_loss: float = 0) -> ChangeSet:
|
||||
if is_valve(name, id):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
if not is_node(name, node2):
|
||||
return ChangeSet()
|
||||
if node1 == node2:
|
||||
return ChangeSet()
|
||||
if type != VALVES_TYPE_PRV and type != VALVES_TYPE_PSV and type != VALVES_TYPE_PBV and type != VALVES_TYPE_FCV and type != VALVES_TYPE_TCV and type != VALVES_TYPE_GPV:
|
||||
return ChangeSet()
|
||||
|
||||
sql = f"insert into _link (id, type) values ('{id}', '{VALVE}');"
|
||||
sql += f"\ninsert into valves (id, node1, node2, diameter, type, setting, minor_loss) values ('{id}', '{node1}', '{node2}', {diameter}, '{type}', {setting}, {minor_loss});"
|
||||
|
||||
undo = f"delete from valves where id = ''{id}'';"
|
||||
undo += f"\ndelete from _link where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'add_valve', API_ADD, VALVE, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def get_valve(name: str, id: str) -> dict[str, Any] | None:
|
||||
row = _query_valve(name, id)
|
||||
if row == None:
|
||||
return None
|
||||
|
||||
ps: dict[str, str] = {}
|
||||
ps['id'] = id
|
||||
ps['node1'] = row['node1']
|
||||
ps['node2'] = row['node2']
|
||||
ps['diameter'] = float(row['diameter'])
|
||||
ps['type'] = row['type']
|
||||
ps['setting'] = float(row['setting'])
|
||||
ps['minor_loss'] = float(row['minor_loss'])
|
||||
return ps
|
||||
|
||||
|
||||
def set_valve(name: str, id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
if not is_valve(name, id):
|
||||
return ChangeSet()
|
||||
if 'node1' in properties:
|
||||
if not is_node(name, properties['node1']) or _get_valve_node2(name, id) == properties['node1']:
|
||||
return ChangeSet()
|
||||
if 'node2' in properties:
|
||||
if not is_node(name, properties['node2']) or _get_valve_node1(name, id) == properties['node2']:
|
||||
return ChangeSet()
|
||||
if 'node1' in properties and 'node2' in properties:
|
||||
if properties['node1'] == properties['node2']:
|
||||
return ChangeSet()
|
||||
if 'type' in properties:
|
||||
t = properties['type']
|
||||
if t != VALVES_TYPE_PRV and t != VALVES_TYPE_PSV and t != VALVES_TYPE_PBV and t != VALVES_TYPE_FCV and t != VALVES_TYPE_TCV and t != VALVES_TYPE_GPV:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_valve(name, id), schema).to_storage()
|
||||
|
||||
new = get_valve(name, id)
|
||||
ps: list[str] = []
|
||||
for key in properties:
|
||||
if key in schema and schema[key]['readonly'] == False:
|
||||
new[key] = properties[key]
|
||||
ps.append(key)
|
||||
new = Serialize(new, schema).to_execution()
|
||||
|
||||
sql = f"update valves set node1 = {new['node1']}, node2 = {new['node2']}, \
|
||||
diameter = {new['diameter']}, type = {new['type']}, setting = {new['setting']}, minor_loss = {new['minor_loss']} where id = '{id}';"
|
||||
undo = f"update valves set node1 = {old['node1']}, node2 = {old['node2']}, \
|
||||
diameter = {old['diameter']}, type = {old['type']}, setting = {old['setting']}, minor_loss = {old['minor_loss']} where id = ''{id}'';"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'set_valve', API_UPDATE, VALVE, id, ps)
|
||||
return get_current_change_set(name)
|
||||
|
||||
|
||||
def delete_valve(name: str, id: str) -> ChangeSet:
|
||||
row = get_valve(name, id)
|
||||
if row == None:
|
||||
return ChangeSet()
|
||||
|
||||
old = Serialize(get_valve(name, id), schema).to_storage()
|
||||
|
||||
sql = f"delete from valves where id = '{id}';"
|
||||
sql += f"\ndelete from _link where id = '{id}';"
|
||||
|
||||
undo = f"insert into _link (id, type) values (''{id}'', ''{VALVE}'');"
|
||||
undo += f"\ninsert into valves (id, node1, node2, diameter, type, setting, minor_loss) \
|
||||
values (''{id}'', {old['node1']}, {old['node2']}, {old['diameter']}, {old['type']}, {old['setting']}, {old['minor_loss']});"
|
||||
|
||||
write(name, sql)
|
||||
add_operation(name, sql.replace("'", "''"), undo, 'delete_valve', API_DELETE, VALVE, id)
|
||||
return get_current_change_set(name)
|
||||
|
||||
'''
|
||||
def add_valve(name: str, id: str, node1: str, node2: str, diameter: float = 0, type: str = VALVES_TYPE_PRV, setting: float = 0, minor_loss: float = 0) -> ChangeSet:
|
||||
if not is_node(name, node1):
|
||||
return ChangeSet()
|
||||
@@ -123,3 +248,4 @@ def get_valve_properties(name: str, id: str) -> dict[str, Any] | None:
|
||||
ps['setting'] = float(row['setting']) if row != None else None
|
||||
ps['minor_loss'] = float(row['minor_loss']) if row != None else None
|
||||
return ps
|
||||
'''
|
||||
74
api/schema.py
Normal file
74
api/schema.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
float_type = type(0.0).__name__
|
||||
str_type = type('').__name__
|
||||
server_point_type = type((0.0,0.0)).__name__
|
||||
client_point_type = type({'x': 0.0, 'y': 0.0}).__name__
|
||||
str_list_type = type(['']).__name__
|
||||
|
||||
|
||||
def define_property(type: str, optional: bool = False, readonly: bool = False) -> dict[str, Any]:
|
||||
return { 'type': type, 'optional': optional, 'readonly': readonly }
|
||||
|
||||
|
||||
class Serialize(object):
|
||||
def __init__(self, row, schema) -> None:
|
||||
self.row = row
|
||||
self.schema = schema
|
||||
|
||||
def to_execution(self, name) -> str:
|
||||
value = self.row[name]
|
||||
type = self.schema[name]['type']
|
||||
|
||||
if value == None:
|
||||
return 'null'
|
||||
|
||||
if type == float_type:
|
||||
return value
|
||||
|
||||
if type == str_type:
|
||||
return f"'{value}'"
|
||||
|
||||
raise Exception(f"Fail to serialize {name} for execution!")
|
||||
|
||||
def to_storage(self, name) -> str:
|
||||
value = self.row[name]
|
||||
type = self.schema[name]['type']
|
||||
|
||||
if value == None:
|
||||
return 'null'
|
||||
|
||||
if type == float_type:
|
||||
return value
|
||||
|
||||
if type == str_type:
|
||||
return f"''{value}''"
|
||||
|
||||
raise Exception(f"Fail to serialize {name} for storage!")
|
||||
|
||||
def to_execution(self):
|
||||
row = self.row.copy()
|
||||
|
||||
for key, value in row.items():
|
||||
if value == None:
|
||||
row[key] = 'null'
|
||||
elif self.schema[key]['type'] == str_type:
|
||||
row[key] = f"'{row[key]}'"
|
||||
elif self.schema[key]['type'] == client_point_type:
|
||||
row[key] = f"'({value['x']},{value['y']})'"
|
||||
|
||||
return row
|
||||
|
||||
def to_storage(self):
|
||||
row = self.row.copy()
|
||||
|
||||
for key, value in row.items():
|
||||
if value == None:
|
||||
row[key] = 'null'
|
||||
elif self.schema[key] == str_type:
|
||||
row[key] = f"''{row[key]}''"
|
||||
elif self.schema[key]['type'] == client_point_type:
|
||||
row[key] = f"''({value['x']},{value['y']})''"
|
||||
|
||||
return row
|
||||
@@ -4,12 +4,17 @@ from .operation import *
|
||||
from .change_set import ChangeSet
|
||||
|
||||
|
||||
def query(name: str, sql: str) -> Row | None:
|
||||
def read(name: str, sql: str) -> Row | None:
|
||||
with conn[name].cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(sql)
|
||||
return cur.fetchone()
|
||||
|
||||
|
||||
def write(name: str, sql: str) -> None:
|
||||
with conn[name].cursor() as cur:
|
||||
cur.execute(sql)
|
||||
|
||||
|
||||
def decorate(value: str | None, type: str, optional: bool) -> str:
|
||||
if optional:
|
||||
value = 'NULL' if value == None else value
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CREATE TYPE API_OPERATION AS ENUM ('add', 'delete', 'update');
|
||||
CREATE TYPE API_OPERATION AS ENUM ('init', 'add', 'delete', 'update');
|
||||
|
||||
CREATE TABLE OPERATION
|
||||
(
|
||||
@@ -7,14 +7,14 @@ CREATE TABLE OPERATION
|
||||
, Undo TEXT NOT NULL
|
||||
, Parent INTEGER REFERENCES OPERATION(ID)
|
||||
, Redo_Child INTEGER REFERENCES OPERATION(ID)
|
||||
, Api TEXT NOT NULL
|
||||
, Api_Operation API_OPERATION NOT NULL
|
||||
, Api_Operation_Type TEXT NOT NULL
|
||||
, Api_Operation_Id TEXT NOT NULL -- VARCHAR(32)
|
||||
, Api_Operation_Property TEXT NOT NULL
|
||||
, Api_Id TEXT NOT NULL
|
||||
, Api_Op API_OPERATION NOT NULL
|
||||
, Api_Object_Type TEXT NOT NULL
|
||||
, Api_Object_Id TEXT NOT NULL
|
||||
, Api_Object_Properties TEXT[]
|
||||
);
|
||||
|
||||
INSERT INTO OPERATION (ID, Redo, Undo) VALUES (0, '', '');
|
||||
INSERT INTO OPERATION (ID, Redo, Undo, Api_Id, Api_Op, Api_Object_Type, Api_Object_Id) VALUES (0, '', '', '', 'init', '', '');
|
||||
|
||||
CREATE TABLE CURRENT_OPERATION
|
||||
(
|
||||
|
||||
@@ -5,3 +5,5 @@ DROP TABLE IF EXISTS SNAPSHOT_OPERATION;
|
||||
DROP TABLE IF EXISTS CURRENT_OPERATION;
|
||||
|
||||
DROP TABLE IF EXISTS OPERATION;
|
||||
|
||||
DROP TYPE IF EXISTS API_OPERATION;
|
||||
|
||||
@@ -17,7 +17,7 @@ class TestApi:
|
||||
delete_project(p)
|
||||
|
||||
def test_project(self):
|
||||
p = "test_title"
|
||||
p = "test_project"
|
||||
|
||||
assert not have_project(p)
|
||||
assert not is_project_open(p)
|
||||
@@ -66,7 +66,10 @@ class TestApi:
|
||||
|
||||
assert get_title(p) == ""
|
||||
|
||||
set_title(p, "title")
|
||||
change = set_title(p, "title").operations[0]
|
||||
assert change['operation'] == 'update'
|
||||
assert change['type'] == 'title'
|
||||
assert change['id'] == ''
|
||||
assert get_title(p) == "title"
|
||||
|
||||
set_title(p, "test")
|
||||
@@ -84,22 +87,22 @@ class TestApi:
|
||||
assert change_set.operations[0]['operation'] == 'add'
|
||||
assert change_set.operations[0]['type'] == JUNCTION
|
||||
assert change_set.operations[0]['id'] == "j0"
|
||||
coord = get_junction_properties(p, 'j0')['coord']
|
||||
coord = get_junction(p, 'j0')['coord']
|
||||
assert coord['x'] == 0.0
|
||||
assert coord['y'] == 10.0
|
||||
z = get_junction_properties(p, 'j0')['elevation']
|
||||
z = get_junction(p, 'j0')['elevation']
|
||||
assert z == 20.0
|
||||
|
||||
assert get_junction_properties(p, 'j') == None
|
||||
assert get_junction_properties(p, 'j0')['demand'] == None
|
||||
assert get_junction_properties(p, 'j0')['demand'] == None
|
||||
change_set = set_junction_demand(p, 'j0', 100.0)
|
||||
assert get_junction(p, 'j') == None
|
||||
assert get_junction(p, 'j0')['demand'] == None
|
||||
assert get_junction(p, 'j0')['demand'] == None
|
||||
change_set = set_junction(p, 'j0', {'demand': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == JUNCTION
|
||||
assert change_set.operations[0]['id'] == 'j0'
|
||||
assert change_set.operations[0]['property'] == 'demand'
|
||||
assert get_junction_properties(p, 'j0')['demand'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['demand']
|
||||
assert get_junction(p, 'j0')['demand'] == 100.0
|
||||
|
||||
# TODO: pattern
|
||||
|
||||
@@ -145,9 +148,9 @@ class TestApi:
|
||||
add_pipe(p, 'p1', 'j1', 'j2')
|
||||
add_pump(p, 'p2', 'j1', 'j2')
|
||||
add_valve(p, 'v1', 'j2', 'j3')
|
||||
assert get_junction_properties(p, 'j1')['links'] == ['p1', 'p2']
|
||||
assert get_junction_properties(p, 'j2')['links'] == ['p1', 'p2', 'v1']
|
||||
assert get_junction_properties(p, 'j3')['links'] == ['v1']
|
||||
assert get_junction(p, 'j1')['links'] == ['p1', 'p2']
|
||||
assert get_junction(p, 'j2')['links'] == ['p1', 'p2', 'v1']
|
||||
assert get_junction(p, 'j3')['links'] == ['v1']
|
||||
|
||||
self.leave(p)
|
||||
|
||||
@@ -165,21 +168,21 @@ class TestApi:
|
||||
change_set = add_reservoir(p, "r0", 0.0, 10.0, 20.0)
|
||||
assert len(change_set.operations) == 0
|
||||
|
||||
assert get_reservoir_properties(p, 'r0')['head'] == 20.0
|
||||
assert get_reservoir_properties(p, 'r0')['head'] == 20.0
|
||||
change_set = set_reservoir_head(p, 'r0', 100.0)
|
||||
assert get_reservoir(p, 'r0')['head'] == 20.0
|
||||
assert get_reservoir(p, 'r0')['head'] == 20.0
|
||||
change_set = set_reservoir(p, 'r0', {'head': 100.0})
|
||||
assert change_set.operations[0]['type'] == RESERVOIR
|
||||
assert change_set.operations[0]['id'] == 'r0'
|
||||
assert change_set.operations[0]['property'] == 'head'
|
||||
assert get_reservoir_properties(p, 'r0')['head'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['head']
|
||||
assert get_reservoir(p, 'r0')['head'] == 100.0
|
||||
|
||||
assert get_reservoir_properties(p, 'r0')['coord'] == { 'x': 0.0, 'y': 10.0 }
|
||||
assert get_reservoir_properties(p, 'r0')['coord'] == { 'x': 0.0, 'y': 10.0 }
|
||||
change_set = set_reservoir_coord(p, 'r0', 100.0, 200.0)
|
||||
assert get_reservoir(p, 'r0')['coord'] == { 'x': 0.0, 'y': 10.0 }
|
||||
assert get_reservoir(p, 'r0')['coord'] == { 'x': 0.0, 'y': 10.0 }
|
||||
change_set = set_reservoir(p, 'r0', {'coord': {'x': 100.0, 'y': 200.0}})
|
||||
assert change_set.operations[0]['type'] == RESERVOIR
|
||||
assert change_set.operations[0]['id'] == 'r0'
|
||||
assert change_set.operations[0]['property'] == 'coord'
|
||||
assert get_reservoir_properties(p, 'r0')['coord'] == { 'x': 100.0, 'y': 200.0 }
|
||||
assert change_set.operations[0]['properties'] == ['coord']
|
||||
assert get_reservoir(p, 'r0')['coord'] == { 'x': 100.0, 'y': 200.0 }
|
||||
|
||||
# TODO: pattern
|
||||
|
||||
@@ -220,73 +223,73 @@ class TestApi:
|
||||
assert tanks[0] == 't0'
|
||||
assert tanks[1] == 't1'
|
||||
|
||||
assert get_tank_properties(p, 't0')['elevation'] == 10.0
|
||||
change_set = set_tank_elevation(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['elevation'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'elevation': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'elevation'
|
||||
assert get_tank_properties(p, 't0')['elevation'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['elevation']
|
||||
assert get_tank(p, 't0')['elevation'] == 100.0
|
||||
|
||||
assert get_tank_properties(p, 't0')['init_level'] == 10.0
|
||||
change_set = set_tank_init_level(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['init_level'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'init_level': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'init_level'
|
||||
assert get_tank_properties(p, 't0')['init_level'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['init_level']
|
||||
assert get_tank(p, 't0')['init_level'] == 100.0
|
||||
|
||||
assert get_tank_properties(p, 't0')['min_level'] == 10.0
|
||||
change_set = set_tank_min_level(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['min_level'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'min_level': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'min_level'
|
||||
assert get_tank_properties(p, 't0')['min_level'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['min_level']
|
||||
assert get_tank(p, 't0')['min_level'] == 100.0
|
||||
|
||||
assert get_tank_properties(p, 't0')['max_level'] == 10.0
|
||||
change_set = set_tank_max_level(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['max_level'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'max_level': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'max_level'
|
||||
assert get_tank_properties(p, 't0')['max_level'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['max_level']
|
||||
assert get_tank(p, 't0')['max_level'] == 100.0
|
||||
|
||||
assert get_tank_properties(p, 't0')['diameter'] == 10.0
|
||||
change_set = set_tank_diameter(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['diameter'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'diameter': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'diameter'
|
||||
assert get_tank_properties(p, 't0')['diameter'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['diameter']
|
||||
assert get_tank(p, 't0')['diameter'] == 100.0
|
||||
|
||||
assert get_tank_properties(p, 't0')['min_vol'] == 10.0
|
||||
change_set = set_tank_min_vol(p, 't0', 100.0)
|
||||
assert get_tank(p, 't0')['min_vol'] == 10.0
|
||||
change_set = set_tank(p, 't0', {'min_vol': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'min_vol'
|
||||
assert get_tank_properties(p, 't0')['min_vol'] == 100.0
|
||||
assert change_set.operations[0]['properties'] == ['min_vol']
|
||||
assert get_tank(p, 't0')['min_vol'] == 100.0
|
||||
|
||||
# TODO: vol_curve
|
||||
|
||||
assert get_tank_properties(p, 't') == None
|
||||
assert get_tank_properties(p, 't0')['overflow'] == None
|
||||
change_set = set_tank_overflow(p, 't0', "XXX")
|
||||
assert get_tank(p, 't') == None
|
||||
assert get_tank(p, 't0')['overflow'] == None
|
||||
change_set = set_tank(p, 't0', {'overflow': "XXX"})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_tank_overflow(p, 't0', OVERFLOW_YES)
|
||||
change_set = set_tank(p, 't0', {'overflow': OVERFLOW_YES})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == TANK
|
||||
assert change_set.operations[0]['id'] == "t0"
|
||||
assert change_set.operations[0]['property'] == 'overflow'
|
||||
assert get_tank_properties(p, 't0')['overflow'] == OVERFLOW_YES
|
||||
assert change_set.operations[0]['properties'] == ['overflow']
|
||||
assert get_tank(p, 't0')['overflow'] == OVERFLOW_YES
|
||||
|
||||
change_set = delete_tank(p, "t0")
|
||||
assert len(change_set.operations) == 1
|
||||
@@ -348,77 +351,77 @@ class TestApi:
|
||||
pipes = get_links(p)
|
||||
assert len(pipes) == 1
|
||||
|
||||
assert get_pipe_properties(p, 'p1')['node1'] == 'j1'
|
||||
assert get_pipe_properties(p, 'p1')['node2'] == 'j2'
|
||||
assert get_pipe_properties(p, 'p1')['length'] == 10.0
|
||||
assert get_pipe_properties(p, 'p1')['diameter'] == 10.0
|
||||
assert get_pipe_properties(p, 'p1')['roughness'] == 10.0
|
||||
assert get_pipe_properties(p, 'p1')['minor_loss'] == 10.0
|
||||
assert get_pipe_properties(p, 'p1')['status'] == PIPE_STATUS_CLOSED
|
||||
assert get_pipe(p, 'p1')['node1'] == 'j1'
|
||||
assert get_pipe(p, 'p1')['node2'] == 'j2'
|
||||
assert get_pipe(p, 'p1')['length'] == 10.0
|
||||
assert get_pipe(p, 'p1')['diameter'] == 10.0
|
||||
assert get_pipe(p, 'p1')['roughness'] == 10.0
|
||||
assert get_pipe(p, 'p1')['minor_loss'] == 10.0
|
||||
assert get_pipe(p, 'p1')['status'] == PIPE_STATUS_CLOSED
|
||||
|
||||
change_set = set_pipe_node1(p, 'p1', 'j2')
|
||||
change_set = set_pipe(p, 'p1', {'node1': 'j2'})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_pipe_node2(p, 'p1', 'j1')
|
||||
change_set = set_pipe(p, 'p1', {'node2': 'j1'})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_pipe_status(p, 'p1', "XXX")
|
||||
change_set = set_pipe(p, 'p1', {'status': 'XXX'})
|
||||
assert len(change_set.operations) == 0
|
||||
|
||||
change_set = set_pipe_node1(p, 'p1', 'j3')
|
||||
change_set = set_pipe(p, 'p1', {'node1': 'j3'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'node1'
|
||||
assert change_set.operations[0]['properties'] == ['node1']
|
||||
|
||||
change_set = set_pipe_node2(p, 'p1', 'j4')
|
||||
change_set = set_pipe(p, 'p1', {'node2': 'j4'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'node2'
|
||||
assert change_set.operations[0]['properties'] == ['node2']
|
||||
|
||||
change_set = set_pipe_length(p, 'p1', 100.0)
|
||||
change_set = set_pipe(p, 'p1', {'length': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'length'
|
||||
assert change_set.operations[0]['properties'] == ['length']
|
||||
|
||||
change_set = set_pipe_diameter(p, 'p1', 100.0)
|
||||
change_set = set_pipe(p, 'p1', {'diameter': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'diameter'
|
||||
assert change_set.operations[0]['properties'] == ['diameter']
|
||||
|
||||
change_set = set_pipe_roughness(p, 'p1', 100.0)
|
||||
change_set = set_pipe(p, 'p1', {'roughness': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'roughness'
|
||||
assert change_set.operations[0]['properties'] == ['roughness']
|
||||
|
||||
change_set = set_pipe_minor_loss(p, 'p1', 100.0)
|
||||
change_set = set_pipe(p, 'p1', {'minor_loss': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'minor_loss'
|
||||
assert change_set.operations[0]['properties'] == ['minor_loss']
|
||||
|
||||
change_set = set_pipe_status(p, 'p1', PIPE_STATUS_OPEN)
|
||||
change_set = set_pipe(p, 'p1', {'status': PIPE_STATUS_OPEN})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PIPE
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'status'
|
||||
assert change_set.operations[0]['properties'] == ['status']
|
||||
|
||||
assert get_pipe_properties(p, 'p1')['node1'] == 'j3'
|
||||
assert get_pipe_properties(p, 'p1')['node2'] == 'j4'
|
||||
assert get_pipe_properties(p, 'p1')['length'] == 100.0
|
||||
assert get_pipe_properties(p, 'p1')['diameter'] == 100.0
|
||||
assert get_pipe_properties(p, 'p1')['roughness'] == 100.0
|
||||
assert get_pipe_properties(p, 'p1')['minor_loss'] == 100.0
|
||||
assert get_pipe_properties(p, 'p1')['status'] == PIPE_STATUS_OPEN
|
||||
assert get_pipe(p, 'p1')['node1'] == 'j3'
|
||||
assert get_pipe(p, 'p1')['node2'] == 'j4'
|
||||
assert get_pipe(p, 'p1')['length'] == 100.0
|
||||
assert get_pipe(p, 'p1')['diameter'] == 100.0
|
||||
assert get_pipe(p, 'p1')['roughness'] == 100.0
|
||||
assert get_pipe(p, 'p1')['minor_loss'] == 100.0
|
||||
assert get_pipe(p, 'p1')['status'] == PIPE_STATUS_OPEN
|
||||
|
||||
change_set = add_pipe(p, 'p2', 'j1', 'j2', 10.0, 10.0, 10.0, 10.0, PIPE_STATUS_CLOSED)
|
||||
assert len(change_set.operations) == 1
|
||||
@@ -485,30 +488,30 @@ class TestApi:
|
||||
pumps = get_links(p)
|
||||
assert len(pumps) == 1
|
||||
|
||||
assert get_pump_properties(p, 'p1')['node1'] == 'j1'
|
||||
assert get_pump_properties(p, 'p1')['node2'] == 'j2'
|
||||
assert get_pump(p, 'p1')['node1'] == 'j1'
|
||||
assert get_pump(p, 'p1')['node2'] == 'j2'
|
||||
|
||||
change_set = set_pump_node1(p, 'p1', 'j2')
|
||||
change_set = set_pump(p, 'p1', {'node1': 'j2'})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_pump_node2(p, 'p1', 'j1')
|
||||
change_set = set_pump(p, 'p1', {'node2': 'j1'})
|
||||
assert len(change_set.operations) == 0
|
||||
|
||||
change_set = set_pump_node1(p, 'p1', 'j3')
|
||||
change_set = set_pump(p, 'p1', {'node1': 'j3'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PUMP
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'node1'
|
||||
assert change_set.operations[0]['properties'] == ['node1']
|
||||
|
||||
change_set = set_pump_node2(p, 'p1', 'j4')
|
||||
change_set = set_pump(p, 'p1', {'node2': 'j4'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == PUMP
|
||||
assert change_set.operations[0]['id'] == 'p1'
|
||||
assert change_set.operations[0]['property'] == 'node2'
|
||||
assert change_set.operations[0]['properties'] == ['node2']
|
||||
|
||||
assert get_pump_properties(p, 'p1')['node1'] == 'j3'
|
||||
assert get_pump_properties(p, 'p1')['node2'] == 'j4'
|
||||
assert get_pump(p, 'p1')['node1'] == 'j3'
|
||||
assert get_pump(p, 'p1')['node2'] == 'j4'
|
||||
|
||||
change_set = add_pump(p, 'p2', 'j1', 'j2')
|
||||
assert len(change_set.operations) == 1
|
||||
@@ -578,68 +581,68 @@ class TestApi:
|
||||
valves = get_links(p)
|
||||
assert len(valves) == 1
|
||||
|
||||
assert get_valve_properties(p, 'v1')['node1'] == 'j1'
|
||||
assert get_valve_properties(p, 'v1')['node2'] == 'j2'
|
||||
assert get_valve_properties(p, 'v1')['diameter'] == 10.0
|
||||
assert get_valve_properties(p, 'v1')['type'] == VALVES_TYPE_FCV
|
||||
assert get_valve_properties(p, 'v1')['setting'] == 10.0
|
||||
assert get_valve_properties(p, 'v1')['minor_loss'] == 10.0
|
||||
assert get_valve(p, 'v1')['node1'] == 'j1'
|
||||
assert get_valve(p, 'v1')['node2'] == 'j2'
|
||||
assert get_valve(p, 'v1')['diameter'] == 10.0
|
||||
assert get_valve(p, 'v1')['type'] == VALVES_TYPE_FCV
|
||||
assert get_valve(p, 'v1')['setting'] == 10.0
|
||||
assert get_valve(p, 'v1')['minor_loss'] == 10.0
|
||||
|
||||
change_set = set_valve_node1(p, 'v1', 'j2')
|
||||
change_set = set_valve(p, 'v1', {'node1': 'j2'})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_valve_node2(p, 'v1', 'j1')
|
||||
change_set = set_valve(p, 'v1', {'node2': 'j1'})
|
||||
assert len(change_set.operations) == 0
|
||||
change_set = set_valve_type(p, 'v1', "XXX")
|
||||
change_set = set_valve(p, 'v1', {'type': "XXX"})
|
||||
assert len(change_set.operations) == 0
|
||||
|
||||
change_set = set_valve_node1(p, 'v1', 'j3')
|
||||
change_set = set_valve(p, 'v1', {'node1': 'j3'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'node1'
|
||||
assert change_set.operations[0]['properties'] == ['node1']
|
||||
|
||||
change_set = set_valve_node2(p, 'v1', 'j4')
|
||||
change_set = set_valve(p, 'v1', {'node2': 'j4'})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'node2'
|
||||
assert change_set.operations[0]['properties'] == ['node2']
|
||||
|
||||
change_set = set_valve_diameter(p, 'v1', 100.0)
|
||||
change_set = set_valve(p, 'v1', {'diameter': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'diameter'
|
||||
assert change_set.operations[0]['properties'] == ['diameter']
|
||||
|
||||
change_set = set_valve_type(p, 'v1', VALVES_TYPE_GPV)
|
||||
change_set = set_valve(p, 'v1', {'type': VALVES_TYPE_GPV})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'type'
|
||||
assert change_set.operations[0]['properties'] == ['type']
|
||||
|
||||
change_set = set_valve_setting(p, 'v1', 100.0)
|
||||
change_set = set_valve(p, 'v1', {'setting': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'setting'
|
||||
assert change_set.operations[0]['properties'] == ['setting']
|
||||
|
||||
change_set = set_valve_minor_loss(p, 'v1', 100.0)
|
||||
change_set = set_valve(p, 'v1', {'minor_loss': 100.0})
|
||||
assert len(change_set.operations) == 1
|
||||
assert change_set.operations[0]['operation'] == 'update'
|
||||
assert change_set.operations[0]['type'] == VALVE
|
||||
assert change_set.operations[0]['id'] == 'v1'
|
||||
assert change_set.operations[0]['property'] == 'minor_loss'
|
||||
assert change_set.operations[0]['properties'] == ['minor_loss']
|
||||
|
||||
assert get_valve_properties(p, 'v1')['node1'] == 'j3'
|
||||
assert get_valve_properties(p, 'v1')['node2'] == 'j4'
|
||||
assert get_valve_properties(p, 'v1')['diameter'] == 100.0
|
||||
assert get_valve_properties(p, 'v1')['type'] == VALVES_TYPE_GPV
|
||||
assert get_valve_properties(p, 'v1')['setting'] == 100.0
|
||||
assert get_valve_properties(p, 'v1')['minor_loss'] == 100.0
|
||||
assert get_valve(p, 'v1')['node1'] == 'j3'
|
||||
assert get_valve(p, 'v1')['node2'] == 'j4'
|
||||
assert get_valve(p, 'v1')['diameter'] == 100.0
|
||||
assert get_valve(p, 'v1')['type'] == VALVES_TYPE_GPV
|
||||
assert get_valve(p, 'v1')['setting'] == 100.0
|
||||
assert get_valve(p, 'v1')['minor_loss'] == 100.0
|
||||
|
||||
change_set = add_valve(p, 'v2', 'j1', 'j2', 10.0, VALVES_TYPE_FCV, 10.0, 10.0)
|
||||
assert len(change_set.operations) == 1
|
||||
@@ -672,5 +675,6 @@ class TestApi:
|
||||
|
||||
self.leave(p)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main()
|
||||
|
||||
198
tjnetwork.py
198
tjnetwork.py
@@ -71,32 +71,23 @@ def copy_project(source: str, new: str) -> None:
|
||||
def get_current_operation(name: str) -> int:
|
||||
return api.get_current_operation(name)
|
||||
|
||||
def undo(name: str) -> None:
|
||||
return api.undo(name)
|
||||
def execute_undo(name: str, discard: bool = False) -> ChangeSet:
|
||||
return api.execute_undo(name, discard)
|
||||
|
||||
def redo(name: str) -> None:
|
||||
return api.redo(name)
|
||||
def execute_redo(name: str) -> ChangeSet:
|
||||
return api.execute_redo(name)
|
||||
|
||||
def have_snapshot(name: str, tag: str) -> bool:
|
||||
return api.have_snapshot(name, tag)
|
||||
|
||||
def take_snapshot(name: str, tag: str) -> None:
|
||||
def take_snapshot(name: str, tag: str) -> int:
|
||||
return api.take_snapshot(name, tag)
|
||||
|
||||
def pick_snapshot(name: str, tag: str) -> None:
|
||||
return api.pick_snapshot(name, tag)
|
||||
def pick_snapshot(name: str, tag: str, discard: bool = False) -> ChangeSet:
|
||||
return api.pick_snapshot(name, tag, discard)
|
||||
|
||||
def have_transaction(name: str) -> bool:
|
||||
return api.have_transaction(name)
|
||||
|
||||
def start_transaction(name: str, strict: bool = False) -> None:
|
||||
return api.start_transaction(name, strict)
|
||||
|
||||
def commit_transaction(name: str) -> None:
|
||||
return api.commit_transaction(name)
|
||||
|
||||
def abort_transaction(name: str) -> None:
|
||||
return api.abort_transaction(name)
|
||||
def sync_with_server(name: str, operation: int) -> ChangeSet:
|
||||
return api.sync_with_server(name, operation)
|
||||
|
||||
|
||||
############################################################
|
||||
@@ -161,192 +152,117 @@ def get_title(name: str) -> str:
|
||||
# junction 2.[JUNCTIONS]
|
||||
############################################################
|
||||
|
||||
def get_junction_property_names(name: str) -> list[str]:
|
||||
return api.get_junction_property_names(name)
|
||||
def get_junction_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_junction_schema(name)
|
||||
|
||||
def add_junction(name: str, junction_id: str, x: float, y: float, elevation: float) -> ChangeSet:
|
||||
return api.add_junction(name, junction_id, x, y, elevation)
|
||||
|
||||
def get_junction(name: str, junction_id: str) -> dict[str, Any] | None:
|
||||
return api.get_junction(name, junction_id)
|
||||
|
||||
def set_junction(name: str, junction_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_junction(name, junction_id, properties)
|
||||
|
||||
def delete_junction(name: str, junction_id: str) -> ChangeSet:
|
||||
return api.delete_junction(name, junction_id)
|
||||
|
||||
def set_junction_elevation(name: str, junction_id: str, elevation: float) -> ChangeSet:
|
||||
return api.set_junction_elevation(name, junction_id, elevation)
|
||||
|
||||
def set_junction_demand(name: str, junction_id: str, demand: float) -> ChangeSet:
|
||||
return api.set_junction_demand(name, junction_id, demand)
|
||||
|
||||
def set_junction_pattern(name: str, junction_id: str, pattern: str) -> ChangeSet:
|
||||
return api.set_junction_pattern(name, junction_id, pattern)
|
||||
|
||||
def set_junction_coord(name: str, junction_id: str, x: float, y: float) -> ChangeSet:
|
||||
return api.set_junction_coord(name, junction_id, x, y)
|
||||
|
||||
def get_junction_properties(name: str, junction_id: str) -> dict[str, Any] | None:
|
||||
return api.get_junction_properties(name, junction_id)
|
||||
|
||||
|
||||
############################################################
|
||||
# reservoir 3.[RESERVOIRS]
|
||||
############################################################
|
||||
|
||||
def get_reservoir_property_names(name: str) -> list[str]:
|
||||
return api.get_reservoir_property_names(name)
|
||||
def get_reservoir_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_reservoir_schema(name)
|
||||
|
||||
def add_reservoir(name: str, reservoir_id: str, x: float, y: float, head: float) -> ChangeSet:
|
||||
return api.add_reservoir(name, reservoir_id, x, y, head)
|
||||
|
||||
def get_reservoir(name: str, reservoir_id: str) -> dict[str, Any] | None:
|
||||
return api.get_reservoir(name, reservoir_id)
|
||||
|
||||
def set_reservoir(name: str, reservoir_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_reservoir(name, reservoir_id, properties)
|
||||
|
||||
def delete_reservoir(name: str, reservoir_id: str) -> ChangeSet:
|
||||
return api.delete_reservoir(name, reservoir_id)
|
||||
|
||||
def set_reservoir_head(name: str, reservoir_id: str, head: float) -> ChangeSet:
|
||||
return api.set_reservoir_head(name, reservoir_id, head)
|
||||
|
||||
def set_reservoir_pattern(name: str, reservoir_id: str, pattern: str) -> ChangeSet:
|
||||
return api.set_reservoir_pattern(name, reservoir_id, pattern)
|
||||
|
||||
def set_reservoir_coord(name: str, reservoir_id: str, x: float, y: float) -> ChangeSet:
|
||||
return api.set_reservoir_coord(name, reservoir_id, x, y)
|
||||
|
||||
def get_reservoir_properties(name: str, reservoir_id: str) -> dict[str, Any] | None:
|
||||
return api.get_reservoir_properties(name, reservoir_id)
|
||||
|
||||
|
||||
############################################################
|
||||
# tank 4.[TANKS]
|
||||
############################################################
|
||||
|
||||
def get_tank_property_names(name: str) -> list[str]:
|
||||
return api.get_tank_property_names(name)
|
||||
def get_tank_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_tank_schema(name)
|
||||
|
||||
def add_tank(name: str, tank_id: str, x: float, y: float, elevation: float, init_level: float = 0, min_level: float = 0, max_level: float = 0, diameter: float = 0, min_vol: float = 0) -> ChangeSet:
|
||||
return api.add_tank(name, tank_id, x, y, elevation, init_level, min_level, max_level, diameter, min_vol)
|
||||
|
||||
def get_tank(name: str, tank_id: str) -> dict[str, Any] | None:
|
||||
return api.get_tank(name, tank_id)
|
||||
|
||||
def set_tank(name: str, tank_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_tank(name, tank_id, properties)
|
||||
|
||||
def delete_tank(name: str, tank_id: str) -> ChangeSet:
|
||||
return api.delete_tank(name, tank_id)
|
||||
|
||||
def set_tank_elevation(name: str, tank_id: str, elevation: float) -> ChangeSet:
|
||||
return api.set_tank_elevation(name, tank_id, elevation)
|
||||
|
||||
def set_tank_init_level(name: str, tank_id: str, init_level: float) -> ChangeSet:
|
||||
return api.set_tank_init_level(name, tank_id, init_level)
|
||||
|
||||
def set_tank_min_level(name: str, tank_id: str, min_level: float) -> ChangeSet:
|
||||
return api.set_tank_min_level(name, tank_id, min_level)
|
||||
|
||||
def set_tank_max_level(name: str, tank_id: str, max_level: float) -> ChangeSet:
|
||||
return api.set_tank_max_level(name, tank_id, max_level)
|
||||
|
||||
def set_tank_diameter(name: str, tank_id: str, diameter: float) -> ChangeSet:
|
||||
return api.set_tank_diameter(name, tank_id, diameter)
|
||||
|
||||
def set_tank_min_vol(name: str, tank_id: str, min_vol: float) -> ChangeSet:
|
||||
return api.set_tank_min_vol(name, tank_id, min_vol)
|
||||
|
||||
def set_tank_vol_curve(name: str, tank_id: str, vol_curve: str) -> ChangeSet:
|
||||
return api.set_tank_vol_curve(name, tank_id, vol_curve)
|
||||
|
||||
def set_tank_overflow(name: str, tank_id: str, overflow: str) -> ChangeSet:
|
||||
return api.set_tank_overflow(name, tank_id, overflow)
|
||||
|
||||
def set_tank_coord(name: str, tank_id: str, x: float, y: float) -> ChangeSet:
|
||||
return api.set_tank_coord(name, tank_id, x, y)
|
||||
|
||||
def get_tank_properties(name: str, tank_id: str) -> dict[str, Any] | None:
|
||||
return api.get_tank_properties(name, tank_id)
|
||||
|
||||
|
||||
############################################################
|
||||
# pipe 4.[PIPES]
|
||||
############################################################
|
||||
|
||||
def get_pipe_property_names(name: str) -> list[str]:
|
||||
return api.get_pipe_property_names(name)
|
||||
def get_pipe_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_pipe_schema(name)
|
||||
|
||||
def add_pipe(name: str, pipe_id: str, node1: str, node2: str, length: float = 0, diameter: float = 0, roughness: float = 0, minor_loss: float = 0, status: str = PIPE_STATUS_OPEN) -> ChangeSet:
|
||||
return api.add_pipe(name, pipe_id, node1, node2, length, diameter, roughness, minor_loss, status)
|
||||
|
||||
def get_pipe(name: str, pipe_id: str) -> dict[str, Any] | None:
|
||||
return api.get_pipe(name, pipe_id)
|
||||
|
||||
def set_pipe(name: str, pipe_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_pipe(name, pipe_id, properties)
|
||||
|
||||
def delete_pipe(name: str, pipe_id: str) -> ChangeSet:
|
||||
return api.delete_pipe(name, pipe_id)
|
||||
|
||||
def set_pipe_node1(name: str, pipe_id: str, node1: str) -> ChangeSet:
|
||||
return api.set_pipe_node1(name, pipe_id, node1)
|
||||
|
||||
def set_pipe_node2(name: str, pipe_id: str, node2: str) -> ChangeSet:
|
||||
return api.set_pipe_node2(name, pipe_id, node2)
|
||||
|
||||
def set_pipe_length(name: str, pipe_id: str, length: float) -> ChangeSet:
|
||||
return api.set_pipe_length(name, pipe_id, length)
|
||||
|
||||
def set_pipe_diameter(name: str, pipe_id: str, diameter: float) -> ChangeSet:
|
||||
return api.set_pipe_diameter(name, pipe_id, diameter)
|
||||
|
||||
def set_pipe_roughness(name: str, pipe_id: str, roughness: float) -> ChangeSet:
|
||||
return api.set_pipe_roughness(name, pipe_id, roughness)
|
||||
|
||||
def set_pipe_minor_loss(name: str, pipe_id: str, minor_loss: float) -> ChangeSet:
|
||||
return api.set_pipe_minor_loss(name, pipe_id, minor_loss)
|
||||
|
||||
def set_pipe_status(name: str, pipe_id: str, status: float) -> ChangeSet:
|
||||
return api.set_pipe_status(name, pipe_id, status)
|
||||
|
||||
def get_pipe_properties(name: str, pipe_id: str) -> dict[str, Any] | None:
|
||||
return api.get_pipe_properties(name, pipe_id)
|
||||
|
||||
|
||||
############################################################
|
||||
# pump 4.[PUMPS]
|
||||
############################################################
|
||||
|
||||
def get_pump_property_names(name: str) -> list[str]:
|
||||
return api.get_pump_property_names(name)
|
||||
def get_pump_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_pump_schema(name)
|
||||
|
||||
def add_pump(name: str, pump_id: str, node1: str, node2: str) -> ChangeSet:
|
||||
return api.add_pump(name, pump_id, node1, node2)
|
||||
|
||||
def get_pump(name: str, pump_id: str) -> dict[str, Any] | None:
|
||||
return api.get_pump(name, pump_id)
|
||||
|
||||
def set_pump(name: str, pump_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_pump(name, pump_id, properties)
|
||||
|
||||
def delete_pump(name: str, pump_id: str) -> ChangeSet:
|
||||
return api.delete_pump(name, pump_id)
|
||||
|
||||
def set_pump_node1(name: str, pump_id: str, node1: str) -> ChangeSet:
|
||||
return api.set_pump_node1(name, pump_id, node1)
|
||||
|
||||
def set_pump_node2(name: str, pump_id: str, node2: str) -> ChangeSet:
|
||||
return api.set_pump_node2(name, pump_id, node2)
|
||||
|
||||
def get_pump_properties(name: str, pump_id: str) -> dict[str, Any] | None:
|
||||
return api.get_pump_properties(name, pump_id)
|
||||
|
||||
|
||||
############################################################
|
||||
# valve 4.[VALVES]
|
||||
############################################################
|
||||
|
||||
def get_valve_property_names(name: str) -> list[str]:
|
||||
return api.get_valve_property_names(name)
|
||||
def get_valve_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_valve_schema(name)
|
||||
|
||||
def add_valve(name: str, valve_id: str, node1: str, node2: str, diameter: float = 0, type: str = VALVES_TYPE_PRV, setting: float = 0, minor_loss: float = 0) -> ChangeSet:
|
||||
return api.add_valve(name, valve_id, node1, node2, diameter, type, setting, minor_loss)
|
||||
|
||||
def get_valve(name: str, valve_id: str) -> dict[str, Any] | None:
|
||||
return api.get_valve(name, valve_id)
|
||||
|
||||
def set_valve(name: str, valve_id: str, properties: dict[str, Any]) -> ChangeSet:
|
||||
return api.set_valve(name, valve_id, properties)
|
||||
|
||||
def delete_valve(name: str, valve_id: str) -> ChangeSet:
|
||||
return api.delete_valve(name, valve_id)
|
||||
|
||||
def set_valve_node1(name: str, valve_id: str, node1: str) -> ChangeSet:
|
||||
return api.set_valve_node1(name, valve_id, node1)
|
||||
|
||||
def set_valve_node2(name: str, valve_id: str, node2: str) -> ChangeSet:
|
||||
return api.set_valve_node2(name, valve_id, node2)
|
||||
|
||||
def set_valve_diameter(name: str, valve_id: str, diameter: float) -> ChangeSet:
|
||||
return api.set_valve_diameter(name, valve_id, diameter)
|
||||
|
||||
def set_valve_type(name: str, valve_id: str, type: str) -> ChangeSet:
|
||||
return api.set_valve_type(name, valve_id, type)
|
||||
|
||||
def set_valve_setting(name: str, valve_id: str, setting: float) -> ChangeSet:
|
||||
return api.set_valve_setting(name, valve_id, setting)
|
||||
|
||||
def set_valve_minor_loss(name: str, valve_id: str, minor_loss: float) -> ChangeSet:
|
||||
return api.set_valve_minor_loss(name, valve_id, minor_loss)
|
||||
|
||||
def get_valve_properties(name: str, pump_id: str) -> dict[str, Any] | None:
|
||||
return api.get_valve_properties(name, pump_id)
|
||||
|
||||
51
try_operation_api.py
Normal file
51
try_operation_api.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from tjnetwork import *
|
||||
|
||||
p = "demo"
|
||||
|
||||
if is_project_open(p):
|
||||
close_project(p)
|
||||
|
||||
if have_project(p):
|
||||
delete_project(p)
|
||||
|
||||
create_project(p)
|
||||
open_project(p)
|
||||
|
||||
print(get_junction_schema(p))
|
||||
print(get_reservoir_schema(p))
|
||||
print(get_tank_schema(p))
|
||||
|
||||
print(add_junction(p, 'j1', 0.0, 0.0, 0.0).operations)
|
||||
print(add_junction(p, 'j2', 0.0, 0.0, 0.0).operations)
|
||||
print(add_junction(p, 'j3', 0.0, 0.0, 0.0).operations)
|
||||
print(add_junction(p, 'j4', 0.0, 0.0, 0.0).operations)
|
||||
|
||||
client_op = get_current_operation(p)
|
||||
print(client_op)
|
||||
print(take_snapshot(p, 'x'))
|
||||
|
||||
print(execute_undo(p).operations)
|
||||
print(execute_undo(p).operations)
|
||||
print(add_junction(p, 'j5', 0.0, 0.0, 0.0).operations)
|
||||
print(add_junction(p, 'j6', 0.0, 0.0, 0.0).operations)
|
||||
|
||||
print(take_snapshot(p, 'xx'))
|
||||
|
||||
print(sync_with_server(p, client_op).operations)
|
||||
|
||||
print(pick_snapshot(p, 'x').operations)
|
||||
|
||||
print(get_junction(p, 'j1'))
|
||||
print(get_junction(p, 'j2'))
|
||||
print(get_junction(p, 'j3'))
|
||||
print(get_junction(p, 'j4'))
|
||||
print(get_junction(p, 'j5'))
|
||||
print(get_junction(p, 'j6'))
|
||||
|
||||
print(set_junction(p, 'j1', {'elevation': 10.0, 'coord': {'x': 10.0, 'y': 10.0}, 'demand': 10.0}).operations)
|
||||
print(get_junction(p, 'j1'))
|
||||
print(execute_undo(p).operations)
|
||||
print(get_junction(p, 'j1'))
|
||||
|
||||
close_project(p)
|
||||
delete_project(p)
|
||||
Reference in New Issue
Block a user