This commit is contained in:
DingZQ
2022-11-12 19:20:53 +08:00
21 changed files with 1085 additions and 125 deletions

View File

@@ -2,7 +2,7 @@ from .project import list_project, have_project, create_project, delete_project
from .project import is_project_open, get_project_open_count, open_project, close_project
from .project import copy_project
from .parser import read_inp
from .api_parser import read_inp
from .operation import API_ADD, API_UPDATE, API_DELETE
from .operation import ChangeSet

View File

@@ -7,13 +7,66 @@ from .s4_tanks import *
from .s5_pipes import *
from .s6_pumps import *
from .s7_valves import *
from .s8_tags import *
from .s9_demands import *
from .s10_status import *
from .s11_patterns import *
from .s12_curves import *
from .s13_controls import *
from .s14_rules import *
from .s15_energy import *
from .s16_emitters import *
from .s17_quality import *
from .s18_sources import *
from .s19_reactions import *
from .s20_mixing import *
from .s21_times import *
from .s22_report import *
from .s23_options import *
from .s24_coordinates import *
from .s25_vertices import *
from .s26_labels import *
from .s27_backdrop import *
from .s28_end import *
def parse_inp(inp: str) -> dict[str, list[str]]:
section_name = ['TITLE', 'JUNCTIONS', 'RESERVOIRS', 'TANKS', 'PIPES',
'PUMPS', 'VALVES', 'TAGS', 'DEMANDS', 'STATUS',
'PATTERNS', 'CURVES', 'CONTROLS', 'RULES', 'ENERGY',
'EMITTERS', 'QUALITY', 'SOURCES', 'REACTIONS', 'MIXING',
'TIMES', 'REPORT', 'OPTIONS', 'COORDINATES', 'VERTICES',
'LABELS', 'BACKDROP', 'END']
file: dict[str, list[str]] = {}
for s in section_name:
file[s] = []
section = ''
for line in open(inp):
line = line.strip()
if line == '':
section = ''
continue
if line.startswith('['):
is_section = False
for s in section_name:
if line.startswith(f'[{s}'):
section = s
is_section = True
break
if is_section:
continue
if section != '':
file[section].append(line)
return file
def read_inp(name: str, inp: str):
@@ -28,25 +81,27 @@ def read_inp(name: str, inp: str):
section = ''
title : str = ''
junctions : dict[str, dict[str, Any]] = {}
reservoirs : dict[str, dict[str, Any]] = {}
tanks : dict[str, dict[str, Any]] = {}
pipes : dict[str, dict[str, Any]] = {}
pumps : dict[str, dict[str, Any]] = {}
valves : dict[str, dict[str, Any]] = {}
demands : dict[str, list[dict[str, Any]]] = {}
status : dict[str, dict[str, Any]] = {}
patterns : dict[str, list[float]] = {}
curves : dict[str, list[dict[str, float]]] = {}
emitters : dict[str, float] = {}
times : dict[str, str] = {}
options : dict[str, str] = {}
file: dict[str, list[str]] = {}
_1_title : str = ''
_2_junctions : dict[str, dict[str, Any]] = {}
_3_reservoirs : dict[str, dict[str, Any]] = {}
_4_tanks : dict[str, dict[str, Any]] = {}
_5_pipes : dict[str, dict[str, Any]] = {}
_6_pumps : dict[str, dict[str, Any]] = {}
_7_valves : dict[str, dict[str, Any]] = {}
_9_demands : dict[str, list[dict[str, Any]]] = {}
_10_status : dict[str, dict[str, Any]] = {}
_11_patterns : dict[str, list[float]] = {}
_12_curves : dict[str, list[dict[str, float]]] = {}
_16_emitters : dict[str, float] = {}
_21_times : dict[str, str] = {}
_22_options : dict[str, str] = {}
for line in open(inp):
line = line.strip()
if line.startswith(';'):
if line.startswith(';') and not line.endswith(':'):
continue
if line.endswith(';'):
line = line.removesuffix(';')
@@ -110,111 +165,111 @@ def read_inp(name: str, inp: str):
continue
if section == 'title':
if title == '':
title += '\n'
title += line
if _1_title == '':
_1_title += '\n'
_1_title += line
continue
elif section == JUNCTION:
junction_demand = float(tokens[2]) if tokens_len >= 3 else None
junction_pattern = tokens[3] if tokens_len == 4 else None
junctions[tokens[0]] = {'id': tokens[0], 'elevation': tokens[1], 'demand': junction_demand, 'pattern': junction_pattern}
_2_junctions[tokens[0]] = {'id': tokens[0], 'elevation': tokens[1], 'demand': junction_demand, 'pattern': junction_pattern}
continue
elif section == RESERVOIR:
reservoir_pattern = tokens[2] if tokens_len == 3 else None
reservoirs[tokens[0]] = {'id': tokens[0], 'head': tokens[1], 'pattern': reservoir_pattern}
_3_reservoirs[tokens[0]] = {'id': tokens[0], 'head': tokens[1], 'pattern': reservoir_pattern}
continue
elif section == TANK:
tank_vol_curve = tokens[7] if tokens_len >= 8 else None
tank_overflow = tokens[8].upper() if tokens_len == 9 else None
tanks[tokens[0]] = {'id': tokens[0], 'elevation': tokens[1], 'init_level': tokens[2], 'min_level': tokens[3], 'max_level': tokens[4], 'diameter': tokens[5], 'min_vol': tokens[6], 'vol_curve': tank_vol_curve, 'overflow': tank_overflow}
_4_tanks[tokens[0]] = {'id': tokens[0], 'elevation': tokens[1], 'init_level': tokens[2], 'min_level': tokens[3], 'max_level': tokens[4], 'diameter': tokens[5], 'min_vol': tokens[6], 'vol_curve': tank_vol_curve, 'overflow': tank_overflow}
continue
elif section == PIPE:
# status is must-have, here fix input
pipe_status = tokens[7].upper() if tokens_len == 8 else PIPE_STATUS_OPEN
pipes[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2], 'length': tokens[3], 'diameter': tokens[4], 'roughness': tokens[5], 'minor_loss': tokens[6], 'status': pipe_status}
_5_pipes[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2], 'length': tokens[3], 'diameter': tokens[4], 'roughness': tokens[5], 'minor_loss': tokens[6], 'status': pipe_status}
continue
elif section == PUMP:
pumps[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2]}
_6_pumps[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2]}
for i in range(3, tokens_len, 2):
pumps[tokens[0]] |= { tokens[i].lower(): tokens[i + 1] }
_6_pumps[tokens[0]] |= { tokens[i].lower(): tokens[i + 1] }
continue
elif section == VALVE:
valves[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2], 'diameter': tokens[3], 'v_type': tokens[4], 'setting': tokens[5], 'minor_loss': tokens[6]}
_7_valves[tokens[0]] = {'id': tokens[0], 'node1': tokens[1], 'node2': tokens[2], 'diameter': tokens[3], 'v_type': tokens[4], 'setting': tokens[5], 'minor_loss': tokens[6]}
continue
elif section == 'demand':
demand_pattern = tokens[2] if tokens_len >= 3 else None
demand_category = tokens[3] if tokens_len == 4 else None
demands[tokens[0]].append({'demand': tokens[1], 'pattern': demand_pattern, 'category': demand_category})
_9_demands[tokens[0]].append({'demand': tokens[1], 'pattern': demand_pattern, 'category': demand_category})
continue
elif section == 'status':
if tokens[0] not in status:
status[tokens[0]] = {}
if tokens[0] not in _10_status:
_10_status[tokens[0]] = {}
setting = None
try:
setting = float(tokens[1])
except:
setting = None
if setting != None:
status[tokens[0]]['setting'] = setting
_10_status[tokens[0]]['setting'] = setting
else:
status[tokens[0]]['status'] = tokens[1].upper()
_10_status[tokens[0]]['status'] = tokens[1].upper()
continue
elif section == PATTERN:
if tokens[0] not in patterns:
patterns[tokens[0]] = []
if tokens[0] not in _11_patterns:
_11_patterns[tokens[0]] = []
for i in range(1, tokens_len):
patterns[tokens[0]].append(float(tokens[i]))
_11_patterns[tokens[0]].append(float(tokens[i]))
continue
elif section == CURVE:
if tokens[0] not in curves:
curves[tokens[0]] = []
if tokens[0] not in _12_curves:
_12_curves[tokens[0]] = []
for i in range(1, tokens_len, 2):
curves[tokens[0]].append({ 'x': float(tokens[i]), 'y': float(tokens[i + 1]) })
_12_curves[tokens[0]].append({ 'x': float(tokens[i]), 'y': float(tokens[i + 1]) })
continue
elif section == 'emitter':
emitters[tokens[0]] = float(tokens[1])
_16_emitters[tokens[0]] = float(tokens[1])
continue
elif section == 'time':
if tokens_len == 2:
times[tokens[0]] = tokens[1]
_21_times[tokens[0]] = tokens[1]
elif tokens_len == 3:
times[tokens[0] + ' ' + tokens[1]] = tokens[2]
_21_times[tokens[0] + ' ' + tokens[1]] = tokens[2]
elif tokens_len == 4:
times[tokens[0] + ' ' + tokens[1]] = tokens[2] + ' ' + tokens[3]
_21_times[tokens[0] + ' ' + tokens[1]] = tokens[2] + ' ' + tokens[3]
continue
elif section == 'option':
if tokens[0] == 'HYDRAULICS' or tokens[0] == 'MAP':
continue
if tokens_len == 2:
options[tokens[0]] = tokens[1]
_22_options[tokens[0]] = tokens[1]
elif tokens_len == 3:
if tokens[0] == 'UNBALANCED' or tokens[0] == 'QUALITY':
options[tokens[0]] = tokens[1] + ' ' + tokens[2]
_22_options[tokens[0]] = tokens[1] + ' ' + tokens[2]
else:
options[tokens[0] + ' ' + tokens[1]] = tokens[2]
_22_options[tokens[0] + ' ' + tokens[1]] = tokens[2]
continue
elif section == 'coordinate':
if tokens[0] in junctions:
junctions[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
elif tokens[0] in reservoirs:
reservoirs[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
elif tokens[0] in tanks:
tanks[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
if tokens[0] in _2_junctions:
_2_junctions[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
elif tokens[0] in _3_reservoirs:
_3_reservoirs[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
elif tokens[0] in _4_tanks:
_4_tanks[tokens[0]] |= {'x': tokens[1], 'y': tokens[2]}
continue
# title
set_title(name, ChangeSet({ 'value': title }))
set_title(name, ChangeSet({ 'value': _1_title }))
# pattern
for key, value in patterns.items():
for key, value in _11_patterns.items():
set_pattern(name, ChangeSet({'id': key, 'factors': value}))
# curve
for key, value in curves.items():
for key, value in _12_curves.items():
set_curve(name, ChangeSet({'id': key, 'coords': value}))
# junction
for value in junctions.values():
for value in _2_junctions.values():
if 'x' not in value:
value['x'] = 0.0
if 'y' not in value:
@@ -222,7 +277,7 @@ def read_inp(name: str, inp: str):
add_junction(name, ChangeSet(value))
# reservoir
for value in reservoirs.values():
for value in _3_reservoirs.values():
if 'x' not in value:
value['x'] = 0.0
if 'y' not in value:
@@ -230,7 +285,7 @@ def read_inp(name: str, inp: str):
add_reservoir(name, ChangeSet(value))
# tank
for value in tanks.values():
for value in _4_tanks.values():
if 'x' not in value:
value['x'] = 0.0
if 'y' not in value:
@@ -238,33 +293,33 @@ def read_inp(name: str, inp: str):
add_tank(name, ChangeSet(value))
# pipe
for value in pipes.values():
for value in _5_pipes.values():
add_pipe(name, ChangeSet(value))
# pump
for value in pumps.values():
for value in _6_pumps.values():
add_pump(name, ChangeSet(value))
# valve
for value in valves.values():
for value in _7_valves.values():
add_valve(name, ChangeSet(value))
# demand
for key, value in demands.items():
for key, value in _9_demands.items():
set_demand(name, ChangeSet({'junction': key, 'demands': value}))
# status
for key, value in status.items():
for key, value in _10_status.items():
set_status(name, ChangeSet({'link': key} | value))
# emitter
for key, value in emitters.items():
for key, value in _16_emitters.items():
set_emitter(name, ChangeSet({'junction': key, 'coefficient': value}))
# time
set_time(name, ChangeSet(times))
set_time(name, ChangeSet(_21_times))
# option
set_option(name, ChangeSet(options))
set_option(name, ChangeSet(_22_options))
close_project(name)

View File

@@ -5,30 +5,127 @@ from .s4_tanks import *
from .s5_pipes import *
from .s6_pumps import *
from .s7_valves import *
from .s8_tags import *
from .s9_demands import *
from .s10_status import *
from .s11_patterns import *
from .s12_curves import *
from .s13_controls import *
from .s14_rules import *
from .s15_energy import *
from .s16_emitters import *
from .s17_quality import *
from .s18_sources import *
from .s19_reactions import *
from .s20_mixing import *
from .s21_times import *
from .s22_report import *
from .s23_options import *
from .s24_coordinates import *
from .s25_vertices import *
from .s26_labels import *
from .s27_backdrop import *
from .s28_end import *
_s1_title = 'title'
_s2_junction = 'junction'
_s3_reservoir = 'reservoir'
_s4_tank = 'tank'
_s5_pipe = 'pipe'
_s6_pump = 'pump'
_s7_valve = 'valve'
_s8_tag = 'tag'
_s9_demand = 'demand'
_s10_status = 'status'
_s11_pattern = 'patten'
_s12_curve = 'curve'
_s13_control = 'control'
_s14_rule = 'rule'
_s15_global_energy = 'global_energy'
_s15_pump_energy = 'pump_energy'
_s16_emitter = 'emitter'
_s17_quality = 'quality'
_s18_source = 'source'
_s19_global_reaction = 'global_reaction'
_s19_pipe_reaction = 'pipe_reaction'
_s19_tank_reaction = 'tank_reaction'
_s20_mixing = 'mixing'
_s21_time = 'time'
_s22_report = 'report'
_s23_option = 'option'
_s24_coordinate = 'coordinate'
_s25_vertex = 'vertex'
_s26_label = 'label'
_s27_backdrop = 'backdrop'
_s28_end = 'end'
def execute_add_command(name: str, cs: ChangeSet) -> ChangeSet:
type = cs.operations[0]['type']
if type == JUNCTION:
if type == _s1_title:
return ChangeSet()
if type == _s2_junction:
return add_junction(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return add_reservoir(name, cs)
elif type == TANK:
elif type == _s4_tank:
return add_tank(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return add_pipe(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return add_pump(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return add_valve(name, cs)
elif type == _s8_tag:
return ChangeSet()
elif type == _s9_demand:
return ChangeSet()
elif type == _s10_status:
return ChangeSet()
elif type == _s11_pattern:
return add_pattern(name, cs)
elif type == _s12_curve:
return add_curve(name, cs)
elif type == _s13_control:
return ChangeSet()
elif type == _s14_rule:
return ChangeSet()
elif type == _s15_global_energy:
return ChangeSet()
elif type == _s15_pump_energy:
return ChangeSet()
elif type == _s16_emitter:
return ChangeSet()
elif type == _s17_quality:
return ChangeSet()
elif type == _s18_source:
return add_source(name, cs)
elif type == _s19_global_reaction:
return ChangeSet()
elif type == _s19_pipe_reaction:
return ChangeSet()
elif type == _s19_tank_reaction:
return ChangeSet()
elif type == _s20_mixing:
return add_mixing(name, cs)
elif type == _s21_time:
return ChangeSet()
elif type == _s22_report:
return ChangeSet()
elif type == _s23_option:
return ChangeSet()
elif type == _s24_coordinate:
return ChangeSet()
elif type == _s25_vertex:
return add_vertex(name, cs)
elif type == _s26_label:
return add_label(name, cs)
elif type == _s27_backdrop:
return ChangeSet()
elif type == _s28_end:
return ChangeSet()
return ChangeSet()
@@ -36,34 +133,68 @@ def execute_add_command(name: str, cs: ChangeSet) -> ChangeSet:
def execute_update_command(name: str, cs: ChangeSet) -> ChangeSet:
type = cs.operations[0]['type']
if type == 'title':
if type == _s1_title:
return set_title(name, cs)
if type == JUNCTION:
if type == _s2_junction:
return set_junction(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return set_reservoir(name, cs)
elif type == TANK:
elif type == _s4_tank:
return set_tank(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return set_pipe(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return set_pump(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return set_valve(name, cs)
elif type == 'demand':
return set_demand(name, cs)
elif type == 'status':
elif type == _s8_tag:
return set_tag(name, cs)
elif type == _s9_demand: # exception, batch command ...
return ChangeSet()
elif type == _s10_status:
return set_status(name, cs)
elif type == PATTERN:
elif type == _s11_pattern:
return set_pattern(name, cs)
elif type == CURVE:
elif type == _s12_curve:
return set_curve(name, cs)
elif type == 'emitter':
elif type == _s13_control:
return set_control(name, cs)
elif type == _s14_rule:
return set_rule(name, cs)
elif type == _s15_global_energy:
return set_global_energy(name, cs)
elif type == _s15_pump_energy:
return set_pump_energy(name, cs)
elif type == _s16_emitter:
return set_emitter(name, cs)
elif type == 'time':
elif type == _s17_quality:
return set_quality(name, cs)
elif type == _s18_source:
return set_source(name, cs)
elif type == _s19_global_reaction:
return set_global_reaction(name, cs)
elif type == _s19_pipe_reaction:
return set_pipe_reaction(name, cs)
elif type == _s19_tank_reaction:
return set_tank_reaction(name, cs)
elif type == _s20_mixing:
return set_mixing(name, cs)
elif type == _s21_time:
return set_time(name, cs)
elif type == 'option':
elif type == _s22_report: # no api now
return ChangeSet()
elif type == _s23_option:
return set_option(name, cs)
elif type == _s24_coordinate: # do not support update here
return ChangeSet()
elif type == _s25_vertex:
return set_vertex(name, cs)
elif type == _s26_label:
return set_label(name, cs)
elif type == _s27_backdrop:
return set_backdrop(name, cs)
elif type == _s28_end: # end
return ChangeSet()
return ChangeSet()
@@ -71,18 +202,68 @@ def execute_update_command(name: str, cs: ChangeSet) -> ChangeSet:
def execute_delete_command(name: str, cs: ChangeSet) -> ChangeSet:
type = cs.operations[0]['type']
if type == JUNCTION:
if type == _s1_title:
return ChangeSet()
if type == _s2_junction:
return delete_junction(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return delete_reservoir(name, cs)
elif type == TANK:
elif type == _s4_tank:
return delete_tank(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return delete_pipe(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return delete_pump(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return delete_valve(name, cs)
elif type == _s8_tag:
return ChangeSet()
elif type == _s9_demand:
return ChangeSet()
elif type == _s10_status:
return ChangeSet()
elif type == _s11_pattern:
return delete_pattern(name, cs)
elif type == _s12_curve:
return delete_curve(name, cs)
elif type == _s13_control:
return ChangeSet()
elif type == _s14_rule:
return ChangeSet()
elif type == _s15_global_energy:
return ChangeSet()
elif type == _s15_pump_energy:
return ChangeSet()
elif type == _s16_emitter:
return ChangeSet()
elif type == _s17_quality:
return ChangeSet()
elif type == _s18_source:
return delete_source(name, cs)
elif type == _s19_global_reaction:
return ChangeSet()
elif type == _s19_pipe_reaction:
return ChangeSet()
elif type == _s19_tank_reaction:
return ChangeSet()
elif type == _s20_mixing:
return delete_mixing(name, cs)
elif type == _s21_time:
return ChangeSet()
elif type == _s22_report:
return ChangeSet()
elif type == _s23_option:
return ChangeSet()
elif type == _s24_coordinate:
return ChangeSet()
elif type == _s25_vertex:
return delete_vertex(name, cs)
elif type == _s26_label:
return delete_label(name, cs)
elif type == _s27_backdrop:
return ChangeSet()
elif type == _s28_end:
return ChangeSet()
return ChangeSet()
@@ -108,18 +289,68 @@ def execute_batch_commands(name: str, cs: ChangeSet) -> ChangeSet:
def cache_add_command(name: str, cs: ChangeSet) -> SqlChangeSet | None:
type = cs.operations[0]['type']
if type == JUNCTION:
if type == _s1_title:
return None
if type == _s2_junction:
return add_junction_cache(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return add_reservoir_cache(name, cs)
elif type == TANK:
elif type == _s4_tank:
return add_tank_cache(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return add_pipe_cache(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return add_pump_cache(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return add_valve_cache(name, cs)
elif type == _s8_tag:
return None
elif type == _s9_demand:
return None
elif type == _s10_status:
return None
elif type == _s11_pattern:
return add_pattern_cache(name, cs)
elif type == _s12_curve:
return add_curve_cache(name, cs)
elif type == _s13_control:
return None
elif type == _s14_rule:
return None
elif type == _s15_global_energy:
return None
elif type == _s15_pump_energy:
return None
elif type == _s16_emitter:
return None
elif type == _s17_quality:
return None
elif type == _s18_source:
return add_source_cache(name, cs)
elif type == _s19_global_reaction:
return None
elif type == _s19_pipe_reaction:
return None
elif type == _s19_tank_reaction:
return None
elif type == _s20_mixing:
return add_mixing_cache(name, cs)
elif type == _s21_time:
return None
elif type == _s22_report:
return None
elif type == _s23_option:
return None
elif type == _s24_coordinate:
return None
elif type == _s25_vertex:
return add_vertex_cache(name, cs)
elif type == _s26_label:
return add_label_cache(name, cs)
elif type == _s27_backdrop:
return None
elif type == _s28_end:
return None
return None
@@ -127,34 +358,68 @@ def cache_add_command(name: str, cs: ChangeSet) -> SqlChangeSet | None:
def cache_update_command(name: str, cs: ChangeSet) -> SqlChangeSet | None:
type = cs.operations[0]['type']
if type == 'title':
if type == _s1_title:
return set_title_cache(name, cs)
if type == JUNCTION:
if type == _s2_junction:
return set_junction_cache(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return set_reservoir_cache(name, cs)
elif type == TANK:
elif type == _s4_tank:
return set_tank_cache(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return set_pipe_cache(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return set_pump_cache(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return set_valve_cache(name, cs)
elif type == 'demand':
return set_demand_cache(name, cs)
elif type == 'status':
elif type == _s8_tag:
return set_tag_cache(name, cs)
elif type == _s9_demand: # exception, batch command ...
return None
elif type == _s10_status:
return set_status_cache(name, cs)
elif type == PATTERN:
elif type == _s11_pattern:
return set_pattern_cache(name, cs)
elif type == CURVE:
elif type == _s12_curve:
return set_curve_cache(name, cs)
elif type == 'emitter':
elif type == _s13_control:
return set_control_cache(name, cs)
elif type == _s14_rule:
return set_rule_cache(name, cs)
elif type == _s15_global_energy:
return set_global_energy_cache(name, cs)
elif type == _s15_pump_energy:
return set_pump_energy_cache(name, cs)
elif type == _s16_emitter:
return set_emitter_cache(name, cs)
elif type == 'time':
elif type == _s17_quality:
return set_quality_cache(name, cs)
elif type == _s18_source:
return set_source_cache(name, cs)
elif type == _s19_global_reaction:
return set_global_reaction_cache(name, cs)
elif type == _s19_pipe_reaction:
return set_pipe_reaction_cache(name, cs)
elif type == _s19_tank_reaction:
return set_tank_reaction_cache(name, cs)
elif type == _s20_mixing:
return set_mixing_cache(name, cs)
elif type == _s21_time:
return set_time_cache(name, cs)
elif type == 'option':
elif type == _s22_report: # no api now
return None
elif type == _s23_option:
return set_option_cache(name, cs)
elif type == _s24_coordinate: # do not support update here
return None
elif type == _s25_vertex:
return set_vertex_cache(name, cs)
elif type == _s26_label:
return set_label_cache(name, cs)
elif type == _s27_backdrop:
return set_backdrop_cache(name, cs)
elif type == _s28_end: # end
return None
return None
@@ -162,18 +427,68 @@ def cache_update_command(name: str, cs: ChangeSet) -> SqlChangeSet | None:
def cache_delete_command(name: str, cs: ChangeSet) -> SqlChangeSet | None:
type = cs.operations[0]['type']
if type == JUNCTION:
if type == _s1_title:
return None
if type == _s2_junction:
return delete_junction_cache(name, cs)
elif type == RESERVOIR:
elif type == _s3_reservoir:
return delete_reservoir_cache(name, cs)
elif type == TANK:
elif type == _s4_tank:
return delete_tank_cache(name, cs)
elif type == PIPE:
elif type == _s5_pipe:
return delete_pipe_cache(name, cs)
elif type == PUMP:
elif type == _s6_pump:
return delete_pump_cache(name, cs)
elif type == VALVE:
elif type == _s7_valve:
return delete_valve_cache(name, cs)
elif type == _s8_tag:
return None
elif type == _s9_demand:
return None
elif type == _s10_status:
return None
elif type == _s11_pattern:
return delete_pattern_cache(name, cs)
elif type == _s12_curve:
return delete_curve_cache(name, cs)
elif type == _s13_control:
return None
elif type == _s14_rule:
return None
elif type == _s15_global_energy:
return None
elif type == _s15_pump_energy:
return None
elif type == _s16_emitter:
return None
elif type == _s17_quality:
return None
elif type == _s18_source:
return delete_source_cache(name, cs)
elif type == _s19_global_reaction:
return None
elif type == _s19_pipe_reaction:
return None
elif type == _s19_tank_reaction:
return None
elif type == _s20_mixing:
return delete_mixing_cache(name, cs)
elif type == _s21_time:
return None
elif type == _s22_report:
return None
elif type == _s23_option:
return None
elif type == _s24_coordinate:
return None
elif type == _s25_vertex:
return delete_vertex_cache(name, cs)
elif type == _s26_label:
return delete_label_cache(name, cs)
elif type == _s27_backdrop:
return None
elif type == _s28_end:
return None
return None
@@ -189,21 +504,33 @@ def execute_batch_command(name: str, cs: ChangeSet) -> ChangeSet:
operation = op['operation']
r = None
demand = None
if operation == API_ADD:
r = cache_add_command(name, ChangeSet(op))
elif operation == API_UPDATE:
r = cache_update_command(name, ChangeSet(op))
if op['type'] == 'demand':
r = set_demand_cache(name, ChangeSet(op))
elif operation == API_DELETE:
r = cache_delete_command(name, ChangeSet(op))
if r == None:
return ChangeSet()
redo_sql_s.append(r.redo_sql)
undo_sql_s.append(r.undo_sql)
redo_cs_s.append(r.redo_cs)
undo_cs_s.append(r.undo_cs)
if op['type'] == 'demand':
redo_sql_s.append(r.redo_sql)
undo_sql_s.append(r.undo_sql)
for d in r.redo_cs:
redo_cs_s.append(d)
for d in r.undo_cs.reverse(): # need reverse again...
undo_cs_s.append(r.undo_cs)
else:
redo_sql_s.append(r.redo_sql)
undo_sql_s.append(r.undo_sql)
redo_cs_s.append(r.redo_cs)
undo_cs_s.append(r.undo_cs)
except:
pass

View File

@@ -43,14 +43,14 @@ class ChangeSet:
class SqlChangeSet:
def __init__(self, redo_sql: str, undo_sql: str, redo_cs: dict[str, str], undo_cs: dict[str, str]) -> None:
def __init__(self, redo_sql: str, undo_sql: str, redo_cs: dict[str, Any], undo_cs: dict[str, Any]) -> None:
self.redo_sql = redo_sql
self.undo_sql = undo_sql
self.redo_cs = redo_cs
self.undo_cs = undo_cs
class BatchSqlChangeSet:
def __init__(self, redo_sql: str, undo_sql: str, redo_cs: list[dict[str, str]], undo_cs: list[dict[str, str]]) -> None:
def __init__(self, redo_sql: str, undo_sql: str, redo_cs: list[dict[str, Any]], undo_cs: list[dict[str, Any]]) -> None:
self.redo_sql = redo_sql
self.undo_sql = undo_sql
self.redo_cs = redo_cs

View File

@@ -66,3 +66,58 @@ def set_status_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_status(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_status_cache(name, cs))
class InpStatus:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.link = str(tokens[0])
self.value = tokens[1]
self.is_status = True
if self.value == LINK_STATUS_OPEN or self.value == LINK_STATUS_CLOSED or self.value == LINK_STATUS_ACTIVE:
self.status = str(self.value)
else:
self.setting = float(self.value)
self.is_status = False
def inp_in_status(section: list[str]) -> ChangeSet:
objs: dict[str, list[InpStatus]] = {}
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpStatus(s)
if obj.link not in objs:
objs[obj.link] = []
objs[obj.link].append(obj)
cs = ChangeSet()
for link, values in objs.items():
obj_cs = {'operation': API_UPDATE, 'type': 'status', 'link' : link, 'status': None, 'setting': None}
for obj in values:
if obj.is_status:
obj_cs['status'] = obj.status
else:
obj_cs['setting'] = obj.setting
cs.append(obj_cs)
return cs
def inp_out_status(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from status')
for obj in objs:
link = obj['link']
status = obj['status'] if obj['status'] != None else ''
setting = obj['setting'] if obj['setting'] != None else ''
if status != '':
lines.append(f'{link} {status}')
if setting != '':
lines.append(f'{link} {setting}')
return lines

View File

@@ -91,3 +91,39 @@ def delete_pattern_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_pattern(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_pattern_cache(name, cs))
def inp_in_pattern(section: list[str]) -> ChangeSet:
descs = {}
patterns: dict[str, list[float]] = {}
count = len(section)
for i in range(0, count):
if section[i].startswith(';'):
# this is description
next = i + 1
if next < count and section[next].startswith(';') == False:
next_tokens = section[next].split()
descs[next_tokens[0]] = section[i].removeprefix(';')
continue
tokens = section[i].split()
if tokens[0] not in patterns:
patterns[tokens[0]] = []
for token in tokens[1:]:
patterns[tokens[0]].append(float(token))
cs = ChangeSet()
for id, factors in patterns.items():
cs.append({'operation': API_ADD, 'type': 'pattern', 'id' : id, 'factors' : factors})
return cs
def inp_out_pattern(name: str) -> list[str]:
lines = []
objs = read_all(name, f"select * from patterns order by _order")
for obj in objs:
id = obj['id']
factor = obj['factor']
lines.append(f'{id} {factor}')
return lines

View File

@@ -119,3 +119,50 @@ def delete_curve_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_curve(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_curve_cache(name, cs))
def inp_in_curve(section: list[str]) -> ChangeSet:
types = {}
descs = {}
curves: dict[str, list[dict[str, float]]] = {}
count = len(section)
for i in range(0, count):
if section[i].startswith(';'):
# this is description
type_plus_desc = section[i].removeprefix(';')
type_plus_desc_tokens = type_plus_desc.split(':')
next = i + 1
if next < count and section[next].startswith(';') == False:
next_tokens = section[next].split()
types[next_tokens[0]] = type_plus_desc_tokens[0].strip()
if len(type_plus_desc_tokens) > 1:
descs[next_tokens[0]] = type_plus_desc_tokens[1].strip()
continue
tokens = section[i].split()
if tokens[0] not in curves:
curves[tokens[0]] = []
curves[tokens[0]].append({'x': float(tokens[1]), 'y': float(tokens[2])})
cs = ChangeSet()
for id, coords in curves.items():
c_type = types[id] if id in types else CURVE_TYPE_PUMP
cs.append({'operation': API_ADD, 'type': 'curve', 'id' : id, 'c_type': c_type, 'coords' : coords})
return cs
def inp_out_curve(name: str) -> list[str]:
lines = []
types = read_all(name, f"select * from _curve")
for type in types:
id = type['id']
# ;type: desc
lines.append(f";{type['type']}:")
objs = read_all(name, f"select * from curves where id = '{id}' order by _order")
for obj in objs:
id = obj['id']
x = obj['x']
y = obj['y']
lines.append(f'{id} {x} {y}')
return lines

View File

@@ -24,3 +24,19 @@ def set_control_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_control(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_control_cache(name, cs))
class InpControl:
def __init__(self, section) -> None:
self.control = '\n'.join(section)
def inp_in_control(section: list[str]) -> ChangeSet:
obj = InpControl(section)
cs = ChangeSet({'operation' : API_UPDATE, 'type': 'control', 'control' : obj.control})
return cs
def inp_out_control(name: str) -> list[str]:
obj = str(get_control(name)['control'])
return obj.split('\n')

View File

@@ -24,3 +24,19 @@ def set_rule_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_rule(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_rule_cache(name, cs))
class InpRule:
def __init__(self, section) -> None:
self.rule = '\n'.join(section)
def inp_in_rule(section: list[str]) -> ChangeSet:
obj = InpRule(section)
cs = ChangeSet({'operation' : API_UPDATE, 'type': 'rule', 'rule' : obj.rule})
return cs
def inp_out_rule(name: str) -> list[str]:
obj = str(get_rule(name)['rule'])
return obj.split('\n')

View File

@@ -25,3 +25,19 @@ def set_title_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_title(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_title_cache(name ,cs))
class InpTitle:
def __init__(self, section) -> None:
self.value = '\n'.join(section)
def inp_in_title(section: list[str]) -> ChangeSet:
obj = InpTitle(section)
cs = ChangeSet({'operation' : API_ADD, 'type': 'title', 'value' : obj.value})
return cs
def inp_out_title(name: str) -> list[str]:
obj = str(get_title(name)['value'])
return obj.split('\n')

View File

@@ -65,3 +65,24 @@ def set_time_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_time(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_time_cache(name, cs))
def inp_in_time(section: list[str]) -> ChangeSet:
cs = g_update_prefix | { 'type' : 'time' }
for s in section:
line = s.upper().strip()
for key in get_time_schema('').keys():
if line.startswith(key):
value = line.removeprefix(key).strip()
cs |= { key : value }
return ChangeSet(cs)
def inp_out_time(name: str) -> list[str]:
lines = []
objs = read_all(name, f"select * from times")
for obj in objs:
key = obj['key']
value = obj['value']
lines.append(f'{key} {value}')
return lines

View File

@@ -103,3 +103,24 @@ def set_option_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def set_option(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, set_option_cache(name, cs))
def inp_in_option(section: list[str]) -> ChangeSet:
cs = g_update_prefix | { 'type' : 'option' }
for s in section:
line = s.upper().strip()
for key in get_option_schema('').keys():
if line.startswith(key):
value = line.removeprefix(key).strip()
cs |= { key : value }
return ChangeSet(cs)
def inp_out_option(name: str) -> list[str]:
lines = []
objs = read_all(name, f"select * from options")
for obj in objs:
key = obj['key']
value = obj['value']
lines.append(f'{key} {value}')
return lines

View File

@@ -1,4 +1,4 @@
from .operation import read
from .operation import *
def _to_client_point(coord: str) -> dict[str, float]:
@@ -9,3 +9,26 @@ def _to_client_point(coord: str) -> dict[str, float]:
def get_node_coord(name: str, id: str) -> dict[str, float]:
row = read(name, f"select * from coordinates where node = '{id}'")
return _to_client_point(row['coord'])
# exception ! need merge to node change set !
def inp_in_coord(section: list[str]) -> dict[str, dict[str, float]]:
coords = {}
for s in section:
# skip comment
if s.startswith(';'):
continue
tokens = s.split()
coords[tokens[0]] = { 'x': tokens[1], 'y': tokens[2] }
return coords
def inp_out_junction(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from coordinates')
for obj in objs:
node = obj['node']
coord = _to_client_point(obj['coord'])
x = coord['x']
y = coord['y']
lines.append(f'{node} {x} {y}')
return lines

View File

@@ -43,6 +43,21 @@ def set_vertex_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
return SqlChangeSet(redo_sql, undo_sql, redo_cs, undo_cs)
def add_vertex_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
result = set_vertex_cache(name, cs)
result.redo_cs |= g_add_prefix
result.undo_cs |= g_delete_prefix
return result
def delete_vertex_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
cs.operations[0]['coords'] = []
result = set_vertex_cache(name, cs)
result.redo_cs |= g_delete_prefix
result.undo_cs |= g_add_prefix
return result
def set_vertex(name: str, cs: ChangeSet) -> ChangeSet:
result = set_vertex_cache(name, cs)
result.redo_cs |= g_update_prefix

View File

@@ -118,3 +118,42 @@ def delete_junction_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_junction(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_junction_cache(name, cs))
class InpJunction:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.elevation = float(tokens[1])
self.demand = float(tokens[2]) if num_without_desc >= 3 else None
self.pattern = str(tokens[3]) if num_without_desc >= 4 else None
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_junction(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpJunction(s)
cs.append({'operation': API_ADD, 'type': 'junction', 'id': obj.id, 'elevation': obj.elevation, 'demand': obj.demand, 'pattern': obj.pattern})
return cs
def inp_out_junction(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from junctions')
for obj in objs:
id = obj['id']
elev = obj['elevation']
demand = obj['demand'] if obj['demand'] != None else ''
pattern = obj['pattern'] if obj['pattern'] != None else ''
desc = ';'
lines.append(f'{id} {elev} {demand} {pattern} {desc}')
return lines

View File

@@ -114,3 +114,40 @@ def delete_reservoir_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_reservoir(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_reservoir_cache(name, cs))
class InpReservoir:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.head = float(tokens[1])
self.pattern = str(tokens[2]) if num_without_desc >= 3 else None
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_reservoir(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpReservoir(s)
cs.append({'operation': API_ADD, 'type': 'reservoir', 'id': obj.id, 'head': obj.head, 'pattern': obj.pattern})
return cs
def inp_out_reservoir(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from reservoirs')
for obj in objs:
id = obj['id']
head = obj['head']
pattern = obj['pattern'] if obj['pattern'] != None else ''
desc = ';'
lines.append(f'{id} {head} {pattern} {desc}')
return lines

View File

@@ -142,3 +142,52 @@ def delete_tank_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_tank(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_tank_cache(name, cs))
class InpTank:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.elevation = float(tokens[1])
self.init_level = float(tokens[2])
self.min_level = float(tokens[3])
self.max_level = float(tokens[4])
self.diameter = float(tokens[5])
self.min_vol = float(tokens[6])
self.vol_curve = str(tokens[7]) if num_without_desc >= 8 else None
self.overflow = str(tokens[8]) if num_without_desc >= 9 else None
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_tank(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpTank(s)
cs.append({'operation': API_ADD, 'type': 'tank', 'id': obj.id, 'elevation': obj.elevation, 'init_level': obj.init_level, 'min_level': obj.min_level, 'max_level': obj.max_level, 'diameter': obj.diameter, 'min_vol': obj.min_vol, 'vol_curve': obj.vol_curve, 'overflow': obj.overflow})
return cs
def inp_out_tank(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from tanks')
for obj in objs:
id = obj['id']
elevation = obj['elevation']
init_level = obj['init_level']
min_level = obj['min_level']
max_level = obj['max_level']
diameter = obj['diameter']
min_vol = obj['min_vol']
vol_curve = obj['vol_curve'] if obj['vol_curve'] != None else ''
overflow = obj['overflow'] if obj['overflow'] != None else ''
desc = ';'
lines.append(f'{id} {elevation} {init_level} {min_level} {max_level} {diameter} {min_vol} {vol_curve} {overflow} {desc}')
return lines

View File

@@ -121,3 +121,51 @@ def delete_pipe_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_pipe(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_pipe_cache(name, cs))
class InpPipe:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.node1 = str(tokens[1])
self.node2 = str(tokens[2])
self.length = float(tokens[3])
self.diameter = float(tokens[4])
self.roughness = float(tokens[5])
self.minor_loss = float(tokens[6])
# status is must-have, here fix input
self.status = str(tokens[7]) if num_without_desc >= 8 else PIPE_STATUS_OPEN
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_pipe(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpPipe(s)
cs.append({'operation': API_ADD, 'type': 'pipe', 'id': obj.id, 'node1': obj.node1, 'node2': obj.node2, 'length': obj.length, 'diameter': obj.diameter, 'roughness': obj.roughness, 'minor_loss': obj.minor_loss, 'status': obj.status})
return cs
def inp_out_pipe(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from pipes')
for obj in objs:
id = obj['id']
node1 = obj['node1']
node2 = obj['node2']
length = obj['length']
diameter = obj['diameter']
roughness = obj['roughness']
minor_loss = obj['minor_loss']
status = obj['vol_curve']
desc = ';'
lines.append(f'{id} {node1} {node2} {length} {diameter} {roughness} {minor_loss} {status} {desc}')
return lines

View File

@@ -112,3 +112,51 @@ def delete_pump_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_pump(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_pump_cache(name, cs))
class InpPump:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.node1 = str(tokens[1])
self.node2 = str(tokens[2])
self.props = {}
for i in range(3, num_without_desc, 2):
self.props |= { tokens[i].lower(): tokens[i + 1] }
self.power = float(self.props['power']) if 'power' in self.props else None
self.head = str(self.props['head']) if 'head' in self.props else None
self.speed = float(self.props['speed']) if 'speed' in self.props else None
self.pattern = str(self.props['pattern']) if 'pattern' in self.props else None
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_pump(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpPump(s)
cs.append({'operation': API_ADD, 'type': 'pump', 'id': obj.id, 'node1': obj.node1, 'node2': obj.node2, 'power': obj.power, 'head': obj.head, 'speed': obj.speed, 'pattern': obj.pattern})
return cs
def inp_out_pump(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from pumps')
for obj in objs:
id = obj['id']
node1 = obj['node1']
node2 = obj['node2']
power = f"POWER {obj['power']}" if obj['power'] != None else ''
head = f"HEAD {obj['head']}" if obj['head'] != None else ''
speed = f"SPEED {obj['speed']}" if obj['speed'] != None else ''
pattern = f"PATTERN {obj['pattern']}" if obj['pattern'] != None else ''
desc = ';'
lines.append(f'{id} {node1} {node2} {power} {head} {speed} {pattern} {desc}')
return lines

View File

@@ -120,3 +120,48 @@ def delete_valve_cache(name: str, cs: ChangeSet) -> SqlChangeSet:
def delete_valve(name: str, cs: ChangeSet) -> ChangeSet:
return execute_command(name, delete_valve_cache(name, cs))
class InpValve:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.id = str(tokens[0])
self.node1 = str(tokens[1])
self.node2 = str(tokens[2])
self.diameter = float(tokens[3])
self.v_type = str(tokens[4])
self.setting = float(tokens[5])
self.minor_loss = float(tokens[6])
self.desc = str(tokens[-1]) if has_desc else None
def inp_in_valve(section: list[str]) -> ChangeSet:
cs = ChangeSet()
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpValve(s)
cs.append({'operation': API_ADD, 'type': 'valve', 'id': obj.id, 'node1': obj.node1, 'node2': obj.node2, 'diameter': obj.diameter, 'v_type': obj.v_type, 'setting': obj.setting, 'minor_loss': obj.minor_loss})
return cs
def inp_out_valve(name: str) -> list[str]:
lines = []
objs = read_all(name, 'select * from valves')
for obj in objs:
id = obj['id']
node1 = obj['node1']
node2 = obj['node2']
diameter = obj['diameter']
v_type = obj['type']
setting = obj['setting']
minor_loss = obj['minor_loss']
desc = ';'
lines.append(f'{id} {node1} {node2} {diameter} {v_type} {setting} {minor_loss} {desc}')
return lines

View File

@@ -84,3 +84,49 @@ def set_demand_cache(name: str, cs: ChangeSet) -> BatchSqlChangeSet:
def set_demand(name: str, cs: ChangeSet) -> ChangeSet:
css = set_demand_cache(name, cs)
return execute_batch(name, css.redo_sql, css.undo_sql, css.redo_cs, css.undo_cs)
class InpDemand:
def __init__(self, line: str) -> None:
tokens = line.split()
num = len(tokens)
has_desc = tokens[-1].startswith(';')
num_without_desc = (num - 1) if has_desc else num
self.junction = str(tokens[0])
self.demand = float(tokens[1])
self.pattern = str(tokens[2]) if num_without_desc >= 3 else None
self.category = str(tokens[3]) if num_without_desc >= 4 else None
def inp_in_demand(section: list[str]) -> ChangeSet:
objs: dict[str, list[InpDemand]] = {}
for s in section:
# skip comment
if s.startswith(';'):
continue
obj = InpDemand(s)
if obj.junction not in objs:
objs[obj.junction] = []
objs[obj.junction].append(obj)
cs = ChangeSet()
for junction, demands in objs.items():
obj_cs = {'operation': API_UPDATE, 'type': 'demand', 'junction' : junction, 'demands' : []}
for obj in demands:
obj_cs['demands'].append({'demand': obj.demand, 'pattern' : obj.pattern, 'category': obj.category})
cs.append(obj_cs)
return cs
def inp_out_demand(name: str) -> list[str]:
lines = []
objs = read_all(name, f"select * from demands order by _order")
for obj in objs:
junction = obj['junction']
demand = obj['demand']
patten = obj['patten'] if obj['patten'] != None else ''
category = f";{obj['category']}" if obj['category'] != None else ';'
lines.append(f'{junction} {demand} {patten} {category}')
return lines