diff --git a/api/inp_in.py b/api/inp_in.py index a9ebb0d..2957c94 100644 --- a/api/inp_in.py +++ b/api/inp_in.py @@ -1,7 +1,8 @@ +import datetime +import os from .project import * -from .database import ChangeSet, get_current_operation, set_restore_operation -from .sections import section_name -from .batch_cmds import execute_batch_commands +from .database import ChangeSet, write +from .sections import * from .s1_title import inp_in_title from .s2_junctions import inp_in_junction from .s3_reservoirs import inp_in_reservoir @@ -12,8 +13,8 @@ from .s7_valves import inp_in_valve from .s8_tags import inp_in_tag from .s9_demands import inp_in_demand from .s10_status import inp_in_status -from .s11_patterns import inp_in_pattern -from .s12_curves import inp_in_curve +from .s11_patterns import pattern_v3_types, inp_in_pattern +from .s12_curves import curve_types, inp_in_curve from .s13_controls import inp_in_control from .s14_rules import inp_in_rule from .s15_energy import inp_in_energy @@ -25,220 +26,255 @@ from .s20_mixing import inp_in_mixing from .s21_times import inp_in_time from .s22_report import inp_in_report from .s23_options import inp_in_option +from .s23_options_v3 import inp_in_option_v3 from .s24_coordinates import inp_in_coord from .s25_vertices import inp_in_vertex from .s26_labels import inp_in_label from .s27_backdrop import inp_in_backdrop -#from .s28_end import * + +_S = 'S' +_L = 'L' + +def _inp_in_option(section: list[str], version: str = '3') -> str: + return inp_in_option_v3(section) if version == '3' else inp_in_option(section) + +_handler = { + TITLE : (_S, inp_in_title), + JUNCTIONS : (_L, inp_in_junction), # line, demand_outside + RESERVOIRS : (_L, inp_in_reservoir), + TANKS : (_L, inp_in_tank), + PIPES : (_L, inp_in_pipe), + PUMPS : (_L, inp_in_pump), + VALVES : (_L, inp_in_valve), + TAGS : (_L, inp_in_tag), + DEMANDS : (_L, inp_in_demand), + STATUS : (_L, inp_in_status), + PATTERNS : (_L, inp_in_pattern), # line, fixed + CURVES : (_L, inp_in_curve), + CONTROLS : (_L, inp_in_control), + RULES : (_L, inp_in_rule), + ENERGY : (_L, inp_in_energy), + EMITTERS : (_L, inp_in_emitter), + QUALITY : (_L, inp_in_quality), + SOURCES : (_L, inp_in_source), + REACTIONS : (_L, inp_in_reaction), + MIXING : (_L, inp_in_mixing), + TIMES : (_S, inp_in_time), + REPORT : (_S, inp_in_report), + OPTIONS : (_S, _inp_in_option), # line, version + COORDINATES : (_L, inp_in_coord), + VERTICES : (_L, inp_in_vertex), + LABELS : (_L, inp_in_label), + BACKDROP : (_S, inp_in_backdrop), + #END : 'END', +} + +_level_1 = [ + TITLE, + PATTERNS, + CURVES, + CONTROLS, + RULES, + TIMES, + REPORT, + OPTIONS, + BACKDROP, +] + +_level_2 = [ + JUNCTIONS, + RESERVOIRS, + TANKS, +] + +_level_3 = [ + PIPES, + PUMPS, + VALVES, + DEMANDS, + EMITTERS, + QUALITY, + SOURCES, + MIXING, + COORDINATES, + LABELS, +] + +_level_4 = [ + TAGS, + STATUS, + ENERGY, + REACTIONS, + VERTICES, +] -def _parse_inp(inp: str) -> dict[str, list[str]]: - file: dict[str, list[str]] = {} - for s in section_name: - file[s] = [] +class SQLBatch: + def __init__(self, project: str, count: int = 100) -> None: + self.batch: list[str] = [] + self.project = project + self.count = count - section = '' + def add(self, sql: str) -> None: + self.batch.append(sql) + if len(self.batch) == self.count: + self.flush() - for line in open(inp): - line = line.strip() - if line == '': - # skip empty line for control and rule - if section == 'CONTROLS' or section == 'RULES': - pass - else: - section = '' - continue + def flush(self) -> None: + write(self.project, ''.join(self.batch)) + self.batch.clear() - 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: + +def _print_time(desc: str) -> datetime.datetime: + now = datetime.datetime.now() + time = now.strftime('%Y-%m-%d %H:%M:%S') + print(f"{time}: {desc}") + return now + + +def _get_file_offset(inp: str) -> tuple[dict[str, list[int]], bool]: + offset: dict[str, list[int]] = {} + + current = '' + demand_outside = False + + with open(inp) as f: + while True: + line = f.readline() + if not line: + break + + line = line.strip() + if line.startswith('['): + for s in section_name: + if line.startswith(f'[{s}'): + if s not in offset: + offset[s] = [] + offset[s].append(f.tell()) + current = s + break + elif line != '' and line.startswith(';') == False: + if current == DEMANDS: + demand_outside = True + + return (offset, demand_outside) + + +def parse_file(project: str, inp: str, version: str = '3') -> None: + start = _print_time(f'Start reading file "{inp}"...') + + _print_time("First scan...") + offset, demand_outside = _get_file_offset(inp) + + levels = _level_1 + _level_2 + _level_3 + _level_4 + + # parse the whole section rather than line + sections : dict[str, list[str]]= {} + for [s, t] in _handler.items(): + if t[0] == _S: + sections[s] = [] + + variable_patterns = [] + current_pattern = None + current_curve = None + curve_type_desc_line = None + + sql_batch = SQLBatch(project) + + _print_time("Second scan...") + with open(inp) as f: + for s in levels: + if s not in offset: continue - if section != '': - file[section].append(line) - - return file - - -def _parse_cs(cs: ChangeSet) -> dict[str, list[str]]: - file: dict[str, list[str]] = {} - for s in section_name: - file[s] = [] - - section = '' - - for line in str(cs.operations[0]['inp']).split('\n'): - line = line.strip() - if line == '': - # skip empty line for control and rule - if section == 'CONTROLS' or section == 'RULES': - pass - else: - 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: + if s == DEMANDS and demand_outside == False: continue - if section != '': - file[section].append(line) + _print_time(f"[{s}]") - return file + is_s = _handler[s][0] == _S + handler = _handler[s][1] + for ptr in offset[s]: + f.seek(ptr) -def _read_inp(file: dict[str, list[str]]) -> ChangeSet: - file_cs: dict[str, ChangeSet] = {} - for s in section_name: - file_cs[s] = ChangeSet() + while True: + line = f.readline() + if not line: + break - for name, section in file.items(): - if name == 'TITLE': - file_cs[name].merge(inp_in_title(section)) - - elif name == 'JUNCTIONS': # + coords - file_cs[name].merge(inp_in_junction(section)) - - elif name == 'RESERVOIRS': # + coords - file_cs[name].merge(inp_in_reservoir(section)) - - elif name == 'TANKS': # + coords - file_cs[name].merge(inp_in_tank(section)) - - elif name == 'PIPES': - file_cs[name].merge(inp_in_pipe(section)) - - elif name == 'PUMPS': - file_cs[name].merge(inp_in_pump(section)) - - elif name == 'VALVES': - file_cs[name].merge(inp_in_valve(section)) - - elif name == 'TAGS': - file_cs[name].merge(inp_in_tag(section)) - - elif name == 'DEMANDS': - file_cs[name].merge(inp_in_demand(section)) - - elif name == 'STATUS': - file_cs[name].merge(inp_in_status(section)) - - elif name == 'PATTERNS': - file_cs[name].merge(inp_in_pattern(section)) - - elif name == 'CURVES': - file_cs[name].merge(inp_in_curve(section)) - - elif name == 'CONTROLS': - file_cs[name].merge(inp_in_control(section)) - - elif name == 'RULES': - file_cs[name].merge(inp_in_rule(section)) - - elif name == 'ENERGY': - file_cs[name].merge(inp_in_energy(section)) - - elif name == 'EMITTERS': - file_cs[name].merge(inp_in_emitter(section)) - - elif name == 'QUALITY': - file_cs[name].merge(inp_in_quality(section)) - - elif name == 'SOURCES': - file_cs[name].merge(inp_in_source(section)) - - elif name == 'REACTIONS': - file_cs[name].merge(inp_in_reaction(section)) - - elif name == 'MIXING': - file_cs[name].merge(inp_in_mixing(section)) - - elif name == 'TIMES': - file_cs[name].merge(inp_in_time(section)) - - elif name == 'REPORT': - file_cs[name].merge(inp_in_report(section)) - - elif name == 'OPTIONS': - file_cs[name].merge(inp_in_option(section)) - - elif name == 'COORDINATES': - coords = inp_in_coord(section) - for s in ['JUNCTIONS', 'RESERVOIRS', 'TANKS']: - for node in file_cs[s].operations: - if node['type'] == 'demand': + line = line.strip() + if line.startswith('['): + break + elif line == '': continue - if node['id'] in coords: - coord = coords[node['id']] - node |= { 'x' : coord['x'], 'y' : coord['y'] } + + if is_s: + sections[s].append(line) else: - print(f"WARNING: [{s}] {node['id']} has no coordinate, set it at origin!") - node |= { 'x' : 0.0, 'y' : 0.0 } + if line.startswith(';'): + if version != '3': #v2 + line = line.removeprefix(';') + if s == PATTERNS: # ;desc + pass + elif s == CURVES: # ;type: desc + curve_type_desc_line = line + continue - elif name == 'VERTICES': - file_cs[name].merge(inp_in_vertex(section)) + if s == PATTERNS: + tokens = line.split() - elif name == 'LABELS': - file_cs[name].merge(inp_in_label(section)) + if tokens[1].upper() in pattern_v3_types: #v3 + sql_batch.add(f"insert into _pattern (id) values ('{tokens[0]}');") + current_pattern = tokens[0] + if tokens[1].upper() == 'VARIABLE': + variable_patterns.append(tokens[0]) + continue - elif name == 'BACKDROP': - file_cs[name].merge(inp_in_backdrop(section)) + if current_pattern != tokens[0]: + sql_batch.add(f"insert into _pattern (id) values ('{tokens[0]}');") + current_pattern = tokens[0] - elif name == 'END': - pass # :) + elif s == CURVES: + tokens = line.split() - # release file - file = {} + if tokens[1].upper() in curve_types: #v3 + sql_batch.add(f"insert into _curve (id, type) values ('{tokens[0]}', '{tokens[1].upper()}');") + current_curve = tokens[0] + continue - cs = ChangeSet() - priorities = [ - 'PATTERNS', - 'CURVES', - 'JUNCTIONS', - 'RESERVOIRS', - 'TANKS', - 'COORDINATES', - 'PIPES', - 'PUMPS', - 'VALVES', - 'DEMANDS', - 'STATUS', - 'OPTIONS', - 'TIMES', - 'EMITTERS', - 'QUALITY', - 'SOURCES', - 'REACTIONS', - 'MIXING', - 'ENERGY', - 'REPORT', - 'VERTICES', - 'CONTROLS', - 'RULES', - 'TITLE', - 'TAGS', - 'LABELS', - 'BACKDROP', - 'END', - ] - for s in priorities: - cs.merge(file_cs[s]) + if current_curve != tokens[0]: + type = curve_types[0] + if curve_type_desc_line != None: + type = curve_type_desc_line.split(':')[0].strip() + sql_batch.add(f"insert into _curve (id, type) values ('{tokens[0]}', '{type}');") + current_curve = tokens[0] + curve_type_desc_line = None - return cs + if s == JUNCTIONS: + sql_batch.add(handler(line, demand_outside)) + elif s == PATTERNS: + sql_batch.add(handler(line, current_pattern not in variable_patterns)) + elif s == OPTIONS: + sql_batch.add(handler(line, version)) + else: + sql_batch.add(handler(line)) + + f.seek(0) + + if is_s: + sql_batch.add(handler(sections[s])) + + sql_batch.flush() + + end = _print_time(f'End reading file "{inp}"') + print(f"Total (in second): {(end-start).seconds}(s)") -def read_inp(project: str, inp: str): +def read_inp(project: str, inp: str, version: str = '3') -> bool: + if version != '3' and version != '2': + version = '2' + if is_project_open(project): close_project(project) @@ -248,34 +284,37 @@ def read_inp(project: str, inp: str): create_project(project) open_project(project) - file = _parse_inp(inp) - cs = _read_inp(file) + parse_file(project, inp, version) - execute_batch_commands(project, cs) - op = get_current_operation(project) - set_restore_operation(project, op) + '''try: + parse_file(project, inp, version) + except: + close_project(project) + delete_project(project) + return False''' close_project(project) + return True -def import_inp(project: str, cs: ChangeSet) -> ChangeSet: - if is_project_open(project): - close_project(project) +def import_inp(project: str, cs: ChangeSet, version: str = '3') -> bool: + if version != '3' and version != '2': + version = '2' - if have_project(project): - delete_project(project) + if 'inp' not in cs.operations[0]: + return False - create_project(project) - open_project(project) + filename = f'inp/{project}_temp.inp' + if os.path.exists(filename): + os.remove(filename) - file = _parse_cs(cs) - new_cs = _read_inp(file) + _print_time(f'Start writing temp file "{filename}"...') + with open(filename, 'w') as f: + f.write(str(cs.operations[0]['inp'])) + _print_time(f'End writing temp file "{filename}"...') - success_cs = execute_batch_commands(project, new_cs) - op = get_current_operation(project) - set_restore_operation(project, op) + result = read_inp(project, filename, version) - close_project(project) + os.remove(filename) - # return ? - return success_cs + return result diff --git a/api/inp_out.py b/api/inp_out.py index 015556b..25568ca 100644 --- a/api/inp_out.py +++ b/api/inp_out.py @@ -1,7 +1,7 @@ import os from .project import * from .database import ChangeSet -from .sections import section_name +from .sections import * from .s1_title import inp_out_title from .s2_junctions import inp_out_junction from .s3_reservoirs import inp_out_reservoir @@ -12,8 +12,8 @@ from .s7_valves import inp_out_valve from .s8_tags import inp_out_tag from .s9_demands import inp_out_demand from .s10_status import inp_out_status -from .s11_patterns import inp_out_pattern -from .s12_curves import inp_out_curve +from .s11_patterns import inp_out_pattern, inp_out_pattern_v3 +from .s12_curves import inp_out_curve, inp_out_curve_v3 from .s13_controls import inp_out_control from .s14_rules import inp_out_rule from .s15_energy import inp_out_energy @@ -25,6 +25,7 @@ from .s20_mixing import inp_out_mixing from .s21_times import inp_out_time from .s22_report import inp_out_report from .s23_options import inp_out_option +from .s23_options_v3 import inp_out_option_v3 from .s24_coordinates import inp_out_coord from .s25_vertices import inp_out_vertex from .s26_labels import inp_out_label @@ -32,7 +33,10 @@ from .s27_backdrop import inp_out_backdrop #from .s28_end import * -def dump_inp(project: str, inp: str): +def dump_inp(project: str, inp: str, version: str = '3'): + if version != '3' and version != '2': + version = '2' + if not have_project(project): return @@ -48,93 +52,102 @@ def dump_inp(project: str, inp: str): file = open(path, mode='w') for name in section_name: - if name == 'TITLE': + if name == TITLE: file.write(f'[{name}]\n') else: file.write(f'\n[{name}]\n') - if name == 'TITLE': + if name == TITLE: file.write('\n'.join(inp_out_title(project))) - elif name == 'JUNCTIONS': # + coords + elif name == JUNCTIONS: # + coords file.write('\n'.join(inp_out_junction(project))) - elif name == 'RESERVOIRS': # + coords + elif name == RESERVOIRS: # + coords file.write('\n'.join(inp_out_reservoir(project))) - elif name == 'TANKS': # + coords + elif name == TANKS: # + coords file.write('\n'.join(inp_out_tank(project))) - elif name == 'PIPES': + elif name == PIPES: file.write('\n'.join(inp_out_pipe(project))) - elif name == 'PUMPS': + elif name == PUMPS: file.write('\n'.join(inp_out_pump(project))) - elif name == 'VALVES': + elif name == VALVES: file.write('\n'.join(inp_out_valve(project))) - elif name == 'TAGS': + elif name == TAGS: file.write('\n'.join(inp_out_tag(project))) - elif name == 'DEMANDS': + elif name == DEMANDS: file.write('\n'.join(inp_out_demand(project))) - elif name == 'STATUS': + elif name == STATUS: file.write('\n'.join(inp_out_status(project))) - elif name == 'PATTERNS': - file.write('\n'.join(inp_out_pattern(project))) + elif name == PATTERNS: + if version == '3': + file.write('\n'.join(inp_out_pattern_v3(project))) + else: + file.write('\n'.join(inp_out_pattern(project))) - elif name == 'CURVES': - file.write('\n'.join(inp_out_curve(project))) + elif name == CURVES: + if version == '3': + file.write('\n'.join(inp_out_curve_v3(project))) + else: + file.write('\n'.join(inp_out_curve(project))) - elif name == 'CONTROLS': + elif name == CONTROLS: file.write('\n'.join(inp_out_control(project))) - elif name == 'RULES': + elif name == RULES: file.write('\n'.join(inp_out_rule(project))) - elif name == 'ENERGY': + elif name == ENERGY: file.write('\n'.join(inp_out_energy(project))) - elif name == 'EMITTERS': + elif name == EMITTERS: file.write('\n'.join(inp_out_emitter(project))) - elif name == 'QUALITY': + elif name == QUALITY: file.write('\n'.join(inp_out_quality(project))) - elif name == 'SOURCES': + elif name == SOURCES: file.write('\n'.join(inp_out_source(project))) - elif name == 'REACTIONS': + elif name == REACTIONS: file.write('\n'.join(inp_out_reaction(project))) - elif name == 'MIXING': + elif name == MIXING: file.write('\n'.join(inp_out_mixing(project))) - elif name == 'TIMES': + elif name == TIMES: file.write('\n'.join(inp_out_time(project))) - elif name == 'REPORT': + elif name == REPORT: file.write('\n'.join(inp_out_report(project))) - elif name == 'OPTIONS': - file.write('\n'.join(inp_out_option(project))) + elif name == OPTIONS: + if version == '3': + file.write('\n'.join(inp_out_option_v3(project))) + else: + file.write('\n'.join(inp_out_option(project))) - elif name == 'COORDINATES': + elif name == COORDINATES: file.write('\n'.join(inp_out_coord(project))) - elif name == 'VERTICES': + elif name == VERTICES: file.write('\n'.join(inp_out_vertex(project))) - elif name == 'LABELS': + elif name == LABELS: file.write('\n'.join(inp_out_label(project))) - elif name == 'BACKDROP': + elif name == BACKDROP: file.write('\n'.join(inp_out_backdrop(project))) - elif name == 'END': + elif name == END: pass # :) file.write('\n') @@ -144,7 +157,10 @@ def dump_inp(project: str, inp: str): close_project(project) -def export_inp(project: str) -> ChangeSet: +def export_inp(project: str, version: str = '3') -> ChangeSet: + if version != '3' and version != '2': + version = '2' + if not have_project(project): return ChangeSet() @@ -156,93 +172,102 @@ def export_inp(project: str) -> ChangeSet: inp = '' for name in section_name: - if name == 'TITLE': + if name == TITLE: inp += f'[{name}]\n' else: inp += f'\n[{name}]\n' - if name == 'TITLE': + if name == TITLE: inp += '\n'.join(inp_out_title(project)) - elif name == 'JUNCTIONS': # + coords + elif name == JUNCTIONS: # + coords inp += '\n'.join(inp_out_junction(project)) - elif name == 'RESERVOIRS': # + coords + elif name == RESERVOIRS: # + coords inp += '\n'.join(inp_out_reservoir(project)) - elif name == 'TANKS': # + coords + elif name == TANKS: # + coords inp += '\n'.join(inp_out_tank(project)) - elif name == 'PIPES': + elif name == PIPES: inp += '\n'.join(inp_out_pipe(project)) - elif name == 'PUMPS': + elif name == PUMPS: inp += '\n'.join(inp_out_pump(project)) - elif name == 'VALVES': + elif name == VALVES: inp += '\n'.join(inp_out_valve(project)) - elif name == 'TAGS': + elif name == TAGS: inp += '\n'.join(inp_out_tag(project)) - elif name == 'DEMANDS': + elif name == DEMANDS: inp += '\n'.join(inp_out_demand(project)) - elif name == 'STATUS': + elif name == STATUS: inp += '\n'.join(inp_out_status(project)) - elif name == 'PATTERNS': - inp += '\n'.join(inp_out_pattern(project)) + elif name == PATTERNS: + if version == '3': + inp += '\n'.join(inp_out_pattern_v3(project)) + else: + inp += '\n'.join(inp_out_pattern(project)) - elif name == 'CURVES': - inp += '\n'.join(inp_out_curve(project)) + elif name == CURVES: + if version == '3': + inp += '\n'.join(inp_out_curve_v3(project)) + else: + inp += '\n'.join(inp_out_curve(project)) - elif name == 'CONTROLS': + elif name == CONTROLS: inp += '\n'.join(inp_out_control(project)) - elif name == 'RULES': + elif name == RULES: inp += '\n'.join(inp_out_rule(project)) - elif name == 'ENERGY': + elif name == ENERGY: inp += '\n'.join(inp_out_energy(project)) - elif name == 'EMITTERS': + elif name == EMITTERS: inp += '\n'.join(inp_out_emitter(project)) - elif name == 'QUALITY': + elif name == QUALITY: inp += '\n'.join(inp_out_quality(project)) - elif name == 'SOURCES': + elif name == SOURCES: inp += '\n'.join(inp_out_source(project)) - elif name == 'REACTIONS': + elif name == REACTIONS: inp += '\n'.join(inp_out_reaction(project)) - elif name == 'MIXING': + elif name == MIXING: inp += '\n'.join(inp_out_mixing(project)) - elif name == 'TIMES': + elif name == TIMES: inp += '\n'.join(inp_out_time(project)) - elif name == 'REPORT': + elif name == REPORT: inp += '\n'.join(inp_out_report(project)) - elif name == 'OPTIONS': - inp += '\n'.join(inp_out_option(project)) + elif name == OPTIONS: + if version == '3': + inp += '\n'.join(inp_out_option_v3(project)) + else: + inp += '\n'.join(inp_out_option(project)) - elif name == 'COORDINATES': + elif name == COORDINATES: inp += '\n'.join(inp_out_coord(project)) - elif name == 'VERTICES': + elif name == VERTICES: inp += '\n'.join(inp_out_vertex(project)) - elif name == 'LABELS': + elif name == LABELS: inp += '\n'.join(inp_out_label(project)) - elif name == 'BACKDROP': + elif name == BACKDROP: inp += '\n'.join(inp_out_backdrop(project)) - elif name == 'END': + elif name == END: pass # :) inp += '\n' diff --git a/api/s10_status.py b/api/s10_status.py index 07d1f50..9aa61c4 100644 --- a/api/s10_status.py +++ b/api/s10_status.py @@ -72,45 +72,21 @@ def set_status(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3][IN][OUT] # link value #-------------------------------------------------------------- -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].upper() - 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) +def inp_in_status(line: str) -> str: + tokens = line.split() - cs = ChangeSet() - for link, values in objs.items(): - obj_cs : dict[str, Any] = g_update_prefix | {'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 + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + link = str(tokens[0]) + value = tokens[1].upper() + if value == LINK_STATUS_OPEN or value == LINK_STATUS_CLOSED or value == LINK_STATUS_ACTIVE: + return f"insert into status (link, status, setting) values ('{link}', '{value}', null);" + else: + return f"insert into status (link, status, setting) values ('{link}', null, {float(value)});" def inp_out_status(name: str) -> list[str]: diff --git a/api/s11_patterns.py b/api/s11_patterns.py index f354537..44bee01 100644 --- a/api/s11_patterns.py +++ b/api/s11_patterns.py @@ -1,5 +1,9 @@ from .database import * +PATTERN_V3_TYPE_FIXED = 'FIXED' +PATTERN_V3_TYPE_VARIABLE = 'VARIABLE' + +pattern_v3_types = [PATTERN_V3_TYPE_FIXED, PATTERN_V3_TYPE_VARIABLE] def get_pattern_schema(name: str) -> dict[str, dict[str, Any]]: return { 'id' : {'type': 'str' , 'optional': False , 'readonly': True }, @@ -98,32 +102,25 @@ def delete_pattern(name: str, cs: ChangeSet) -> ChangeSet: # ;desc # id mult1 mult2 ..... #-------------------------------------------------------------- -def inp_in_pattern(section: list[str]) -> ChangeSet: - descs = {} - patterns: dict[str, list[float]] = {} +#-------------------------------------------------------------- +# [EPA3][IN][OUT] +# id FIXED (interval) +# id factor1 factor2 ... +# id VARIABLE +# id time1 factor1 time2 factor2 ... +#-------------------------------------------------------------- - 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]] = [] +def inp_in_pattern(line: str, fixed: bool = True) -> str: + tokens = line.split() + sql = '' + if fixed: for token in tokens[1:]: - patterns[tokens[0]].append(float(token)) - - cs = ChangeSet() - for id, factors in patterns.items(): - cs.append(g_add_prefix | {'type': 'pattern', 'id' : id, 'factors' : factors}) - - #print(descs) - return cs + sql += f"insert into patterns (id, factor) values ('{tokens[0]}', {float(token)});" + else: + for token in tokens[1::2]: + sql += f"insert into patterns (id, factor) values ('{tokens[0]}', {float(token)});" + return sql def inp_out_pattern(name: str) -> list[str]: @@ -136,49 +133,6 @@ def inp_out_pattern(name: str) -> list[str]: return lines -#-------------------------------------------------------------- -# [EPA3][IN][OUT] -# id FIXED (interval) -# id factor1 factor2 ... -# id VARIABLE -# id time1 factor1 time2 factor2 ... -#-------------------------------------------------------------- -def inp_in_pattern_v3(section: list[str]) -> ChangeSet: - patterns: dict[str, list[float]] = {} - - variable_patterns: list[str] = [] - - count = len(section) - for i in range(0, count): - if section[i].startswith(';'): - continue - - tokens = section[i].split() - - # for EPA3, ignore time of variable pattern... - if tokens[1] == 'VARIABLE': - variable_patterns.append(tokens[0]) - continue - elif tokens[1] == 'FIXED': - continue - - if tokens[0] not in patterns: - patterns[tokens[0]] = [] - if tokens[0] not in variable_patterns: - for token in tokens[1:]: - patterns[tokens[0]].append(float(token)) - else: - for token in tokens[1::2]: - patterns[tokens[0]].append(float(token)) - - cs = ChangeSet() - for id, factors in patterns.items(): - cs.append(g_add_prefix | {'type': 'pattern', 'id' : id, 'factors' : factors}) - - #print(descs) - return cs - - def inp_out_pattern_v3(name: str) -> list[str]: lines = [] objs = read_all(name, f"select * from patterns order by _order") diff --git a/api/s12_curves.py b/api/s12_curves.py index 89235cd..34780b0 100644 --- a/api/s12_curves.py +++ b/api/s12_curves.py @@ -5,6 +5,8 @@ CURVE_TYPE_EFFICIENCY = 'EFFICIENCY' CURVE_TYPE_VOLUME = 'VOLUME' CURVE_TYPE_HEADLOSS = 'HEADLOSS' +curve_types = [CURVE_TYPE_PUMP, CURVE_TYPE_EFFICIENCY, CURVE_TYPE_VOLUME, CURVE_TYPE_HEADLOSS] + def get_curve_schema(name: str) -> dict[str, dict[str, Any]]: return { 'id' : {'type': 'str' , 'optional': False , 'readonly': True }, 'c_type' : {'type': 'str' , 'optional': False , 'readonly': False}, @@ -126,37 +128,16 @@ def delete_curve(name: str, cs: ChangeSet) -> ChangeSet: # ;type: desc # id x y #-------------------------------------------------------------- -def inp_in_curve(section: list[str]) -> ChangeSet: - types = {} - descs = {} - curves: dict[str, list[dict[str, float]]] = {} +#-------------------------------------------------------------- +# [EPA3][IN][OUT] +# id type +# id x y +#-------------------------------------------------------------- - count = len(section) - for i in range(0, count): - if section[i].startswith(';'): - # ;type: desc - 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().upper() - 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(g_add_prefix | {'type': 'curve', 'id' : id, 'c_type': c_type, 'coords' : coords}) - - #print(descs) - return cs +def inp_in_curve(line: str) -> str: + tokens = line.split() + return f"insert into curves (id, x, y) values ('{tokens[0]}', {float(tokens[1])}, {float(tokens[2])});" def inp_out_curve(name: str) -> list[str]: @@ -175,40 +156,6 @@ def inp_out_curve(name: str) -> list[str]: return lines -#-------------------------------------------------------------- -# [EPA3][IN][OUT] -# id type -# id x y -#-------------------------------------------------------------- -def inp_in_curve_v3(section: list[str]) -> ChangeSet: - types = {} - curves: dict[str, list[dict[str, float]]] = {} - - count = len(section) - for i in range(0, count): - if section[i].startswith(';'): - continue - - tokens = section[i].split() - - # for EPA3 - if tokens[1] == 'PUMP' or tokens[1] == 'EFFICIENCY' or tokens[1] == 'VOLUME' or tokens[1] == 'HEADLOSS': - types[tokens[0]] = tokens[1] - continue - - 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(g_add_prefix | {'type': 'curve', 'id' : id, 'c_type': c_type, 'coords' : coords}) - - #print(descs) - return cs - - def inp_out_curve_v3(name: str) -> list[str]: lines = [] types = read_all(name, f"select * from _curve") diff --git a/api/s13_controls.py b/api/s13_controls.py index 95832a3..8f50de4 100644 --- a/api/s13_controls.py +++ b/api/s13_controls.py @@ -42,10 +42,10 @@ def set_control(name: str, cs: ChangeSet) -> ChangeSet: # (0) (1) (2) (3) (4) (5) (6) (7) # todo... #-------------------------------------------------------------- -def inp_in_control(section: list[str]) -> ChangeSet: - if len(section) > 0: - return ChangeSet(g_update_prefix | {'type': 'control', 'controls' : section}) - return ChangeSet() + + +def inp_in_control(line: str) -> str: + return f"insert into controls (line) values ('{line}');" def inp_out_control(name: str) -> list[str]: diff --git a/api/s14_rules.py b/api/s14_rules.py index 714c78c..49a47cf 100644 --- a/api/s14_rules.py +++ b/api/s14_rules.py @@ -38,10 +38,10 @@ def set_rule(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3] # TODO... #-------------------------------------------------------------- -def inp_in_rule(section: list[str]) -> ChangeSet: - if len(section) > 0: - return ChangeSet(g_update_prefix | {'type': 'rule', 'rules' : section}) - return ChangeSet() + + +def inp_in_rule(line: str) -> str: + return f"insert into rules (line) values ('{line}');" def inp_out_rule(name: str) -> list[str]: diff --git a/api/s15_energy.py b/api/s15_energy.py index 8b7551c..8bca11b 100644 --- a/api/s15_energy.py +++ b/api/s15_energy.py @@ -137,36 +137,37 @@ def set_pump_energy(name: str, cs: ChangeSet) -> ChangeSet: # PUMP id {PRICE/PATTERN/EFFIC} value # DEMAND CHARGE value #-------------------------------------------------------------- -def inp_in_energy(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - if s.startswith(';'): - continue - tokens = s.strip().split() - - if tokens[0].upper() == 'PUMP': - pump = tokens[1] - key = tokens[2].lower() - value = tokens[3] - if key == 'price': - value = float(value) - cs.append(g_update_prefix | { 'type' : 'pump_energy', 'pump' : pump, key: value }) +def inp_in_energy(line: str) -> str: + tokens = line.split() + if tokens[0].upper() == 'PUMP': + pump = tokens[1] + key = tokens[2].lower() + value = tokens[3] + if key == 'price': + value = float(value) else: - line = s.upper().strip() - for key in get_energy_schema('').keys(): - if line.startswith(key): - value = line.removeprefix(key).strip() + value = f"'{value}'" + if key == 'efficiency': + key = 'effic' - # exception here - if line.startswith('GLOBAL EFFICIENCY'): - value = line.removeprefix('GLOBAL EFFICIENCY').strip() - - cs.append(g_update_prefix | { 'type' : 'energy', key : value }) + return f"insert into energy_pump_{key} (pump, {key}) values ('{pump}', {value});" - return cs + else: + line = line.upper().strip() + for key in get_energy_schema('').keys(): + if line.startswith(key): + value = line.removeprefix(key).strip() + + # exception here + if line.startswith('GLOBAL EFFICIENCY'): + value = line.removeprefix('GLOBAL EFFICIENCY').strip() + + return f"update energy set value = '{value}' where key = '{key}';" + + return '' def inp_out_energy(name: str) -> list[str]: diff --git a/api/s16_emitters.py b/api/s16_emitters.py index 844a3fc..ee88df4 100644 --- a/api/s16_emitters.py +++ b/api/s16_emitters.py @@ -66,27 +66,19 @@ def set_emitter(name: str, cs: ChangeSet) -> ChangeSet: # [EPA3][IN][OUT] # node Ke (exponent pattern) #-------------------------------------------------------------- -class InpEmitter: - 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.coefficient = float(tokens[1]) -def inp_in_emitter(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpEmitter(s) - cs.append(g_update_prefix | {'type': 'emitter', 'junction': obj.junction, 'coefficient': obj.coefficient}) - return cs +def inp_in_emitter(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + junction = str(tokens[0]) + coefficient = float(tokens[1]) + + return f"insert into emitters (junction, coefficient) values ('{junction}', {coefficient});" def inp_out_emitter(name: str) -> list[str]: diff --git a/api/s17_quality.py b/api/s17_quality.py index faf30fe..a524e0c 100644 --- a/api/s17_quality.py +++ b/api/s17_quality.py @@ -63,27 +63,19 @@ def set_quality(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3][IN][OUT] # node initqual #-------------------------------------------------------------- -class InpQuality: - 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.node = str(tokens[0]) - self.quality = float(tokens[1]) -def inp_in_quality(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpQuality(s) - cs.append(g_update_prefix | {'type': 'quality', 'node': obj.node, 'quality': obj.quality}) - return cs +def inp_in_quality(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + node = str(tokens[0]) + quality = float(tokens[1]) + + return f"insert into quality (node, quality) values ('{node}', {quality});" def inp_out_quality(name: str) -> list[str]: diff --git a/api/s18_sources.py b/api/s18_sources.py index 9c1e210..dcc4db9 100644 --- a/api/s18_sources.py +++ b/api/s18_sources.py @@ -106,29 +106,23 @@ def delete_source(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3][IN][OUT] # node sourcetype quality (pattern) #-------------------------------------------------------------- -class InpSource: - 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.node = str(tokens[0]) - self.s_type = str(tokens[1].upper()) - self.strength = float(tokens[2]) - self.pattern = str(tokens[3]) if num_without_desc >= 4 else None -def inp_in_source(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpSource(s) - cs.append(g_add_prefix | {'type': 'source', 'node': obj.node, 's_type': obj.s_type, 'strength': obj.strength, 'pattern': obj.pattern}) - return cs +def inp_in_source(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + node = str(tokens[0]) + s_type = str(tokens[1].upper()) + strength = float(tokens[2]) + pattern = str(tokens[3]) if num_without_desc >= 4 else None + pattern = f"'{pattern}'" if pattern != None else 'null' + + return f"insert into sources (node, type, strength, pattern) values ('{node}', '{s_type}', {strength}, {pattern});" + def inp_out_source(name: str) -> list[str]: diff --git a/api/s19_reactions.py b/api/s19_reactions.py index 5c9117a..19b9c3f 100644 --- a/api/s19_reactions.py +++ b/api/s19_reactions.py @@ -192,34 +192,30 @@ def set_tank_reaction(name: str, cs: ChangeSet) -> ChangeSet: # LIMITING POTENTIAL value # ROUGHNESS CORRELATION value #-------------------------------------------------------------- -def inp_in_reaction(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - if s.startswith(';'): - continue - tokens = s.strip().split() - token0 = tokens[0].upper() - if token0 == 'BULK' or token0 == 'WALL': - pipe = tokens[1] - key = token0.lower() - value = tokens[2] - cs.append(g_update_prefix | { 'type' : 'pipe_reaction', 'pipe' : pipe, key: value }) +def inp_in_reaction(line: str) -> str: + tokens = line.split() + token0 = tokens[0].upper() + if token0 == 'BULK' or token0 == 'WALL': + pipe = tokens[1] + key = token0.lower() + value = tokens[2] + return f"insert into reactions_pipe_{key} (pipe, value) values ('{pipe}', {value});" - elif token0 == 'TANK': - tank = tokens[1] - value = tokens[2] - cs.append(g_update_prefix | { 'type' : 'tank_reaction', 'tank' : tank, 'value': value }) + elif token0 == 'TANK': + tank = tokens[1] + value = tokens[2] + return f"insert into reactions_tank (tank, value) values ('{tank}', {value});" - else: - line = s.upper().strip() - for key in get_reaction_schema('').keys(): - if line.startswith(key): - value = line.removeprefix(key).strip() - cs.append(g_update_prefix | { 'type' : 'reaction', key : value }) + else: + line = line.upper().strip() + for key in get_reaction_schema('').keys(): + if line.startswith(key): + value = line.removeprefix(key).strip() + return f"update reactions set value = '{value}' where key = '{key}';" - return cs + return '' def inp_out_reaction(name: str) -> list[str]: diff --git a/api/s1_title.py b/api/s1_title.py index c650cc9..c897c62 100644 --- a/api/s1_title.py +++ b/api/s1_title.py @@ -27,17 +27,12 @@ def set_title(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, set_title_cmd(name ,cs)) -class InpTitle: - def __init__(self, section) -> None: - self.value = '\n'.join(section) - - -def inp_in_title(section: list[str]) -> ChangeSet: +def inp_in_title(section: list[str]) -> str: if section == []: - return ChangeSet() + return '' - obj = InpTitle(section) - return ChangeSet(g_update_prefix | {'type': 'title', 'value' : obj.value}) + title = '\n'.join(section) + return f"update title set value = '{title}';" def inp_out_title(name: str) -> list[str]: diff --git a/api/s20_mixing.py b/api/s20_mixing.py index 1a9704c..1a43465 100644 --- a/api/s20_mixing.py +++ b/api/s20_mixing.py @@ -101,28 +101,21 @@ def delete_mixing(name: str, cs: ChangeSet) -> ChangeSet: # TankID MixModel FractVolume # FractVolume if type == MIX2 #-------------------------------------------------------------- -class InpMixing: - 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.tank = str(tokens[0]) - self.model = str(tokens[1].upper()) - self.value = float(tokens[3]) if num_without_desc >= 4 else None -def inp_in_mixing(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpMixing(s) - cs.append(g_add_prefix | {'type': 'mixing', 'tank': obj.tank, 'model': obj.model, 'value': obj.value}) - return cs +def inp_in_mixing(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + tank = str(tokens[0]) + model = str(tokens[1].upper()) + value = float(tokens[3]) if num_without_desc >= 4 else None + value = value if value != None else 'null' + + return f"insert into mixing (tank, model, value) values ('{tank}', '{model}', {value});" def inp_out_mixing(name: str) -> list[str]: diff --git a/api/s21_times.py b/api/s21_times.py index 4e74263..590e91d 100644 --- a/api/s21_times.py +++ b/api/s21_times.py @@ -81,20 +81,20 @@ def set_time(name: str, cs: ChangeSet) -> ChangeSet: # START CLOCKTIME value (AM PM) # [EPA3] supports [EPA2] keyword #-------------------------------------------------------------- -def inp_in_time(section: list[str]) -> ChangeSet: - if len(section) > 0: - cs = g_update_prefix | { 'type' : 'time' } - for s in section: - if s.startswith(';'): - continue - - 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) - return ChangeSet() + + +def inp_in_time(section: list[str]) -> str: + sql = '' + for s in section: + if s.startswith(';'): + continue + + line = s.upper().strip() + for key in get_time_schema('').keys(): + if line.startswith(key): + value = line.removeprefix(key).strip() + sql += f"update times set value = '{value}' where key = '{key}';" + return sql def inp_out_time(name: str) -> list[str]: diff --git a/api/s22_report.py b/api/s22_report.py index f396142..02b675b 100644 --- a/api/s22_report.py +++ b/api/s22_report.py @@ -18,8 +18,10 @@ from .database import * # [EPA3][NOT SUPPORT] # TRIALS {YES/NO} #-------------------------------------------------------------- -def inp_in_report(section: list[str]) -> ChangeSet: - return ChangeSet() + + +def inp_in_report(section: list[str]) -> str: + return '' def inp_out_report(name: str) -> list[str]: diff --git a/api/s23_options.py b/api/s23_options.py index 01ec503..6748f76 100644 --- a/api/s23_options.py +++ b/api/s23_options.py @@ -11,7 +11,7 @@ def set_option(name: str, cs: ChangeSet) -> ChangeSet: return execute_batch_command(name, new_cs) -def inp_in_option(section: list[str]) -> ChangeSet: +def _inp_in_option(section: list[str]) -> ChangeSet: if len(section) <= 0: return ChangeSet() @@ -22,9 +22,10 @@ def inp_in_option(section: list[str]) -> ChangeSet: tokens = s.strip().split() if tokens[0].upper() == 'PATTERN': # can not upper id - cs |= { 'PATTERN' : tokens[1] } + value = tokens[1] if len(tokens) > 1 else '' + cs |= { 'PATTERN' : value } elif tokens[0].upper() == 'QUALITY': # can not upper trace node - value = tokens[1] + value = tokens[1] if len(tokens) > 1 else '' if len(tokens) > 2: value += f' {tokens[2]}' cs |= { 'QUALITY' : value } @@ -40,6 +41,20 @@ def inp_in_option(section: list[str]) -> ChangeSet: return result +def inp_in_option(section: list[str]) -> str: + sql = '' + result = _inp_in_option(section) + for op in result.operations: + for key in op.keys(): + if key == 'operation' or key == 'type': + continue + if op['type'] == 'option': + sql += f"update options set value = '{op[key]}' where key = '{key}';" + else: + sql += f"update options_v3 set value = '{op[key]}' where key = '{key}';" + return sql + + def inp_out_option(name: str) -> list[str]: lines = [] objs = read_all(name, f"select * from options") diff --git a/api/s23_options_v3.py b/api/s23_options_v3.py index 65e2691..4e62c88 100644 --- a/api/s23_options_v3.py +++ b/api/s23_options_v3.py @@ -16,7 +16,8 @@ def _parse_v2(v2_lines: list[str]) -> dict[str, str]: for s in v2_lines: tokens = s.split() if tokens[0].upper() == 'PATTERN': # can not upper id - cs_v2 |= { 'PATTERN' : tokens[1] } + value = tokens[1] if len(tokens) > 1 else '' + cs_v2 |= { 'PATTERN' : value } elif tokens[0].upper() == 'QUALITY': # can not upper trace node value = tokens[1] if len(tokens) > 2: @@ -31,7 +32,7 @@ def _parse_v2(v2_lines: list[str]) -> dict[str, str]: return cs_v2 -def inp_in_option_v3(section: list[str]) -> ChangeSet: +def _inp_in_option_v3(section: list[str]) -> ChangeSet: if len(section) <= 0: return ChangeSet() @@ -44,7 +45,11 @@ def inp_in_option_v3(section: list[str]) -> ChangeSet: tokens = s.strip().split() key = tokens[0] if key in get_option_v3_schema('').keys(): - value = tokens[1] if len(tokens) >= 2 else '' + value = '' + if len(tokens) == 2: + value = tokens[1] + elif len(tokens) > 2: + value = ' '.join(tokens[1:]) cs_v3 |= { key : value } else: v2_lines.append(s.strip()) @@ -58,6 +63,20 @@ def inp_in_option_v3(section: list[str]) -> ChangeSet: return result +def inp_in_option_v3(section: list[str]) -> str: + sql = '' + result = _inp_in_option_v3(section) + for op in result.operations: + for key in op.keys(): + if key == 'operation' or key == 'type': + continue + if op['type'] == 'option_v3': + sql += f"update options_v3 set value = '{op[key]}' where key = '{key}';" + else: + sql += f"update options set value = '{op[key]}' where key = '{key}';" + return sql + + def inp_out_option_v3(name: str) -> list[str]: lines = [] objs = read_all(name, f"select * from options_v3") diff --git a/api/s24_coordinates.py b/api/s24_coordinates.py index aa30517..0df02db 100644 --- a/api/s24_coordinates.py +++ b/api/s24_coordinates.py @@ -16,15 +16,13 @@ def get_node_coord(name: str, id: str) -> dict[str, float]: # id x y #-------------------------------------------------------------- # 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_in_coord(line: str) -> str: + tokens = line.split() + node = tokens[0] + coord = f"'({tokens[1]}, {tokens[2]})'" + return f"insert into coordinates (node, coord) values ('{node}', {coord});" def inp_out_coord(name: str) -> list[str]: diff --git a/api/s25_vertices.py b/api/s25_vertices.py index 932de52..96c381c 100644 --- a/api/s25_vertices.py +++ b/api/s25_vertices.py @@ -80,22 +80,14 @@ def delete_vertex(name: str, cs: ChangeSet) -> ChangeSet: # id x y # [EPA3][NOT SUPPORT] #-------------------------------------------------------------- -def inp_in_vertex(section: list[str]) -> ChangeSet: - vertices: dict[str, list[dict[str, float]]] = {} - for s in section: - if s.startswith(';'): - continue - tokens = s.split() - if tokens[0] not in vertices: - vertices[tokens[0]] = [] - vertices[tokens[0]].append({'x': float(tokens[1]), 'y': float(tokens[2])}) - - cs = ChangeSet() - for link, coords in vertices.items(): - cs.append(g_add_prefix | {'type': 'vertex', 'link' : link, 'coords' : coords}) - return cs +def inp_in_vertex(line: str) -> str: + tokens = line.split() + link = tokens[0] + x = float(tokens[1]) + y = float(tokens[2]) + return f"insert into vertices (link, x, y) values ('{link}', {x}, {y});" def inp_out_vertex(name: str) -> list[str]: diff --git a/api/s26_labels.py b/api/s26_labels.py index 172f352..437bc0e 100644 --- a/api/s26_labels.py +++ b/api/s26_labels.py @@ -99,29 +99,20 @@ def delete_label(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, delete_label_cmd(name, cs)) -class InpLabel: - def __init__(self, line: str) -> None: - tokens = line.split() +def inp_in_label(line: str) -> str: + tokens = line.split() - num = len(tokens) - has_desc = tokens[-1].startswith(';') - num_without_desc = (num - 1) if has_desc else num + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num - self.x = float(tokens[0]) - self.y = float(tokens[1]) - self.label = str(tokens[2]) - self.node = str(tokens[3]) if num >= 4 else None + x = float(tokens[0]) + y = float(tokens[1]) + label = str(tokens[2]) + node = str(tokens[3]) if num >= 4 else None + node = f"'{node}'" if node != None else 'null' - -def inp_in_label(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpLabel(s) - cs.append(g_add_prefix | {'type': 'label', 'x': obj.x, 'y': obj.y, 'label': obj.label, 'node': obj.node}) - return cs + return f"insert into labels (x, y, label, node) values ({x}, {y}, '{label}', {node});" def inp_out_label(name: str) -> list[str]: diff --git a/api/s27_backdrop.py b/api/s27_backdrop.py index 030eb81..9766948 100644 --- a/api/s27_backdrop.py +++ b/api/s27_backdrop.py @@ -26,16 +26,12 @@ def set_backdrop(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, set_backdrop_cmd(name, cs)) -class InpBackdrop: - def __init__(self, section) -> None: - self.value = '\n'.join(section) +def inp_in_backdrop(section: list[str]) -> str: + if section == []: + return '' - -def inp_in_backdrop(section: list[str]) -> ChangeSet: - if len(section) > 0: - obj = InpBackdrop(section) - return ChangeSet(g_update_prefix | {'type': 'backdrop', 'content' : obj.value}) - return ChangeSet() + content = '\n'.join(section) + return f"update backdrop set content = '{content}';" def inp_out_backdrop(name: str) -> list[str]: diff --git a/api/s2_junctions.py b/api/s2_junctions.py index 860da1a..68e6a48 100644 --- a/api/s2_junctions.py +++ b/api/s2_junctions.py @@ -125,31 +125,27 @@ def delete_junction(name: str, cs: ChangeSet) -> ChangeSet: # [OUT] # id elev. * * minpressure fullpressure #-------------------------------------------------------------- -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(g_add_prefix | {'type': 'junction', 'id': obj.id, 'elevation': obj.elevation, 'demand': obj.demand, 'pattern': obj.pattern}) - cs.append(g_update_prefix | { 'type': 'demand', 'junction': obj.id, 'demands': [{'demand': obj.demand, 'pattern': obj.pattern, 'category': None}] }) - return cs +def inp_in_junction(line: str, demand_outside: bool) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + elevation = float(tokens[1]) + demand = float(tokens[2]) if num_without_desc >= 3 else None + pattern = str(tokens[3]) if num_without_desc >= 4 else None + pattern = f"'{pattern}'" if pattern != None else 'null' + desc = str(tokens[-1]) if has_desc else None + + sql = f"insert into _node (id, type) values ('{id}', 'junction');insert into junctions (id, elevation) values ('{id}', {elevation});" + if demand != None and demand_outside == False: + sql += f"insert into demands (junction, demand, pattern) values ('{id}', {demand}, {pattern});" + + return sql def inp_out_junction(name: str) -> list[str]: diff --git a/api/s3_reservoirs.py b/api/s3_reservoirs.py index 3a9760a..caf8a53 100644 --- a/api/s3_reservoirs.py +++ b/api/s3_reservoirs.py @@ -120,29 +120,22 @@ def delete_reservoir(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3][IN][OUT] # id elev (pattern) ;desc #-------------------------------------------------------------- -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(g_add_prefix | {'type': 'reservoir', 'id': obj.id, 'head': obj.head, 'pattern': obj.pattern}) - return cs +def inp_in_reservoir(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + head = float(tokens[1]) + pattern = str(tokens[2]) if num_without_desc >= 3 else None + pattern = f"'{pattern}'" if pattern != None else 'null' + desc = str(tokens[-1]) if has_desc else None + + return f"insert into _node (id, type) values ('{id}', 'reservoir');insert into reservoirs (id, head, pattern) values ('{id}', {head}, {pattern});" def inp_out_reservoir(name: str) -> list[str]: diff --git a/api/s4_tanks.py b/api/s4_tanks.py index ad92d8f..688e28a 100644 --- a/api/s4_tanks.py +++ b/api/s4_tanks.py @@ -156,35 +156,29 @@ def delete_tank(name: str, cs: ChangeSet) -> ChangeSet: # [EPA3] # id elev initlevel minlevel maxlevel diam minvol (vcurve) #-------------------------------------------------------------- -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]) if num_without_desc >= 7 else 0.0 - self.vol_curve = str(tokens[7]) if num_without_desc >= 8 and tokens[7] != '*' else None - self.overflow = str(tokens[8].upper()) 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(g_add_prefix | {'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_in_tank(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + elevation = float(tokens[1]) + init_level = float(tokens[2]) + min_level = float(tokens[3]) + max_level = float(tokens[4]) + diameter = float(tokens[5]) + min_vol = float(tokens[6]) if num_without_desc >= 7 else 0.0 + vol_curve = str(tokens[7]) if num_without_desc >= 8 and tokens[7] != '*' else None + vol_curve = f"'{vol_curve}'" if vol_curve != None else 'null' + overflow = str(tokens[8].upper()) if num_without_desc >= 9 else None + overflow = f"'{overflow}'" if overflow != None else 'null' + desc = str(tokens[-1]) if has_desc else None + + return f"insert into _node (id, type) values ('{id}', 'tank');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});" def inp_out_tank(name: str) -> list[str]: diff --git a/api/s5_pipes.py b/api/s5_pipes.py index f7c05b8..e9a40a5 100644 --- a/api/s5_pipes.py +++ b/api/s5_pipes.py @@ -130,35 +130,27 @@ def delete_pipe(name: str, cs: ChangeSet) -> ChangeSet: # [OUT] # id node1 node2 length diam rcoeff lcoeff (status) ;desc #-------------------------------------------------------------- -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].upper()) 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(g_add_prefix | {'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_in_pipe(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + node1 = str(tokens[1]) + node2 = str(tokens[2]) + length = float(tokens[3]) + diameter = float(tokens[4]) + roughness = float(tokens[5]) + minor_loss = float(tokens[6]) + # status is must-have, here fix input + status = str(tokens[7].upper()) if num_without_desc >= 8 else PIPE_STATUS_OPEN + desc = str(tokens[-1]) if has_desc else None + + return f"insert into _link (id, type) values ('{id}', 'pipe');insert into pipes (id, node1, node2, length, diameter, roughness, minor_loss, status) values ('{id}', '{node1}', '{node2}', {length}, {diameter}, {roughness}, {minor_loss}, '{status}');" def inp_out_pipe(name: str) -> list[str]: diff --git a/api/s6_pumps.py b/api/s6_pumps.py index aa2071f..1fb06da 100644 --- a/api/s6_pumps.py +++ b/api/s6_pumps.py @@ -119,36 +119,32 @@ def delete_pump(name: str, cs: ChangeSet) -> ChangeSet: # id node1 node2 KEYWORD value {KEYWORD value ...} ;desc # where KEYWORD = [POWER,HEAD,PATTERN,SPEED] #-------------------------------------------------------------- -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(g_add_prefix | {'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_in_pump(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + node1 = str(tokens[1]) + node2 = str(tokens[2]) + props = {} + for i in range(3, num_without_desc, 2): + props |= { tokens[i].lower(): tokens[i + 1] } + power = float(props['power']) if 'power' in props else None + power = power if power != None else 'null' + head = str(props['head']) if 'head' in props else None + head = f"'{head}'" if head != None else 'null' + speed = float(props['speed']) if 'speed' in props else None + speed = speed if speed != None else 'null' + pattern = str(props['pattern']) if 'pattern' in props else None + pattern = f"'{pattern}'" if pattern != None else 'null' + desc = str(tokens[-1]) if has_desc else None + + return f"insert into _link (id, type) values ('{id}', 'pump');insert into pumps (id, node1, node2, power, head, speed, pattern) values ('{id}', '{node1}', '{node2}', {power}, {head}, {speed}, {pattern});" def inp_out_pump(name: str) -> list[str]: diff --git a/api/s7_valves.py b/api/s7_valves.py index fcd5b72..5ab210b 100644 --- a/api/s7_valves.py +++ b/api/s7_valves.py @@ -128,33 +128,25 @@ def delete_valve(name: str, cs: ChangeSet) -> ChangeSet: # for GPV, setting is string = head curve id # [NOT SUPPORT] for PCV, add loss curve if present #-------------------------------------------------------------- -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].upper()) - self.setting = str(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(g_add_prefix | {'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_in_valve(line: str) -> str: + tokens = line.split() + + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + id = str(tokens[0]) + node1 = str(tokens[1]) + node2 = str(tokens[2]) + diameter = float(tokens[3]) + v_type = str(tokens[4].upper()) + setting = str(tokens[5]) + minor_loss = float(tokens[6]) + desc = str(tokens[-1]) if has_desc else None + + return f"insert into _link (id, type) values ('{id}', 'valve');insert into valves (id, node1, node2, diameter, type, setting, minor_loss) values ('{id}', '{node1}', '{node2}', {diameter}, '{v_type}', '{setting}', {minor_loss});" def inp_out_valve(name: str) -> list[str]: diff --git a/api/s8_tags.py b/api/s8_tags.py index 9dd8a32..8ae4a5d 100644 --- a/api/s8_tags.py +++ b/api/s8_tags.py @@ -79,28 +79,22 @@ def set_tag(name: str, cs: ChangeSet) -> ChangeSet: return execute_command(name, set_tag_cmd(name, cs)) -class InpTag: - def __init__(self, line: str) -> None: - tokens = line.split() +def inp_in_tag(line: str) -> str: + tokens = line.split() - num = len(tokens) - has_desc = tokens[-1].startswith(';') - num_without_desc = (num - 1) if has_desc else num + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num - self.t_type = str(tokens[0].upper()) - self.id = str(tokens[1]) - self.tag = str(tokens[2]) + t_type = str(tokens[0].upper()) + id = str(tokens[1]) + tag = str(tokens[2]) - -def inp_in_tag(section: list[str]) -> ChangeSet: - cs = ChangeSet() - for s in section: - # skip comment - if s.startswith(';'): - continue - obj = InpTag(s) - cs.append(g_update_prefix | {'type': 'tag', 't_type': obj.t_type, 'id': obj.id, 'tag': obj.tag}) - return cs + if t_type == TAG_TYPE_NODE: + return f"insert into tags_node (id, tag) values ('{id}', '{tag}');" + elif t_type == TAG_TYPE_LINK: + return f"insert into tags_link (id, tag) values ('{id}', '{tag}');" + return '' def inp_out_tag(name: str) -> list[str]: diff --git a/api/s9_demands.py b/api/s9_demands.py index 2fedb1e..e1465e4 100644 --- a/api/s9_demands.py +++ b/api/s9_demands.py @@ -63,38 +63,23 @@ def set_demand(name: str, cs: ChangeSet) -> ChangeSet: # [EPA2][EPA3][IN][OUT] # node base_demand (pattern) ;category #-------------------------------------------------------------- -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) +def inp_in_demand(line: str) -> str: + tokens = line.split() - cs = ChangeSet() - for junction, demands in objs.items(): - obj_cs : dict[str, Any] = g_update_prefix | {'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 + num = len(tokens) + has_desc = tokens[-1].startswith(';') + num_without_desc = (num - 1) if has_desc else num + + junction = str(tokens[0]) + demand = float(tokens[1]) + pattern = str(tokens[2]) if num_without_desc >= 3 else None + pattern = f"'{pattern}'" if pattern != None else 'null' + category = str(tokens[3]) if num_without_desc >= 4 else None + category = f"'{category}'" if category != None else 'null' + + return f"insert into demands (junction, demand, pattern, category) values ('{junction}', {demand}, {pattern}, {category});" def inp_out_demand(name: str) -> list[str]: diff --git a/api/sections.py b/api/sections.py index bd0c097..0a9ee75 100644 --- a/api/sections.py +++ b/api/sections.py @@ -34,9 +34,38 @@ s29_scada_device = 'scada_device' s30_scada_device_data = 'scada_device_data' s31_scada_element = 'scada_element' -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'] +TITLE = 'TITLE' +JUNCTIONS = 'JUNCTIONS' +RESERVOIRS = 'RESERVOIRS' +TANKS = 'TANKS' +PIPES = 'PIPES' +PUMPS = 'PUMPS' +VALVES = 'VALVES' +TAGS = 'TAGS' +DEMANDS = 'DEMANDS' +STATUS = 'STATUS' +PATTERNS = 'PATTERNS' +CURVES = 'CURVES' +CONTROLS = 'CONTROLS' +RULES = 'RULES' +ENERGY = 'ENERGY' +EMITTERS = 'EMITTERS' +QUALITY = 'QUALITY' +SOURCES = 'SOURCES' +REACTIONS = 'REACTIONS' +MIXING = 'MIXING' +TIMES = 'TIMES' +REPORT = 'REPORT' +OPTIONS = 'OPTIONS' +COORDINATES = 'COORDINATES' +VERTICES = 'VERTICES' +LABELS = 'LABELS' +BACKDROP = 'BACKDROP' +END = 'END' + +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] diff --git a/build_db.py b/build_db.py index 31f04b1..cb764c0 100644 --- a/build_db.py +++ b/build_db.py @@ -1,14 +1,14 @@ from tjnetwork import * files = [ - #'bwsn', - #'exnet', - #'fengxian', - #'jbh', - #'nanjing', - #'net3', - #'zj', - #'suzhouhe', + 'bwsn', + 'exnet', + 'fengxian', + 'jbh', + 'nanjing', + 'net3', + 'zj', + 'suzhouhe', ] def inp2db(): @@ -20,7 +20,7 @@ def db2inp(): dump_inp(file, f'./db_inp/{file}.db.inp') if __name__ == '__main__': - #inp2db() + inp2db() #db2inp() #print(run_inp('net3')) pass diff --git a/epanet/__init__.py b/epanet/__init__.py index b2473ee..7aedf70 100644 --- a/epanet/__init__.py +++ b/epanet/__init__.py @@ -1 +1 @@ -from .epanet2 import run_project, run_inp, dump_output \ No newline at end of file +from .epanet import run_project, run_inp, dump_output \ No newline at end of file diff --git a/epanet/epanet2.py b/epanet/epanet.py similarity index 92% rename from epanet/epanet2.py rename to epanet/epanet.py index 766cde0..330639e 100644 --- a/epanet/epanet2.py +++ b/epanet/epanet.py @@ -227,17 +227,21 @@ def dump_output(path: str) -> str: return json.dumps(data) -def run_project(name: str) -> str: +def run_project(name: str, version: str = '2') -> str: + if version != '3' and version != '2': + version = '2' + if not project.have_project(name): raise Exception(f'Not found project [{name}]') dir = os.path.abspath(os.getcwd()) db_inp = os.path.join(os.path.join(dir, 'db_inp'), name + '.db.inp') - inp_out.dump_inp(name, db_inp) + inp_out.dump_inp(name, db_inp, version) input = name + '.db' - exe = os.path.join(os.path.join(dir, 'epanet'), 'runepanet.exe') + program = 'runepanet.exe' if version == '2' else 'run-epanet3.exe' + exe = os.path.join(os.path.join(dir, 'epanet'), program) inp = os.path.join(os.path.join(dir, 'db_inp'), input + '.inp') rpt = os.path.join(os.path.join(dir, 'temp'), input + '.rpt') opt = os.path.join(os.path.join(dir, 'temp'), input + '.opt') @@ -250,17 +254,24 @@ def run_project(name: str) -> str: data['simulation_result'] = 'failed' else: data['simulation_result'] = 'successful' - data |= _dump_output(opt) + if version == '2': + data |= _dump_output(opt) + else: + pass # TODO: epanet3 output format? data['report'] = dump_report(rpt) return json.dumps(data) -def run_inp(name: str) -> str: +def run_inp(name: str, version: str = '2') -> str: + if version != '3' and version != '2': + version = '2' + dir = os.path.abspath(os.getcwd()) - exe = os.path.join(os.path.join(dir, 'epanet'), 'runepanet.exe') + program = 'runepanet.exe' if version == '2' else 'run-epanet3.exe' + exe = os.path.join(os.path.join(dir, 'epanet'), program) inp = os.path.join(os.path.join(dir, 'inp'), name + '.inp') rpt = os.path.join(os.path.join(dir, 'temp'), name + '.rpt') opt = os.path.join(os.path.join(dir, 'temp'), name + '.opt') @@ -273,7 +284,10 @@ def run_inp(name: str) -> str: data['simulation_result'] = 'failed' else: data['simulation_result'] = 'successful' - data |= _dump_output(opt) + if version == '2': + data |= _dump_output(opt) + else: + pass # TODO: epanet3 output format? data['report'] = dump_report(rpt) diff --git a/tjnetwork.py b/tjnetwork.py index de55849..b8cd257 100644 --- a/tjnetwork.py +++ b/tjnetwork.py @@ -185,24 +185,24 @@ def close_project(name: str) -> None: def copy_project(source: str, new: str) -> None: return api.copy_project(source, new) -def read_inp(name: str, inp: str) -> None: - return api.read_inp(name, inp) +def read_inp(name: str, inp: str, version: str = '3') -> bool: + return api.read_inp(name, inp, version) -def dump_inp(name: str, inp: str) -> None: - return api.dump_inp(name, inp) +def dump_inp(name: str, inp: str, version: str = '3') -> None: + return api.dump_inp(name, inp, version) -def import_inp(name: str, cs: ChangeSet) -> ChangeSet: - return api.import_inp(name, cs) +def import_inp(name: str, cs: ChangeSet, version: str = '3') -> bool: + return api.import_inp(name, cs, version) -def export_inp(name: str) -> ChangeSet: - return api.export_inp(name) +def export_inp(name: str, version: str = '3') -> ChangeSet: + return api.export_inp(name, version) -def run_project(name: str) -> str: - return epanet.run_project(name) +def run_project(name: str, version: str = '2') -> str: + return epanet.run_project(name, version) # put in inp folder, name without extension -def run_inp(name: str) -> str: - return epanet.run_inp(name) +def run_inp(name: str, version: str = '2') -> str: + return epanet.run_inp(name, version) # path is absolute path def dump_output(path: str) -> str: