diff --git a/api/__init__.py b/api/__init__.py index 737d03e..71a3948 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -38,4 +38,6 @@ 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 get_valve_schema, add_valve, get_valve, set_valve, delete_valve +from .s9_demands import get_demand_schema, get_demand, set_demand + from .s24_coordinates import get_node_coord diff --git a/api/operation.py b/api/operation.py index 79a3a3b..d418874 100644 --- a/api/operation.py +++ b/api/operation.py @@ -51,6 +51,12 @@ def read(name: str, sql: str) -> Row: return row +def read_all(name: str, sql: str) -> list[Row]: + with conn[name].cursor(row_factory=dict_row) as cur: + cur.execute(sql) + return cur.fetchall() + + def write(name: str, sql: str) -> None: with conn[name].cursor() as cur: cur.execute(sql) diff --git a/api/s9_demands.py b/api/s9_demands.py new file mode 100644 index 0000000..01b798b --- /dev/null +++ b/api/s9_demands.py @@ -0,0 +1,56 @@ +from .operation import * +from .s0_base import * + + +def get_demand_schema(name: str) -> dict[str, dict[str, Any]]: + return { 'junction' : {'type': 'str' , 'optional': False , 'readonly': True }, + 'demands' : {'type': 'list' , 'optional': False , 'readonly': False, + 'element': { 'demand' : {'type': 'float' , 'optional': False , 'readonly': False }, + 'patten' : {'type': 'str' , 'optional': True , 'readonly': False }, + 'category': {'type': 'str' , 'optional': True , 'readonly': False }}}} + + +def get_demand(name: str, junction: str) -> dict[str, Any]: + des = read_all(name, f"select * from demands where junction = '{junction}'") + ds = [] + for r in des: + d = {} + d['demand'] = float(r['demand']) + d['pattern'] = str(r['pattern']) if r['pattern'] != None else None + d['category'] = str(r['category']) if r['category'] != None else None + ds.append(d) + return { 'junction': junction, 'demands': ds } + +# { 'operation': 'update', 'type': 'demand', 'junction': 'j1', 'demands': [{'demand': 0.0, 'patten': None, 'category': None}] } +def set_demand(name: str, cs: ChangeSet) -> ChangeSet: + junction = cs.operations[0]['junction'] + old = get_demand(name, junction) + new = { 'junction': junction, 'demands': [] } + + f_junction = f"'{junction}'" + + redo_sql = f"delete from demands where junction = {f_junction};" + for r in cs.operations[0]['demands']: + demand = float(r['demand']) + pattern = str(r['pattern']) if 'pattern' in r and r['pattern'] != None else None + category = str(r['category']) if 'category' in r and r['category'] != None else None + f_demand = demand + f_pattern = f"'{pattern}'" if pattern != None else 'null' + f_category = f"'{category}'" if category != None else 'null' + redo_sql += f"\ninsert into demands (junction, demand, pattern, category) values ({f_junction}, {f_demand}, {f_pattern}, {f_category});" + new['demands'].append({ 'demand': demand, 'pattern': pattern, 'category': category }) + + undo_sql = f"delete from demands where junction = {f_junction};" + for r in old['demands']: + demand = float(r['demand']) + pattern = str(r['pattern']) + category = str(r['category']) + f_demand = demand + f_pattern = f"'{pattern}'" if pattern != None else 'null' + f_category = f"'{category}'" if category != None else 'null' + undo_sql += f"\ninsert into demands (junction, demand, pattern, category) values ({f_junction}, {f_demand}, {f_pattern}, {f_category});" + + redo_cs = g_update_prefix | { 'type': 'demand' } | new + undo_cs = g_update_prefix | { 'type': 'demand' } | old + + return execute_command(name, redo_sql, undo_sql, redo_cs, undo_cs) diff --git a/script/sql/create/9.demands.sql b/script/sql/create/9.demands.sql index 6e4b2a5..d2d2943 100644 --- a/script/sql/create/9.demands.sql +++ b/script/sql/create/9.demands.sql @@ -5,5 +5,5 @@ create table demands junction varchar(32) references junctions(id) not null , demand numeric not null , pattern varchar(32) references _pattern(id) -, category text not null +, category text ); diff --git a/test_tjnetwork.py b/test_tjnetwork.py index 34c48e1..a0d88aa 100644 --- a/test_tjnetwork.py +++ b/test_tjnetwork.py @@ -1174,6 +1174,72 @@ class TestApi: self.leave(p) + def test_demand(self): + p = 'test_demand' + self.enter(p) + + add_junction(p, ChangeSet({'id': 'j1', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + assert is_junction(p, 'j1') + + set_demand(p, ChangeSet({'junction': 'j1', 'demands': [{'demand': 10.0, 'pattern': None, 'category': 'x'}, + {'demand': 20.0, 'pattern': None, 'category': None}]})) + d = get_demand(p, 'j1') + assert d['junction'] == 'j1' + ds = d['demands'] + assert len(ds) == 2 + assert ds[0]['demand'] == 10.0 + assert ds[0]['pattern'] == None + assert ds[0]['category'] == 'x' + assert ds[1]['demand'] == 20.0 + assert ds[1]['pattern'] == None + assert ds[1]['category'] == None + + self.leave(p) + + + def test_demand_op(self): + p = 'test_demand' + self.enter(p) + + add_junction(p, ChangeSet({'id': 'j1', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + assert is_junction(p, 'j1') + + cs = set_demand(p, ChangeSet({'junction': 'j1', 'demands': [{'demand': 10.0, 'pattern': None, 'category': 'x'}, + {'demand': 20.0, 'pattern': None, 'category': None}]})).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'demand' + assert cs['junction'] == 'j1' + ds = cs['demands'] + assert len(ds) == 2 + assert ds[0]['demand'] == 10.0 + assert ds[0]['pattern'] == None + assert ds[0]['category'] == 'x' + assert ds[1]['demand'] == 20.0 + assert ds[1]['pattern'] == None + assert ds[1]['category'] == None + + cs = execute_undo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'demand' + assert cs['junction'] == 'j1' + assert len(cs['demands']) == 0 + + cs = execute_redo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'demand' + assert cs['junction'] == 'j1' + ds = cs['demands'] + assert len(ds) == 2 + assert ds[0]['demand'] == 10.0 + assert ds[0]['pattern'] == None + assert ds[0]['category'] == 'x' + assert ds[1]['demand'] == 20.0 + assert ds[1]['pattern'] == None + assert ds[1]['category'] == None + + self.leave(p) + + def test_snapshot(self): p = "test_snapshot" self.enter(p) diff --git a/tjnetwork.py b/tjnetwork.py index 06082be..72e193e 100644 --- a/tjnetwork.py +++ b/tjnetwork.py @@ -290,6 +290,21 @@ def delete_valve(name: str, cs: ChangeSet) -> ChangeSet: return api.delete_valve(name, cs) +############################################################ +# demands 9.[DEMANDS] +############################################################ + +def get_demand_schema(name: str) -> dict[str, dict[str, Any]]: + return api.get_demand_schema(name) + +def get_demand(name: str, junction: str) -> dict[str, Any]: + return api.get_demand(name, junction) + +# { 'operation': 'update', 'type': 'demand', 'junction': 'j1', 'demands': [{'demand': 0.0, 'patten': None, 'category': None}] } +def set_demand(name: str, cs: ChangeSet) -> ChangeSet: + return api.set_demand(name, cs) + + ############################################################ # coord 24.[COORDINATES] ############################################################