diff --git a/api/__init__.py b/api/__init__.py index 42255a3..511778b 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -52,4 +52,11 @@ from .s16_emitters import get_emitter_schema, get_emitter, set_emitter from .s21_times import TIME_STATISTIC_NONE, TIME_STATISTIC_AVERAGED, TIME_STATISTIC_MINIMUM, TIME_STATISTIC_MAXIMUM, TIME_STATISTIC_RANGE from .s21_times import get_time_schema, get_time, set_time +from .s23_options import OPTION_UNITS_CFS, OPTION_UNITS_GPM, OPTION_UNITS_MGD, OPTION_UNITS_IMGD, OPTION_UNITS_AFD, OPTION_UNITS_LPS, OPTION_UNITS_LPM, OPTION_UNITS_MLD, OPTION_UNITS_CMH, OPTION_UNITS_CMD +from .s23_options import OPTION_HEADLOSS_HW, OPTION_HEADLOSS_DW, OPTION_HEADLOSS_CM +from .s23_options import OPTION_UNBALANCED_STOP, OPTION_UNBALANCED_CONTINUE +from .s23_options import OPTION_DEMAND_MODEL_DDA, OPTION_DEMAND_MODEL_PDA +from .s23_options import OPTION_QUALITY_NONE, OPTION_QUALITY_CHEMICAL, OPTION_QUALITY_AGE, OPTION_QUALITY_TRACE +from .s23_options import get_option_schema, get_option, set_option + from .s24_coordinates import get_node_coord diff --git a/api/command.py b/api/command.py index c293d28..791e147 100644 --- a/api/command.py +++ b/api/command.py @@ -11,6 +11,7 @@ from .s11_patterns import * from .s12_curves import * from .s16_emitters import * from .s21_times import * +from .s23_options import * def execute_add_command(name: str, cs: ChangeSet) -> ChangeSet: @@ -61,6 +62,8 @@ def execute_update_command(name: str, cs: ChangeSet) -> ChangeSet: return set_emitter(name, cs) elif type == 'time': return set_time(name, cs) + elif type == 'option': + return set_option(name, cs) return ChangeSet() diff --git a/api/s22_options.py b/api/s22_options.py deleted file mode 100644 index e69de29..0000000 diff --git a/api/s23_options.py b/api/s23_options.py new file mode 100644 index 0000000..7d04fef --- /dev/null +++ b/api/s23_options.py @@ -0,0 +1,101 @@ +from .operation import * + +OPTION_UNITS_CFS = 'CFS' +OPTION_UNITS_GPM = 'GPM' +OPTION_UNITS_MGD = 'MGD' +OPTION_UNITS_IMGD = 'IMGD' +OPTION_UNITS_AFD = 'AFD' +OPTION_UNITS_LPS = 'LPS' +OPTION_UNITS_LPM = 'LPM' +OPTION_UNITS_MLD = 'MLD' +OPTION_UNITS_CMH = 'CMH' +OPTION_UNITS_CMD = 'CMD' + +OPTION_HEADLOSS_HW = 'H-W' +OPTION_HEADLOSS_DW = 'D-W' +OPTION_HEADLOSS_CM = 'C-M' + +#OPTION_HYDRAULICS_USE = 'USE' +#OPTION_HYDRAULICS_SAVE = 'SAVE' + +OPTION_UNBALANCED_STOP = 'STOP' +OPTION_UNBALANCED_CONTINUE = 'CONTINUE' + +OPTION_DEMAND_MODEL_DDA = 'DDA' +OPTION_DEMAND_MODEL_PDA = 'PDA' + +OPTION_QUALITY_NONE = 'NONE' +OPTION_QUALITY_CHEMICAL = 'CHEMICAL' +OPTION_QUALITY_AGE = 'AGE' +OPTION_QUALITY_TRACE = 'TRACE' + +element_schema = {'type': 'str' , 'optional': True , 'readonly': False} + +def get_option_schema(name: str) -> dict[str, dict[str, Any]]: + return { 'UNITS' : element_schema, + 'HEADLOSS' : element_schema, + #'HYDRAULICS' : element_schema, + 'VISCOSITY' : element_schema, + 'SPECIFIC GRAVITY' : element_schema, + 'TRIALS' : element_schema, + 'ACCURACY' : element_schema, + 'FLOWCHANGE' : element_schema, + 'HEADERROR' : element_schema, + 'CHECKFREQ' : element_schema, + 'MAXCHECK' : element_schema, + 'DAMPLIMIT' : element_schema, + 'UNBALANCED' : element_schema, + 'DEMAND MODEL' : element_schema, + 'MINIMUM PRESSURE' : element_schema, + 'REQUIRED PRESSURE' : element_schema, + 'PRESSURE EXPONENT' : element_schema, + 'PATTERN' : element_schema, + 'DEMAND MULTIPLIER' : element_schema, + 'EMITTER EXPONENT' : element_schema, + 'QUALITY' : element_schema, + 'DIFFUSIVITY' : element_schema, + 'TOLERANCE' : element_schema, + #'QUALITY' : element_schema, + } + + +def get_option(name: str) -> dict[str, Any]: + ts = read_all(name, f"select * from options") + d = {} + for e in ts: + d[e['key']] = str(e['value']) + return d + + +def set_option(name: str, cs: ChangeSet) -> ChangeSet: + raw_old = get_option(name) + + old = {} + new = {} + + new_dict = cs.operations[0] + schema = get_option_schema(name) + for key in schema.keys(): + if key in new_dict: + old[key] = str(raw_old[key]) + new[key] = str(new_dict[key]) + + redo_cs = g_update_prefix | { 'type' : 'option' } + + redo_sql = '' + for key, value in new.items(): + if redo_sql != '': + redo_sql += '\n' + redo_sql += f"update options set value = '{value}' where key = '{key}';" + redo_cs |= { key: value } + + undo_cs = g_update_prefix | { 'type' : 'option' } + + undo_sql = '' + for key, value in old.items(): + if undo_sql != '': + undo_sql += '\n' + undo_sql += f"update options set value = '{value}' where key = '{key}';" + undo_cs |= { key: value } + + return execute_command(name, redo_sql, undo_sql, redo_cs, undo_cs) diff --git a/test_tjnetwork.py b/test_tjnetwork.py index c4f6c0c..c5d4b1a 100644 --- a/test_tjnetwork.py +++ b/test_tjnetwork.py @@ -1596,6 +1596,174 @@ class TestApi: self.leave(p) + def test_option(self): + p = 'test_option' + self.enter(p) + + o = get_option(p) + assert o['UNITS'] == OPTION_UNITS_GPM + assert o['HEADLOSS'] == OPTION_HEADLOSS_HW + assert o['VISCOSITY'] == '1.0' + assert o['SPECIFIC GRAVITY'] == '1.0' + assert o['TRIALS'] == '40' + assert o['ACCURACY'] == '0.001' + assert o['FLOWCHANGE'] == '0' + assert o['HEADERROR'] == '0' + assert o['CHECKFREQ'] == '2' + assert o['MAXCHECK'] == '10' + assert o['DAMPLIMIT'] == '0' + assert o['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert o['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert o['MINIMUM PRESSURE'] == '0' + assert o['REQUIRED PRESSURE'] == '0.1' + assert o['PRESSURE EXPONENT'] == '0.5' + assert o['PATTERN'] == '1' + assert o['DEMAND MULTIPLIER'] == '1.0' + assert o['EMITTER EXPONENT'] == '0.5' + assert o['QUALITY'] == OPTION_QUALITY_NONE + assert o['DIFFUSIVITY'] == '1.0' + assert o['TOLERANCE'] == '0.01' + + o['UNITS'] = OPTION_UNITS_LPS + set_option(p, ChangeSet(o)) + + o = get_option(p) + assert o['UNITS'] == OPTION_UNITS_LPS + assert o['HEADLOSS'] == OPTION_HEADLOSS_HW + assert o['VISCOSITY'] == '1.0' + assert o['SPECIFIC GRAVITY'] == '1.0' + assert o['TRIALS'] == '40' + assert o['ACCURACY'] == '0.001' + assert o['FLOWCHANGE'] == '0' + assert o['HEADERROR'] == '0' + assert o['CHECKFREQ'] == '2' + assert o['MAXCHECK'] == '10' + assert o['DAMPLIMIT'] == '0' + assert o['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert o['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert o['MINIMUM PRESSURE'] == '0' + assert o['REQUIRED PRESSURE'] == '0.1' + assert o['PRESSURE EXPONENT'] == '0.5' + assert o['PATTERN'] == '1' + assert o['DEMAND MULTIPLIER'] == '1.0' + assert o['EMITTER EXPONENT'] == '0.5' + assert o['QUALITY'] == OPTION_QUALITY_NONE + assert o['DIFFUSIVITY'] == '1.0' + assert o['TOLERANCE'] == '0.01' + + self.leave(p) + + + def test_option_op(self): + p = 'test_option_op' + self.enter(p) + + o = get_option(p) + assert o['UNITS'] == OPTION_UNITS_GPM + assert o['HEADLOSS'] == OPTION_HEADLOSS_HW + assert o['VISCOSITY'] == '1.0' + assert o['SPECIFIC GRAVITY'] == '1.0' + assert o['TRIALS'] == '40' + assert o['ACCURACY'] == '0.001' + assert o['FLOWCHANGE'] == '0' + assert o['HEADERROR'] == '0' + assert o['CHECKFREQ'] == '2' + assert o['MAXCHECK'] == '10' + assert o['DAMPLIMIT'] == '0' + assert o['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert o['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert o['MINIMUM PRESSURE'] == '0' + assert o['REQUIRED PRESSURE'] == '0.1' + assert o['PRESSURE EXPONENT'] == '0.5' + assert o['PATTERN'] == '1' + assert o['DEMAND MULTIPLIER'] == '1.0' + assert o['EMITTER EXPONENT'] == '0.5' + assert o['QUALITY'] == OPTION_QUALITY_NONE + assert o['DIFFUSIVITY'] == '1.0' + assert o['TOLERANCE'] == '0.01' + + o['UNITS'] = OPTION_UNITS_LPS + cs = set_option(p, ChangeSet(o)).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'option' + assert cs['UNITS'] == OPTION_UNITS_LPS + assert cs['HEADLOSS'] == OPTION_HEADLOSS_HW + assert cs['VISCOSITY'] == '1.0' + assert cs['SPECIFIC GRAVITY'] == '1.0' + assert cs['TRIALS'] == '40' + assert cs['ACCURACY'] == '0.001' + assert cs['FLOWCHANGE'] == '0' + assert cs['HEADERROR'] == '0' + assert cs['CHECKFREQ'] == '2' + assert cs['MAXCHECK'] == '10' + assert cs['DAMPLIMIT'] == '0' + assert cs['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert cs['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert cs['MINIMUM PRESSURE'] == '0' + assert cs['REQUIRED PRESSURE'] == '0.1' + assert cs['PRESSURE EXPONENT'] == '0.5' + assert cs['PATTERN'] == '1' + assert cs['DEMAND MULTIPLIER'] == '1.0' + assert cs['EMITTER EXPONENT'] == '0.5' + assert cs['QUALITY'] == OPTION_QUALITY_NONE + assert cs['DIFFUSIVITY'] == '1.0' + assert cs['TOLERANCE'] == '0.01' + + cs = execute_undo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'option' + assert cs['UNITS'] == OPTION_UNITS_GPM + assert cs['HEADLOSS'] == OPTION_HEADLOSS_HW + assert cs['VISCOSITY'] == '1.0' + assert cs['SPECIFIC GRAVITY'] == '1.0' + assert cs['TRIALS'] == '40' + assert cs['ACCURACY'] == '0.001' + assert cs['FLOWCHANGE'] == '0' + assert cs['HEADERROR'] == '0' + assert cs['CHECKFREQ'] == '2' + assert cs['MAXCHECK'] == '10' + assert cs['DAMPLIMIT'] == '0' + assert cs['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert cs['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert cs['MINIMUM PRESSURE'] == '0' + assert cs['REQUIRED PRESSURE'] == '0.1' + assert cs['PRESSURE EXPONENT'] == '0.5' + assert cs['PATTERN'] == '1' + assert cs['DEMAND MULTIPLIER'] == '1.0' + assert cs['EMITTER EXPONENT'] == '0.5' + assert cs['QUALITY'] == OPTION_QUALITY_NONE + assert cs['DIFFUSIVITY'] == '1.0' + assert cs['TOLERANCE'] == '0.01' + + cs = execute_redo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'option' + assert cs['UNITS'] == OPTION_UNITS_LPS + assert cs['HEADLOSS'] == OPTION_HEADLOSS_HW + assert cs['VISCOSITY'] == '1.0' + assert cs['SPECIFIC GRAVITY'] == '1.0' + assert cs['TRIALS'] == '40' + assert cs['ACCURACY'] == '0.001' + assert cs['FLOWCHANGE'] == '0' + assert cs['HEADERROR'] == '0' + assert cs['CHECKFREQ'] == '2' + assert cs['MAXCHECK'] == '10' + assert cs['DAMPLIMIT'] == '0' + assert cs['UNBALANCED'] == OPTION_UNBALANCED_STOP + assert cs['DEMAND MODEL'] == OPTION_DEMAND_MODEL_DDA + assert cs['MINIMUM PRESSURE'] == '0' + assert cs['REQUIRED PRESSURE'] == '0.1' + assert cs['PRESSURE EXPONENT'] == '0.5' + assert cs['PATTERN'] == '1' + assert cs['DEMAND MULTIPLIER'] == '1.0' + assert cs['EMITTER EXPONENT'] == '0.5' + assert cs['QUALITY'] == OPTION_QUALITY_NONE + assert cs['DIFFUSIVITY'] == '1.0' + assert cs['TOLERANCE'] == '0.01' + + self.leave(p) + + def test_snapshot(self): p = "test_snapshot" self.enter(p) diff --git a/tjnetwork.py b/tjnetwork.py index 33e7ff7..8c637c6 100644 --- a/tjnetwork.py +++ b/tjnetwork.py @@ -50,6 +50,32 @@ TIME_STATISTIC_MINIMUM = api.TIME_STATISTIC_MINIMUM TIME_STATISTIC_MAXIMUM = api.TIME_STATISTIC_MAXIMUM TIME_STATISTIC_RANGE = api.TIME_STATISTIC_RANGE +OPTION_UNITS_CFS = api.OPTION_UNITS_CFS +OPTION_UNITS_GPM = api.OPTION_UNITS_GPM +OPTION_UNITS_MGD = api.OPTION_UNITS_MGD +OPTION_UNITS_IMGD = api.OPTION_UNITS_IMGD +OPTION_UNITS_AFD = api.OPTION_UNITS_AFD +OPTION_UNITS_LPS = api.OPTION_UNITS_LPS +OPTION_UNITS_LPM = api.OPTION_UNITS_LPM +OPTION_UNITS_MLD = api.OPTION_UNITS_MLD +OPTION_UNITS_CMH = api.OPTION_UNITS_CMH +OPTION_UNITS_CMD = api.OPTION_UNITS_CMD + +OPTION_HEADLOSS_HW = api.OPTION_HEADLOSS_HW +OPTION_HEADLOSS_DW = api.OPTION_HEADLOSS_DW +OPTION_HEADLOSS_CM = api.OPTION_HEADLOSS_CM + +OPTION_UNBALANCED_STOP = api.OPTION_UNBALANCED_STOP +OPTION_UNBALANCED_CONTINUE = api.OPTION_UNBALANCED_CONTINUE + +OPTION_DEMAND_MODEL_DDA = api.OPTION_DEMAND_MODEL_DDA +OPTION_DEMAND_MODEL_PDA = api.OPTION_DEMAND_MODEL_PDA + +OPTION_QUALITY_NONE = api.OPTION_QUALITY_NONE +OPTION_QUALITY_CHEMICAL = api.OPTION_QUALITY_CHEMICAL +OPTION_QUALITY_AGE = api.OPTION_QUALITY_AGE +OPTION_QUALITY_TRACE = api.OPTION_QUALITY_TRACE + ############################################################ # project @@ -387,6 +413,20 @@ def set_time(name: str, cs: ChangeSet) -> ChangeSet: return api.set_time(name, cs) +############################################################ +# option 23.[OPTIONS] +############################################################ + +def get_option_schema(name: str) -> dict[str, dict[str, Any]]: + return api.get_option_schema(name) + +def get_option(name: str) -> dict[str, Any]: + return api.get_option(name) + +def set_option(name: str, cs: ChangeSet) -> ChangeSet: + return api.set_option(name, cs) + + ############################################################ # coord 24.[COORDINATES] ############################################################