diff --git a/modules/systemPerformance/REWET/CMakeLists.txt b/modules/systemPerformance/REWET/CMakeLists.txt index 8acea396f..aba45fc45 100644 --- a/modules/systemPerformance/REWET/CMakeLists.txt +++ b/modules/systemPerformance/REWET/CMakeLists.txt @@ -1,4 +1,3 @@ -add_subdirectory(REWET) simcenter_add_python_script(SCRIPT damage_convertor.py) simcenter_add_python_script(SCRIPT preprocessorIO.py) simcenter_add_python_script(SCRIPT REWET_Wrapper.py) diff --git a/modules/systemPerformance/REWET/REWET/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/CMakeLists.txt deleted file mode 100644 index 8717d9ecd..000000000 --- a/modules/systemPerformance/REWET/REWET/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -add_subdirectory(EnhancedWNTR) -add_subdirectory(Input) -add_subdirectory(Output) -add_subdirectory(restoration) -add_subdirectory(Sim) -simcenter_add_python_script(SCRIPT __init__.py) -simcenter_add_python_script(SCRIPT Damage.py) -simcenter_add_python_script(SCRIPT initial.py) -simcenter_add_python_script(SCRIPT main.py) -simcenter_add_python_script(SCRIPT Project.py) -simcenter_add_python_script(SCRIPT repair.py) -simcenter_add_python_script(SCRIPT Report_Reading.py) -simcenter_add_python_script(SCRIPT Result_Project.py) -simcenter_add_python_script(SCRIPT StochasticModel.py) -simcenter_add_python_script(SCRIPT timeline.py) \ No newline at end of file diff --git a/modules/systemPerformance/REWET/REWET/Damage.py b/modules/systemPerformance/REWET/REWET/Damage.py deleted file mode 100644 index 00e58c304..000000000 --- a/modules/systemPerformance/REWET/REWET/Damage.py +++ /dev/null @@ -1,1197 +0,0 @@ -"""Created on Mon Mar 23 13:54:21 2020 -This module is responsible for calculating damage to t=different componenst of -the system, including pipe lines. pupmo and so. -@author: snaeimi -""" # noqa: N999, D205, D400 - -import logging -import math -import pickle - -import numpy as np -import pandas as pd -import wntrfr -from EnhancedWNTR.morph.link import break_pipe, split_pipe -from scipy.stats import lognorm -from wntrfr.network.model import LinkStatus - -logger = logging.getLogger(__name__) - - -class EarthquakeScenario: # noqa: D101 - def __init__(self, magnitude, depth, x_coord, y_coord, eq_time): - self.M = abs(magnitude) - self.depth = abs(depth) - self.coordinate = {} - self.coordinate['X'] = x_coord - self.coordinate['Y'] = y_coord - self.time = abs(eq_time) - - def getWNTREarthquakeObject(self): # noqa: N802, D102 - return wntrfr.scenario.Earthquake( - (self.coordinate['X'], self.coordinate['Y']), self.M, self.depth - ) - - -class Damage: # noqa: D101 - def __init__(self, registry, scenario_set): - self.scenario_set = scenario_set - self.pipe_leak = pd.Series(dtype='O') - self.pipe_break = pd.Series(dtype='O') - self.pipe_all_damages = None - self.tank_damage = pd.Series(dtype='O') - self.node_damage = pd.Series(dtype='O') - # self._earthquake = pd.Series(dtype="O") - self._registry = registry - self.default_time = 4 - # if damageEndTime==None: - self.end_time = 100 - # else: - # self.end_time=damageEndTime - self.is_timely_sorted = False - - self._pipe_last_ratio = pd.Series(dtype='float64') - self.damaged_pumps = pd.Series(dtype='float64') - self.nodal_equavalant_diameter = None - - # self._nodal_damage_method = None - self._pipe_damage_method = 1 - - def readDamageFromPickleFile( # noqa: N802 - self, - pickle_file_name, - csv_file_name, - csv_index=None, - ): - """This function is only for the sake of reading picke file that nafiseg gives to me - This function shall not be in any distribution that we release - - Parameters - ---------- - pickle_file_name : string - name file of path + name file of the pickle file - csv_file_name : name file of path + name file of the csv file - - Returns - ------- - - """ # noqa: D205, D400, D401, D404, D414, DOC202, RUF100 - with open(pickle_file_name, 'rb') as pckf: # noqa: PTH123 - w = pickle.load(pckf) # noqa: S301 - - name_list = pd.read_csv(csv_file_name, index_col=csv_index) - damage_name_list = [] - damage_mat_list = [] - - for ind, val in w.items(): - if ind[4] == 0 and val == 1: - refr = ind[2] - damage_name_list.append(name_list.index[refr]) - damage_mat_list.append(name_list['material'][refr]) - - damage_list = pd.DataFrame() - damage_list['name'] = damage_name_list - damage_list['material'] = damage_mat_list - damage_state_probability = { - 'STL': [0.2, 0.8], - 'CI': [0.2, 0.8], - 'DI': [0, 1], - 'CON': [0.2, 0.8], - 'RS': [0.2, 0.8], - } - damage_list = self.sampleDamageStatesBasedOnMaterialFragility( - damage_list, damage_state_probability - ) - # return damage_list - self.addPipeDamageByDamageList(damage_list, 1, 0) - - # print(name_list) - - def readPumpDamage(self, file_name): # noqa: N802, D102 - pump_list = pd.read_csv(file_name) - self.damaged_pumps = pump_list['Pump_ID'] - - def readNodalDamage(self, file_address): # noqa: N802, D102 - temp = pd.read_csv(file_address) - for ind, val in temp.iterrows(): # noqa: B007 - temp_data = {} - temp_data['node_name'] = str(val['NodeID']) - temp_data['node_RR'] = val['RR'] - temp_data['node_Pre_EQ_Demand'] = ( - val['Pre_EQ_Demand'] * 6.30901964 / 100000 - ) # *0.5 - temp_data['node_Post_EQ_Demand'] = ( - val['Post_EQ_Demand'] * 6.30901964 / 100000 - ) # *0.5 # * 6.30901964/100000*(1+0.01*val['setNumDamages']) - temp_data['node_Pipe_Length'] = val['PipeLength'] - temp_data['Number_of_damages'] = val['setNumDamages'] - temp_data['node_Customer'] = val['#Customer'] - temp_data['node_LargeUser'] = val['LargeUser'] - - self.node_damage = self.node_damage.append(pd.Series(data=[temp_data])) - - self.node_damage.reset_index(drop=True, inplace=True) # noqa: PD002 - - def setNodalDamageModelParameter(self, damage_param): # noqa: N802, D102 - self._registry.nodal_equavalant_diameter = damage_param - - def readDamageGiraffeFormat(self, break_file_name, leak_file_name): # noqa: N802, D102 - break_temp = pd.read_csv(break_file_name) - leak_temp = pd.read_csv(leak_file_name) - - temp_break_pipe_ID = break_temp['PipeID'] # noqa: N806 - temp_leak_pipe_ID = leak_temp['PipeID'] # noqa: N806 - - if temp_break_pipe_ID.dtype != 'O': - temp_break_pipe_ID = temp_break_pipe_ID.apply(lambda x: str(x)) # noqa: N806 - break_temp['PipeID'] = temp_break_pipe_ID - - if temp_leak_pipe_ID.dtype != 'O': - temp_leak_pipe_ID = temp_leak_pipe_ID.apply(lambda x: str(x)) # noqa: N806 - leak_temp['PipeID'] = temp_leak_pipe_ID - - temp1 = break_temp[['PipeID', 'BreakRatio']] - temp1._is_copy = None # noqa: SLF001 - temp1['damage'] = 'break' - temp1.rename(columns={'BreakRatio': 'ratio'}, inplace=True) # noqa: PD002 - - temp2 = leak_temp[['PipeID', 'LeakRatio']] - temp2._is_copy = None # noqa: SLF001 - temp2.rename(columns={'LeakRatio': 'ratio'}, inplace=True) # noqa: PD002 - temp2['damage'] = 'leak' - - temp = pd.concat([temp1, temp2]) - - temp = temp.sort_values(['PipeID', 'ratio'], ascending=(True, False)) - - unique_pipe_ID = temp['PipeID'].unique().tolist() # noqa: N806 - - for pipe_ID in unique_pipe_ID: # noqa: N806 - selected_damage = temp[temp['PipeID'] == pipe_ID] - - if 'break' in selected_damage['damage'].tolist(): - number = len(selected_damage) - tmp_break = { - 'pipe_id': pipe_ID, - 'break_loc': 0.5, - 'break_time': self.default_time, - 'number': number, - } - self.pipe_break = self.pipe_break.append( - pd.Series( - data=[tmp_break], index=[int(tmp_break['break_time'] * 3600)] - ) - ) - - else: - number = len(selected_damage) - temp_leak_D = pd.Series(data=selected_damage.index) # noqa: N806 - temp_leak_D = temp_leak_D.apply(lambda x: leak_temp.loc[x, 'LeakD']) # noqa: N806 - - leak_D = ((temp_leak_D**2).sum()) ** 0.5 # noqa: N806 - tmp_leak = { - 'pipe_id': pipe_ID, - 'leak_loc': 0.5, - 'leakD': leak_D / 100 * 2.54, - 'leak_type': 1, - 'leak_time': self.default_time, - 'number': number, - } - self.pipe_leak = self.pipe_leak.append( - pd.Series( - data=[tmp_leak], index=[int(tmp_leak['leak_time'] * 3600)] - ) - ) - - def addPipeDamageByDamageList(self, damage_list, leak_type_ref, break_type_ref): # noqa: ARG002, N802, D102 - # leaked_damage = damage_list[damage_list['damage_state']==leak_type_ref] - - for ind, row in damage_list.iterrows(): # noqa: B007 - if row['damage_state'] == 0: # break - tmp_break = { - 'pipe_id': row['name'], - 'break_loc': 0.5, - 'break_time': self.default_time, - } - self.pipe_break = self.pipe_break.append( - pd.Series( - data=[tmp_break], index=[int(tmp_break['break_time'] * 3600)] - ) - ) - elif row.damage_state == 1: # leak - tmp_leak = { - 'pipe_id': row['name'], - 'leak_loc': 0.5, - 'leak_type': 1, - 'leak_time': self.default_time, - } - self.pipe_leak = self.pipe_leak.append( - pd.Series( - data=[tmp_leak], index=[int(tmp_leak['leak_time'] * 3600)] - ) - ) - else: - raise ValueError('There is an unknown damage type') # noqa: EM101, TRY003 - - def readDamageFromTextFile(self, path): # noqa: N802 - """Reads a damage from scenario from a text file and add the information - to the damage class object. - - Parameters - ---------- - [path] : str - The input file name - - """ # noqa: D205, D401 - if path == None: # noqa: E711 - raise ValueError('None in path') # noqa: EM101, TRY003 - file = open(path) # noqa: SIM115, PTH123 - lines = file.readlines() - line_cnt = 0 - for line in lines: - line_cnt += 1 # noqa: SIM113 - sline = line.split() - line_length = len(sline) - - if sline[0].lower() == 'leak': - # print(len(sline)) - temp_leak = {} - if line_length < 4: # noqa: PLR2004 - raise OSError( - 'There must be at least 4 arguments in line' + repr(line_cnt) - ) - # print('Probelm 1') - temp_leak['pipe_id'] = sline[1] - temp_leak['leak_loc'] = float(sline[2]) - temp_leak['leak_type'] = int(sline[3]) - if line_length > 4: # noqa: PLR2004 - temp_leak['leak_time'] = float(sline[4]) - else: - temp_leak['leak_time'] = self.default_time - self.pipe_leak = self.pipe_leak.append( - pd.Series( - data=[temp_leak], index=[int(temp_leak['leak_time'] * 3600)] - ) - ) - - elif sline[0].lower() == 'break': - if line_length < 3: # noqa: PLR2004 - raise OSError('Line cannot have more than three arguments') # noqa: EM101, TRY003 - # print('Probelm 2') - temp_break = {} - temp_break['pipe_id'] = sline[1] - temp_break['break_loc'] = float(sline[2]) - if line_length > 3: # noqa: PLR2004 - temp_break['break_time'] = float(sline[3]) - else: - temp_break['break_time'] = self.default_time - # print( type(temp_break['break_time'])) - self.pipe_break = self.pipe_break.append( - pd.Series( - data=[temp_break], - index=[int(temp_break['break_time'] * 3600)], - ) - ) - else: - logger.warning(sline) - logger.warning( - 'No recogniziable command in damage file, line' # noqa: G003 - + repr(line_cnt) - + '\n' - ) - file.close() - - def applyNodalDamage(self, WaterNetwork, current_time): # noqa: C901, N802, N803 - """Apply Nodal Damage - - Parameters - ---------- - WaterNetwork : Water Network Model - DESCRIPTION. - - Returns - ------- - None. - - """ # noqa: D400, DOC202, RUF100 - if self.node_damage.empty: - print('no node damage at all') # noqa: T201 - return - - curren_time_node_damage = self.node_damage[current_time] - - if type(curren_time_node_damage) == dict: # noqa: E721 - curren_time_node_damage = pd.Series( - [curren_time_node_damage], index=[current_time] - ) - elif type(curren_time_node_damage) == pd.Series: # noqa: E721 - if curren_time_node_damage.empty: - print('No node damage at time ' + str(current_time)) # noqa: T201 - return - else: - raise ValueError( - 'Node damage has a unknown type: ' - + str(type(curren_time_node_damage)) - + ' at time: ' - + str(current_time) - ) - - # self._nodal_damage_method = self._registry.settings['damage_node_model'] - method = self._registry.settings['damage_node_model'] - if method == 'Predefined_demand': - for ind, val in curren_time_node_damage.items(): # noqa: B007, PERF102 - node_name = val['node_name'] - pre_EQ_Demand = val['node_Pre_EQ_Demand'] # noqa: N806 - post_EQ_Demand = val['node_Post_EQ_Demand'] # noqa: N806 - - # if node_name not in WaterNetwork.node_name_list and icheck==True: - # raise ValueError('Node in damage list is not in water network model: '+repr(node_name)) - # elif icheck==False: - # continue - node_cur_dem = ( - WaterNetwork.get_node(node_name) # noqa: SLF001 - .demand_timeseries_list._list[0] - .base_value - ) - # print(str(pre_EQ_Demand) + ' ' + str(node_cur_dem)) - # print(node_name) - if abs(pre_EQ_Demand - node_cur_dem) > 0.001: # noqa: PLR2004 - raise # noqa: PLE0704 - - ratio = post_EQ_Demand / pre_EQ_Demand - - WaterNetwork.get_node(node_name).demand_timeseries_list._list[ # noqa: SLF001 - 0 - ].base_value = node_cur_dem * ratio - - self._registry.addNodalDemandChange( - val['node_name'], node_cur_dem, post_EQ_Demand - ) - demand_damage = self.estimateNodalDamage() - self._registry.addNodalDamage(demand_damage) - - elif ( - method == 'equal_diameter_emitter' # noqa: PLR1714 - or method == 'equal_diameter_reservoir' - ): - temp1 = [] - temp2 = [] - temp_new_explicit_leak_data = [] - for ind, val in curren_time_node_damage.items(): # noqa: B007, PERF102 - node_name = val['node_name'] - number_of_damages = val['Number_of_damages'] - pipe_length = val['node_Pipe_Length'] * 1000 - - if node_name not in WaterNetwork.node_name_list: - raise ValueError( - 'Node name of damages not in node name list: ' + node_name - ) - - new_node_name, new_pipe_name, mp, q = ( - self.addExplicitLeakWithReservoir( - node_name, number_of_damages, pipe_length, WaterNetwork - ) - ) - # self._registry.nodal_damage_nodes.add(new_node_name) - # post_EQ_Demand = val['node_Post_EQ_Demand'] - # pre_EQ_Demand = val['node_Pre_EQ_Demand'] - # self._registry.addNodalDemandChange(val['node_name'], pre_EQ_Demand, post_EQ_Demand) - temp1.append(node_name) - temp2.append(val['Number_of_damages']) - - self._registry.active_nodal_damages.update( - {new_node_name: node_name} - ) - temp_data = { - 'mean_pressure': mp, - 'new_pipe_name': new_pipe_name, - 'new_node_name': new_node_name, - 'pipe_length': pipe_length, - 'orginal_flow': q, - } - temp_new_explicit_leak_data.append(temp_data) - - demand_damage = pd.Series(data=temp2, index=temp1) - new_pipe_name_list = dict(zip(temp1, temp_new_explicit_leak_data)) - self._registry.addNodalDamage(demand_damage, new_pipe_name_list) - elif method == 'SDD': - for ind, val in curren_time_node_damage.items(): # noqa: B007, PERF102 - node_name = val['node_name'] - number_of_damages = val['Number_of_damages'] - pipe_length = val['node_Pipe_Length'] * 1000 - if node_name not in WaterNetwork.node_name_list: - raise ValueError( - 'Node name of damages not in node name list: ' + node_name - ) - maximum_node_demand = 10 - pipe_equal_length = pipe_length / 10 - _hl = 8 - _C = 100 # noqa: N806 - before_damage_pipe_length = pipe_equal_length / 2 - over_designed_diameter = ( - 10.67 * (maximum_node_demand / _C) ** 1.852 * (pipe_length / _hl) - ) - over_designed_diameter = over_designed_diameter ** (1 / 4.8704) - - equavalant_damaged_pipe_diameter = self.scenario_set[ - 'equavalant_damage_diameter' - ] - equavalant_pipe_diameter = ( - np.sqrt(number_of_damages) * equavalant_damaged_pipe_diameter - ) - - node = WaterNetwork.get_node(node_name) - new_elavation = node.elevation - - # Midlle junction definition - new_coord = (node.coordinates[0] + 10, node.coordinates[1] + 10) - middle_node_name = 'lk_mdl_' + node_name - WaterNetwork.add_junction( - middle_node_name, elevation=new_elavation, coordinates=new_coord - ) - - # Leak reservoir definition - new_coord = (new_coord[0] + 10, new_coord[1] + 10) - new_resevoir_name = 'lk_aux_' + node_name - WaterNetwork.add_reservoir( - new_resevoir_name, base_head=new_elavation, coordinates=new_coord - ) - - # Node-to-middle-junction pipe definition - OVD_pipe_name = 'lk_ODP_' + node_name # noqa: N806 - WaterNetwork.add_pipe( - OVD_pipe_name, - node_name, - middle_node_name, - length=before_damage_pipe_length, - diameter=over_designed_diameter, - roughness=_C, - ) - - # Middle_node_to_reservoir pipe definition - new_pipe_name = 'lk_pipe_' + node_name - WaterNetwork.add_pipe( - new_pipe_name, - middle_node_name, - new_resevoir_name, - length=1, - diameter=equavalant_pipe_diameter, - roughness=1000000, - ) - - self._registry.explicit_nodal_damages[node_name] = { - 'ODD', - over_designed_diameter, - } - else: - raise ValueError('Unknown nodal damage method') # noqa: EM101, TRY003 - - # return WaterNetwork - - def getNd(self, mp, number_of_damages, sum_of_length): # noqa: N802, D102 - rr = number_of_damages / sum_of_length * 1000 - - node_damage_parametrs = self._registry.settings['node_damage_model'] - # {'a':0.0036, 'aa':1, 'b':0, 'bb':0, 'c':-0.877, 'cc':1, 'd':0, 'dd':0, 'e':0.0248, 'ee1':1, 'ee2':1, 'f':0, 'ff1':0, 'ff2':0, "damage_node_model": "equal_diameter_emitter"} - x = node_damage_parametrs['x'] - a = node_damage_parametrs['a'] - aa = node_damage_parametrs['aa'] - b = node_damage_parametrs['b'] - bb = node_damage_parametrs['bb'] - c = node_damage_parametrs['c'] - cc = node_damage_parametrs['cc'] - d = node_damage_parametrs['d'] - dd = node_damage_parametrs['dd'] - e = node_damage_parametrs['e'] - ee1 = node_damage_parametrs['ee1'] - ee2 = node_damage_parametrs['ee2'] - f = node_damage_parametrs['f'] - ff1 = node_damage_parametrs['ff1'] - ff2 = node_damage_parametrs['ff2'] - - # nd = 0.0036*mp + 0.9012 + (0.0248*mp-0.877)*rr - nd = ( - a * mp**aa - + b * mp**bb - + c * rr**cc - + d * rr**dd - + e * (mp**ee1) * (rr**ee2) - + f * (mp**ff1) * (rr**ff2) - + x - ) - nd = 0.0036 * float(mp) + 0.9012 + (0.0248 * float(mp) - 0.877) * float(rr) - return nd # noqa: RET504 - - def getNd2(self, mp, number_of_damages, sum_of_length): # noqa: N802, D102 - rr = number_of_damages / sum_of_length * 1000 - - node_damage_parametrs = self._registry.settings['node_damage_model'] - # {'a':0.0036, 'aa':1, 'b':0, 'bb':0, 'c':-0.877, 'cc':1, 'd':0, 'dd':0, 'e':0.0248, 'ee1':1, 'ee2':1, 'f':0, 'ff1':0, 'ff2':0, "damage_node_model": "equal_diameter_emitter"} - x = node_damage_parametrs['x'] - a = node_damage_parametrs['a'] - aa = node_damage_parametrs['aa'] - b = node_damage_parametrs['b'] - bb = node_damage_parametrs['bb'] - c = node_damage_parametrs['c'] - cc = node_damage_parametrs['cc'] - d = node_damage_parametrs['d'] - dd = node_damage_parametrs['dd'] - e = node_damage_parametrs['e'] - ee1 = node_damage_parametrs['ee1'] - ee2 = node_damage_parametrs['ee2'] - f = node_damage_parametrs['f'] - ff1 = node_damage_parametrs['ff1'] - ff2 = node_damage_parametrs['ff2'] - - nd = ( - a * mp**aa - + b * mp**bb - + c * rr**cc - + d * rr**dd - + e * (mp**ee1) * (rr**ee2) - + f * (mp**ff1) * (rr**ff2) - + x - ) - - return nd # noqa: RET504 - - def getEmitterCdAndElevation( # noqa: N802, D102 - self, - real_node_name, - wn, - number_of_damages, - sum_of_length, - mp, - q, - ): - mp = mp * 1.4223 # this is because our CURRENT relationship is base on psi - rr = number_of_damages / sum_of_length * 1000 # noqa: F841 - nd = self.getNd(mp, number_of_damages, sum_of_length) - # equavalant_pipe_diameter = ( ((nd-1)*q)**2 /(0.125*9.81*3.14**2 * mp/1.4223) )**(1/4) * 1 - - if real_node_name == 'CC1381': - print(nd) # noqa: T201 - nd2 = self.getNd2(mp, number_of_damages, sum_of_length) - print(nd2) # noqa: T201 - - node = wn.get_node(real_node_name) # noqa: F841 - # new_elavation = node.elevation - - nd = nd - 1 - # nd0 = 0.0036*0 + 0.9012 + (0.0248*0-0.877)*rr - nd0 = self.getNd(0, number_of_damages, sum_of_length) - if real_node_name == 'CC1381': - print(nd0) # noqa: T201 - nd02 = self.getNd2(0, number_of_damages, sum_of_length) - print(nd02) # noqa: T201 - nd0 = nd0 - 1 - alpha = (nd - nd0) / (mp) - mp0 = -1 * (nd0) / alpha - mp0 = mp0 / 1.4223 - cd = alpha * q - return cd, mp0 - - def addExplicitLeakWithReservoir( # noqa: N802, D102 - self, - node_name, - number_of_damages, - sum_of_length, - wn, - ): - method = self._registry.settings['damage_node_model'] - if ( - method == 'equal_diameter_emitter' # noqa: PLR1714 - or method == 'equal_diameter_reservoir' - ): - node = wn.get_node(node_name) - new_elavation = node.elevation - new_coord = (node.coordinates[0] + 10, node.coordinates[1] + 10) - - pressure = self._registry.result.node['pressure'][node_name] - mp = pressure.mean() - - if mp < 0: - mp = 1 - node = wn.get_node(node_name) - new_elavation = node.elevation - new_coord = (node.coordinates[0] + 10, node.coordinates[1] + 10) - - new_node_name = 'lk_aux_' + node_name - new_pipe_name = 'lk_pipe_' + node_name - new_C = 100000000000 # noqa: N806 - - equavalant_pipe_diameter = 1 - q = node.demand_timeseries_list[0].base_value - if method == 'equal_diameter_emitter': - cd, mp0 = self.getEmitterCdAndElevation( - node_name, wn, number_of_damages, sum_of_length, mp, q - ) - wn.add_junction( - new_node_name, - elevation=new_elavation + mp0, - coordinates=new_coord, - ) - nn = wn.get_node(new_node_name) - nn._emitter_coefficient = cd # noqa: SLF001 - wn.options.hydraulic.emitter_exponent = 1 - wn.add_pipe( - new_pipe_name, - node_name, - new_node_name, - diameter=equavalant_pipe_diameter, - length=1, - roughness=new_C, - check_valve=True, - ) - # wn.add_reservoir(new_node_name+'_res', base_head = new_elavation + 10000, coordinates = new_coord) - # wn.add_pipe(new_pipe_name+'_res', node_name, new_node_name+'_res', diameter=1, length=1, roughness=new_C, check_valve_flag=True) - - elif method == 'equal_diameter_reservoir': - nd = self.getNd(mp, number_of_damages, sum_of_length) - equavalant_pipe_diameter = ( - ((nd - 1) * q) ** 2 / (0.125 * 9.81 * math.pi**2 * mp) - ) ** (1 / 4) * 1 - wn.add_reservoir( - new_node_name, base_head=new_elavation, coordinates=new_coord - ) - wn.add_pipe( - new_pipe_name, - node_name, - new_node_name, - diameter=equavalant_pipe_diameter, - length=1, - roughness=new_C, - check_valve=True, - minor_loss=1, - ) - self._registry.addEquavalantDamageHistory( - node_name, - new_node_name, - new_pipe_name, - equavalant_pipe_diameter, - number_of_damages, - ) - - elif method == 'SOD': - pass - # first_pipe_length = sum_of_length/5*2 - # second_pipe_length = sum_of_length/5*3 - # new_coord_mid = (node.xxcoordinates[0]+10,node.coordinates[1]+10) - # new_coord_dem = (node.coordinates[0]+20,node.coordinates[1]+20) - # new_coord_res = (node.coordinates[0]+10,node.coordinates[1]+20) - - else: - raise ValueError('Unkown Method') # noqa: EM101, TRY003 - return new_node_name, new_pipe_name, mp, q - - def estimateNodalDamage(self): # noqa: N802, D102 - # res = pd.Series() - temp1 = [] - temp2 = [] - for ind, val in self.node_damage.items(): # noqa: B007, PERF102 - pipes_length = val['node_Pipe_Length'] - pipes_RR = val['node_RR'] # noqa: N806 - temp1.append(val['node_name']) - temp2.append(int(np.round(pipes_RR * pipes_length))) - res = pd.Series(data=temp2, index=temp1) - return res # noqa: RET504 - - def getPipeDamageListAt(self, time): # noqa: N802, D102 - damaged_pipe_name_list = [] - - if self.pipe_all_damages.empty: - return damaged_pipe_name_list - - current_time_pipe_damages = self.pipe_all_damages[time] - if type(current_time_pipe_damages) == pd.core.series.Series: # noqa: E721 - current_time_pipe_damages = current_time_pipe_damages.to_list() - else: - current_time_pipe_damages = [current_time_pipe_damages] - - damaged_pipe_name_list = [ - cur_damage['pipe_id'] for cur_damage in current_time_pipe_damages - ] - damaged_pipe_name_list = list(set(damaged_pipe_name_list)) - return damaged_pipe_name_list # noqa: RET504 - - def applyPipeDamages(self, WaterNetwork, current_time): # noqa: C901, N802, N803 - """Apply the damage that we have in damage object. the damage is either - predicted or read from somewhere. - - Parameters - ---------- - WaterNetwork : wntrfr.network.model.WaterNetworkModel - water network model to be modified according to the damage - - registry : Registry object - - current_time : int - current time - - """ # noqa: D205 - last_pipe_id = None - same_pipe_damage_cnt = None - - if self.pipe_all_damages.empty: - print('No Pipe damages at all') # noqa: T201 - return - - current_time_pipe_damages = self.pipe_all_damages[current_time] - if type(current_time_pipe_damages) == dict: # noqa: E721 - current_time_pipe_damages = pd.Series( - [current_time_pipe_damages], index=[current_time] - ) - elif type(current_time_pipe_damages) == pd.Series: # noqa: E721 - if current_time_pipe_damages.empty: - print('No Pipe damages at time ' + str(current_time)) # noqa: T201 - return - else: - raise ValueError( - 'Pipe damage has a unknown type: ' - + str(type(current_time_pipe_damages)) - + ' at time: ' - + str(current_time) - ) - - all_damages = current_time_pipe_damages.to_list() - for cur_damage in all_damages: - # print(cur_damage) - - pipe_id = cur_damage['pipe_id'] - # same_pipe_damage_cnt = 1 - if pipe_id == last_pipe_id: - same_pipe_damage_cnt += 1 - else: - last_pipe_id = pipe_id - same_pipe_damage_cnt = 1 - - if cur_damage['type'] == 'leak': - damage_time = current_time / 3600 # cur_damage['damage_time'] - new_node_id = pipe_id + '_leak_' + repr(same_pipe_damage_cnt) - new_pipe_id = pipe_id + '_leak_B_' + repr(same_pipe_damage_cnt) - material = cur_damage['Material'] - area = None - if 'leakD' in cur_damage: - diam = cur_damage['leakD'] - area = math.pi * (diam / 2) ** 2 - else: - # diam = 100*WaterNetwork.get_link(pipe_id).diameter - # area= 0.6032*diam/10000 - # pipe_damage_factor = self.scenario_set['pipe_damage_diameter_factor'] - diam_m = WaterNetwork.get_link(pipe_id).diameter - - # print(material) - if material in self._registry.settings['pipe_damage_model']: - damage_parameters = self._registry.settings[ - 'pipe_damage_model' - ][material] - else: - damage_parameters = self._registry.settings[ - 'default_pipe_damage_model' - ] - alpha = damage_parameters['alpha'] - beta = damage_parameters['beta'] - gamma = damage_parameters['gamma'] - a = damage_parameters['a'] - b = damage_parameters['b'] - - dd = alpha * diam_m**a + beta * diam_m**b + gamma - dd = dd * 1.2 - - area = math.pi * dd**2 / 4 - last_ratio = 1 - if pipe_id in self._pipe_last_ratio: - last_ratio = self._pipe_last_ratio.loc[pipe_id] - - ratio = cur_damage['damage_loc'] / last_ratio - if ratio >= 1: - raise ValueError( - 'IN LEAK: ratio is bigger than or equal to 1 for pipe:' - + repr(pipe_id) - + ' ' - + repr(ratio) - + ' ' - + repr(cur_damage['damage_loc']) - + ' ' - + repr(last_ratio) - ) - self._pipe_last_ratio.loc[pipe_id] = ratio - - number = 1 - if 'number' in cur_damage: - number = cur_damage['number'] - - sub_type = 1 - if 'sub_type' in cur_damage: - sub_type = cur_damage['sub_type'] - - WaterNetwork = split_pipe( # noqa: N806 - WaterNetwork, - pipe_id, - new_pipe_id, - new_node_id, - split_at_point=ratio, - return_copy=False, - ) - leak_node = WaterNetwork.get_node(new_node_id) - leak_node.add_leak( - WaterNetwork, - area=area, - discharge_coeff=1, - start_time=damage_time, - end_time=self.end_time + 1, - ) - self._registry.addPipeDamageToRegistry( - new_node_id, - { - 'number': number, - 'damage_type': 'leak', - 'damage_subtype': sub_type, - 'pipe_A': pipe_id, - 'pipe_B': new_pipe_id, - 'orginal_pipe': pipe_id, - }, - ) - # self._registry.addPipeDamageToDamageRestorationData(pipe_id, 'leak', damage_time) - - elif cur_damage['type'] == 'break': - last_ratio = 1 - if pipe_id in self._pipe_last_ratio: - last_ratio = self._pipe_last_ratio.loc[pipe_id] - - ratio = cur_damage['damage_loc'] / last_ratio - if ratio >= 1: - raise ValueError( - 'IN BREAK: ratio is bigger than or equal to 1 for pipe:' - + repr(pipe_id) - + ' ' - + repr(ratio) - + ' ' - + repr(cur_damage['damage_loc']) - + ' ' - + repr(last_ratio) - ) - - self._pipe_last_ratio.loc[pipe_id] = ratio - - number = 1 - if 'number' in cur_damage: - number = cur_damage['number'] - - damage_time = current_time / 3600 - logger.debug( - 'trying to break: ' + cur_damage['pipe_id'] + repr(damage_time) # noqa: G003 - ) - # Naming new nodes and new pipe - new_node_id_for_old_pipe = ( - pipe_id + '_breakA_' + repr(same_pipe_damage_cnt) - ) - new_node_id_for_new_pipe = ( - pipe_id + '_breakB_' + repr(same_pipe_damage_cnt) - ) - new_pipe_id = pipe_id + '_Break_' + repr(same_pipe_damage_cnt) - new_node_id = new_node_id_for_old_pipe - # breaking the node - WaterNetwork = break_pipe( # noqa: N806 - WaterNetwork, - pipe_id, - new_pipe_id, - new_node_id_for_old_pipe, - new_node_id_for_new_pipe, - split_at_point=ratio, - return_copy=False, - ) - - diam = WaterNetwork.get_link(pipe_id).diameter - area = (diam**2) * math.pi / 4 - break_node_for_old_pipe = WaterNetwork.get_node( - new_node_id_for_old_pipe - ) - break_node_for_old_pipe.add_leak( - WaterNetwork, - area=area, - discharge_coeff=1, - start_time=float(damage_time), - end_time=self.end_time + 0.1, - ) - break_node_for_new_pipe = WaterNetwork.get_node( - new_node_id_for_new_pipe - ) - break_node_for_new_pipe.add_leak( - WaterNetwork, - area=area, - start_time=float(damage_time), - end_time=self.end_time + 0.1, - ) - - self._registry.addPipeDamageToRegistry( - new_node_id_for_old_pipe, - { - 'number': number, - 'damage_type': 'break', - 'pipe_A': pipe_id, - 'pipe_B': new_pipe_id, - 'orginal_pipe': pipe_id, - 'node_A': new_node_id_for_old_pipe, - 'node_B': new_node_id_for_new_pipe, - }, - ) - # self._registry.addPipeDamageToDamageRestorationData(pipe_id, 'break', damage_time) - else: - raise ValueError( - 'undefined damage type: ' - + repr(cur_damage['type']) - + ". Accpetale type of famages are either 'creack' or 'break'." - ) - self._registry.addRestorationDataOnPipe( - new_node_id, damage_time, cur_damage['type'] - ) - # return WaterNetwork - - def applyTankDamages(self, WaterNetwork, current_time): # noqa: N802, N803, D102 - if self.tank_damage.empty: - print('No Tank Damage at all') # noqa: T201 - return - - current_time_tank_damage = self.tank_damage[current_time] - if type(current_time_tank_damage) != str: # noqa: E721 - if current_time_tank_damage.empty: - print('No Tank Damage at time ' + str(current_time)) # noqa: T201 - return - else: - current_time_tank_damage = pd.Series( - [current_time_tank_damage], index=[current_time] - ) - # print(current_time_tank_damage) - for ind, value in current_time_tank_damage.items(): # noqa: B007, PERF102 - # if value not in WaterNetwork.tank_name_list: - # continue #contibue if there is not a tank with such damage - # connected_link_list = [] - link_name_list_connected_to_node = WaterNetwork.get_links_for_node( - value - ) # must be here - # for link_name in link_name_list_connected_to_node: - - # link = WaterNetwork.get_link(link_name) - # if value == link.start_node.name: - # connected_link_list.append((0, link_name)) - # elif value == link.end_node.name: - # connected_link_list.append((1, link_name) ) - - tank = WaterNetwork.get_node(value) - coord = tank.coordinates - new_coord = (coord[0] + 10, coord[1] + 10) - elevation = tank.elevation - new_mid_node_name = value + '_tank_mid' - WaterNetwork.add_junction( - new_mid_node_name, elevation=elevation, coordinates=new_coord - ) - - new_pipe_name = value + '_tank_mid_pipe' - # print(value + str(" -> " ) + new_pipe_name) - WaterNetwork.add_pipe( - new_pipe_name, value, new_mid_node_name, initial_status='CLOSED' - ) - - new_node = WaterNetwork.get_node(new_mid_node_name) - - for link_name in link_name_list_connected_to_node: - link = WaterNetwork.get_link(link_name) - - if value == link.start_node.name: - link.start_node = new_node - elif value == link.end_node.name: - link.end_node = new_node - else: - raise # noqa: PLE0704 - - def applyPumpDamages(self, WaterNetwork, current_time): # noqa: N802, N803, D102 - # print(type(self.damaged_pumps)) - if self.damaged_pumps.empty: - print('No pump damage at all') # noqa: T201 - return - - pump_damage_at_time = self.damaged_pumps[current_time] - if type(pump_damage_at_time) != str: # noqa: E721 - if pump_damage_at_time.empty: - print('No Pump Damage at time ' + str(current_time)) # noqa: T201 - return - else: - pump_damage_at_time = pd.Series( - [pump_damage_at_time], index=[current_time] - ) - for ind, values in pump_damage_at_time.items(): # noqa: B007, PERF102 - WaterNetwork.get_link(values).initial_status = LinkStatus(0) - - def read_earthquake(self, earthquake_file_name): - """Parameters - ---------- - earthquake_file_name : str - path to the text file that include earthquake definition file - - Raises - ------ - ValueError - If the file name is not provided, a valueError will be returned - IOError - If the information inside the text file is not valid, then IOError - will be returned - - Returns - ------- - None. - - """ # noqa: D205 - if type(earthquake_file_name) != str: # noqa: E721 - raise ValueError('string is wanted for earthqiake fie name') # noqa: EM101, TRY003 - - file = open(earthquake_file_name) # noqa: SIM115, PTH123 - lines = file.readlines() - ct = 0 - for line in lines: - ct += 1 # noqa: SIM113 - sline = line.split() - line_length = len(sline) - if line_length != 5: # noqa: PLR2004 - raise OSError( - 'there should be 5 values in line ' - + repr(ct) - + '\n M[SPACE]depth[SPACE]X coordinate[SPACE]Y coordinate{SPACE]Time' - ) - temp_EQ = EarthquakeScenario( # noqa: N806 - float(sline[0]), - float(sline[1]), - float(sline[2]), - float(sline[3]), - float(sline[4]), - ) - self._earthquake = self._earthquake.append( - pd.Series(temp_EQ, index=[int(temp_EQ.time)]) - ) - file.close() - self.sortEarthquakeListTimely() - - def sortEarthquakeListTimely(self): # noqa: N802 - """This functions sorts the list of earthquakes in a timely manner - - Returns - ------- - None. - - """ # noqa: D400, D401, D404, DOC202, RUF100 - self._earthquake.sort_index() - self.is_timely_sorted = True - - def predictDamage(self, wn, iClear=False): # noqa: FBT002, N802, N803 - """This function predict the water network model damage based on probabilistic method. - - Parameters - ---------- - wn : wntrfr.network.model.WaterNetworkModel - Water Network Model to be used to model the damages - clear : TYPE, optional - Boolian value, determining if the leak and break list must be - cleared before predicting and adding. The default is False. - - Returns - ------- - None. - - """ # noqa: D401, D404, DOC202, RUF100 - if iClear: - self.pipe_leak = pd.Series() - self.pipe_break = pd.Series() - - for eq_in, eq in self._earthquake.items(): # noqa: B007, PERF102 - wntr_eq = eq.getWNTREarthquakeObject() - distance_to_pipes = wntr_eq.distance_to_epicenter( - wn, element_type=wntrfr.network.Pipe - ) - pga = wntr_eq.pga_attenuation_model(distance_to_pipes) - pgv = wntr_eq.pgv_attenuation_model(distance_to_pipes) - repair_rate = wntr_eq.repair_rate_model(pgv) # noqa: F841 - fc = wntrfr.scenario.FragilityCurve() - fc.add_state('leak', 1, {'Default': lognorm(0.5, scale=0.2)}) - fc.add_state('break', 2, {'Default': lognorm(0.5, scale=0.5)}) - failure_probability = fc.cdf_probability(pga) - damage_state = fc.sample_damage_state(failure_probability) - - for pipe_ID, ds in damage_state.items(): # noqa: N806 - # if wn.get_link(pipe_ID).status==0: - # continue - if ds == None: # noqa: E711 - continue - if ds.lower() == 'leak': - temp = { - 'pipe_id': pipe_ID, - 'leak_loc': 0.5, - 'leak_type': 1, - 'leak_time': eq.time / 3600, - } - self.pipe_leak = self.pipe_leak.append( - pd.Series(data=[temp], index=[int(eq.time)]) - ) - if ds.lower() == 'break': - temp = { - 'pipe_id': pipe_ID, - 'break_loc': 0.5, - 'break_time': eq.time / 3600, - } - self.pipe_break = self.pipe_break.append( - pd.Series(data=[temp], index=[int(eq.time)]) - ) - - def get_damage_distinct_time(self): - """Get distinct time for all kind of damages - - Returns - ------- - damage_time_list : list - Distinct time for all kind of damages - - """ # noqa: D400 - pipe_damage_unique_time = self.pipe_all_damages.index.unique().tolist() - node_damage_unique_time = self.node_damage.index.unique().tolist() - tank_damage_unique_time = self.tank_damage.index.unique().tolist() - pump_damage_unique_time = self.damaged_pumps.index.unique().tolist() - - all_damages_time = [] - all_damages_time.extend(pipe_damage_unique_time) - all_damages_time.extend(node_damage_unique_time) - all_damages_time.extend(tank_damage_unique_time) - all_damages_time.extend(pump_damage_unique_time) - - all_damages_time = list(set(all_damages_time)) - all_damages_time.sort() - - # damage_time_list = all_pipe_damage_time.unique().tolist() - # damage_time_list.sort() - return all_damages_time - - def get_earthquake_distict_time(self): - """Checks if the earthquake time are in order. Then the it will get - distinct earthquake time sand return it - - Raises - ------ - ValueError - when the earthquake in not in order. - - Returns - ------- - pandas.Series() - a list of distinct time of earthquake. - - """ # noqa: D205, D400, D401 - reg = [] - if self.is_timely_sorted == False: # noqa: E712 - self.sortEarthquakeListTimely() - - time_list = self._earthquake.index - last_value = None - for time in iter(time_list): - if last_value == None or last_value < time: # noqa: E711 - reg.append(time) - last_value = time - - return pd.Series(reg) diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/CMakeLists.txt deleted file mode 100644 index 50f1192c9..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_subdirectory(epanet) -add_subdirectory(morph) -add_subdirectory(network) -add_subdirectory(sim) -simcenter_add_python_script(SCRIPT __init__.py) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/__init__.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/__init__.py deleted file mode 100644 index b74acee6d..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# noqa: N999, D104 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/CMakeLists.txt deleted file mode 100644 index a5f0e860c..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_subdirectory(windows) -add_subdirectory(Darwin) -simcenter_add_python_script(SCRIPT __init__.py) -simcenter_add_python_script(SCRIPT io.py) -simcenter_add_python_script(SCRIPT toolkit.py) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/CMakeLists.txt deleted file mode 100644 index b9f5825f1..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ - -simcenter_add_python_script(SCRIPT libepanet22_mod.dylib) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/libepanet22_mod.dylib b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/libepanet22_mod.dylib deleted file mode 100755 index 5e16b07d1..000000000 Binary files a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/Darwin/libepanet22_mod.dylib and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/__init__.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/__init__.py deleted file mode 100644 index b74acee6d..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# noqa: N999, D104 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/io.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/io.py deleted file mode 100644 index c9fef211c..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/io.py +++ /dev/null @@ -1,4348 +0,0 @@ -"""The wntrfr.epanet.io module contains methods for reading/writing EPANET input and output files. - -.. rubric:: Contents - -.. autosummary:: - - InpFile - BinFile -s -""" - -import datetime -import difflib -import logging -import os -import re -import sys -import warnings -from collections import OrderedDict - -import numpy as np -import pandas as pd -import wntrfr -import wntrfr.network -from wntrfr.epanet.util import ( - EN, - FlowUnits, - HydParam, - MassUnits, - MixType, - PressureUnits, - QualParam, - QualType, - ResultType, - StatisticsType, - from_si, - to_si, -) -from wntrfr.network.base import Link -from wntrfr.network.controls import ( - AndCondition, - Comparison, - Control, - ControlAction, - OrCondition, - Rule, - SimTimeCondition, - TimeOfDayCondition, - ValueCondition, - _ControlType, -) -from wntrfr.network.elements import Junction, Pipe, Pump, Tank, Valve -from wntrfr.network.model import ( - LinkStatus, - WaterNetworkModel, -) - -# from .time_utils import run_lineprofile -sys_default_enc = sys.getdefaultencoding() - - -logger = logging.getLogger(__name__) - -_INP_SECTIONS = [ - '[OPTIONS]', - '[TITLE]', - '[JUNCTIONS]', - '[RESERVOIRS]', - '[TANKS]', - '[PIPES]', - '[PUMPS]', - '[VALVES]', - '[EMITTERS]', - '[CURVES]', - '[PATTERNS]', - '[ENERGY]', - '[STATUS]', - '[CONTROLS]', - '[RULES]', - '[DEMANDS]', - '[QUALITY]', - '[REACTIONS]', - '[SOURCES]', - '[MIXING]', - '[TIMES]', - '[REPORT]', - '[COORDINATES]', - '[VERTICES]', - '[LABELS]', - '[BACKDROP]', - '[TAGS]', -] - -_JUNC_ENTRY = ' {name:20} {elev:15.11g} {dem:15.11g} {pat:24} {com:>3s}\n' -_JUNC_LABEL = '{:21} {:>12s} {:>12s} {:24}\n' - -_RES_ENTRY = ' {name:20s} {head:15.11g} {pat:>24s} {com:>3s}\n' -_RES_LABEL = '{:21s} {:>20s} {:>24s}\n' - -_TANK_ENTRY = ' {name:20s} {elev:15.11g} {initlev:15.11g} {minlev:15.11g} {maxlev:15.11g} {diam:15.11g} {minvol:15.11g} {curve:20s} {overflow:20s} {com:>3s}\n' -_TANK_LABEL = ( - '{:21s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s} {:20s} {:20s}\n' -) - -_PIPE_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {len:15.11g} {diam:15.11g} {rough:15.11g} {mloss:15.11g} {status:>20s} {com:>3s}\n' -_PIPE_LABEL = '{:21s} {:20s} {:20s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s}\n' - -_PUMP_ENTRY = ( - ' {name:20s} {node1:20s} {node2:20s} {ptype:8s} {params:20s} {com:>3s}\n' -) -_PUMP_LABEL = '{:21s} {:20s} {:20s} {:20s}\n' - -_VALVE_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {diam:15.11g} {vtype:4s} {set:15.11g} {mloss:15.11g} {com:>3s}\n' -_GPV_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {diam:15.11g} {vtype:4s} {set:20s} {mloss:15.11g} {com:>3s}\n' -_VALVE_LABEL = '{:21s} {:20s} {:20s} {:>20s} {:4s} {:>20s} {:>20s}\n' - -_CURVE_ENTRY = ' {name:10s} {x:12f} {y:12f} {com:>3s}\n' -_CURVE_LABEL = '{:11s} {:12s} {:12s}\n' - - -def _split_line(line): - _vc = line.split(';', 1) - _cmnt = None - _vals = None - if len(_vc) == 0: - pass - elif len(_vc) == 1: - _vals = _vc[0].split() - elif _vc[0] == '': - _cmnt = _vc[1] - else: - _vals = _vc[0].split() - _cmnt = _vc[1] - return _vals, _cmnt - - -def _is_number(s): - """Checks if input is a number - - Parameters - ---------- - s : anything - - Returns - ------- - bool - Input is a number - - """ # noqa: D400, D401 - try: - float(s) - return True # noqa: TRY300 - except ValueError: - return False - - -def _str_time_to_sec(s): - """Converts EPANET time format to seconds. - - Parameters - ---------- - s : string - EPANET time string. Options are 'HH:MM:SS', 'HH:MM', 'HH' - - - Returns - ------- - int - Integer value of time in seconds. - - """ # noqa: D401 - pattern1 = re.compile(r'^(\d+):(\d+):(\d+)$') - time_tuple = pattern1.search(s) - if bool(time_tuple): - return ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - + int(round(float(time_tuple.groups()[2]))) - ) - else: # noqa: RET505 - pattern2 = re.compile(r'^(\d+):(\d+)$') - time_tuple = pattern2.search(s) - if bool(time_tuple): - return ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - ) - else: # noqa: RET505 - pattern3 = re.compile(r'^(\d+)$') - time_tuple = pattern3.search(s) - if bool(time_tuple): - return int(time_tuple.groups()[0]) * 60 * 60 - else: # noqa: RET505 - raise RuntimeError('Time format in ' 'INP file not recognized. ') # noqa: EM101, TRY003 - - -def _clock_time_to_sec(s, am_pm): # noqa: C901 - """Converts EPANET clocktime format to seconds. - - Parameters - ---------- - s : string - EPANET time string. Options are 'HH:MM:SS', 'HH:MM', HH' - - am : string - options are AM or PM - - - Returns - ------- - int - Integer value of time in seconds - - """ # noqa: D401 - if am_pm.upper() == 'AM': - am = True - elif am_pm.upper() == 'PM': - am = False - else: - raise RuntimeError('am_pm option not recognized; options are AM or PM') # noqa: EM101, TRY003 - - pattern1 = re.compile(r'^(\d+):(\d+):(\d+)$') - time_tuple = pattern1.search(s) - if bool(time_tuple): - time_sec = ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - + int(round(float(time_tuple.groups()[2]))) - ) - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - pattern2 = re.compile(r'^(\d+):(\d+)$') - time_tuple = pattern2.search(s) - if bool(time_tuple): - time_sec = ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - ) - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - pattern3 = re.compile(r'^(\d+)$') - time_tuple = pattern3.search(s) - if bool(time_tuple): - time_sec = int(time_tuple.groups()[0]) * 60 * 60 - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - raise RuntimeError('Time format in ' 'INP file not recognized. ') # noqa: EM101, TRY003 - - -def _sec_to_string(sec): - hours = int(sec / 3600.0) - sec -= hours * 3600 - mm = int(sec / 60.0) - sec -= mm * 60 - return (hours, mm, int(sec)) - - -class InpFile: - """EPANET INP file reader and writer class. - - This class provides read and write functionality for EPANET INP files. - The EPANET Users Manual provides full documentation for the INP file format. - """ - - def __init__(self): - self.sections = OrderedDict() - for sec in _INP_SECTIONS: - self.sections[sec] = [] - self.mass_units = None - self.flow_units = None - self.top_comments = [] - self.curves = OrderedDict() - - def read(self, inp_files, wn=None): # noqa: C901 - """Read an EPANET INP file and load data into a water network model object. - Both EPANET 2.0 and EPANET 2.2 INP file options are recognized and handled. - - Parameters - ---------- - inp_files : str or list - An EPANET INP input file or list of INP files to be combined - wn : WaterNetworkModel, optional - An optional network model to append onto; by default a new model is created. - - Returns - ------- - :class:`~wntrfr.network.model.WaterNetworkModel` - A water network model object - - """ # noqa: D205 - if wn is None: - wn = WaterNetworkModel() - self.wn = wn - if not isinstance(inp_files, list): - inp_files = [inp_files] - wn.name = inp_files[0] - - self.curves = OrderedDict() - self.top_comments = [] - self.sections = OrderedDict() - for sec in _INP_SECTIONS: - self.sections[sec] = [] - self.mass_units = None - self.flow_units = None - - for filename in inp_files: - section = None - lnum = 0 - edata = {'fname': filename} - with open(filename, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - edata['lnum'] = lnum - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.startswith('['): # noqa: RET507 - vals = line.split(None, 1) - sec = vals[0].upper() - # Add handlers to deal with extra 'S'es (or missing 'S'es) in INP file - if sec not in _INP_SECTIONS: - trsec = sec.replace(']', 'S]') - if trsec in _INP_SECTIONS: - sec = trsec - if sec not in _INP_SECTIONS: - trsec = sec.replace('S]', ']') - if trsec in _INP_SECTIONS: - sec = trsec - edata['sec'] = sec - if sec in _INP_SECTIONS: - section = sec - # logger.info('%(fname)s:%(lnum)-6d %(sec)13s section found' % edata) - continue - elif sec == '[END]': # noqa: RET507 - # logger.info('%(fname)s:%(lnum)-6d %(sec)13s end of file found' % edata) - section = None - break - else: - raise RuntimeError( - '%(fname)s:%(lnum)d: Invalid section "%(sec)s"' - % edata - ) - elif section is None and line.startswith(';'): - self.top_comments.append(line[1:]) - continue - elif section is None: - logger.debug('Found confusing line: %s', repr(line)) - raise RuntimeError( - '%(fname)s:%(lnum)d: Non-comment outside of valid section!' - % edata - ) - # We have text, and we are in a section - self.sections[section].append((lnum, line)) - - # Parse each of the sections - # The order of operations is important as certain things require prior knowledge - - # OPTIONS - self._read_options() - - # TIMES - self._read_times() - - # CURVES - self._read_curves() - - # PATTERNS - self._read_patterns() - - # JUNCTIONS - self._read_junctions() - - # RESERVOIRS - self._read_reservoirs() - - # TANKS - self._read_tanks() - - # PIPES - self._read_pipes() - - # PUMPS - self._read_pumps() - - # VALVES - self._read_valves() - - # COORDINATES - self._read_coordinates() - - # SOURCES - self._read_sources() - - # STATUS - self._read_status() - - # CONTROLS - self._read_controls() - - # RULES - self._read_rules() - - # REACTIONS - self._read_reactions() - - # TITLE - self._read_title() - - # ENERGY - self._read_energy() - - # DEMANDS - self._read_demands() - - # EMITTERS - self._read_emitters() - - # QUALITY - self._read_quality() - - self._read_mixing() - self._read_report() - self._read_vertices() - self._read_labels() - - # Parse Backdrop - self._read_backdrop() - - # TAGS - self._read_tags() - - # Set the _inpfile io data inside the water network, so it is saved somewhere - wn._inpfile = self # noqa: SLF001 - - # Finish tags - self._read_end() - - return self.wn - - def write(self, filename, wn, units=None, version=2.2, force_coordinates=False): # noqa: FBT002 - """Write a water network model into an EPANET INP file. - - .. note:: - - Please note that by default, an EPANET 2.2 formatted file is written by wntrfr. An INP file - with version 2.2 options *will not* work with EPANET 2.0 (neither command line nor GUI). - By default, WNTR will use the EPANET 2.2 toolkit. - - - Parameters - ---------- - filename : str - Name of the EPANET INP file. - units : str, int or FlowUnits - Name of the units for the EPANET INP file to be written in. - version : float, {2.0, **2.2**} - Defaults to 2.2; use 2.0 to guarantee backward comparability, but this will turn off PDD mode - and suppress the writing of other EPANET 2.2-specific options. If PDD mode is specified, a - warning will be issued. - force_coordinates : bool - This only applies if `self.options.graphics.map_filename` is not `None`, - and will force the COORDINATES section to be written even if a MAP file is - provided. False by default, but coordinates **are** written by default since - the MAP file is `None` by default. - - """ - if not isinstance(wn, WaterNetworkModel): - raise ValueError('Must pass a WaterNetworkModel object') # noqa: EM101, TRY003, TRY004 - if units is not None and isinstance(units, str): - units = units.upper() - self.flow_units = FlowUnits[units] - elif units is not None and isinstance(units, FlowUnits): - self.flow_units = units - elif units is not None and isinstance(units, int): - self.flow_units = FlowUnits(units) - elif self.flow_units is not None: - self.flow_units = self.flow_units - elif isinstance(wn.options.hydraulic.inpfile_units, str): - units = wn.options.hydraulic.inpfile_units.upper() - self.flow_units = FlowUnits[units] - else: - self.flow_units = FlowUnits.GPM - if self.mass_units is None: - self.mass_units = MassUnits.mg - with open(filename, 'wb') as f: # noqa: PTH123 - self._write_title(f, wn) - self._write_junctions(f, wn) - self._write_reservoirs(f, wn) - self._write_tanks(f, wn, version=version) - self._write_pipes(f, wn) - self._write_pumps(f, wn) - self._write_valves(f, wn) - - self._write_tags(f, wn) - self._write_demands(f, wn) - self._write_status(f, wn) - self._write_patterns(f, wn) - self._write_curves(f, wn) - self._write_controls(f, wn) - self._write_rules(f, wn) - self._write_energy(f, wn) - self._write_emitters(f, wn) - - self._write_quality(f, wn) - self._write_sources(f, wn) - self._write_reactions(f, wn) - self._write_mixing(f, wn) - - self._write_times(f, wn) - self._write_report(f, wn) - self._write_options(f, wn, version=version) - - if wn.options.graphics.map_filename is None or force_coordinates is True: - self._write_coordinates(f, wn) - self._write_vertices(f, wn) - self._write_labels(f, wn) - self._write_backdrop(f, wn) - - self._write_end(f, wn) - - # Network Components - - def _read_title(self): - lines = [] - for lnum, line in self.sections['[TITLE]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - lines.append(line) - self.wn.title = lines - - def _write_title(self, f, wn): - if wn.name is not None: - f.write(f'; Filename: {wn.name}\n'.encode(sys_default_enc)) - f.write( - f'; WNTR: {wntrfr.__version__}\n; Created: {datetime.datetime.now():%Y-%m-%d %H:%M:%S}\n'.encode( # noqa: DTZ005 - sys_default_enc - ) - ) - f.write('[TITLE]\n'.encode(sys_default_enc)) - if hasattr(wn, 'title'): - for line in wn.title: - f.write(f'{line}\n'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_junctions(self): - # try: - for lnum, line in self.sections['[JUNCTIONS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if len(current) > 3: # noqa: PLR2004 - pat = current[3] - elif self.wn.options.hydraulic.pattern: - pat = self.wn.options.hydraulic.pattern - else: - pat = self.wn.patterns.default_pattern - base_demand = 0.0 - if len(current) > 2: # noqa: PLR2004 - base_demand = to_si( - self.flow_units, float(current[2]), HydParam.Demand - ) - self.wn.add_junction( - current[0], - base_demand, - pat, - to_si(self.flow_units, float(current[1]), HydParam.Elevation), - demand_category=None, - ) - - # except Exception as e: - # print(line) - # raise e - - def _write_junctions(self, f, wn): - f.write('[JUNCTIONS]\n'.encode(sys_default_enc)) - f.write( - _JUNC_LABEL.format(';ID', 'Elevation', 'Demand', 'Pattern').encode( - sys_default_enc - ) - ) - nnames = list(wn.junction_name_list) - # nnames.sort() - for junction_name in nnames: - junction = wn.nodes[junction_name] - - # sina added this - if junction._is_isolated == True: # noqa: SLF001, E712 - continue - - if junction.demand_timeseries_list: - base_demands = junction.demand_timeseries_list.base_demand_list() - demand_patterns = junction.demand_timeseries_list.pattern_list() - if base_demands: - base_demand = base_demands[0] - else: - base_demand = 0.0 - if demand_patterns: - if demand_patterns[0] == wn.options.hydraulic.pattern: - demand_pattern = None - else: - demand_pattern = demand_patterns[0] - else: - demand_pattern = None - else: - base_demand = 0.0 - demand_pattern = None - E = { # noqa: N806 - 'name': junction_name, - 'elev': from_si( - self.flow_units, junction.elevation, HydParam.Elevation - ), - 'dem': from_si(self.flow_units, base_demand, HydParam.Demand), - 'pat': '', - 'com': ';', - } - if demand_pattern is not None: - E['pat'] = str(demand_pattern) - f.write(_JUNC_ENTRY.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_reservoirs(self): - for lnum, line in self.sections['[RESERVOIRS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if len(current) == 2: # noqa: PLR2004 - self.wn.add_reservoir( - current[0], - to_si( - self.flow_units, float(current[1]), HydParam.HydraulicHead - ), - ) - else: - self.wn.add_reservoir( - current[0], - to_si( - self.flow_units, float(current[1]), HydParam.HydraulicHead - ), - current[2], - ) - - def _write_reservoirs(self, f, wn): - f.write('[RESERVOIRS]\n'.encode(sys_default_enc)) - f.write(_RES_LABEL.format(';ID', 'Head', 'Pattern').encode(sys_default_enc)) - nnames = list(wn.reservoir_name_list) - # nnames.sort() - for reservoir_name in nnames: - reservoir = wn.nodes[reservoir_name] - - # sina added this - if reservoir._is_isolated == True: # noqa: SLF001, E712 - continue - - E = { # noqa: N806 - 'name': reservoir_name, - 'head': from_si( - self.flow_units, - reservoir.head_timeseries.base_value, - HydParam.HydraulicHead, - ), - 'com': ';', - } - if reservoir.head_timeseries.pattern is None: - E['pat'] = '' - else: - E['pat'] = reservoir.head_timeseries.pattern.name - f.write(_RES_ENTRY.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_tanks(self): - for lnum, line in self.sections['[TANKS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - volume = None - if len(current) >= 8: # Volume curve provided # noqa: PLR2004 - volume = float(current[6]) - curve_name = current[7] - if curve_name == '*': - curve_name = None - else: - curve_points = [] - for point in self.curves[curve_name]: - x = to_si(self.flow_units, point[0], HydParam.Length) - y = to_si(self.flow_units, point[1], HydParam.Volume) - curve_points.append((x, y)) - self.wn.add_curve(curve_name, 'VOLUME', curve_points) - # curve = self.wn.get_curve(curve_name) - if len(current) == 9: # noqa: PLR2004 - overflow = current[8] - else: - overflow = False - elif len(current) == 7: # noqa: PLR2004 - curve_name = None - overflow = False - volume = float(current[6]) - elif len(current) == 6: # noqa: PLR2004 - curve_name = None - overflow = False - volume = 0.0 - else: - raise RuntimeError('Tank entry format not recognized.') # noqa: EM101, TRY003 - self.wn.add_tank( - current[0], - to_si(self.flow_units, float(current[1]), HydParam.Elevation), - to_si(self.flow_units, float(current[2]), HydParam.Length), - to_si(self.flow_units, float(current[3]), HydParam.Length), - to_si(self.flow_units, float(current[4]), HydParam.Length), - to_si(self.flow_units, float(current[5]), HydParam.TankDiameter), - to_si(self.flow_units, float(volume), HydParam.Volume), - curve_name, - overflow, - ) - - def _write_tanks(self, f, wn, version=2.2): - f.write('[TANKS]\n'.encode(sys_default_enc)) - if version != 2.2: # noqa: PLR2004 - f.write( - _TANK_LABEL.format( - ';ID', - 'Elevation', - 'Init Level', - 'Min Level', - 'Max Level', - 'Diameter', - 'Min Volume', - 'Volume Curve', - '', - ).encode(sys_default_enc) - ) - else: - f.write( - _TANK_LABEL.format( - ';ID', - 'Elevation', - 'Init Level', - 'Min Level', - 'Max Level', - 'Diameter', - 'Min Volume', - 'Volume Curve', - 'Overflow', - ).encode(sys_default_enc) - ) - nnames = list(wn.tank_name_list) - # nnames.sort() - for tank_name in nnames: - tank = wn.nodes[tank_name] - - if tank._is_isolated == True: # sina added this # noqa: SLF001, E712 - continue - - E = { # noqa: N806 - 'name': tank_name, - 'elev': from_si(self.flow_units, tank.elevation, HydParam.Elevation), - 'initlev': from_si( - self.flow_units, tank.init_level, HydParam.HydraulicHead - ), - 'minlev': from_si( - self.flow_units, tank.min_level, HydParam.HydraulicHead - ), - 'maxlev': from_si( - self.flow_units, tank.max_level, HydParam.HydraulicHead - ), - 'diam': from_si( - self.flow_units, tank.diameter, HydParam.TankDiameter - ), - 'minvol': from_si(self.flow_units, tank.min_vol, HydParam.Volume), - 'curve': '', - 'overflow': '', - 'com': ';', - } - if tank.vol_curve is not None: - E['curve'] = tank.vol_curve.name - if version == 2.2: # noqa: PLR2004 - if tank.overflow: - E['overflow'] = 'YES' - if tank.vol_curve is None: - E['curve'] = '*' - f.write(_TANK_ENTRY.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_pipes(self): - for lnum, line in self.sections['[PIPES]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if len(current) == 8: # noqa: PLR2004 - minor_loss = float(current[6]) - if current[7].upper() == 'CV': - link_status = LinkStatus.Open - check_valve = True - else: - link_status = LinkStatus[current[7].upper()] - check_valve = False - elif len(current) == 7: # noqa: PLR2004 - minor_loss = float(current[6]) - link_status = LinkStatus.Open - check_valve = False - elif len(current) == 6: # noqa: PLR2004 - minor_loss = 0.0 - link_status = LinkStatus.Open - check_valve = False - - self.wn.add_pipe( - current[0], - current[1], - current[2], - to_si(self.flow_units, float(current[3]), HydParam.Length), - to_si(self.flow_units, float(current[4]), HydParam.PipeDiameter), - float(current[5]), - minor_loss, - link_status, - check_valve, - ) - - def _write_pipes(self, f, wn): - f.write('[PIPES]\n'.encode(sys_default_enc)) - f.write( - _PIPE_LABEL.format( - ';ID', - 'Node1', - 'Node2', - 'Length', - 'Diameter', - 'Roughness', - 'Minor Loss', - 'Status', - ).encode(sys_default_enc) - ) - lnames = list(wn.pipe_name_list) - # lnames.sort() - for pipe_name in lnames: - pipe = wn.links[pipe_name] - - if pipe._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - E = { # noqa: N806 - 'name': pipe_name, - 'node1': pipe.start_node_name, - 'node2': pipe.end_node_name, - 'len': from_si(self.flow_units, pipe.length, HydParam.Length), - 'diam': from_si( - self.flow_units, pipe.diameter, HydParam.PipeDiameter - ), - 'rough': pipe.roughness, - 'mloss': pipe.minor_loss, - 'status': str(pipe.initial_status), - 'com': ';', - } - if pipe.check_valve: - E['status'] = 'CV' - f.write(_PIPE_ENTRY.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_pumps(self): # noqa: C901 - def create_curve(curve_name): - curve_points = [] - if ( - curve_name not in self.wn.curve_name_list - or self.wn.get_curve(curve_name) is None - ): - for point in self.curves[curve_name]: - x = to_si(self.flow_units, point[0], HydParam.Flow) - y = to_si(self.flow_units, point[1], HydParam.HydraulicHead) - curve_points.append((x, y)) - self.wn.add_curve(curve_name, 'HEAD', curve_points) - curve = self.wn.get_curve(curve_name) - return curve # noqa: RET504 - - for lnum, line in self.sections['[PUMPS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - - pump_type = None - value = None - speed = None - pattern = None - - for i in range(3, len(current), 2): - if current[i].upper() == 'HEAD': - # assert pump_type is None, 'In [PUMPS] entry, specify either HEAD or POWER once.' - pump_type = 'HEAD' - value = create_curve(current[i + 1]).name - elif current[i].upper() == 'POWER': - # assert pump_type is None, 'In [PUMPS] entry, specify either HEAD or POWER once.' - pump_type = 'POWER' - value = to_si( - self.flow_units, float(current[i + 1]), HydParam.Power - ) - elif current[i].upper() == 'SPEED': - # assert speed is None, 'In [PUMPS] entry, SPEED may only be specified once.' - speed = float(current[i + 1]) - elif current[i].upper() == 'PATTERN': - # assert pattern is None, 'In [PUMPS] entry, PATTERN may only be specified once.' - pattern = self.wn.get_pattern(current[i + 1]).name - else: - raise RuntimeError('Pump keyword in inp file not recognized.') # noqa: EM101, TRY003 - - if speed is None: - speed = 1.0 - - if pump_type is None: - raise RuntimeError( # noqa: TRY003 - 'Either head curve id or pump power must be specified for all pumps.' # noqa: EM101 - ) - self.wn.add_pump( - current[0], current[1], current[2], pump_type, value, speed, pattern - ) - - def _write_pumps(self, f, wn): - f.write('[PUMPS]\n'.encode(sys_default_enc)) - f.write( - _PUMP_LABEL.format(';ID', 'Node1', 'Node2', 'Properties').encode( - sys_default_enc - ) - ) - lnames = list(wn.pump_name_list) - # lnames.sort() - for pump_name in lnames: - pump = wn.links[pump_name] - - if pump._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - E = { # noqa: N806 - 'name': pump_name, - 'node1': pump.start_node_name, - 'node2': pump.end_node_name, - 'ptype': pump.pump_type, - 'params': '', - # 'speed_keyword': 'SPEED', - # 'speed': pump.speed_timeseries.base_value, - 'com': ';', - } - if pump.pump_type == 'HEAD': - E['params'] = pump.pump_curve_name - elif pump.pump_type == 'POWER': - E['params'] = str( - from_si(self.flow_units, pump.power, HydParam.Power) - ) - else: - raise RuntimeError('Only head or power info is supported of pumps.') # noqa: EM101, TRY003 - tmp_entry = _PUMP_ENTRY - if pump.speed_timeseries.base_value != 1: - E['speed_keyword'] = 'SPEED' - E['speed'] = pump.speed_timeseries.base_value - tmp_entry = ( - tmp_entry.rstrip('\n').rstrip('}').rstrip('com:>3s').rstrip(' {') - + ' {speed_keyword:8s} {speed:15.11g} {com:>3s}\n' - ) - if pump.speed_timeseries.pattern is not None: - tmp_entry = ( - tmp_entry.rstrip('\n').rstrip('}').rstrip('com:>3s').rstrip(' {') - + ' {pattern_keyword:10s} {pattern:20s} {com:>3s}\n' - ) - E['pattern_keyword'] = 'PATTERN' - E['pattern'] = pump.speed_timeseries.pattern.name - f.write(tmp_entry.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_valves(self): - for lnum, line in self.sections['[VALVES]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if len(current) == 6: # noqa: PLR2004 - current.append(0.0) - elif len(current) != 7: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - 'The [VALVES] section of an INP file must have 6 or 7 entries.' # noqa: EM101 - ) - valve_type = current[4].upper() - if valve_type in ['PRV', 'PSV', 'PBV']: - valve_set = to_si( - self.flow_units, float(current[5]), HydParam.Pressure - ) - elif valve_type == 'FCV': - valve_set = to_si(self.flow_units, float(current[5]), HydParam.Flow) - elif valve_type == 'TCV': - valve_set = float(current[5]) - elif valve_type == 'GPV': - curve_name = current[5] - curve_points = [] - for point in self.curves[curve_name]: - x = to_si(self.flow_units, point[0], HydParam.Flow) - y = to_si(self.flow_units, point[1], HydParam.HeadLoss) - curve_points.append((x, y)) - self.wn.add_curve(curve_name, 'HEADLOSS', curve_points) - valve_set = curve_name - else: - raise RuntimeError('VALVE type "%s" unrecognized' % valve_type) # noqa: UP031 - self.wn.add_valve( - current[0], - current[1], - current[2], - to_si(self.flow_units, float(current[3]), HydParam.PipeDiameter), - current[4].upper(), - float(current[6]), - valve_set, - ) - - def _write_valves(self, f, wn): - f.write('[VALVES]\n'.encode(sys_default_enc)) - f.write( - _VALVE_LABEL.format( - ';ID', 'Node1', 'Node2', 'Diameter', 'Type', 'Setting', 'Minor Loss' - ).encode(sys_default_enc) - ) - lnames = list(wn.valve_name_list) - # lnames.sort() - for valve_name in lnames: - valve = wn.links[valve_name] - - if valve._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - E = { # noqa: N806 - 'name': valve_name, - 'node1': valve.start_node_name, - 'node2': valve.end_node_name, - 'diam': from_si( - self.flow_units, valve.diameter, HydParam.PipeDiameter - ), - 'vtype': valve.valve_type, - 'set': valve.initial_setting, - 'mloss': valve.minor_loss, - 'com': ';', - } - valve_type = valve.valve_type - formatter = _VALVE_ENTRY - if valve_type in ['PRV', 'PSV', 'PBV']: - valve_set = from_si( - self.flow_units, valve.initial_setting, HydParam.Pressure - ) - elif valve_type == 'FCV': - valve_set = from_si( - self.flow_units, valve.initial_setting, HydParam.Flow - ) - elif valve_type == 'TCV': - valve_set = valve.initial_setting - elif valve_type == 'GPV': - valve_set = valve.headloss_curve_name - formatter = _GPV_ENTRY - E['set'] = valve_set - f.write(formatter.format(**E).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_emitters(self): - for lnum, line in self.sections[ # noqa: B007 - '[EMITTERS]' - ]: # Private attribute on junctions - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - junction = self.wn.get_node(current[0]) - junction.emitter_coefficient = to_si( - self.flow_units, float(current[1]), HydParam.EmitterCoeff - ) - - def _write_emitters(self, f, wn): - f.write('[EMITTERS]\n'.encode(sys_default_enc)) - entry = '{:10s} {:10s}\n' - label = '{:10s} {:10s}\n' - f.write(label.format(';ID', 'Flow coefficient').encode(sys_default_enc)) - njunctions = list(wn.junction_name_list) - # njunctions.sort() - for junction_name in njunctions: - junction = wn.nodes[junction_name] - - # Sina added this - if junction._is_isolated == True: # noqa: SLF001, E712 - continue - - if junction.emitter_coefficient: - val = from_si( - self.flow_units, - junction.emitter_coefficient, - HydParam.EmitterCoeff, - ) - f.write( - entry.format(junction_name, str(val)).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - # System Operation - - def _read_curves(self): - for lnum, line in self.sections['[CURVES]']: # noqa: B007 - # It should be noted carefully that these lines are never directly - # applied to the WaterNetworkModel object. Because different curve - # types are treated differently, each of the curves are converted - # the first time they are used, and this is used to build up a - # dictionary for those conversions to take place. - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - curve_name = current[0] - if curve_name not in self.curves: - self.curves[curve_name] = [] - self.curves[curve_name].append((float(current[1]), float(current[2]))) - self.wn.curves[curve_name] = None - - def _write_curves(self, f, wn): # noqa: C901 - f.write('[CURVES]\n'.encode(sys_default_enc)) - f.write( - _CURVE_LABEL.format(';ID', 'X-Value', 'Y-Value').encode(sys_default_enc) - ) - curves = list(wn.curve_name_list) - # curves.sort() - for curve_name in curves: - curve = wn.get_curve(curve_name) - if curve.curve_type == 'VOLUME': - f.write(f';VOLUME: {curve_name}\n'.encode(sys_default_enc)) - for point in curve.points: - x = from_si(self.flow_units, point[0], HydParam.Length) - y = from_si(self.flow_units, point[1], HydParam.Volume) - f.write( - _CURVE_ENTRY.format( - name=curve_name, x=x, y=y, com=';' - ).encode(sys_default_enc) - ) - elif curve.curve_type == 'HEAD': - f.write(f';PUMP: {curve_name}\n'.encode(sys_default_enc)) - for point in curve.points: - x = from_si(self.flow_units, point[0], HydParam.Flow) - y = from_si(self.flow_units, point[1], HydParam.HydraulicHead) - f.write( - _CURVE_ENTRY.format( - name=curve_name, x=x, y=y, com=';' - ).encode(sys_default_enc) - ) - elif curve.curve_type == 'EFFICIENCY': - f.write(f';EFFICIENCY: {curve_name}\n'.encode(sys_default_enc)) - for point in curve.points: - x = from_si(self.flow_units, point[0], HydParam.Flow) - y = point[1] - f.write( - _CURVE_ENTRY.format( - name=curve_name, x=x, y=y, com=';' - ).encode(sys_default_enc) - ) - elif curve.curve_type == 'HEADLOSS': - f.write(f';HEADLOSS: {curve_name}\n'.encode(sys_default_enc)) - for point in curve.points: - x = from_si(self.flow_units, point[0], HydParam.Flow) - y = from_si(self.flow_units, point[1], HydParam.HeadLoss) - f.write( - _CURVE_ENTRY.format( - name=curve_name, x=x, y=y, com=';' - ).encode(sys_default_enc) - ) - else: - f.write(f';UNKNOWN: {curve_name}\n'.encode(sys_default_enc)) - for point in curve.points: - x = point[0] - y = point[1] - f.write( - _CURVE_ENTRY.format( - name=curve_name, x=x, y=y, com=';' - ).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_patterns(self): - _patterns = OrderedDict() - for lnum, line in self.sections['[PATTERNS]']: # noqa: B007 - # read the lines for each pattern -- patterns can be multiple lines of arbitrary length - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - pattern_name = current[0] - if pattern_name not in _patterns: - _patterns[pattern_name] = [] - for i in current[1:]: - _patterns[pattern_name].append(float(i)) - else: - for i in current[1:]: - _patterns[pattern_name].append(float(i)) - for pattern_name, pattern in _patterns.items(): - # add the patterns to the water network model - self.wn.add_pattern(pattern_name, pattern) - if not self.wn.options.hydraulic.pattern and '1' in _patterns.keys(): # noqa: SIM118 - # If there is a pattern called "1", then it is the default pattern if no other is supplied - self.wn.options.hydraulic.pattern = '1' - elif self.wn.options.hydraulic.pattern not in _patterns.keys(): # noqa: SIM118 - # Sanity check - if the default pattern does not exist and it is not '1' then balk - # If default is '1' but it does not exist, then it is constant - # Any other default that does not exist is an error - if ( - self.wn.options.hydraulic.pattern is not None - and self.wn.options.hydraulic.pattern != '1' - ): - raise KeyError( # noqa: TRY003 - f'Default pattern {self.wn.options.hydraulic.pattern} is undefined' # noqa: EM102 - ) - self.wn.options.hydraulic.pattern = None - - def _write_patterns(self, f, wn): - num_columns = 6 - f.write('[PATTERNS]\n'.encode(sys_default_enc)) - f.write( - '{:10s} {:10s}\n'.format(';ID', 'Multipliers').encode(sys_default_enc) - ) - patterns = list(wn.pattern_name_list) - # patterns.sort() - for pattern_name in patterns: - pattern = wn.get_pattern(pattern_name) - count = 0 - for i in pattern.multipliers: - if count % num_columns == 0: - f.write(f'\n{pattern_name:s} {i:f}'.encode(sys_default_enc)) - else: - f.write(f' {i:f}'.encode(sys_default_enc)) - count += 1 # noqa: SIM113 - f.write('\n'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_energy(self): # noqa: C901 - for lnum, line in self.sections['[ENERGY]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - # Only add head curves for pumps - if current[0].upper() == 'GLOBAL': - if current[1].upper() == 'PRICE': - self.wn.options.energy.global_price = from_si( - self.flow_units, float(current[2]), HydParam.Energy - ) - elif current[1].upper() == 'PATTERN': - self.wn.options.energy.global_pattern = current[2] - elif current[1].upper() in ['EFFIC', 'EFFICIENCY']: - self.wn.options.energy.global_efficiency = float(current[2]) - else: - logger.warning('Unknown entry in ENERGY section: %s', line) - elif current[0].upper() == 'DEMAND': - self.wn.options.energy.demand_charge = float(current[2]) - elif current[0].upper() == 'PUMP': - pump_name = current[1] - pump = self.wn.links[pump_name] - if current[2].upper() == 'PRICE': - pump.energy_price = from_si( - self.flow_units, float(current[3]), HydParam.Energy - ) - elif current[2].upper() == 'PATTERN': - pump.energy_pattern = current[3] - elif current[2].upper() in ['EFFIC', 'EFFICIENCY']: - curve_name = current[3] - curve_points = [] - for point in self.curves[curve_name]: - x = to_si(self.flow_units, point[0], HydParam.Flow) - y = point[1] - curve_points.append((x, y)) - self.wn.add_curve(curve_name, 'EFFICIENCY', curve_points) - curve = self.wn.get_curve(curve_name) - pump.efficiency = curve - else: - logger.warning('Unknown entry in ENERGY section: %s', line) - else: - logger.warning('Unknown entry in ENERGY section: %s', line) - - def _write_energy(self, f, wn): - f.write('[ENERGY]\n'.encode(sys_default_enc)) - if True: # wn.energy is not None: - if wn.options.energy.global_efficiency is not None: - f.write( - f'GLOBAL EFFICIENCY {wn.options.energy.global_efficiency:.4f}\n'.encode( - sys_default_enc - ) - ) - if wn.options.energy.global_price is not None: - f.write( - 'GLOBAL PRICE {:.4f}\n'.format( - to_si( - self.flow_units, - wn.options.energy.global_price, - HydParam.Energy, - ) - ).encode(sys_default_enc) - ) - if wn.options.energy.demand_charge is not None: - f.write( - f'DEMAND CHARGE {wn.options.energy.demand_charge:.4f}\n'.encode( - sys_default_enc - ) - ) - if wn.options.energy.global_pattern is not None: - f.write( - f'GLOBAL PATTERN {wn.options.energy.global_pattern:s}\n'.encode( - sys_default_enc - ) - ) - lnames = list(wn.pump_name_list) - lnames.sort() - for pump_name in lnames: - pump = wn.links[pump_name] - if pump.efficiency is not None: - f.write( - f'PUMP {pump_name:10s} EFFIC {pump.efficiency.name:s}\n'.encode( - sys_default_enc - ) - ) - if pump.energy_price is not None: - f.write( - f'PUMP {pump_name:10s} PRICE {to_si(self.flow_units, pump.energy_price, HydParam.Energy):.4f}\n'.encode( - sys_default_enc - ) - ) - if pump.energy_pattern is not None: - f.write( - f'PUMP {pump_name:10s} PATTERN {pump.energy_pattern:s}\n'.encode( - sys_default_enc - ) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_status(self): - for lnum, line in self.sections['[STATUS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - # assert(len(current) == 2), ("Error reading [STATUS] block, Check format.") - link = self.wn.get_link(current[0]) - if ( - current[1].upper() == 'OPEN' - or current[1].upper() == 'CLOSED' - or current[1].upper() == 'ACTIVE' - ): - new_status = LinkStatus[current[1].upper()] - link.initial_status = new_status - link._user_status = new_status # noqa: SLF001 - else: - if isinstance(link, wntrfr.network.Valve): - new_status = LinkStatus.Active - valve_type = link.valve_type - if valve_type in ['PRV', 'PSV', 'PBV']: - setting = to_si( - self.flow_units, float(current[1]), HydParam.Pressure - ) - elif valve_type == 'FCV': - setting = to_si( - self.flow_units, float(current[1]), HydParam.Flow - ) - elif valve_type == 'TCV': - setting = float(current[1]) - else: - continue - else: - new_status = LinkStatus.Open - setting = float(current[1]) - # link.setting = setting - link.initial_setting = setting - link._user_status = new_status # noqa: SLF001 - link.initial_status = new_status - - def _write_status(self, f, wn): - f.write('[STATUS]\n'.encode(sys_default_enc)) - f.write('{:10s} {:10s}\n'.format(';ID', 'Setting').encode(sys_default_enc)) - - pnames = list(wn.pump_name_list) - for pump_name in pnames: - pump = wn.links[pump_name] - - if pump._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - if pump.initial_status == LinkStatus.Closed: - f.write( - f'{pump_name:10s} {LinkStatus(pump.initial_status).name:10s}\n'.encode( - sys_default_enc - ) - ) - else: - setting = pump.initial_setting - if isinstance(setting, float) and setting != 1.0: - f.write( - f'{pump_name:10s} {setting:10.7g}\n'.encode(sys_default_enc) - ) - - vnames = list(wn.valve_name_list) - # lnames.sort() - for valve_name in vnames: - valve = wn.links[valve_name] - - if valve._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - # valve_type = valve.valve_type - - if ( - valve.initial_status != LinkStatus.Active - ): # LinkStatus.Opened, LinkStatus.Open, - f.write( - f'{valve_name:10s} {LinkStatus(valve.initial_status).name:10s}\n'.encode( - sys_default_enc - ) - ) - # if valve_type in ['PRV', 'PSV', 'PBV']: - # valve_set = from_si(self.flow_units, valve.initial_setting, HydParam.Pressure) - # elif valve_type == 'FCV': - # valve_set = from_si(self.flow_units, valve.initial_setting, HydParam.Flow) - # elif valve_type == 'TCV': - # valve_set = valve.initial_setting - # elif valve_type == 'GPV': - # valve_set = None - # if valve_set is not None: - # f.write('{:10s} {:10.7g}\n'.format(valve_name, float(valve_set)).encode(sys_default_enc)) - - f.write('\n'.encode(sys_default_enc)) - - def _read_controls(self): - control_count = 0 - for lnum, line in self.sections['[CONTROLS]']: # noqa: B007 - control_count += 1 - control_name = 'control ' + str(control_count) - - control_obj = _read_control_line( - line, self.wn, self.flow_units, control_name - ) - if control_obj is None: - control_count -= 1 # control was not found - continue - - if control_name in self.wn.control_name_list: - warnings.warn( - f'One or more [CONTROLS] were duplicated in "{self.wn.name}"; duplicates are ignored.', - stacklevel=0, - ) - logger.warning(f'Control already exists: "{control_name}"') - else: - self.wn.add_control(control_name, control_obj) - - def _write_controls(self, f, wn): # noqa: C901 - def get_setting(control_action, control_name): - value = control_action._value # noqa: SLF001 - attribute = control_action._attribute.lower() # noqa: SLF001 - if attribute == 'status': - setting = LinkStatus(value).name - elif attribute == 'base_speed': - setting = str(value) - elif attribute == 'setting' and isinstance( - control_action._target_obj, # noqa: SLF001 - Valve, - ): - valve = control_action._target_obj # noqa: SLF001 - valve_type = valve.valve_type - if valve_type == 'PRV' or valve_type == 'PSV' or valve_type == 'PBV': # noqa: PLR1714 - setting = str(from_si(self.flow_units, value, HydParam.Pressure)) - elif valve_type == 'FCV': - setting = str(from_si(self.flow_units, value, HydParam.Flow)) - elif valve_type == 'TCV': - setting = str(value) - elif valve_type == 'GPV': - setting = value - else: - raise ValueError('Valve type not recognized' + str(valve_type)) - elif attribute == 'setting': - setting = value - else: - setting = None - logger.warning( - 'Could not write control ' + str(control_name) + ' - skipping' # noqa: G003 - ) - - return setting - - f.write('[CONTROLS]\n'.encode(sys_default_enc)) - # Time controls and conditional controls only - for text, all_control in wn.controls(): - control_action = all_control._then_actions[0] # noqa: SLF001 - - # Sina added this - if control_action._target_obj._is_isolated == True: # noqa: SLF001, E712 - continue - - if all_control.epanet_control_type is not _ControlType.rule: - if ( - len(all_control._then_actions) != 1 # noqa: SLF001 - or len(all_control._else_actions) != 0 # noqa: SLF001 - ): - logger.error('Too many actions on CONTROL "%s"' % text) # noqa: G002, UP031 - raise RuntimeError('Too many actions on CONTROL "%s"' % text) # noqa: UP031 - if not isinstance(control_action.target()[0], Link): - continue - if isinstance( - all_control._condition, # noqa: SLF001 - (SimTimeCondition, TimeOfDayCondition), - ): - entry = '{ltype} {link} {setting} AT {compare} {time:g}\n' - vals = { - 'ltype': control_action._target_obj.link_type, # noqa: SLF001 - 'link': control_action._target_obj.name, # noqa: SLF001 - 'setting': get_setting(control_action, text), - 'compare': 'TIME', - 'time': all_control._condition._threshold / 3600.0, # noqa: SLF001 - } - if vals['setting'] is None: - continue - if isinstance(all_control._condition, TimeOfDayCondition): # noqa: SLF001 - vals['compare'] = 'CLOCKTIME' - f.write(entry.format(**vals).encode(sys_default_enc)) - elif ( - all_control._condition._source_obj._is_isolated == True # noqa: SLF001, E712 - ): # Sina added this - continue - elif isinstance(all_control._condition, (ValueCondition)): # noqa: SLF001 - entry = '{ltype} {link} {setting} IF {ntype} {node} {compare} {thresh}\n' - vals = { - 'ltype': control_action._target_obj.link_type, # noqa: SLF001 - 'link': control_action._target_obj.name, # noqa: SLF001 - 'setting': get_setting(control_action, text), - 'ntype': all_control._condition._source_obj.node_type, # noqa: SLF001 - 'node': all_control._condition._source_obj.name, # noqa: SLF001 - 'compare': 'above', - 'thresh': 0.0, - } - if vals['setting'] is None: - continue - if all_control._condition._relation in [ # noqa: SLF001 - np.less, - np.less_equal, - Comparison.le, - Comparison.lt, - ]: - vals['compare'] = 'below' - threshold = all_control._condition._threshold # noqa: SLF001 - if isinstance(all_control._condition._source_obj, Tank): # noqa: SLF001 - vals['thresh'] = from_si( - self.flow_units, threshold, HydParam.HydraulicHead - ) - elif isinstance(all_control._condition._source_obj, Junction): # noqa: SLF001 - vals['thresh'] = from_si( - self.flow_units, threshold, HydParam.Pressure - ) - else: - raise RuntimeError( # noqa: TRY004 - 'Unknown control for EPANET INP files: %s' # noqa: UP031 - % type(all_control) - ) - f.write(entry.format(**vals).encode(sys_default_enc)) - elif not isinstance(all_control, Control): - raise RuntimeError( - 'Unknown control for EPANET INP files: %s' # noqa: UP031 - % type(all_control) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_rules(self): - rules = _EpanetRule.parse_rules_lines( - self.sections['[RULES]'], self.flow_units, self.mass_units - ) - for rule in rules: - ctrl = rule.generate_control(self.wn) - self.wn.add_control(ctrl.name, ctrl) - logger.debug('Added %s', str(ctrl)) - # wn._en_rules = '\n'.join(self.sections['[RULES]']) - # logger.warning('RULES are reapplied directly to an Epanet INP file on write; otherwise unsupported.') - - def _write_rules(self, f, wn): - f.write('[RULES]\n'.encode(sys_default_enc)) - for text, all_control in wn.controls(): - entry = '{}\n' - if all_control.epanet_control_type == _ControlType.rule: - # Sina added this begin - try: - if all_control._then_actions[0]._target_obj._is_isolated == True: # noqa: SLF001, E712 - continue - except: # noqa: S110, E722 - pass - - try: - if all_control.condition._source_obj._is_isolated == True: # noqa: SLF001, E712 - continue - except: # noqa: S110, E722 - pass - - # Sina added this end - - if all_control.name == '': - all_control._name = text # noqa: SLF001 - rule = _EpanetRule('blah', self.flow_units, self.mass_units) - rule.from_if_then_else(all_control) - f.write(entry.format(str(rule)).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_demands(self): - demand_num = 0 - has_been_read = set() - for lnum, line in self.sections['[DEMANDS]']: # noqa: B007 - ldata = line.split(';') - if len(ldata) > 1 and (ldata[1] != ''): - category = ldata[1] - else: - category = None - current = ldata[0].split() - if current == []: - continue - demand_num = demand_num + 1 - node = self.wn.get_node(current[0]) - if len(current) == 2: # noqa: PLR2004 - pattern = None - else: - pattern = self.wn.get_pattern(current[2]) - if node.name not in has_been_read: - has_been_read.add(node.name) - while len(node.demand_timeseries_list) > 0: - del node.demand_timeseries_list[-1] - # In EPANET, the [DEMANDS] section overrides demands specified in [JUNCTIONS] - # node.demand_timeseries_list.remove_category('EN2 base') - node.demand_timeseries_list.append( - ( - to_si(self.flow_units, float(current[1]), HydParam.Demand), - pattern, - category, - ) - ) - - def _write_demands(self, f, wn): - f.write('[DEMANDS]\n'.encode(sys_default_enc)) - entry = '{:10s} {:10s} {:10s}{:s}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';ID', 'Demand', 'Pattern').encode(sys_default_enc)) - nodes = list(wn.junction_name_list) - # nodes.sort() - for node in nodes: - # Sina added this - if wn.get_node(node)._is_isolated == True: # noqa: SLF001, E712 - continue - demands = wn.get_node(node).demand_timeseries_list - if len(demands) > 1: - for ct, demand in enumerate(demands): # noqa: B007 - cat = str(demand.category) - # if cat == 'EN2 base': - # cat = '' - if cat.lower() == 'none': - cat = '' - else: - cat = ' ;' + demand.category - E = { # noqa: N806 - 'node': node, - 'base': from_si( - self.flow_units, demand.base_value, HydParam.Demand - ), - 'pat': '', - 'cat': cat, - } - if demand.pattern_name in wn.pattern_name_list: - E['pat'] = demand.pattern_name - f.write( - entry.format( - E['node'], str(E['base']), E['pat'], E['cat'] - ).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - # Water Quality - - def _read_quality(self): - for lnum, line in self.sections['[QUALITY]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - node = self.wn.get_node(current[0]) - if self.wn.options.quality.parameter == 'CHEMICAL': - quality = to_si( - self.flow_units, - float(current[1]), - QualParam.Concentration, - mass_units=self.mass_units, - ) - elif self.wn.options.quality.parameter == 'AGE': - quality = to_si( - self.flow_units, float(current[1]), QualParam.WaterAge - ) - else: - quality = float(current[1]) - node.initial_quality = quality - - def _write_quality(self, f, wn): - f.write('[QUALITY]\n'.encode(sys_default_enc)) - entry = '{:10s} {:10s}\n' - label = '{:10s} {:10s}\n' # noqa: F841 - nnodes = list(wn.nodes.keys()) - # nnodes.sort() - for node_name in nnodes: - node = wn.nodes[node_name] - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if node.initial_quality: - if wn.options.quality.parameter == 'CHEMICAL': - quality = from_si( - self.flow_units, - node.initial_quality, - QualParam.Concentration, - mass_units=self.mass_units, - ) - elif wn.options.quality.parameter == 'AGE': - quality = from_si( - self.flow_units, node.initial_quality, QualParam.WaterAge - ) - else: - quality = node.initial_quality - f.write( - entry.format(node_name, str(quality)).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_reactions(self): # noqa: C901 - BulkReactionCoeff = QualParam.BulkReactionCoeff # noqa: N806 - WallReactionCoeff = QualParam.WallReactionCoeff # noqa: N806 - if self.mass_units is None: - self.mass_units = MassUnits.mg - for lnum, line in self.sections['[REACTIONS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - # assert len(current) == 3, ('INP file option in [REACTIONS] block ' - # 'not recognized: ' + line) - key1 = current[0].upper() - key2 = current[1].upper() - val3 = float(current[2]) - if key1 == 'ORDER': - if key2 == 'BULK': - self.wn.options.reaction.bulk_order = int(float(current[2])) - elif key2 == 'WALL': - self.wn.options.reaction.wall_order = int(float(current[2])) - elif key2 == 'TANK': - self.wn.options.reaction.tank_order = int(float(current[2])) - elif key1 == 'GLOBAL': - if key2 == 'BULK': - self.wn.options.reaction.bulk_coeff = to_si( - self.flow_units, - val3, - BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=self.wn.options.reaction.bulk_order, - ) - elif key2 == 'WALL': - self.wn.options.reaction.wall_coeff = to_si( - self.flow_units, - val3, - WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=self.wn.options.reaction.wall_order, - ) - elif key1 == 'BULK': - pipe = self.wn.get_link(current[1]) - pipe.bulk_coeff = to_si( - self.flow_units, - val3, - BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=self.wn.options.reaction.bulk_order, - ) - elif key1 == 'WALL': - pipe = self.wn.get_link(current[1]) - pipe.wall_coeff = to_si( - self.flow_units, - val3, - WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=self.wn.options.reaction.wall_order, - ) - elif key1 == 'TANK': - tank = self.wn.get_node(current[1]) - tank.bulk_coeff = to_si( - self.flow_units, - val3, - BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=self.wn.options.reaction.bulk_order, - ) - elif key1 == 'LIMITING': - self.wn.options.reaction.limiting_potential = float(current[2]) - elif key1 == 'ROUGHNESS': - self.wn.options.reaction.roughness_correl = float(current[2]) - else: - raise RuntimeError('Reaction option not recognized: %s' % key1) # noqa: UP031 - - def _write_reactions(self, f, wn): - f.write('[REACTIONS]\n'.encode(sys_default_enc)) - f.write( - ';Type Pipe/Tank Coefficient\n'.encode( - sys_default_enc - ) - ) - entry_int = ' {:s} {:s} {:d}\n' - entry_float = ' {:s} {:s} {:<10.4f}\n' - for tank_name, tank in wn.nodes(Tank): - if tank._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if tank.bulk_coeff is not None: - f.write( - entry_float.format( - 'TANK', - tank_name, - from_si( - self.flow_units, - tank.bulk_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.reaction.bulk_order, - ), - ).encode(sys_default_enc) - ) - for pipe_name, pipe in wn.links(Pipe): - if pipe._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if pipe.bulk_coeff is not None: - f.write( - entry_float.format( - 'BULK', - pipe_name, - from_si( - self.flow_units, - pipe.bulk_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.reaction.bulk_order, - ), - ).encode(sys_default_enc) - ) - if pipe.wall_coeff is not None: - f.write( - entry_float.format( - 'WALL', - pipe_name, - from_si( - self.flow_units, - pipe.wall_coeff, - QualParam.WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.reaction.wall_order, - ), - ).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - # f.write('[REACTIONS]\n'.encode(sys_default_enc)) # EPANET GUI puts this line in here - f.write( - entry_int.format( - 'ORDER', 'BULK', int(wn.options.reaction.bulk_order) - ).encode(sys_default_enc) - ) - f.write( - entry_int.format( - 'ORDER', 'TANK', int(wn.options.reaction.tank_order) - ).encode(sys_default_enc) - ) - f.write( - entry_int.format( - 'ORDER', 'WALL', int(wn.options.reaction.wall_order) - ).encode(sys_default_enc) - ) - f.write( - entry_float.format( - 'GLOBAL', - 'BULK', - from_si( - self.flow_units, - wn.options.reaction.bulk_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.reaction.bulk_order, - ), - ).encode(sys_default_enc) - ) - f.write( - entry_float.format( - 'GLOBAL', - 'WALL', - from_si( - self.flow_units, - wn.options.reaction.wall_coeff, - QualParam.WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.reaction.wall_order, - ), - ).encode(sys_default_enc) - ) - if wn.options.reaction.limiting_potential is not None: - f.write( - entry_float.format( - 'LIMITING', 'POTENTIAL', wn.options.reaction.limiting_potential - ).encode(sys_default_enc) - ) - if wn.options.reaction.roughness_correl is not None: - f.write( - entry_float.format( - 'ROUGHNESS', 'CORRELATION', wn.options.reaction.roughness_correl - ).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_sources(self): - source_num = 0 - for lnum, line in self.sections['[SOURCES]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - # assert(len(current) >= 3), ("Error reading sources. Check format.") - source_num = source_num + 1 - if current[0].upper() == 'MASS': - strength = to_si( - self.flow_units, - float(current[2]), - QualParam.SourceMassInject, - self.mass_units, - ) - else: - strength = to_si( - self.flow_units, - float(current[2]), - QualParam.Concentration, - self.mass_units, - ) - if len(current) == 3: # noqa: PLR2004 - self.wn.add_source( - 'INP' + str(source_num), current[0], current[1], strength, None - ) - else: - self.wn.add_source( - 'INP' + str(source_num), - current[0], - current[1], - strength, - current[3], - ) - - def _write_sources(self, f, wn): - f.write('[SOURCES]\n'.encode(sys_default_enc)) - entry = '{:10s} {:10s} {:10s} {:10s}\n' - label = '{:10s} {:10s} {:10s} {:10s}\n' - f.write( - label.format(';Node', 'Type', 'Quality', 'Pattern').encode( - sys_default_enc - ) - ) - nsources = list(wn._sources.keys()) # noqa: SLF001 - # nsources.sort() - for source_name in nsources: - source = wn._sources[source_name] # noqa: SLF001 - - if source._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - if source.source_type.upper() == 'MASS': - strength = from_si( - self.flow_units, - source.strength_timeseries.base_value, - QualParam.SourceMassInject, - self.mass_units, - ) - else: # CONC, SETPOINT, FLOWPACED - strength = from_si( - self.flow_units, - source.strength_timeseries.base_value, - QualParam.Concentration, - self.mass_units, - ) - - E = { # noqa: N806 - 'node': source.node_name, - 'type': source.source_type, - 'quality': str(strength), - 'pat': '', - } - if source.strength_timeseries.pattern_name is not None: - E['pat'] = source.strength_timeseries.pattern_name - f.write( - entry.format( - E['node'], E['type'], str(E['quality']), E['pat'] - ).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_mixing(self): - for lnum, line in self.sections['[MIXING]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - key = current[1].upper() - tank_name = current[0] - tank = self.wn.get_node(tank_name) - if key == 'MIXED': - tank.mixing_model = MixType.Mix1 - elif key == '2COMP' and len(current) > 2: # noqa: PLR2004 - tank.mixing_model = MixType.Mix2 - tank.mixing_fraction = float(current[2]) - elif key == '2COMP' and len(current) < 3: # noqa: PLR2004 - raise RuntimeError( - 'Mixing model 2COMP requires fraction on tank %s' % tank_name # noqa: UP031 - ) - elif key == 'FIFO': - tank.mixing_model = MixType.FIFO - elif key == 'LIFO': - tank.mixing_model = MixType.LIFO - - def _write_mixing(self, f, wn): - f.write('[MIXING]\n'.encode(sys_default_enc)) - f.write( - '{:20s} {:5s} {}\n'.format(';Tank ID', 'Model', 'Fraction').encode( - sys_default_enc - ) - ) - lnames = list(wn.tank_name_list) - # lnames.sort() - for tank_name in lnames: - tank = wn.nodes[tank_name] - if tank._mixing_model is not None: # noqa: SLF001 - # Sina added this - if tank._is_isolated == True: # noqa: SLF001, E712 - continue - if tank._mixing_model in [MixType.Mixed, MixType.Mix1, 0]: # noqa: SLF001 - f.write(f' {tank_name:19s} MIXED\n'.encode(sys_default_enc)) - elif tank._mixing_model in [ # noqa: SLF001 - MixType.TwoComp, - MixType.Mix2, - '2comp', - '2COMP', - 1, - ]: - f.write( - f' {tank_name:19s} 2COMP {tank.mixing_fraction}\n'.encode( - sys_default_enc - ) - ) - elif tank._mixing_model in [MixType.FIFO, 2]: # noqa: SLF001 - f.write(f' {tank_name:19s} FIFO\n'.encode(sys_default_enc)) - elif tank._mixing_model in [MixType.LIFO, 3]: # noqa: SLF001 - f.write(f' {tank_name:19s} LIFO\n'.encode(sys_default_enc)) - elif ( - isinstance(tank._mixing_model, str) # noqa: SLF001 - and tank.mixing_fraction is not None - ): - f.write( - f' {tank_name:19s} {tank._mixing_model} {tank.mixing_fraction}\n'.encode( # noqa: SLF001 - sys_default_enc - ) - ) - elif isinstance(tank._mixing_model, str): # noqa: SLF001 - f.write( - f' {tank_name:19s} {tank._mixing_model}\n'.encode( # noqa: SLF001 - sys_default_enc - ) - ) - else: - logger.warning('Unknown mixing model: %s', tank._mixing_model) # noqa: SLF001 - f.write('\n'.encode(sys_default_enc)) - - # Options and Reporting - - def _read_options(self): # noqa: C901, PLR0912 - edata = OrderedDict() - wn = self.wn - opts = wn.options - for lnum, line in self.sections['[OPTIONS]']: - edata['lnum'] = lnum - edata['sec'] = '[OPTIONS]' - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) < 2: # noqa: PLR2004 - edata['key'] = words[0] - raise RuntimeError( - '%(lnum)-6d %(sec)13s no value provided for %(key)s' % edata - ) - key = words[0].upper() - if key == 'UNITS': - self.flow_units = FlowUnits[words[1].upper()] - opts.hydraulic.inpfile_units = words[1].upper() - elif key == 'HEADLOSS': - opts.hydraulic.headloss = words[1].upper() - elif key == 'HYDRAULICS': - opts.hydraulic.hydraulics = words[1].upper() - opts.hydraulic.hydraulics_filename = words[2] - elif key == 'QUALITY': - mode = words[1].upper() - if mode in ['NONE', 'AGE']: - opts.quality.parameter = words[1].upper() - elif mode == 'TRACE': - opts.quality.parameter = 'TRACE' - opts.quality.trace_node = words[2] - else: - opts.quality.parameter = 'CHEMICAL' - opts.quality.chemical_name = words[1] - if len(words) > 2: # noqa: PLR2004 - if 'mg' in words[2].lower(): - self.mass_units = MassUnits.mg - opts.quality.inpfile_units = words[2] - elif 'ug' in words[2].lower(): - self.mass_units = MassUnits.ug - opts.quality.inpfile_units = words[2] - else: - raise ValueError( # noqa: TRY003 - 'Invalid chemical units in OPTIONS section' # noqa: EM101 - ) - else: - self.mass_units = MassUnits.mg - opts.quality.inpfile_units = 'mg/L' - elif key == 'VISCOSITY': - opts.hydraulic.viscosity = float(words[1]) - elif key == 'DIFFUSIVITY': - opts.quality.diffusivity = float(words[1]) - elif key == 'SPECIFIC': - opts.hydraulic.specific_gravity = float(words[2]) - elif key == 'TRIALS': - opts.hydraulic.trials = int(float(words[1])) - elif key == 'ACCURACY': - opts.hydraulic.accuracy = float(words[1]) - elif key == 'HEADERROR': - opts.hydraulic.headerror = float(words[1]) - elif key == 'FLOWCHANGE': - opts.hydraulic.flowchange = float(words[1]) - elif key == 'UNBALANCED': - opts.hydraulic.unbalanced = words[1].upper() - if len(words) > 2: # noqa: PLR2004 - opts.hydraulic.unbalanced_value = int(words[2]) - elif key == 'MINIMUM': - minimum_pressure = to_si( - self.flow_units, float(words[2]), HydParam.Pressure - ) - opts.hydraulic.minimum_pressure = minimum_pressure - elif key == 'REQUIRED': - required_pressure = to_si( - self.flow_units, float(words[2]), HydParam.Pressure - ) - opts.hydraulic.required_pressure = required_pressure - elif key == 'PRESSURE': - if len(words) > 2: # noqa: PLR2004 - if words[1].upper() == 'EXPONENT': - opts.hydraulic.pressure_exponent = float(words[2]) - else: - edata['key'] = ' '.join(words) - raise RuntimeError( - '%(lnum)-6d %(sec)13s unknown option %(key)s' % edata - ) - else: - opts.hydraulic.inpfile_pressure_units = words[1] - elif key == 'PATTERN': - opts.hydraulic.pattern = words[1] - elif key == 'DEMAND': - if len(words) > 2: # noqa: PLR2004 - if words[1].upper() == 'MULTIPLIER': - opts.hydraulic.demand_multiplier = float(words[2]) - elif words[1].upper() == 'MODEL': - opts.hydraulic.demand_model = words[2] - else: - edata['key'] = ' '.join(words) - raise RuntimeError( - '%(lnum)-6d %(sec)13s unknown option %(key)s' % edata - ) - else: - edata['key'] = ' '.join(words) - raise RuntimeError( - '%(lnum)-6d %(sec)13s no value provided for %(key)s' - % edata - ) - elif key == 'EMITTER': - if len(words) > 2: # noqa: PLR2004 - opts.hydraulic.emitter_exponent = float(words[2]) - else: - edata['key'] = 'EMITTER EXPONENT' - raise RuntimeError( - '%(lnum)-6d %(sec)13s no value provided for %(key)s' - % edata - ) - elif key == 'TOLERANCE': - opts.quality.tolerance = float(words[1]) - elif key == 'CHECKFREQ': - opts.hydraulic.checkfreq = float(words[1]) - elif key == 'MAXCHECK': - opts.hydraulic.maxcheck = float(words[1]) - elif key == 'DAMPLIMIT': - opts.hydraulic.damplimit = float(words[1]) - elif key == 'MAP': - opts.graphics.map_filename = words[1] - elif len(words) == 2: # noqa: PLR2004 - edata['key'] = words[0] - setattr(opts, words[0].lower(), float(words[1])) - logger.warning( - '%(lnum)-6d %(sec)13s option "%(key)s" is undocumented; adding, but please verify syntax', - edata, - ) - elif len(words) == 3: # noqa: PLR2004 - edata['key'] = words[0] + ' ' + words[1] - setattr( - opts, - words[0].lower() + '_' + words[1].lower(), - float(words[2]), - ) - logger.warning( - '%(lnum)-6d %(sec)13s option "%(key)s" is undocumented; adding, but please verify syntax', - edata, - ) - if isinstance(opts.time.report_timestep, (float, int)): - if opts.time.report_timestep < opts.time.hydraulic_timestep: - raise RuntimeError( # noqa: TRY003 - 'opts.report_timestep must be greater than or equal to opts.hydraulic_timestep.' # noqa: EM101 - ) - if opts.time.report_timestep % opts.time.hydraulic_timestep != 0: - raise RuntimeError( # noqa: TRY003 - 'opts.report_timestep must be a multiple of opts.hydraulic_timestep' # noqa: EM101 - ) - - def _write_options(self, f, wn, version=2.2): # noqa: C901 - f.write('[OPTIONS]\n'.encode(sys_default_enc)) - entry_string = '{:20s} {:20s}\n' - entry_float = '{:20s} {:.11g}\n' - f.write( - entry_string.format('UNITS', self.flow_units.name).encode( - sys_default_enc - ) - ) - - f.write( - entry_string.format('HEADLOSS', wn.options.hydraulic.headloss).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format( - 'SPECIFIC GRAVITY', wn.options.hydraulic.specific_gravity - ).encode(sys_default_enc) - ) - - f.write( - entry_float.format('VISCOSITY', wn.options.hydraulic.viscosity).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format('TRIALS', wn.options.hydraulic.trials).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format('ACCURACY', wn.options.hydraulic.accuracy).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format('CHECKFREQ', wn.options.hydraulic.checkfreq).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format('MAXCHECK', wn.options.hydraulic.maxcheck).encode( - sys_default_enc - ) - ) - - # EPANET 2.2 OPTIONS - if version == 2.0: # noqa: PLR2004 - pass - else: - if wn.options.hydraulic.headerror != 0: - f.write( - entry_float.format( - 'HEADERROR', wn.options.hydraulic.headerror - ).encode(sys_default_enc) - ) - - if wn.options.hydraulic.flowchange != 0: - f.write( - entry_float.format( - 'FLOWCHANGE', wn.options.hydraulic.flowchange - ).encode(sys_default_enc) - ) - - # EPANET 2.x OPTIONS - if wn.options.hydraulic.damplimit != 0: - f.write( - entry_float.format( - 'DAMPLIMIT', wn.options.hydraulic.damplimit - ).encode(sys_default_enc) - ) - - if wn.options.hydraulic.unbalanced_value is None: - f.write( - entry_string.format( - 'UNBALANCED', wn.options.hydraulic.unbalanced - ).encode(sys_default_enc) - ) - else: - f.write( - '{:20s} {:s} {:d}\n'.format( - 'UNBALANCED', - wn.options.hydraulic.unbalanced, - wn.options.hydraulic.unbalanced_value, - ).encode(sys_default_enc) - ) - - if wn.options.hydraulic.pattern is not None: - f.write( - entry_string.format('PATTERN', wn.options.hydraulic.pattern).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format( - 'DEMAND MULTIPLIER', wn.options.hydraulic.demand_multiplier - ).encode(sys_default_enc) - ) - - # EPANET 2.2 OPTIONS - if version == 2.0: # noqa: PLR2004 - if wn.options.hydraulic.demand_model in ['PDA', 'PDD']: - logger.critical( - 'You have specified a PDD analysis using EPANET 2.0. This is not supported in EPANET 2.0. The analysis will default to DD mode.' - ) - elif wn.options.hydraulic.demand_model in ['PDA', 'PDD']: - f.write( - '{:20s} {}\n'.format( - 'DEMAND MODEL', wn.options.hydraulic.demand_model - ).encode(sys_default_enc) - ) - - minimum_pressure = from_si( - self.flow_units, - wn.options.hydraulic.minimum_pressure, - HydParam.Pressure, - ) - f.write( - '{:20s} {:.2f}\n'.format( - 'MINIMUM PRESSURE', minimum_pressure - ).encode(sys_default_enc) - ) - - required_pressure = from_si( - self.flow_units, - wn.options.hydraulic.required_pressure, - HydParam.Pressure, - ) - if ( - required_pressure >= 0.1 # noqa: PLR2004 - ): # EPANET lower limit on required pressure = 0.1 (in psi or m) - f.write( - '{:20s} {:.2f}\n'.format( - 'REQUIRED PRESSURE', required_pressure - ).encode(sys_default_enc) - ) - else: - warnings.warn( # noqa: B028 - 'REQUIRED PRESSURE is below the lower limit for EPANET (0.1 in psi or m). The value has been set to 0.1 in the INP file.' - ) - logger.warning( - 'REQUIRED PRESSURE is below the lower limit for EPANET (0.1 in psi or m). The value has been set to 0.1 in the INP file.' - ) - f.write( - '{:20s} {:.2f}\n'.format('REQUIRED PRESSURE', 0.1).encode( - sys_default_enc - ) - ) - f.write( - '{:20s} {}\n'.format( - 'PRESSURE EXPONENT', wn.options.hydraulic.pressure_exponent - ).encode(sys_default_enc) - ) - - if wn.options.hydraulic.inpfile_pressure_units is not None: - f.write( - entry_string.format( - 'PRESSURE', wn.options.hydraulic.inpfile_pressure_units - ).encode(sys_default_enc) - ) - - # EPANET 2.0+ OPTIONS - f.write( - entry_float.format( - 'EMITTER EXPONENT', wn.options.hydraulic.emitter_exponent - ).encode(sys_default_enc) - ) - - if wn.options.quality.parameter.upper() in ['NONE', 'AGE']: - f.write( - entry_string.format('QUALITY', wn.options.quality.parameter).encode( - sys_default_enc - ) - ) - elif wn.options.quality.parameter.upper() == 'TRACE': - f.write( - '{:20s} {} {}\n'.format( - 'QUALITY', - wn.options.quality.parameter, - wn.options.quality.trace_node, - ).encode(sys_default_enc) - ) - else: - f.write( - '{:20s} {} {}\n'.format( - 'QUALITY', - wn.options.quality.chemical_name, - wn.options.quality.inpfile_units, - ).encode(sys_default_enc) - ) - - f.write( - entry_float.format('DIFFUSIVITY', wn.options.quality.diffusivity).encode( - sys_default_enc - ) - ) - - f.write( - entry_float.format('TOLERANCE', wn.options.quality.tolerance).encode( - sys_default_enc - ) - ) - - if wn.options.hydraulic.hydraulics is not None: - f.write( - '{:20s} {:s} {:<30s}\n'.format( - 'HYDRAULICS', - wn.options.hydraulic.hydraulics, - wn.options.hydraulic.hydraulics_filename, - ).encode(sys_default_enc) - ) - - if wn.options.graphics.map_filename is not None: - f.write( - entry_string.format('MAP', wn.options.graphics.map_filename).encode( - sys_default_enc - ) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_times(self): - opts = self.wn.options - time_format = ['am', 'AM', 'pm', 'PM'] - for lnum, line in self.sections['[TIMES]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if current[0].upper() == 'DURATION': - opts.time.duration = ( - int(float(current[1]) * 3600) - if _is_number(current[1]) - else int(_str_time_to_sec(current[1])) - ) - elif current[0].upper() == 'HYDRAULIC': - opts.time.hydraulic_timestep = ( - int(float(current[2]) * 3600) - if _is_number(current[2]) - else int(_str_time_to_sec(current[2])) - ) - elif current[0].upper() == 'QUALITY': - opts.time.quality_timestep = ( - int(float(current[2]) * 3600) - if _is_number(current[2]) - else int(_str_time_to_sec(current[2])) - ) - elif current[1].upper() == 'CLOCKTIME': - if len(current) > 3: # noqa: PLR2004 - time_format = current[3].upper() - else: - # Kludge for 24hr time that needs an AM/PM - time_format = 'AM' - time = current[2] - opts.time.start_clocktime = _clock_time_to_sec(time, time_format) - elif current[0].upper() == 'STATISTIC': - opts.time.statistic = current[1].upper() - else: - # Other time options: RULE TIMESTEP, PATTERN TIMESTEP, REPORT TIMESTEP, REPORT START - key_string = current[0] + '_' + current[1] - setattr( - opts.time, - key_string.lower(), - int(float(current[2]) * 3600) - if _is_number(current[2]) - else int(_str_time_to_sec(current[2])), - ) - - def _write_times(self, f, wn): - f.write('[TIMES]\n'.encode(sys_default_enc)) - entry = '{:20s} {:10s}\n' - time_entry = '{:20s} {:02d}:{:02d}:{:02d}\n' - time = wn.options.time - - hrs, mm, sec = _sec_to_string(time.duration) - f.write(time_entry.format('DURATION', hrs, mm, sec).encode(sys_default_enc)) - - hrs, mm, sec = _sec_to_string(time.hydraulic_timestep) - f.write( - time_entry.format('HYDRAULIC TIMESTEP', hrs, mm, sec).encode( - sys_default_enc - ) - ) - - hrs, mm, sec = _sec_to_string(time.quality_timestep) - f.write( - time_entry.format('QUALITY TIMESTEP', hrs, mm, sec).encode( - sys_default_enc - ) - ) - - hrs, mm, sec = _sec_to_string(time.pattern_timestep) - f.write( - time_entry.format('PATTERN TIMESTEP', hrs, mm, sec).encode( - sys_default_enc - ) - ) - - hrs, mm, sec = _sec_to_string(time.pattern_start) - f.write( - time_entry.format('PATTERN START', hrs, mm, sec).encode(sys_default_enc) - ) - - hrs, mm, sec = _sec_to_string(time.report_timestep) - f.write( - time_entry.format('REPORT TIMESTEP', hrs, mm, sec).encode( - sys_default_enc - ) - ) - - hrs, mm, sec = _sec_to_string(time.report_start) - f.write( - time_entry.format('REPORT START', hrs, mm, sec).encode(sys_default_enc) - ) - - hrs, mm, sec = _sec_to_string(time.start_clocktime) - - # Sina added this to WNTR-1: this adds the ability to run correctly for - # time steps that are more than the first day - day = int(hrs / 24) - hrs -= day * 24 - - if hrs < 12: # noqa: PLR2004 - time_format = ' AM' - else: - hrs -= 12 - time_format = ' PM' - f.write( - '{:20s} {:02d}:{:02d}:{:02d}{:s}\n'.format( - 'START CLOCKTIME', hrs, mm, sec, time_format - ).encode(sys_default_enc) - ) - - hrs, mm, sec = _sec_to_string(time.rule_timestep) - - f.write( - time_entry.format('RULE TIMESTEP', hrs, mm, int(sec)).encode( - sys_default_enc - ) - ) - f.write( - entry.format('STATISTIC', wn.options.time.statistic).encode( - sys_default_enc - ) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_report(self): # noqa: C901 - for lnum, line in self.sections['[REPORT]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if current[0].upper() in ['PAGE', 'PAGESIZE']: - self.wn.options.report.pagesize = int(current[1]) - elif current[0].upper() == 'FILE': - self.wn.options.report.file = current[1] - elif current[0].upper() == 'STATUS': - self.wn.options.report.status = current[1].upper() - elif current[0].upper() == 'SUMMARY': - self.wn.options.report.summary = current[1].upper() - elif current[0].upper() == 'ENERGY': - self.wn.options.report.energy = current[1].upper() - elif current[0].upper() == 'NODES': - if current[1].upper() == 'NONE': - self.wn.options.report.nodes = False - elif current[1].upper() == 'ALL': - self.wn.options.report.nodes = True - elif not isinstance(self.wn.options.report.nodes, list): - self.wn.options.report.nodes = [] - for ct in range(len(current) - 2): - i = ct + 2 - self.wn.options.report.nodes.append(current[i]) - else: - for ct in range(len(current) - 2): - i = ct + 2 - self.wn.options.report.nodes.append(current[i]) - elif current[0].upper() == 'LINKS': - if current[1].upper() == 'NONE': - self.wn.options.report.links = False - elif current[1].upper() == 'ALL': - self.wn.options.report.links = True - elif not isinstance(self.wn.options.report.links, list): - self.wn.options.report.links = [] - for ct in range(len(current) - 2): - i = ct + 2 - self.wn.options.report.links.append(current[i]) - else: - for ct in range(len(current) - 2): - i = ct + 2 - self.wn.options.report.links.append(current[i]) - elif ( - current[0].lower() not in self.wn.options.report.report_params.keys() # noqa: SIM118 - ): - logger.warning('Unknown report parameter: %s', current[0]) - continue - elif current[1].upper() == 'YES': - self.wn.options.report.report_params[current[0].lower()] = True - elif current[1].upper() == 'NO': - self.wn.options.report.report_params[current[0].lower()] = False - else: - self.wn.options.report.param_opts[current[0].lower()][ - current[1].upper() - ] = float(current[2]) - - def _write_report(self, f, wn): # noqa: C901 - f.write('[REPORT]\n'.encode(sys_default_enc)) - report = wn.options.report - if report.status.upper() != 'NO': - f.write(f'STATUS {report.status}\n'.encode(sys_default_enc)) - if report.summary.upper() != 'YES': - f.write(f'SUMMARY {report.summary}\n'.encode(sys_default_enc)) - if report.pagesize is not None: - f.write(f'PAGE {report.pagesize}\n'.encode(sys_default_enc)) - if report.report_filename is not None: - f.write(f'FILE {report.report_filename}\n'.encode(sys_default_enc)) - if report.energy.upper() != 'NO': - f.write(f'ENERGY {report.status}\n'.encode(sys_default_enc)) - if report.nodes is True: - f.write('NODES ALL\n'.encode(sys_default_enc)) - elif isinstance(report.nodes, str): - f.write(f'NODES {report.nodes}\n'.encode(sys_default_enc)) - elif isinstance(report.nodes, list): - for ct, node in enumerate(report.nodes): - if ct == 0: - f.write(f'NODES {node}'.encode(sys_default_enc)) - elif ct % 10 == 0: - f.write(f'\nNODES {node}'.encode(sys_default_enc)) - else: - f.write(f' {node}'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - if report.links is True: - f.write('LINKS ALL\n'.encode(sys_default_enc)) - elif isinstance(report.links, str): - f.write(f'LINKS {report.links}\n'.encode(sys_default_enc)) - elif isinstance(report.links, list): - for ct, link in enumerate(report.links): - if ct == 0: - f.write(f'LINKS {link}'.encode(sys_default_enc)) - elif ct % 10 == 0: - f.write(f'\nLINKS {link}'.encode(sys_default_enc)) - else: - f.write(f' {link}'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - # FIXME: defaults no longer located here # noqa: FIX001, TD001, TD002 - # for key, item in report.report_params.items(): - # if item[1] != item[0]: - # f.write('{:10s} {}\n'.format(key.upper(), item[1]).encode(sys_default_enc)) - for key, item in report.param_opts.items(): - for opt, val in item.items(): - f.write( - f'{key.upper():10s} {opt.upper():10s} {val}\n'.encode( - sys_default_enc - ) - ) - f.write('\n'.encode(sys_default_enc)) - - # Network Map/Tags - - def _read_coordinates(self): - for lnum, line in self.sections['[COORDINATES]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - # assert(len(current) == 3), ("Error reading node coordinates. Check format.") - node = self.wn.get_node(current[0]) - node.coordinates = (float(current[1]), float(current[2])) - - def _write_coordinates(self, f, wn): - f.write('[COORDINATES]\n'.encode(sys_default_enc)) - entry = '{:10s} {:20.9f} {:20.9f}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';Node', 'X-Coord', 'Y-Coord').encode(sys_default_enc)) - for name, node in wn.nodes(): - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - val = node.coordinates - f.write(entry.format(name, val[0], val[1]).encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_vertices(self): - for lnum, line in self.sections['[VERTICES]']: # noqa: B007 - line = line.split(';')[0].strip() # noqa: PLW2901 - current = line.split() - if current == []: - continue - if len(current) != 3: # noqa: PLR2004 - logger.warning('Invalid VERTICES line: %s', line) - continue - link_name = current[0] - link = self.wn.get_link(link_name) - link._vertices.append((float(current[1]), float(current[2]))) # noqa: SLF001 - - def _write_vertices(self, f, wn): - f.write('[VERTICES]\n'.encode(sys_default_enc)) - entry = '{:10s} {:20.9f} {:20.9f}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';Link', 'X-Coord', 'Y-Coord').encode(sys_default_enc)) - for name, link in wn.links(): - if link._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - for vert in ( - link._vertices # noqa: SLF001 - ): # Sina: I unindented this and the next line. Possible Bug in WNTR-1 - f.write(entry.format(name, vert[0], vert[1]).encode(sys_default_enc)) - - f.write('\n'.encode(sys_default_enc)) - - def _read_labels(self): - labels = [] - for lnum, line in self.sections['[LABELS]']: # noqa: B007 - line = line.split(';')[0].strip() # noqa: PLW2901 - current = line.split() - if current == []: - continue - labels.append(line) - self.wn._labels = labels # noqa: SLF001 - - def _write_labels(self, f, wn): - f.write('[LABELS]\n'.encode(sys_default_enc)) - if wn._labels is not None: # noqa: SLF001 - for label in wn._labels: # noqa: SLF001 - f.write(f' {label}\n'.encode(sys_default_enc)) - f.write('\n'.encode(sys_default_enc)) - - def _read_backdrop(self): - for lnum, line in self.sections['[BACKDROP]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - key = current[0].upper() - if key == 'DIMENSIONS' and len(current) > 4: # noqa: PLR2004 - self.wn.options.graphics.dimensions = [ - current[1], - current[2], - current[3], - current[4], - ] - elif key == 'UNITS' and len(current) > 1: - self.wn.options.graphics.units = current[1] - elif key == 'FILE' and len(current) > 1: - self.wn.options.graphics.image_filename = current[1] - elif key == 'OFFSET' and len(current) > 2: # noqa: PLR2004 - self.wn.options.graphics.offset = [current[1], current[2]] - - def _write_backdrop(self, f, wn): - if wn.options.graphics is not None: - f.write('[BACKDROP]\n'.encode(sys_default_enc)) - if wn.options.graphics.dimensions is not None: - f.write( - f'DIMENSIONS {wn.options.graphics.dimensions[0]} {wn.options.graphics.dimensions[1]} {wn.options.graphics.dimensions[2]} {wn.options.graphics.dimensions[3]}\n'.encode( - sys_default_enc - ) - ) - if wn.options.graphics.units is not None: - f.write( - f'UNITS {wn.options.graphics.units}\n'.encode(sys_default_enc) - ) - if wn.options.graphics.image_filename is not None: - f.write( - f'FILE {wn.options.graphics.image_filename}\n'.encode( - sys_default_enc - ) - ) - if wn.options.graphics.offset is not None: - f.write( - f'OFFSET {wn.options.graphics.offset[0]} {wn.options.graphics.offset[1]}\n'.encode( - sys_default_enc - ) - ) - f.write('\n'.encode(sys_default_enc)) - - def _read_tags(self): - for lnum, line in self.sections['[TAGS]']: # noqa: B007 - line = line.split(';')[0] # noqa: PLW2901 - current = line.split() - if current == []: - continue - if current[0] == 'NODE': - node = self.wn.get_node(current[1]) - node.tag = current[2] - elif current[0] == 'LINK': - link = self.wn.get_link(current[1]) - link.tag = current[2] - else: - continue - - def _write_tags(self, f, wn): - f.write('[TAGS]\n'.encode(sys_default_enc)) - entry = '{:10s} {:10s} {:10s}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';type', 'name', 'tag').encode(sys_default_enc)) - nnodes = list(wn.node_name_list) - # nnodes.sort() - for node_name in nnodes: - node = wn.nodes[node_name] - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if node.tag: - f.write( - entry.format('NODE', node_name, node.tag).encode(sys_default_enc) - ) - nlinks = list(wn.link_name_list) - nlinks.sort() - for link_name in nlinks: - link = wn.links[link_name] - - if link._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if link.tag: - f.write( - entry.format('LINK', link_name, link.tag).encode(sys_default_enc) - ) - f.write('\n'.encode(sys_default_enc)) - - # End of File - - def _read_end(self): - """Finalize read by verifying that all curves have been dealt with""" # noqa: D400 - - def create_curve(curve_name): - curve_points = [] - if ( - curve_name not in self.wn.curve_name_list - or self.wn.get_curve(curve_name) is None - ): - for point in self.curves[curve_name]: - x = point[0] - y = point[1] - curve_points.append((x, y)) - self.wn.add_curve(curve_name, None, curve_points) - curve = self.wn.get_curve(curve_name) - return curve # noqa: RET504 - - curve_name_list = self.wn.curve_name_list - for name, curvedata in self.curves.items(): # noqa: B007, PERF102 - if name not in curve_name_list or self.wn.get_curve(name) is None: - warnings.warn( # noqa: B028 - f'Not all curves were used in "{self.wn.name}"; added with type None, units conversion left to user' - ) - logger.warning( - f'Curve was not used: "{name}"; saved as curve type None and unit conversion not performed' - ) - create_curve(name) - - def _write_end(self, f, wn): # noqa: ARG002 - f.write('[END]\n'.encode(sys_default_enc)) - - -class _EpanetRule: - """contains the text for an EPANET rule""" # noqa: D400 - - def __init__(self, ruleID, inp_units=None, mass_units=None): # noqa: N803 - self.inp_units = inp_units - self.mass_units = mass_units - self.ruleID = ruleID - self._if_clauses = [] - self._then_clauses = [] - self._else_clauses = [] - self.priority = 0 - - @classmethod - def parse_rules_lines( # noqa: C901 - cls, - lines, - flow_units=FlowUnits.SI, - mass_units=MassUnits.mg, - ) -> list: - rules = list() # noqa: C408 - rule = None - in_if = False - in_then = False - in_else = False - new_lines = list() # noqa: C408 - new_line = list() # noqa: C408 - for line in lines: - if isinstance(line, (tuple, list)): - line = line[1] # noqa: PLW2901 - line = line.split(';')[0] # noqa: PLW2901 - words = line.strip().split() - for word in words: - if word.upper() in [ - 'RULE', - 'IF', - 'THEN', - 'ELSE', - 'AND', - 'OR', - 'PRIORITY', - ]: - if len(new_line) > 0: - text = ' '.join(new_line) - new_lines.append(text) - new_line = list() # noqa: C408 - new_line.append(word) - if len(new_line) > 0: - text = ' '.join(new_line) - new_lines.append(text) - - for line in new_lines: - words = line.split() - if words == []: - continue - if len(words) == 0: - continue - if words[0].upper() == 'RULE': - if rule is not None: - rules.append(rule) - rule = _EpanetRule(words[1], flow_units, mass_units) - in_if = False - in_then = False - in_else = False - elif words[0].upper() == 'IF': - in_if = True - in_then = False - in_else = False - rule.add_if(line) - elif words[0].upper() == 'THEN': - in_if = False - in_then = True - in_else = False - rule.add_then(line) - elif words[0].upper() == 'ELSE': - in_if = False - in_then = False - in_else = True - rule.add_else(line) - elif words[0].upper() == 'PRIORITY': - in_if = False - in_then = False - in_else = False - rule.set_priority(words[1]) - elif in_if: - rule.add_if(line) - elif in_then: - rule.add_then(line) - elif in_else: - rule.add_else(line) - else: - continue - if rule is not None: - rules.append(rule) - return rules - - def from_if_then_else(self, control): - """Create a rule from a Rule object""" # noqa: D400 - if isinstance(control, Rule): - self.ruleID = control.name - self.add_control_condition(control._condition) # noqa: SLF001 - for ct, action in enumerate(control._then_actions): # noqa: SLF001 - if ct == 0: - self.add_action_on_true(action) - else: - self.add_action_on_true(action, ' AND') - for ct, action in enumerate(control._else_actions): # noqa: SLF001 - if ct == 0: - self.add_action_on_false(action) - else: - self.add_action_on_false(action, ' AND') - self.set_priority(control._priority) # noqa: SLF001 - else: - raise ValueError( # noqa: TRY004 - 'Invalid control type for rules: %s' % control.__class__.__name__ # noqa: UP031 - ) - - def add_if(self, clause): - """Add an "if/and/or" clause from an INP file""" # noqa: D400 - self._if_clauses.append(clause) - - def add_control_condition(self, condition, prefix=' IF'): # noqa: C901 - """Add a ControlCondition from an IfThenElseControl""" # noqa: D400 - if isinstance(condition, OrCondition): - self.add_control_condition(condition._condition_1, prefix) # noqa: SLF001 - self.add_control_condition(condition._condition_2, ' OR') # noqa: SLF001 - elif isinstance(condition, AndCondition): - self.add_control_condition(condition._condition_1, prefix) # noqa: SLF001 - self.add_control_condition(condition._condition_2, ' AND') # noqa: SLF001 - elif isinstance(condition, TimeOfDayCondition): - fmt = '{} SYSTEM CLOCKTIME {} {}' - clause = fmt.format( - prefix, - condition._relation.text, # noqa: SLF001 - condition._sec_to_clock(condition._threshold), # noqa: SLF001 - ) - self.add_if(clause) - elif isinstance(condition, SimTimeCondition): - fmt = '{} SYSTEM TIME {} {}' - clause = fmt.format( - prefix, - condition._relation.text, # noqa: SLF001 - condition._sec_to_hours_min_sec(condition._threshold), # noqa: SLF001 - ) - self.add_if(clause) - elif isinstance(condition, ValueCondition): - fmt = ( - '{} {} {} {} {} {}' # CONJ, TYPE, ID, ATTRIBUTE, RELATION, THRESHOLD - ) - attr = condition._source_attr # noqa: SLF001 - val_si = condition._repr_value(attr, condition._threshold) # noqa: SLF001 - if attr.lower() == 'demand': - value = f'{from_si(self.inp_units, val_si, HydParam.Demand):.6g}' - elif attr.lower() in ['head', 'level']: - value = ( - f'{from_si(self.inp_units, val_si, HydParam.HydraulicHead):.6g}' - ) - elif attr.lower() == 'flow': - value = f'{from_si(self.inp_units, val_si, HydParam.Flow):.6g}' - elif attr.lower() == 'pressure': - value = f'{from_si(self.inp_units, val_si, HydParam.Pressure):.6g}' - elif attr.lower() == 'setting': - if isinstance(condition._source_obj, Valve): # noqa: SLF001 - if condition._source_obj.valve_type.upper() in [ # noqa: SLF001 - 'PRV', - 'PBV', - 'PSV', - ]: - value = from_si(self.inp_units, val_si, HydParam.Pressure) - elif condition._source_obj.valve_type.upper() == 'FCV': # noqa: SLF001 - value = from_si(self.inp_units, val_si, HydParam.Flow) - else: - value = val_si - else: - value = val_si - value = f'{value:.6g}' - else: # status - value = val_si - if isinstance(condition._source_obj, Valve): # noqa: SLF001 - cls = 'Valve' - elif isinstance(condition._source_obj, Pump): # noqa: SLF001 - cls = 'Pump' - else: - cls = condition._source_obj.__class__.__name__ # noqa: SLF001 - clause = fmt.format( - prefix, - cls, - condition._source_obj.name, # noqa: SLF001 - condition._source_attr, # noqa: SLF001 - condition._relation.symbol, # noqa: SLF001 - value, - ) - self.add_if(clause) - else: - raise ValueError('Unknown ControlCondition for EPANET Rules') # noqa: EM101, TRY003, TRY004 - - def add_then(self, clause): - """Add a "then/and" clause from an INP file""" # noqa: D400 - self._then_clauses.append(clause) - - def add_action_on_true(self, action, prefix=' THEN'): # noqa: C901 - """Add a "then" action from an IfThenElseControl""" # noqa: D400 - if isinstance(action, ControlAction): - fmt = '{} {} {} {} = {}' - attr = action._attribute # noqa: SLF001 - val_si = action._repr_value() # noqa: SLF001 - if attr.lower() == 'demand': - value = f'{from_si(self.inp_units, val_si, HydParam.Demand):.6g}' - elif attr.lower() in ['head', 'level']: - value = ( - f'{from_si(self.inp_units, val_si, HydParam.HydraulicHead):.6g}' - ) - elif attr.lower() == 'flow': - value = f'{from_si(self.inp_units, val_si, HydParam.Flow):.6g}' - elif attr.lower() == 'pressure': - value = f'{from_si(self.inp_units, val_si, HydParam.Pressure):.6g}' - elif attr.lower() == 'setting': - if isinstance(action.target()[0], Valve): - if action.target()[0].valve_type.upper() in [ - 'PRV', - 'PBV', - 'PSV', - ]: - value = from_si(self.inp_units, val_si, HydParam.Pressure) - elif action.target()[0].valve_type.upper() == 'FCV': - value = from_si(self.inp_units, val_si, HydParam.Flow) - else: - value = val_si - else: - value = val_si - value = f'{value:.6g}' - else: # status - value = val_si - if isinstance(action.target()[0], Valve): - cls = 'Valve' - elif isinstance(action.target()[0], Pump): - cls = 'Pump' - else: - cls = action.target()[0].__class__.__name__ - clause = fmt.format( - prefix, cls, action.target()[0].name, action.target()[1], value - ) - self.add_then(clause) - - def add_else(self, clause): - """Add an "else/and" clause from an INP file""" # noqa: D400 - self._else_clauses.append(clause) - - def add_action_on_false(self, action, prefix=' ELSE'): # noqa: C901 - """Add an "else" action from an IfThenElseControl""" # noqa: D400 - if isinstance(action, ControlAction): - fmt = '{} {} {} {} = {}' - attr = action._attribute # noqa: SLF001 - val_si = action._repr_value() # noqa: SLF001 - if attr.lower() == 'demand': - value = f'{from_si(self.inp_units, val_si, HydParam.Demand):.6g}' - elif attr.lower() in ['head', 'level']: - value = ( - f'{from_si(self.inp_units, val_si, HydParam.HydraulicHead):.6g}' - ) - elif attr.lower() == 'flow': - value = f'{from_si(self.inp_units, val_si, HydParam.Flow):.6g}' - elif attr.lower() == 'pressure': - value = f'{from_si(self.inp_units, val_si, HydParam.Pressure):.6g}' - elif attr.lower() == 'setting': - if isinstance(action.target()[0], Valve): - if action.target()[0].valve_type.upper() in [ - 'PRV', - 'PBV', - 'PSV', - ]: - value = from_si(self.inp_units, val_si, HydParam.Pressure) - elif action.target()[0].valve_type.upper() == 'FCV': - value = from_si(self.inp_units, val_si, HydParam.Flow) - else: - value = val_si - else: - value = val_si - value = f'{value:.6g}' - else: # status - value = val_si - if isinstance(action.target()[0], Valve): - cls = 'Valve' - elif isinstance(action.target()[0], Pump): - cls = 'Pump' - else: - cls = action.target()[0].__class__.__name__ - clause = fmt.format( - prefix, cls, action.target()[0].name, action.target()[1], value - ) - self.add_else(clause) - - def set_priority(self, priority): - self.priority = int(float(priority)) - - def __str__(self): - if self.priority >= 0: - if len(self._else_clauses) > 0: - return 'RULE {}\n{}\n{}\n{}\n PRIORITY {}\n ; end of rule\n'.format( - self.ruleID, - '\n'.join(self._if_clauses), - '\n'.join(self._then_clauses), - '\n'.join(self._else_clauses), - self.priority, - ) - else: # noqa: RET505 - return 'RULE {}\n{}\n{}\n PRIORITY {}\n ; end of rule\n'.format( - self.ruleID, - '\n'.join(self._if_clauses), - '\n'.join(self._then_clauses), - self.priority, - ) - elif len(self._else_clauses) > 0: - return 'RULE {}\n{}\n{}\n{}\n ; end of rule\n'.format( - self.ruleID, - '\n'.join(self._if_clauses), - '\n'.join(self._then_clauses), - '\n'.join(self._else_clauses), - ) - else: - return 'RULE {}\n{}\n{}\n ; end of rule\n'.format( - self.ruleID, - '\n'.join(self._if_clauses), - '\n'.join(self._then_clauses), - ) - - def generate_control(self, model): # noqa: C901 - condition_list = [] - for line in self._if_clauses: - condition = None - words = line.split() - if words[1].upper() == 'SYSTEM': - if words[2].upper() == 'DEMAND': - # TODO: system demand # noqa: TD002 - pass - elif words[2].upper() == 'TIME': - condition = SimTimeCondition( - model, words[3], ' '.join(words[4:]) - ) - else: - condition = TimeOfDayCondition( - model, words[3], ' '.join(words[4:]) - ) - else: - attr = words[3].lower() - value = ValueCondition._parse_value(words[5]) # noqa: SLF001 - if attr.lower() == 'demand': - value = to_si(self.inp_units, value, HydParam.Demand) - elif attr.lower() == 'head' or attr.lower() == 'level': - value = to_si(self.inp_units, value, HydParam.HydraulicHead) - elif attr.lower() == 'flow': - value = to_si(self.inp_units, value, HydParam.Flow) - elif attr.lower() == 'pressure': - value = to_si(self.inp_units, value, HydParam.Pressure) - elif attr.lower() == 'setting': - link = model.get_link(words[2]) - if isinstance(link, wntrfr.network.Pump): - value = value # noqa: PLW0127 - elif isinstance(link, wntrfr.network.Valve): - if link.valve_type.upper() in ['PRV', 'PBV', 'PSV']: - value = to_si(self.inp_units, value, HydParam.Pressure) - elif link.valve_type.upper() == 'FCV': - value = to_si(self.inp_units, value, HydParam.Flow) - if words[1].upper() in ['NODE', 'JUNCTION', 'RESERVOIR', 'TANK']: - condition = ValueCondition( - model.get_node(words[2]), - words[3].lower(), - words[4].lower(), - value, - ) - elif words[1].upper() in ['LINK', 'PIPE', 'PUMP', 'VALVE']: - condition = ValueCondition( - model.get_link(words[2]), - words[3].lower(), - words[4].lower(), - value, - ) - else: - # FIXME: raise error # noqa: FIX001, TD001, TD002 - pass - if words[0].upper() == 'IF' or words[0].upper() == 'AND': - condition_list.append(condition) - elif words[0].upper() == 'OR': - if len(condition_list) > 0: - other = condition_list[-1] - condition_list.remove(other) - else: - # FIXME: raise error # noqa: FIX001, TD001, TD002 - pass - conj = OrCondition(other, condition) - condition_list.append(conj) - final_condition = None - for condition in condition_list: - if final_condition is None: - final_condition = condition - else: - final_condition = AndCondition(final_condition, condition) - then_acts = [] - for act in self._then_clauses: - words = act.strip().split() - if len(words) < 6: # noqa: PLR2004 - # TODO: raise error # noqa: TD002 - pass - link = model.get_link(words[2]) - attr = words[3].lower() - value = ValueCondition._parse_value(words[5]) # noqa: SLF001 - if attr.lower() == 'demand': - value = to_si(self.inp_units, value, HydParam.Demand) - elif attr.lower() in ['head', 'level']: - value = to_si(self.inp_units, value, HydParam.HydraulicHead) - elif attr.lower() == 'flow': - value = to_si(self.inp_units, value, HydParam.Flow) - elif attr.lower() == 'pressure': - value = to_si(self.inp_units, value, HydParam.Pressure) - elif attr.lower() == 'setting': - if isinstance(link, Valve): - if link.valve_type.upper() in ['PRV', 'PBV', 'PSV']: - value = to_si(self.inp_units, value, HydParam.Pressure) - elif link.valve_type.upper() == 'FCV': - value = to_si(self.inp_units, value, HydParam.Flow) - then_acts.append(ControlAction(link, attr, value)) - else_acts = [] - for act in self._else_clauses: - words = act.strip().split() - if len(words) < 6: # noqa: PLR2004 - # TODO: raise error # noqa: TD002 - pass - link = model.get_link(words[2]) - attr = words[3].lower() - value = ValueCondition._parse_value(words[5]) # noqa: SLF001 - if attr.lower() == 'demand': - value = to_si(self.inp_units, value, HydParam.Demand) - elif attr.lower() in ['head', 'level']: - value = to_si(self.inp_units, value, HydParam.HydraulicHead) - elif attr.lower() == 'flow': - value = to_si(self.inp_units, value, HydParam.Flow) - elif attr.lower() == 'pressure': - value = to_si(self.inp_units, value, HydParam.Pressure) - elif attr.lower() == 'setting': - if isinstance(link, Valve): - if link.valve_type.upper() in ['PRV', 'PBV', 'PSV']: - value = to_si(self.inp_units, value, HydParam.Pressure) - elif link.valve_type.upper() == 'FCV': - value = to_si(self.inp_units, value, HydParam.Flow) - else_acts.append(ControlAction(link, attr, value)) - return Rule( - final_condition, - then_acts, - else_acts, - priority=self.priority, - name=self.ruleID, - ) - - -class BinFile: - """EPANET binary output file reader. - - This class provides read functionality for EPANET binary output files. - - Parameters - ---------- - results_type : list of :class:`~wntrfr.epanet.util.ResultType`, default=None - This parameter is *only* active when using a subclass of the BinFile that implements - a custom reader or writer. - If ``None``, then all results will be saved (node quality, demand, link flow, etc.). - Otherwise, a list of result types can be passed to limit the memory used. - network : bool, default=False - Save a new WaterNetworkModel from the description in the output binary file. Certain - elements may be missing, such as patterns and curves, if this is done. - energy : bool, default=False - Save the pump energy results. - statistics : bool, default=False - Save the statistics lines (different from the stats flag in the inp file) that are - automatically calculated regarding hydraulic conditions. - convert_status : bool, default=True - Convert the EPANET link status (8 values) to simpler WNTR status (3 values). By - default, this is done, and the encoded-cause status values are converted simple state - values, instead. - - Returns - ------- - :class:`~wntrfr.sim.results.SimulationResults` - A WNTR results object will be created and added to the instance after read. - - """ - - def __init__( - self, - result_types=None, - network=False, # noqa: FBT002 - energy=False, # noqa: FBT002 - statistics=False, # noqa: FBT002 - convert_status=True, # noqa: FBT002 - ): - if os.name in ['nt', 'dos'] or sys.platform == 'darwin': - self.ftype = '=f4' - else: - self.ftype = '=f4' - self.idlen = 32 - self.convert_status = convert_status - self.hydraulic_id = None - self.quality_id = None - self.node_names = None - self.link_names = None - self.report_times = None - self.flow_units = None - self.pres_units = None - self.mass_units = None - self.quality_type = None - self.num_nodes = None - self.num_tanks = None - self.num_links = None - self.num_pumps = None - self.num_valves = None - self.report_start = None - self.report_step = None - self.duration = None - self.chemical = None - self.chem_units = None - self.inp_file = None - self.report_file = None - self.results = wntrfr.sim.SimulationResults() - if result_types is None: - self.items = [member for name, member in ResultType.__members__.items()] - else: - self.items = result_types - self.create_network = network - self.keep_energy = energy - self.keep_statistics = statistics - - def _get_time(self, t): - s = int(t) - h = int(s / 3600) - s -= h * 3600 - m = int(s / 60) - s -= m * 60 - s = int(s) - return f'{h:02}:{m:02}:{s:02}' - - def save_network_desc_line(self, element, values): - """Save network description meta-data and element characteristics. - - This method, by default, does nothing. It is available to be overloaded, but the - core implementation assumes that an INP file exists that will have a better, - human readable network description. - - Parameters - ---------- - element : str - The information being saved - values : numpy.array - The values that go with the information - - """ - - def save_energy_line(self, pump_idx, pump_name, values): - """Save pump energy from the output file. - - This method, by default, does nothing. It is available to be overloaded - in order to save information for pump energy calculations. - - Parameters - ---------- - pump_idx : int - the pump index - pump_name : str - the pump name - values : numpy.array - the values to save - - """ - - def finalize_save(self, good_read, sim_warnings): - """Post-process data before writing results. - - This method, by default, does nothing. It is available to be overloaded - in order to post process data. - - Parameters - ---------- - good_read : bool - was the full file read correctly - sim_warnings : int - were there warnings issued during the simulation - - """ - - # @run_lineprofile() - def read( # noqa: C901, PLR0915 - self, - filename, - convergence_error=False, # noqa: FBT002 - darcy_weisbach=False, # noqa: FBT002 - convert=True, # noqa: FBT002 - ): - """Read a binary file and create a results object. - - Parameters - ---------- - filename : str - An EPANET BIN output file - convergence_error: bool (optional) - If convergence_error is True, an error will be raised if the - simulation does not converge. If convergence_error is False, partial results are returned, - a warning will be issued, and results.error_code will be set to 0 - if the simulation does not converge. Default = False. - - Returns - ------- - object - returns a WaterNetworkResults object - - """ - self.results = wntrfr.sim.SimulationResults() - - logger.debug('Read binary EPANET data from %s', filename) - dt_str = 'u1' # .format(self.idlen) - with open(filename, 'rb') as fin: # noqa: PTH123 - ftype = self.ftype - idlen = self.idlen # noqa: F841 - logger.debug('... read prolog information ...') - prolog = np.fromfile(fin, dtype=np.int32, count=15) - magic1 = prolog[0] - version = prolog[1] - nnodes = prolog[2] - ntanks = prolog[3] - nlinks = prolog[4] - npumps = prolog[5] - nvalve = prolog[6] - wqopt = QualType(prolog[7]) - srctrace = prolog[8] - flowunits = FlowUnits(prolog[9]) - presunits = PressureUnits(prolog[10]) - statsflag = StatisticsType(prolog[11]) - reportstart = prolog[12] - reportstep = prolog[13] - duration = prolog[14] - logger.debug('EPANET/Toolkit version %d', version) - logger.debug( - 'Nodes: %d; Tanks/Resrv: %d Links: %d; Pumps: %d; Valves: %d', - nnodes, - ntanks, - nlinks, - npumps, - nvalve, - ) - logger.debug( - 'WQ opt: %s; Trace Node: %s; Flow Units %s; Pressure Units %s', - wqopt, - srctrace, - flowunits, - presunits, - ) - logger.debug( - 'Statistics: %s; Report Start %d, step %d; Duration=%d sec', - statsflag, - reportstart, - reportstep, - duration, - ) - - # Ignore the title lines - np.fromfile(fin, dtype=np.uint8, count=240) - inpfile = np.fromfile(fin, dtype=np.uint8, count=260) - rptfile = np.fromfile(fin, dtype=np.uint8, count=260) - chemical = bytes( - np.fromfile(fin, dtype=dt_str, count=self.idlen)[:] - ).decode(sys_default_enc) - # wqunits = ''.join([chr(f) for f in np.fromfile(fin, dtype=np.uint8, count=idlen) if f!=0 ]) - wqunits = bytes( - np.fromfile(fin, dtype=dt_str, count=self.idlen)[:] - ).decode(sys_default_enc) - mass = wqunits.split('/', 1)[0] - if mass in ['mg', 'ug', 'mg', 'ug']: - massunits = MassUnits[mass] - else: - massunits = MassUnits.mg - self.flow_units = flowunits - self.pres_units = presunits - self.quality_type = wqopt - self.mass_units = massunits - self.num_nodes = nnodes - self.num_tanks = ntanks - self.num_links = nlinks - self.num_pumps = npumps - self.num_valves = nvalve - self.report_start = reportstart - self.report_step = reportstep - self.duration = duration - self.chemical = chemical - self.chem_units = wqunits - self.inp_file = inpfile - self.report_file = rptfile - nodenames = [] - linknames = [] - nodenames = [ - bytes(np.fromfile(fin, dtype=dt_str, count=self.idlen)) - .decode(sys_default_enc) - .replace('\x00', '') - for _ in range(nnodes) - ] - linknames = [ - bytes(np.fromfile(fin, dtype=dt_str, count=self.idlen)) - .decode(sys_default_enc) - .replace('\x00', '') - for _ in range(nlinks) - ] - self.node_names = np.array(nodenames) - self.link_names = np.array(linknames) - linkstart = np.array( # noqa: F841 - np.fromfile(fin, dtype=np.int32, count=nlinks), dtype=int - ) - linkend = np.array( # noqa: F841 - np.fromfile(fin, dtype=np.int32, count=nlinks), dtype=int - ) - linktype = np.fromfile(fin, dtype=np.int32, count=nlinks) - tankidxs = np.fromfile(fin, dtype=np.int32, count=ntanks) # noqa: F841 - tankarea = np.fromfile(fin, dtype=np.dtype(ftype), count=ntanks) # noqa: F841 - elevation = np.fromfile(fin, dtype=np.dtype(ftype), count=nnodes) # noqa: F841 - linklen = np.fromfile(fin, dtype=np.dtype(ftype), count=nlinks) # noqa: F841 - diameter = np.fromfile(fin, dtype=np.dtype(ftype), count=nlinks) # noqa: F841 - """ - self.save_network_desc_line('link_start', linkstart) - self.save_network_desc_line('link_end', linkend) - self.save_network_desc_line('link_type', linktype) - self.save_network_desc_line('tank_node_index', tankidxs) - self.save_network_desc_line('tank_area', tankarea) - self.save_network_desc_line('node_elevation', elevation) - self.save_network_desc_line('link_length', linklen) - self.save_network_desc_line('link_diameter', diameter) - """ - logger.debug('... read energy data ...') - for i in range(npumps): # noqa: B007 - pidx = int(np.fromfile(fin, dtype=np.int32, count=1)) - energy = np.fromfile(fin, dtype=np.dtype(ftype), count=6) - self.save_energy_line(pidx, linknames[pidx - 1], energy) - peakenergy = np.fromfile(fin, dtype=np.dtype(ftype), count=1) - self.peak_energy = peakenergy - - logger.debug('... read EP simulation data ...') - reporttimes = np.arange( - reportstart, - duration + reportstep - (duration % reportstep), - reportstep, - ) - nrptsteps = len(reporttimes) - statsN = nrptsteps # noqa: N806, F841 - if statsflag in [ - StatisticsType.Maximum, - StatisticsType.Minimum, - StatisticsType.Range, - ]: - nrptsteps = 1 - reporttimes = [reportstart + reportstep] - self.num_periods = nrptsteps - self.report_times = reporttimes - - # set up results metadata dictionary - """ - if wqopt == QualType.Age: - self.results.meta['quality_mode'] = 'AGE' - self.results.meta['quality_units'] = 's' - elif wqopt == QualType.Trace: - self.results.meta['quality_mode'] = 'TRACE' - self.results.meta['quality_units'] = '%' - self.results.meta['quality_trace'] = srctrace - elif wqopt == QualType.Chem: - self.results.meta['quality_mode'] = 'CHEMICAL' - self.results.meta['quality_units'] = wqunits - self.results.meta['quality_chem'] = chemical - self.results.time = reporttimes - self.save_network_desc_line('report_times', reporttimes) - self.save_network_desc_line('node_elevation', pd.Series(data=elevation, index=nodenames)) - self.save_network_desc_line('link_length', pd.Series(data=linklen, index=linknames)) - self.save_network_desc_line('link_diameter', pd.Series(data=diameter, index=linknames)) - self.save_network_desc_line('stats_mode', statsflag) - self.save_network_desc_line('stats_N', statsN) - nodetypes = np.array(['Junction']*self.num_nodes, dtype='|S10') - nodetypes[tankidxs-1] = 'Tank' - nodetypes[tankidxs[tankarea==0]-1] = 'Reservoir' - linktypes = np.array(['Pipe']*self.num_links) - linktypes[ linktype == EN.PUMP ] = 'Pump' - linktypes[ linktype > EN.PUMP ] = 'Valve' - self.save_network_desc_line('link_type', pd.Series(data=linktypes, index=linknames, copy=True)) - linktypes[ linktype == EN.CVPIPE ] = 'CV' - linktypes[ linktype == EN.FCV ] = 'FCV' - linktypes[ linktype == EN.PRV ] = 'PRV' - linktypes[ linktype == EN.PSV ] = 'PSV' - linktypes[ linktype == EN.PBV ] = 'PBV' - linktypes[ linktype == EN.TCV ] = 'TCV' - linktypes[ linktype == EN.GPV ] = 'GPV' - self.save_network_desc_line('link_subtype', pd.Series(data=linktypes, index=linknames, copy=True)) - self.save_network_desc_line('node_type', pd.Series(data=nodetypes, index=nodenames, copy=True)) - self.save_network_desc_line('node_names', np.array(nodenames, dtype=str)) - self.save_network_desc_line('link_names', np.array(linknames, dtype=str)) - names = np.array(nodenames, dtype=str) - self.save_network_desc_line('link_start', pd.Series(data=names[linkstart-1], index=linknames, copy=True)) - self.save_network_desc_line('link_end', pd.Series(data=names[linkend-1], index=linknames, copy=True)) - """ - - # type_list = 4*nnodes*['node'] + 8*nlinks*['link'] - name_list = nodenames * 4 + linknames * 8 - valuetype = ( - nnodes * ['demand'] - + nnodes * ['head'] - + nnodes * ['pressure'] - + nnodes * ['quality'] - + nlinks * ['flow'] - + nlinks * ['velocity'] - + nlinks * ['headloss'] - + nlinks * ['linkquality'] - + nlinks * ['linkstatus'] - + nlinks * ['linksetting'] - + nlinks * ['reactionrate'] - + nlinks * ['frictionfactor'] - ) - - # tuples = zip(type_list, valuetype, name_list) - tuples = list(zip(valuetype, name_list)) - # tuples = [(valuetype[i], v) for i, v in enumerate(name_list)] - index = pd.MultiIndex.from_tuples(tuples, names=['value', 'name']) - - try: - data = np.fromfile( - fin, - dtype=np.dtype(ftype), - count=(4 * nnodes + 8 * nlinks) * nrptsteps, - ) - except Exception as e: - logger.exception('Failed to process file: %s', e) # noqa: TRY401 - - N = int(np.floor(len(data) / (4 * nnodes + 8 * nlinks))) # noqa: N806 - if nrptsteps > N: - t = reporttimes[N] - if convergence_error: - logger.error( - 'Simulation did not converge at time ' # noqa: G003 - + self._get_time(t) - + '.' - ) - raise RuntimeError( - 'Simulation did not converge at time ' - + self._get_time(t) - + '.' - ) - else: # noqa: RET506 - data = data[0 : N * (4 * nnodes + 8 * nlinks)] - data = np.reshape(data, (N, (4 * nnodes + 8 * nlinks))) - reporttimes = reporttimes[0:N] - warnings.warn( # noqa: B028 - 'Simulation did not converge at time ' - + self._get_time(t) - + '.' - ) - self.results.error_code = wntrfr.sim.results.ResultsStatus.error - else: - data = np.reshape(data, (nrptsteps, (4 * nnodes + 8 * nlinks))) - self.results.error_code = None - - df = pd.DataFrame(data.transpose(), index=index, columns=reporttimes) # noqa: PD901 - df = df.transpose() # noqa: PD901 - - self.results.node = {} - self.results.link = {} - self.results.network_name = self.inp_file - - if convert: - # Node Results - self.results.node['demand'] = HydParam.Demand._to_si( # noqa: SLF001 - self.flow_units, df['demand'] - ) - self.results.node['head'] = HydParam.HydraulicHead._to_si( # noqa: SLF001 - self.flow_units, df['head'] - ) - self.results.node['pressure'] = HydParam.Pressure._to_si( # noqa: SLF001 - self.flow_units, df['pressure'] - ) - - # Water Quality Results (node and link) - if self.quality_type is QualType.Chem: - self.results.node['quality'] = QualParam.Concentration._to_si( # noqa: SLF001 - self.flow_units, df['quality'], mass_units=self.mass_units - ) - self.results.link['quality'] = QualParam.Concentration._to_si( # noqa: SLF001 - self.flow_units, - df['linkquality'], - mass_units=self.mass_units, - ) - elif self.quality_type is QualType.Age: - self.results.node['quality'] = QualParam.WaterAge._to_si( # noqa: SLF001 - self.flow_units, df['quality'], mass_units=self.mass_units - ) - self.results.link['quality'] = QualParam.WaterAge._to_si( # noqa: SLF001 - self.flow_units, - df['linkquality'], - mass_units=self.mass_units, - ) - else: - self.results.node['quality'] = df['quality'] - self.results.link['quality'] = df['linkquality'] - - # Link Results - self.results.link['flowrate'] = HydParam.Flow._to_si( # noqa: SLF001 - self.flow_units, df['flow'] - ) - self.results.link['velocity'] = HydParam.Velocity._to_si( # noqa: SLF001 - self.flow_units, df['velocity'] - ) - - headloss = np.array(df['headloss']) - headloss[:, linktype < 2] = to_si( # noqa: PLR2004 - self.flow_units, - headloss[:, linktype < 2], # noqa: PLR2004 - HydParam.HeadLoss, - ) # Pipe or CV - headloss[:, linktype >= 2] = to_si( # noqa: PLR2004 - self.flow_units, - headloss[:, linktype >= 2], # noqa: PLR2004 - HydParam.Length, - ) # Pump or Valve - self.results.link['headloss'] = pd.DataFrame( - data=headloss, columns=linknames, index=reporttimes - ) - - status = np.array(df['linkstatus']) - if self.convert_status: - status[status <= 2] = 0 # noqa: PLR2004 - status[status == 3] = 1 # noqa: PLR2004 - status[status >= 5] = 1 # noqa: PLR2004 - status[status == 4] = 2 # noqa: PLR2004 - self.results.link['status'] = pd.DataFrame( - data=status, columns=linknames, index=reporttimes - ) - - setting = np.array(df['linksetting']) - # pump setting is relative speed (unitless) - setting[:, linktype == EN.PIPE] = to_si( - self.flow_units, - setting[:, linktype == EN.PIPE], - HydParam.RoughnessCoeff, - darcy_weisbach=darcy_weisbach, - ) - setting[:, linktype == EN.PRV] = to_si( - self.flow_units, - setting[:, linktype == EN.PRV], - HydParam.Pressure, - ) - setting[:, linktype == EN.PSV] = to_si( - self.flow_units, - setting[:, linktype == EN.PSV], - HydParam.Pressure, - ) - setting[:, linktype == EN.PBV] = to_si( - self.flow_units, - setting[:, linktype == EN.PBV], - HydParam.Pressure, - ) - setting[:, linktype == EN.FCV] = to_si( - self.flow_units, setting[:, linktype == EN.FCV], HydParam.Flow - ) - self.results.link['setting'] = pd.DataFrame( - data=setting, columns=linknames, index=reporttimes - ) - - self.results.link['friction_factor'] = df['frictionfactor'] - self.results.link['reaction_rate'] = QualParam.ReactionRate._to_si( # noqa: SLF001 - self.flow_units, df['reactionrate'], self.mass_units - ) - else: - self.results.node['demand'] = df['demand'] - self.results.node['head'] = df['head'] - self.results.node['pressure'] = df['pressure'] - self.results.node['quality'] = df['quality'] - - self.results.link['flowrate'] = df['flow'] - self.results.link['headloss'] = df['headloss'] - self.results.link['velocity'] = df['velocity'] - self.results.link['quality'] = df['linkquality'] - self.results.link['status'] = df['linkstatus'] - self.results.link['setting'] = df['linksetting'] - self.results.link['friction_factor'] = df['frictionfactor'] - self.results.link['reaction_rate'] = df['reactionrate'] - - logger.debug('... read epilog ...') - # Read the averages and then the number of periods for checks - averages = np.fromfile(fin, dtype=np.dtype(ftype), count=4) - self.averages = averages - np.fromfile(fin, dtype=np.int32, count=1) - warnflag = np.fromfile(fin, dtype=np.int32, count=1) - magic2 = np.fromfile(fin, dtype=np.int32, count=1) - if magic1 != magic2: - logger.critical( - 'The magic number did not match -- binary incomplete or incorrectly read. If you believe this file IS complete, please try a different float type. Current type is "%s"', - ftype, - ) - # print numperiods, warnflag, magic - if warnflag != 0: - logger.warning('Warnings were issued during simulation') - self.finalize_save(magic1 == magic2, warnflag) - - return self.results - - -class NoSectionError(Exception): # noqa: D101 - pass - - -class _InpFileDifferHelper: # pragma: no cover - def __init__(self, f): - """Parameters - ---------- - f: str - - """ # noqa: D205 - self._f = open(f) # noqa: SIM115, PTH123 - self._num_lines = len(self._f.readlines()) - self._end = self._f.tell() - self._f.seek(0) - - @property - def f(self): - return self._f - - def iter(self, start=0, stop=None, skip_section_headings=True): # noqa: FBT002 - if stop is None: - stop = self._end - f = self.f - f.seek(start) - while f.tell() != stop: - loc = f.tell() - line = f.readline() - if line.startswith(';'): - continue - if skip_section_headings: - if line.startswith('['): - continue - if len(line.split()) == 0: - continue - line = line.split(';')[0] - yield loc, line - - def get_section(self, sec): - """Parameters - ---------- - sec: str - The section - - Returns - ------- - start: int - The starting point in the file for sec - end: int - The ending point in the file for sec - - """ # noqa: D205 - start = None - end = None - in_sec = False - for loc, line in self.iter(0, None, skip_section_headings=False): - line = line.split(';')[0] # noqa: PLW2901 - if sec in line: - start = loc - in_sec = True - elif '[' in line: - if in_sec: - end = loc - in_sec = False - break - if start is None: - raise NoSectionError('Could not find section ' + sec) - if end is None: - end = self._end - return start, end - - def contains_section(self, sec): - """Parameters - ---------- - sec: str - - """ # noqa: D205 - try: - self.get_section(sec) - return True # noqa: DOC201, RUF100, TRY300 - except NoSectionError: - return False - - -def _convert_line(line): # pragma: no cover - """Parameters - ---------- - line: str - - Returns - ------- - list - - """ # noqa: D205 - line = line.upper().split() - tmp = [] - for i in line: - if '.' in i: - try: - tmp.append(float(i)) - except: # noqa: E722 - tmp.append(i) - else: - try: - tmp.append(int(i)) - except: # noqa: E722 - tmp.append(i) - return tmp - - -# pragma: no cover -def _compare_lines(line1, line2, tol=1e-14): - """Parameters - ---------- - line1: list of str - line2: list of str - - Returns - ------- - bool - - """ # noqa: D205 - if len(line1) != len(line2): - return False - - for i, a in enumerate(line1): - b = line2[i] - if isinstance(a, (int, float)) or ( - isinstance(a, int) and isinstance(b, int) - ): - if a != b: - return False - elif isinstance(a, (int, float)) and isinstance(b, (int, float)): - if abs(a - b) > tol: - return False - elif a != b: - return False - - return True - - -def _clean_line(wn, sec, line): # pragma: no cover - """Parameters - ---------- - wn: wntrfr.network.WaterNetworkModel - sec: str - line: list of str - - Returns - ------- - new_list: list of str - - """ # noqa: D205 - if sec == '[JUNCTIONS]': - if len(line) == 4: # noqa: PLR2004 - other = wn.options.hydraulic.pattern - if other is None: - other = 1 - if isinstance(line[3], int) and isinstance(other, int): - other = int(other) - if line[3] == other: - return line[:3] - - return line - - -def _read_control_line(line, wn, flow_units, control_name): # noqa: C901 - """Parameters - ---------- - line: str - wn: wntrfr.network.WaterNetworkModel - flow_units: str - control_name: str - - Returns - ------- - control_obj: Control - - """ # noqa: D205 - line = line.split(';')[0] - current = line.split() - if current == []: - return None - link_name = current[1] - link = wn.get_link(link_name) - if current[5].upper() != 'TIME' and current[5].upper() != 'CLOCKTIME': - node_name = current[5] - current = [i.upper() for i in current] - current[1] = link_name # don't capitalize the link name - - # Create the control action object - - status = current[2].upper() - if ( - status == 'OPEN' # noqa: PLR1714 - or status == 'OPENED' - or status == 'CLOSED' - or status == 'ACTIVE' - ): - setting = LinkStatus[status].value - action_obj = wntrfr.network.ControlAction(link, 'status', setting) - elif isinstance(link, wntrfr.network.Pump): - action_obj = wntrfr.network.ControlAction( - link, 'base_speed', float(current[2]) - ) - elif isinstance(link, wntrfr.network.Valve): - if ( - link.valve_type == 'PRV' # noqa: PLR1714 - or link.valve_type == 'PSV' - or link.valve_type == 'PBV' - ): - setting = to_si(flow_units, float(current[2]), HydParam.Pressure) - elif link.valve_type == 'FCV': - setting = to_si(flow_units, float(current[2]), HydParam.Flow) - elif link.valve_type == 'TCV': - setting = float(current[2]) - elif link.valve_type == 'GPV': - setting = current[2] - else: - raise ValueError( # noqa: TRY003 - f'Unrecognized valve type {link.valve_type} while parsing control {line}' # noqa: EM102 - ) - action_obj = wntrfr.network.ControlAction(link, 'setting', setting) - else: - raise RuntimeError( - f'Links of type {type(link)} can only have controls that change\n' # noqa: ISC003 - + f'the link status. Control: {line}' - ) - - # Create the control object - # control_count += 1 - # control_name = 'control '+str(control_count) - if 'TIME' not in current and 'CLOCKTIME' not in current: - threshold = None - if 'IF' in current: - node = wn.get_node(node_name) - if current[6] == 'ABOVE': - oper = np.greater - elif current[6] == 'BELOW': - oper = np.less - else: - raise RuntimeError( - 'The following control is not recognized: ' + line - ) - # OKAY - we are adding in the elevation. This is A PROBLEM - # IN THE INP WRITER. Now that we know, we can fix it, but - # if this changes, it will affect multiple pieces, just an - # FYI. - if node.node_type == 'Junction': - threshold = to_si( - flow_units, float(current[7]), HydParam.Pressure - ) # + node.elevation - control_obj = Control._conditional_control( # noqa: SLF001 - node, 'pressure', oper, threshold, action_obj, control_name - ) - elif node.node_type == 'Tank': - threshold = to_si( - flow_units, float(current[7]), HydParam.HydraulicHead - ) # + node.elevation - control_obj = Control._conditional_control( # noqa: SLF001 - node, 'level', oper, threshold, action_obj, control_name - ) - else: - raise RuntimeError('The following control is not recognized: ' + line) - # control_name = '' - # for i in range(len(current)-1): - # control_name = control_name + '/' + current[i] - # control_name = control_name + '/' + str(round(threshold, 2)) - elif 'CLOCKTIME' not in current: # at time - if 'TIME' not in current: - raise ValueError(f'Unrecognized line in inp file: {line}') # noqa: EM102, TRY003 - - if ':' in current[5]: - run_at_time = int(_str_time_to_sec(current[5])) - else: - run_at_time = int(float(current[5]) * 3600) - control_obj = Control._time_control( # noqa: SLF001 - wn, - run_at_time, - 'SIM_TIME', - False, # noqa: FBT003 - action_obj, - control_name, - ) - # control_name = '' - # for i in range(len(current)-1): - # control_name = control_name + '/' + current[i] - # control_name = control_name + '/' + str(run_at_time) - else: # at clocktime - if len(current) < 7: # noqa: PLR2004 - if ':' in current[5]: - run_at_time = int(_str_time_to_sec(current[5])) - else: - run_at_time = int(float(current[5]) * 3600) - else: - run_at_time = int(_clock_time_to_sec(current[5], current[6])) - control_obj = Control._time_control( # noqa: SLF001 - wn, - run_at_time, - 'CLOCK_TIME', - True, # noqa: FBT003 - action_obj, - control_name, - ) - # control_name = '' - # for i in range(len(current)-1): - # control_name = control_name + '/' + current[i] - # control_name = control_name + '/' + str(run_at_time) - return control_obj - - -def _diff_inp_files( # noqa: C901 - file1, - file2=None, - float_tol=1e-8, - max_diff_lines_per_section=5, - htmldiff_file='diff.html', -): # pragma: no cover - """Parameters - ---------- - file1: str - file2: str - float_tol: float - max_diff_lines_per_section: int - htmldiff_file: str - - """ # noqa: D205 - wn = InpFile().read(file1) - f1 = _InpFileDifferHelper(file1) - if file2 is None: - file2 = 'temp.inp' - wn.write_inpfile(file2) - f2 = _InpFileDifferHelper(file2) - - different_lines_1 = [] - different_lines_2 = [] - n = 0 - - for section in _INP_SECTIONS: - if not f1.contains_section(section): - if f2.contains_section(section): - print(f'\tfile1 does not contain section {section} but file2 does.') # noqa: T201 - continue - start1, stop1 = f1.get_section(section) - start2, stop2 = f2.get_section(section) - - if section == '[PATTERNS]': - new_lines_1 = [] - new_lines_2 = [] - label = None - tmp_line = None - tmp_loc = None - for loc1, line1 in f1.iter(start1, stop1): - tmp_label = line1.split()[0] - if tmp_label != label: - if label is not None: - new_lines_1.append((tmp_loc, tmp_line)) - tmp_loc = loc1 - tmp_line = line1 - label = tmp_label - else: - tmp_line += ' ' + ' '.join(line1.split()[1:]) - if tmp_line is not None: - new_lines_1.append((tmp_loc, tmp_line)) - label = None - tmp_line = None - tmp_loc = None - for loc2, line2 in f2.iter(start2, stop2): - tmp_label = line2.split()[0] - if tmp_label != label: - if label is not None: - new_lines_2.append((tmp_loc, tmp_line)) - tmp_loc = loc2 - tmp_line = line2 - label = tmp_label - else: - tmp_line += ' ' + ' '.join(line2.split()[1:]) - if tmp_line is not None: - new_lines_2.append((tmp_loc, tmp_line)) - else: - new_lines_1 = list(f1.iter(start1, stop1)) - new_lines_2 = list(f2.iter(start2, stop2)) - - different_lines_1.append(section) - different_lines_2.append(section) - - if len(new_lines_1) != len(new_lines_2): - assert len(different_lines_1) == len(different_lines_2) - n1 = 0 - n2 = 0 - for loc1, line1 in new_lines_1: # noqa: B007 - different_lines_1.append(line1) - n1 += 1 - for loc2, line2 in new_lines_2: # noqa: B007 - different_lines_2.append(line2) - n2 += 1 - if n1 > n2: - n = n1 - n2 - for i in range(n): # noqa: B007 - different_lines_2.append('') # noqa: PERF401 - elif n2 > n1: - n = n2 - n1 - for i in range(n): # noqa: B007 - different_lines_1.append('') # noqa: PERF401 - else: - raise RuntimeError('Unexpected') # noqa: EM101 - continue - - section_line_counter = 0 - f2_iter = iter(new_lines_2) - for loc1, line1 in new_lines_1: # noqa: B007 - orig_line_1 = line1 - loc2, line2 = next(f2_iter) - orig_line_2 = line2 - line1 = _convert_line(line1) # noqa: PLW2901 - line2 = _convert_line(line2) - line1 = _clean_line(wn, section, line1) # noqa: PLW2901 - line2 = _clean_line(wn, section, line2) - if not _compare_lines(line1, line2, tol=float_tol): - if section_line_counter < max_diff_lines_per_section: - section_line_counter = section_line_counter + 1 - else: - break - different_lines_1.append(orig_line_1) - different_lines_2.append(orig_line_2) - - if len(different_lines_1) < 200: # If lines < 200 use difflib # noqa: PLR2004 - differ = difflib.HtmlDiff() - html_diff = differ.make_file(different_lines_1, different_lines_2) - else: # otherwise, create a simple html file - differ_df = pd.DataFrame( - [different_lines_1, different_lines_2], index=[file1, file2] - ).transpose() - html_diff = differ_df.to_html() - - g = open(htmldiff_file, 'w') # noqa: SIM115, PTH123 - g.write(html_diff) - g.close() - - return n # noqa: DOC201, RUF100 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/toolkit.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/toolkit.py deleted file mode 100644 index a2d5d265e..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/toolkit.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Created on Wed May 26 16:11:36 2021 - -@author: snaeimi -""" # noqa: D400 - -import ctypes -import logging -import os -import platform -import sys - -import numpy as np -import wntrfr.epanet.toolkit -from pkg_resources import resource_filename - -logger = logging.getLogger(__name__) - - -class EpanetException(Exception): # noqa: N818, D101 - pass - - -class ENepanet(wntrfr.epanet.toolkit.ENepanet): # noqa: D101 - def __init__( # noqa: C901 - self, - inpfile='', - rptfile='', - binfile='', - changed_epanet=False, # noqa: FBT002 - version=2.2, - ): - if changed_epanet == False or changed_epanet == True: # noqa: E712, PLR1714 - self.changed_epanet = changed_epanet - else: - raise ValueError('changed_epanet must be a boolean value') # noqa: EM101, TRY003 - - if changed_epanet == False: # noqa: E712 - super().__init__(inpfile, rptfile, binfile, version=version) - else: - try: # noqa: SIM105 - super().__init__(inpfile, rptfile, binfile, version=version) - except: # noqa: S110, E722 - pass # to add robustness for the time when for the WNTR - # cannot load the umodified DLLs for any reason - - if float(version) != 2.2: # noqa: PLR2004 - raise ValueError( # noqa: TRY003 - 'EPANET version must be 2.2 when using the changed version' # noqa: EM101 - ) - - elif float(version) == 2.2: # noqa: RET506, PLR2004 - libnames = ['epanet22_mod', 'epanet22_win32_mod'] - if '64' in platform.machine(): - libnames.insert(0, 'epanet22_amd64_mod') - for lib in libnames: - try: - if os.name in ['nt', 'dos']: - libepanet = resource_filename( - __name__, - 'Windows/%s.dll' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.windll.LoadLibrary(libepanet) - elif sys.platform == 'darwin': - libepanet = resource_filename( - __name__, - 'Darwin/lib%s.dylib' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.cdll.LoadLibrary(libepanet) - else: - libepanet = resource_filename( - __name__, - 'Linux/lib%s.so' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.cdll.LoadLibrary(libepanet) - return # noqa: TRY300 - except Exception as E1: # noqa: PERF203 - if lib == libnames[-1]: - raise E1 # noqa: TRY201 - finally: - if version >= 2.2 and '32' not in lib: # noqa: PLR2004 - self._project = ctypes.c_uint64() - elif version >= 2.2: # noqa: PLR2004 - self._project = ctypes.c_uint32() - else: - self._project = None - - def ENSetIgnoreFlag(self, ignore_flag=0): # noqa: N802, D102 - if abs(ignore_flag - np.round(ignore_flag)) > 0.00001 or ignore_flag < 0: # noqa: PLR2004 - logger.error( - 'ignore_flag must be int value and bigger than zero' # noqa: G003 - + str(ignore_flag) - ) - flag = ctypes.c_int(int(ignore_flag)) # noqa: F841 - # print('++++++++++++++++++++++') - # self.ENlib.ENEXTENDEDsetignoreflag(flag) diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/CMakeLists.txt deleted file mode 100644 index 66864b707..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ - -simcenter_add_python_script(SCRIPT epanet22_mod.dll) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/epanet22_mod.dll b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/epanet22_mod.dll deleted file mode 100644 index 4da98afe0..000000000 Binary files a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/epanet/windows/epanet22_mod.dll and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/CMakeLists.txt deleted file mode 100644 index 6dca797fb..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -simcenter_add_python_script(SCRIPT link.py) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/link.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/link.py deleted file mode 100644 index 584acb288..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/morph/link.py +++ /dev/null @@ -1,280 +0,0 @@ -"""The wntrfr.morph.link module contains functions to split/break pipes.""" # noqa: INP001 - -import copy -import logging - -from wntrfr.network.elements import Pipe, Reservoir - -logger = logging.getLogger(__name__) - - -def split_pipe( - wn, - pipe_name_to_split, - new_pipe_name, - new_junction_name, - add_pipe_at_end=True, # noqa: FBT002 - split_at_point=0.5, - return_copy=True, # noqa: FBT002 -): - """Split a pipe by adding a junction and one new pipe segment. - - This function splits the original pipe into two pipes by adding a new - junction and new pipe to the model. - The updated model retains the original length of the pipe section. - The split occurs at a user specified distance between the - original start and end nodes of the pipe (in that direction). - The new pipe can be added to either end of the original pipe. - - * The new junction has a base demand of 0 and the default demand pattern. - The elevation and coordinates of the new junction are based on a linear - interpolation between the end points of the original pipe. - - * The new pipe has the same diameter, roughness, minor loss, - and base status of the original pipe. - - * Check valves are not added to the new - pipe. Since the new pipe can be connected at either the start - or the end of the original pipe, the user can control if the split occurs before - or after a check valve. - - * No controls are added to the new pipe; the original pipe keeps any controls. - - Parameters - ---------- - wn: wntr WaterNetworkModel - Water network model - pipe_name_to_split: string - Name of the pipe to split. - new_pipe_name: string - Name of the new pipe to be added as the split part of the pipe. - new_junction_name: string - Name of the new junction to be added. - add_pipe_at_end: bool, optional - If True, add the new pipe between the new node and the original end node. - If False, add the new pipe between the original start node and the new node. - split_at_point: float, optional - Between 0 and 1, the position along the original pipe where the new - junction will be located. - return_copy: bool, optional - If True, modify and return a copy of the WaterNetworkModel object. - If False, modify and return the original WaterNetworkModel object. - - Returns - ------- - wntr WaterNetworkModel - Water network model with split pipe - - """ - wn2 = _split_or_break_pipe( - wn, - pipe_name_to_split, - new_pipe_name, - [new_junction_name], - add_pipe_at_end, - split_at_point, - 'SPLIT', - return_copy, - ) - - return wn2 # noqa: RET504 - - -def break_pipe( - wn, - pipe_name_to_split, - new_pipe_name, - new_junction_name_old_pipe, - new_junction_name_new_pipe, - add_pipe_at_end=True, # noqa: FBT002 - split_at_point=0.5, - return_copy=True, # noqa: FBT002 -): - """Break a pipe by adding a two unconnected junctions and one new pipe segment. - - This function splits the original pipe into two disconnected pipes by - adding two new junctions and new pipe to the model. - **This provides a true broken pipe -- i.e., there is no longer flow - possible from one side of the break to the other. This is more likely to - introduce non-convergable hydraulics than a simple split_pipe with a leak - added.** - The updated model retains the original length of the pipe section. - The split occurs at a user specified distance between the - original start and end nodes of the pipe (in that direction). - The new pipe can be added to either end of the original pipe. - - * The new junction has a base demand of 0 and the default demand pattern. - The elevation and coordinates of the new junction are based on a linear - interpolation between the end points of the original pipe. - - * The new pipe has the same diameter, roughness, minor loss, - and base status of the original pipe. - - * Check valves are not added to the new - pipe. Since the new pipe can be connected at either the start - or the end of the original pipe, the user can control if the split occurs before - or after a check valve. - - * No controls are added to the new pipe; the original pipe keeps any controls. - - Parameters - ---------- - wn: wntr WaterNetworkModel - Water network model - pipe_name_to_split: string - Name of the pipe to split. - new_pipe_name: string - Name of the new pipe to be added as the split part of the pipe. - new_junction_name_old_pipe: string - Name of the new junction to be added to the original pipe - new_junction_name_new_pipe: string - Name of the new junction to be added to the new pipe - add_pipe_at_end: bool, optional - If True, add the new pipe at after the new junction. If False, add the - new pipe before the new junction - split_at_point: float, optional - Relative position (value between 0 and 1) along the original pipe - where the new junction will be located. - return_copy: bool, optional - If True, modify and return a copy of the WaterNetworkModel object. - If False, modify and return the original WaterNetworkModel object. - - Returns - ------- - wntr WaterNetworkModel - Water network model with pipe break - - """ - wn2 = _split_or_break_pipe( - wn, - pipe_name_to_split, - new_pipe_name, - [new_junction_name_old_pipe, new_junction_name_new_pipe], - add_pipe_at_end, - split_at_point, - 'BREAK', - return_copy, - ) - - return wn2 # noqa: RET504 - - -def _split_or_break_pipe( # noqa: C901 - wn, - pipe_name_to_split, - new_pipe_name, - new_junction_names, - add_pipe_at_end, - split_at_point, - flag, - return_copy, -): - if return_copy: # Get a copy of the WaterNetworkModel - wn2 = copy.deepcopy(wn) - else: - wn2 = wn - - pipe = wn2.get_link(pipe_name_to_split) - - # Do sanity checks - if not isinstance(pipe, Pipe): - raise ValueError('You can only split pipes.') # noqa: EM101, TRY003, TRY004 - if split_at_point < 0 or split_at_point > 1: - raise ValueError('split_at_point must be between 0 and 1') # noqa: EM101, TRY003 - # Sina edited here - # node_list = [node_name for node_name, node in wn2.nodes()] - # link_list = [link_name for link_name, link in wn2.links()] - # for new_junction_name in new_junction_names: - # if new_junction_name in wn.node_name_list: - # raise RuntimeError('The junction name you provided is already \ - # being used for another node.') - # if new_pipe_name in wn.link_name_list: - # raise RuntimeError('The new link name you provided is already being \ - # used for another link.') - - # Get start and end node info - start_node = pipe.start_node - end_node = pipe.end_node - - # calculate the new elevation - if isinstance(start_node, Reservoir): - junction_elevation = end_node.elevation - elif isinstance(end_node, Reservoir): - junction_elevation = start_node.elevation - else: - e0 = start_node.elevation - de = end_node.elevation - e0 - junction_elevation = e0 + de * split_at_point - - # calculate the new coordinates - x0 = pipe.start_node.coordinates[0] - dx = pipe.end_node.coordinates[0] - x0 - y0 = pipe.start_node.coordinates[1] - dy = pipe.end_node.coordinates[1] - y0 - junction_coordinates = (x0 + dx * split_at_point, y0 + dy * split_at_point) - - # add the new junction - # for new_junction_name in new_junction_names: - wn2.add_junction( - new_junction_names[0], - base_demand=0.0, - demand_pattern=None, - elevation=junction_elevation, - coordinates=junction_coordinates, - ) - if len(new_junction_names) == 2: # noqa: PLR2004 - wn2.add_junction( - new_junction_names[1], - base_demand=0.0, - demand_pattern=None, - elevation=junction_elevation, - coordinates=junction_coordinates, - ) - - original_length = pipe.length - - if flag == 'BREAK': - j0 = new_junction_names[0] - j1 = new_junction_names[1] - elif flag == 'SPLIT': - j0 = new_junction_names[0] - j1 = new_junction_names[0] - - if add_pipe_at_end: - pipe.end_node = wn2.get_node(j0) - # add new pipe and change original length - wn2.add_pipe( - new_pipe_name, - j1, - end_node.name, - original_length * (1 - split_at_point), - pipe.diameter, - pipe.roughness, - pipe.minor_loss, - pipe.status, - pipe.cv, - ) - pipe.length = original_length * split_at_point - else: # add pipe at start - pipe.start_node = wn2.get_node(j0) - # add new pipe and change original length - wn2.add_pipe( - new_pipe_name, - start_node.name, - j1, - original_length * split_at_point, - pipe.diameter, - pipe.roughness, - pipe.minor_loss, - pipe.status, - pipe.cv, - ) - pipe.length = original_length * (1 - split_at_point) - - if pipe.cv: - logger.warning( - 'You are splitting a pipe with a check valve. The new \ - pipe will not have a check valve.' - ) - - return wn2 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/CMakeLists.txt deleted file mode 100644 index d3ac84fe8..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -simcenter_add_python_script(SCRIPT __init__.py) -simcenter_add_python_script(SCRIPT model.py) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/__init__.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/__init__.py deleted file mode 100644 index b74acee6d..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# noqa: N999, D104 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/model.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/model.py deleted file mode 100644 index ec54f7220..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/network/model.py +++ /dev/null @@ -1,348 +0,0 @@ -"""The wntrfr.network.model module includes methods to build a water network -model. - -.. rubric:: Contents - -.. autosummary:: - - WaterNetworkModel - PatternRegistry - CurveRegistry - SourceRegistry - NodeRegistry - LinkRegistry - -""" # noqa: D205 - -import logging -import math -from collections import OrderedDict - -import numpy as np -from wntrfr.network import WaterNetworkModel -from wntrfr.network.base import LinkStatus -from wntrfr.network.elements import Pump, Valve - -from ..epanet.io import InpFile # noqa: TID252 - -logger = logging.getLogger(__name__) - - -class WaterNetworkModel(WaterNetworkModel): - """Water network model class. - - Parameters - ---------- - inp_file_name: string (optional) - Directory and filename of EPANET inp file to load into the - WaterNetworkModel object. - - """ - - def __init__(self, inp_file_name=None): - super().__init__(inp_file_name) - self.breakage_link = {} - self.expicit_leak = [] - - def updateWaterNetworkModelWithResult( # noqa: C901, N802 - self, - result, - registry, # noqa: ARG002 - latest_simulation_time=None, - ): - """Updates Water Network Model consistent with result model. must be only - used with EPANET solver or just in case you really know what you are - doing. - - Parameters - ---------- - result : Water Network Result - - latest_simulation_time : int - latest time of simulation(duration of the latest run), to be - checked with time in result. Defaylt None. - - Raises - ------ - ValueError - When simulation object is not of type EpanetSimulator - When latest simulation time is provided and is not consistent with - latest time in result. - When Tank level gets less than zero - - - Returns - ------- - None. - - """ # noqa: D205, D401, DOC202, RUF100 - max_time = result.node['head'].index.max() - if latest_simulation_time == None: # noqa: E711 - latest_simulation_time = max_time - elif latest_simulation_time != max_time: - raise ValueError( # noqa: TRY003 - 'Provided LATEST SIMULATION TIME id not consistent with the latest time in RESULT' # noqa: EM101 - ) - - avilable_tank_name_list = set(self.tank_name_list).intersection( - result.node['head'].columns - ) - for tank_name in avilable_tank_name_list: - # if tank_name not in result.node['head'].columns: - # continue - tank_level = None - head = None - - cur_node = self.get_node(tank_name) - if cur_node._is_isolated: # noqa: SLF001 - continue - head = result.node['head'].loc[max_time, tank_name] - - tank_level = head - cur_node.elevation - tank_level = max(tank_level, 0) - - tank_level = max(tank_level, cur_node.min_level) - - if tank_level - cur_node.max_level > 0: - tank_level = cur_node.max_level - - cur_node.init_level = abs(tank_level) - cur_node._head = cur_node.elevation + tank_level # noqa: SLF001 - - if tank_level < 0.0: - logger.error('head= ' + repr(head)) # noqa: G003 - logger.error('elevation= ' + repr(cur_node.elevation)) # noqa: G003 - logger.error('tank_level= ' + repr(tank_level)) # noqa: G003 - raise ValueError( - 'Tank Level for ' + tank_name + ' is less than zero' - ) - - for link_name in self.link_name_list: - link = self.get_link(link_name) - setting = None - status = None - try: - setting = result.link['setting'].loc[max_time, link_name] - status = result.link['status'].loc[max_time, link_name] - except: # noqa: S112, E722 - # logger.error(link_name + ' exist in WaterNetwork but does not exist in result') - # raise ValueError(link_name + ' exist in WaterNetwork but does not exist in result') - continue - - if isinstance(link, Valve): - link.settings = float(setting) - - elif isinstance(link, Pump): - link.setting.base_value = float(setting) - - if status == 0: - link._user_status = LinkStatus.Closed # noqa: SLF001 - - elif status == 1: - link._user_status = LinkStatus.Open # noqa: SLF001 - - elif status == 2: # noqa: PLR2004 - link._user_status = LinkStatus.Active # noqa: SLF001 - - else: - logger.error('Element type is: ' + repr(type(link))) # noqa: G003 - logger.error('Status is : ' + repr(status)) # noqa: G003 - - def read_inpfile(self, filename): - """Defines water network model components from an EPANET INP file - - Parameters - ---------- - filename : string - Name of the INP file. - - """ # noqa: D400, D401 - inpfile = InpFile() - inpfile.read(filename, wn=self) - self._inpfile = inpfile - - def write_inpfile(self, filename, units=None): - """Writes the current water network model to an EPANET INP file - - Parameters - ---------- - filename : string - Name of the inp file. - units : str, int or FlowUnits - Name of the units being written to the inp file. - - """ # noqa: D400, D401 - if self._inpfile is None: - logger.warning( - 'Writing a minimal INP file without saved non-WNTR options (energy, etc.)' - ) - self._inpfile = InpFile() - if units is None: - units = self._options.hydraulic.en2_units - self._inpfile.write(filename, self, units=units) - - def implicitLeakToExplicitEMitter(self, registry): # noqa: N802, D102 - if len(self.expicit_leak) > 0: - raise ValueError('Explicit leak is not reset') # noqa: EM101, TRY003 - - registry.active_pipe_damages = OrderedDict() - for node_name in self.node_name_list: - node = self.get_node(node_name) - - if node._leak: # noqa: SLF001 - if node_name in self.expicit_leak: - raise ValueError( - 'The node name in already in leak memory: ' + node_name - ) - - new_node_name = node_name + '-nn' - new_coord = (node.coordinates[0] + 1, node.coordinates[1] + 1) - self.add_junction( - new_node_name, elevation=node.elevation, coordinates=new_coord - ) - new_node = self.get_node(new_node_name) - - new_pipe_name = node_name + '-elk' - self.add_pipe( - new_pipe_name, - node_name, - new_node_name, - diameter=100, - length=1, - roughness=1000000, - check_valve=True, - ) - - cd = node.leak_area * (2) ** 0.5 # (m^3ps/(KPa^0.5)) - cd = cd / (0.145038**0.5) # (gpm/(Psi^0.5)) - # When writing to emitter, function from_si changes m^3ps to GPM - - new_node._emitter_coefficient = cd # noqa: SLF001 - - if node.demand_timeseries_list[0].base_value > 0.001: # noqa: PLR2004 - raise ValueError('leak node has demand: ' + node_name) - temp = { - 'node_name': node_name, - 'method': 'emitter', - 'element1': new_pipe_name, - 'element2': new_node_name, - 'attr1': cd, - } - self.expicit_leak.append(temp) - registry.explicit_leak_node[node_name] = new_node_name - registry.active_pipe_damages.update({new_node_name: node_name}) - - def implicitLeakToExplicitReservoir(self, registry): # noqa: N802, D102 - if len(self.expicit_leak) > 0: - raise ValueError('Explicit leak is not reset') # noqa: EM101, TRY003 - registry.active_pipe_damages = OrderedDict() - for node_name in self.node_name_list: - node = self.get_node(node_name) - - if node._leak: # noqa: SLF001 - if node_name in self.expicit_leak: - raise ValueError( - 'The node name in already in leak memory: ' + node_name - ) - - new_node_name = node_name + '_nn' - new_coord = (node.coordinates[0] + 1, node.coordinates[1] + 1) - self.add_reservoir( - new_node_name, base_head=node.elevation, coordinates=new_coord - ) - - new_pipe_name = node_name + '-rlk' - diameter = np.sqrt(node.leak_area * 4 / math.pi) - self.add_pipe( - new_pipe_name, - node_name, - new_node_name, - diameter=diameter, - length=1, - roughness=1000000, - minor_loss=1, - check_valve=True, - ) - - if node.demand_timeseries_list[0].base_value > 0.001: # noqa: PLR2004 - raise ValueError('leak node has demand: ' + node_name) - temp = { - 'node_name': node_name, - 'method': 'reservoir', - 'element1': new_pipe_name, - 'element2': new_node_name, - } - self.expicit_leak.append(temp) - registry.explicit_leak_node[node_name] = new_node_name - registry.active_pipe_damages.update({new_node_name: node_name}) - - def resetExplicitLeak(self): # noqa: N802, D102 - for data in self.expicit_leak: - new_pipe_name = data['element1'] - new_node_name = data['element2'] - - self.remove_link(new_pipe_name, force=True) - self.get_node(new_node_name)._emitter_coefficient = None # noqa: SLF001 - self.remove_node(new_node_name, force=True) - - self.expicit_leak = [] - - def linkBreackage(self, registry): # noqa: N802, D102 - if len(self.breakage_link) > 0: - raise ValueError('Breakckage is not unliked') # noqa: EM101, TRY003 - - self.breakage_link = {} - pipe_damage_table = registry.getDamageData('PIPE') - broken_pipe_damage_table = pipe_damage_table[ - pipe_damage_table['damage_type'] == 'break' - ] - - for damage_node, row in broken_pipe_damage_table.iterrows(): # noqa: B007 - if registry.getPipeDamageAttribute('repair', damage_node) == True: # noqa: E712 - continue - pipe_A, pipe_B, orginal_pipe, node_A, node_B = registry.getBreakData( # noqa: N806 - damage_node - ) - - pipe_name_list = self.pipe_name_list - junction_name_list = self.junction_name_list - - iPipe_A_in = pipe_A in pipe_name_list # noqa: N806 - iPipe_B_in = pipe_B in pipe_name_list # noqa: N806 - iNode_A_in = node_A in junction_name_list # noqa: N806 - iNode_B_in = node_B in junction_name_list # noqa: N806 - - if not iPipe_A_in or not iPipe_B_in or not iNode_A_in or not iNode_B_in: - if iPipe_A_in or iPipe_B_in or iNode_A_in or iNode_B_in: - raise ValueError( - 'The damage is partially removed?: ' - + repr(iPipe_A_in) - + ', ' - + repr(iPipe_B_in) - + ', ' - + repr(iNode_A_in) - + ', ' - + repr(iNode_B_in) - + ', ' - + repr(damage_node) - ) - else: - node1 = self.get_link(pipe_A).start_node - node2 = self.get_link(pipe_B).end_node - - new_pipe_name = damage_node + '_BLP' - self.add_pipe( - new_pipe_name, - node1.name, - node2.name, - length=1, - diameter=1 * 2.54 / 100, - roughness=100, - ) - self.breakage_link[damage_node] = new_pipe_name - - def unlinkBreackage(self): # noqa: N802, D102 - for damage_node, link_pipe_name in self.breakage_link.items(): # noqa: B007, PERF102 - self.remove_link(link_pipe_name, force=True) - - self.breakage_link = {} diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/CMakeLists.txt deleted file mode 100644 index febda1413..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -simcenter_add_python_script(SCRIPT __init__.py) -simcenter_add_python_script(SCRIPT epanet.py) -simcenter_add_python_script(SCRIPT io.py) -simcenter_add_python_script(SCRIPT results.py) -simcenter_add_python_script(SCRIPT toolkit.py) - - diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/__init__.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/__init__.py deleted file mode 100644 index b74acee6d..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# noqa: N999, D104 diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/epanet.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/epanet.py deleted file mode 100644 index e9d529c3b..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/epanet.py +++ /dev/null @@ -1,785 +0,0 @@ -"""Created on Tue Jun 1 17:09:25 2021 - -@author: snaeimi -""" # noqa: D400 - -import itertools -import logging -import math -from collections import OrderedDict - -import numpy as np -import scipy.sparse.csr -import wntrfr.epanet.io -from Report_Reading import Report_Reading -from wntrfr.network.io import write_inpfile -from wntrfr.network.model import LinkStatus -from wntrfr.sim.core import _get_csr_data_index -from wntrfr.sim.epanet import EpanetSimulator -from wntrfr.sim.network_isolation import check_for_isolated_junctions, get_long_size -from wntrfr.utils.ordered_set import OrderedSet - -from ..epanet import toolkit # noqa: TID252 - -logger = logging.getLogger(__name__) - - -class EpanetSimulator(EpanetSimulator): - """Fast EPANET simulator class. - - Use the EPANET DLL to run an INP file as-is, and read the results from the - binary output file. Multiple water quality simulations are still possible - using the WQ keyword in the run_sim function. Hydraulics will be stored and - saved to a file. This file will not be deleted by default, nor will any - binary files be deleted. - - The reason this is considered a "fast" simulator is due to the fact that there - is no looping within Python. The "ENsolveH" and "ENsolveQ" toolkit - functions are used instead. - - Parameters - ---------- - wn : WaterNetworkModel - Water network model - mode: DD or PDD with default None value(read mode from InpFile, if there is no mode - provided in inpdile either, it will be DD) If there is a conflict between mode in - the class argument and inpfile, the augment will supersede the InpFile - reader : wntrfr.epanet.io.BinFile derived object - Defaults to None, which will create a new wntrfr.epanet.io.BinFile object with - the results_types specified as an init option. Otherwise, a fully - result_types : dict - Defaults to None, or all results. Otherwise, is a keyword dictionary to pass to - the reader to specify what results should be saved. - - - .. seealso:: - - wntrfr.epanet.io.BinFile - - """ - - def __init__(self, wn): - super(EpanetSimulator, self).__init__(wn) # noqa: UP008 - - # Sina added this for time manipulate function - - self._initial_hydraulic_timestep = wn.options.time.hydraulic_timestep - self._initial_report_timestep = wn.options.time.hydraulic_timestep - - # Sina added this for isolation init - long_size = get_long_size() - if long_size == 4: # noqa: PLR2004 - self._int_dtype = np.int32 - else: - assert long_size == 8 # noqa: PLR2004 - self._int_dtype = np.int64 - self._link_name_to_id = OrderedDict() - self._link_id_to_name = OrderedDict() - self._node_name_to_id = OrderedDict() - self._node_id_to_name = OrderedDict() - self._initialize_name_id_maps() - # sina end - - def manipulateTimeOrder( # noqa: N802, D102 - self, - begin_time, - end_time, - change_time_step=False, # noqa: FBT002 - min_correction_time_step=None, - ): - time_dif = end_time - begin_time - min_step_time = min_correction_time_step - self._wn.options.time.duration = time_dif - if time_dif <= 1: - self._wn.options.time.report_timestep = time_dif - self._wn.options.time.pattern_start = begin_time - self._wn.options.time.start_clocktime = begin_time - if change_time_step: - if min_correction_time_step == None: # noqa: E711 - raise ValueError( # noqa: TRY003 - 'if change_time_step is True, then min_correction_time_step must be provided' # noqa: EM101 - ) - - self._wn.options.time.hydraulic_timestep = ( - self._initial_hydraulic_timestep - ) - self._wn.options.time.report_timestep = self._initial_report_timestep - time_step = min( - self._wn.options.time.hydraulic_timestep, - self._wn.options.time.report_timestep, - ) - min_step_time = min(min_step_time, time_step) - iFinished = False # noqa: N806 - i = 1 - logger.debug('time_dif= ' + repr(time_dif)) # noqa: G003 - - time_step_list = list(range(min_step_time, time_step, min_step_time)) - time_step_list.append(time_step) - while i <= len(time_step_list): - if time_dif % time_step_list[-i] == 0: - new_time_step = time_step_list[-i] - iFinished = True # noqa: N806 - break - elif i == len(time_step_list): # noqa: RET508 - raise ('There was no time check when creating time event?') # noqa: B016 - i += 1 - if iFinished == False: # noqa: E712 - raise RuntimeError('no timestep is found') # noqa: EM101, TRY003 - self._wn.options.time.report_timestep = new_time_step - - def run_sim( # noqa: C901 - self, - file_prefix='temp', - save_hyd=False, # noqa: FBT002 - use_hyd=False, # noqa: FBT002 - hydfile=None, - version=2.2, - convergence_error=False, # noqa: FBT002, ARG002 - start_time=None, - iModified=True, # noqa: FBT002, N803 - ): - """Run the EPANET simulator. - - Runs the EPANET simulator through the compiled toolkit DLL. Can use/save hydraulics - to allow for separate WQ runs. - - Parameters - ---------- - file_prefix : str - Default prefix is "temp". All files (.inp, .bin/.out, .hyd, .rpt) use this prefix - use_hyd : bool - Will load hydraulics from ``file_prefix + '.hyd'`` or from file specified in `hydfile_name` - save_hyd : bool - Will save hydraulics to ``file_prefix + '.hyd'`` or to file specified in `hydfile_name` - hydfile : str - Optionally specify a filename for the hydraulics file other than the `file_prefix` - - """ - solver_parameters_list = [(1, 10, 0), (10, 100, 0), (10, 100, 0.01)] - # solver_parameters_list = [(10,100, 0.01), (10, 100, 0), (1,10, 0)] - # balanced_system = False - run_successful = False - i = 0 - for solver_parameter in solver_parameters_list: - i += 1 - print(solver_parameter) # noqa: T201 - self._wn.options.hydraulic.checkfreq = solver_parameter[0] - self._wn.options.hydraulic.maxcheck = solver_parameter[1] - self._wn.options.hydraulic.damplimit = solver_parameter[2] - self._wn.options.hydraulic.unbalanced_value = 100 - - inpfile = file_prefix + '.inp' - write_inpfile( - self._wn, - inpfile, - units=self._wn.options.hydraulic.inpfile_units, - version=version, - ) - - enData = toolkit.ENepanet(changed_epanet=iModified, version=version) # noqa: N806 - rptfile = file_prefix + '.rpt' - outfile = file_prefix + '.bin' - if hydfile is None: - hydfile = file_prefix + '.hyd' - enData.ENopen(inpfile, rptfile, outfile) - if use_hyd: - enData.ENusehydfile(hydfile) - logger.debug('Loaded hydraulics') - else: - try: - enData.ENsolveH() - except Exception as err: - enData.ENclose() - if err.args[0] == 'EPANET Error 110': - print(enData.errcode) # noqa: T201 - run_successful = False - if i < len(solver_parameters_list): - continue - else: # noqa: RET507 - raise err # noqa: TRY201 - else: - raise err # noqa: TRY201 - else: - run_successful = True - logger.debug('Solved hydraulics') - if save_hyd: - enData.ENsavehydfile(hydfile) - logger.debug('Saved hydraulics') - - try: - enData.ENsolveQ() - logger.debug('Solved quality') - enData.ENreport() - logger.debug('Ran quality') - except Exception as err: - enData.ENclose() - raise err # noqa: TRY201 - enData.ENclose() - logger.debug('Completed run') - result_data = self.reader.read(outfile) - - self._updateResultStartTime(result_data, start_time) - - report_data = Report_Reading(rptfile) - - result_data.maximum_trial_time = [] - - for time in report_data.maximum_trial_time: - result_data.maximum_trial_time.append(time + start_time) - if run_successful: - break - - return result_data, run_successful # noqa: DOC201, RUF100 - - def _updateResultStartTime(self, result_data, start_time): # noqa: N802 - for res_type, res in result_data.link.items(): # noqa: B007, PERF102 - # result_data.link[res_type].index = res - res.index = res.index + start_time - - for res_type, res in result_data.node.items(): # noqa: B007, PERF102 - # result_data.link[res_type].index = res - res.index = res.index + start_time - - def _get_isolated_junctions_and_links( - self, - prev_isolated_junctions, - prev_isolated_links, - ): - self._prev_isolated_junctions = prev_isolated_junctions - self._prev_isolated_links = prev_isolated_links - - self._initialize_internal_graph() - logger_level = logger.getEffectiveLevel() - - if logger_level <= logging.DEBUG: - logger.debug('checking for isolated junctions and links') - for j in self._prev_isolated_junctions: - try: - junction = self._wn.get_node(j) - junction._is_isolated = False # noqa: SLF001 - except: # noqa: S110, PERF203, E722 - pass - for l in self._prev_isolated_links: # noqa: E741 - try: - link = self._wn.get_link(l) - link._is_isolated = False # noqa: SLF001 - except: # noqa: S110, PERF203, E722 - pass - node_indicator = np.ones(self._wn.num_nodes, dtype=self._int_dtype) - check_for_isolated_junctions( - self._source_ids, - node_indicator, - self._internal_graph.indptr, - self._internal_graph.indices, - self._internal_graph.data, - self._number_of_connections, - ) - - isolated_junction_ids = [ - i for i in range(len(node_indicator)) if node_indicator[i] == 1 - ] - isolated_junctions = OrderedSet() - isolated_links = OrderedSet() - for j_id in isolated_junction_ids: - j = self._node_id_to_name[j_id] - junction = self._wn.get_node(j) - junction._is_isolated = True # noqa: SLF001 - isolated_junctions.add(j) - connected_links = self._wn.get_links_for_node(j) - for l in connected_links: # noqa: E741 - link = self._wn.get_link(l) - link._is_isolated = True # noqa: SLF001 - isolated_links.add(l) - - if logger_level <= logging.DEBUG: - if len(isolated_junctions) > 0 or len(isolated_links) > 0: - raise ValueError(f'isolated junctions: {isolated_junctions}') # noqa: EM102, TRY003 - logger.debug(f'isolated links: {isolated_links}') - - self._prev_isolated_junctions = isolated_junctions - self._prev_isolated_links = isolated_links - return isolated_junctions, isolated_links - - def _initialize_internal_graph(self): # noqa: C901 - n_links = OrderedDict() - rows = [] - cols = [] - vals = [] - for link_name, link in itertools.chain( # noqa: B007 - self._wn.pipes(), self._wn.pumps(), self._wn.valves() - ): - from_node_name = link.start_node_name - to_node_name = link.end_node_name - from_node_id = self._node_name_to_id[from_node_name] - to_node_id = self._node_name_to_id[to_node_name] - if (from_node_id, to_node_id) not in n_links: - n_links[(from_node_id, to_node_id)] = 0 - n_links[(to_node_id, from_node_id)] = 0 - n_links[(from_node_id, to_node_id)] += 1 - n_links[(to_node_id, from_node_id)] += 1 - rows.append(from_node_id) - cols.append(to_node_id) - rows.append(to_node_id) - cols.append(from_node_id) - if link.initial_status == wntrfr.network.LinkStatus.closed: - vals.append(0) - vals.append(0) - # sina remove comment amrks - elif link.link_type == 'Pipe': - if link.cv: - vals.append(1) - vals.append(0) - else: - vals.append(1) - vals.append(1) - elif link.link_type == 'Valve': - if ( - link.valve_type == 'PRV' # noqa: PLR1714 - or link.valve_type == 'PSV' - or link.valve_type == 'FCV' - ): - vals.append(1) - vals.append(0) - else: - vals.append(1) - vals.append(1) - else: - vals.append(1) - vals.append(1) - - rows = np.array(rows, dtype=self._int_dtype) - cols = np.array(cols, dtype=self._int_dtype) - vals = np.array(vals, dtype=self._int_dtype) - self._internal_graph = scipy.sparse.csr_matrix((vals, (rows, cols))) - - ndx_map = OrderedDict() - for link_name, link in self._wn.links(): # noqa: B007 - from_node_name = link.start_node_name - to_node_name = link.end_node_name - from_node_id = self._node_name_to_id[from_node_name] - to_node_id = self._node_name_to_id[to_node_name] - ndx1 = _get_csr_data_index( - self._internal_graph, from_node_id, to_node_id - ) - ndx2 = _get_csr_data_index( - self._internal_graph, to_node_id, from_node_id - ) - ndx_map[link] = (ndx1, ndx2) - self._map_link_to_internal_graph_data_ndx = ndx_map - - self._number_of_connections = [0 for i in range(self._wn.num_nodes)] - for node_id in self._node_id_to_name.keys(): # noqa: SIM118 - self._number_of_connections[node_id] = ( - self._internal_graph.indptr[node_id + 1] - - self._internal_graph.indptr[node_id] - ) - self._number_of_connections = np.array( - self._number_of_connections, dtype=self._int_dtype - ) - - self._node_pairs_with_multiple_links = OrderedDict() - for from_node_id, to_node_id in n_links.keys(): # noqa: SIM118 - if n_links[(from_node_id, to_node_id)] > 1: # noqa: RUF031, RUF100 - if ( - to_node_id, - from_node_id, - ) in self._node_pairs_with_multiple_links: - continue - self._internal_graph[from_node_id, to_node_id] = 0 - self._internal_graph[to_node_id, from_node_id] = 0 - from_node_name = self._node_id_to_name[from_node_id] - to_node_name = self._node_id_to_name[to_node_id] - tmp_list = self._node_pairs_with_multiple_links[ - (from_node_id, to_node_id) # noqa: RUF031, RUF100 - ] = [] - for link_name in self._wn.get_links_for_node(from_node_name): - link = self._wn.get_link(link_name) - if ( - link.start_node_name == to_node_name # noqa: PLR1714 - or link.end_node_name == to_node_name - ): - tmp_list.append(link) - if link.initial_status != wntrfr.network.LinkStatus.closed: - ndx1, ndx2 = ndx_map[link] - self._internal_graph.data[ndx1] = 1 - self._internal_graph.data[ndx2] = 1 - - self._source_ids = [] - for node_name, node in self._wn.tanks(): - if node.init_level - node.min_level < 0.01: # noqa: PLR2004 - continue - node_id = self._node_name_to_id[node_name] - self._source_ids.append(node_id) - - for node_name, node in self._wn.reservoirs(): # noqa: B007 - connected_link_name_list = self._wn.get_links_for_node( - node_name - ) # this is to exclude the reservoirs that are for leak only - out_going_link_list_name = [ - link_name - for link_name in connected_link_name_list - if self._wn.get_link(link_name).link_type != 'Pipe' - ] - out_going_pipe_list_name = [ - self._wn.get_link(pipe_name) - for pipe_name in connected_link_name_list - if self._wn.get_link(pipe_name).link_type == 'Pipe' - ] - out_going_pipe_list_name = [ - link.name - for link in out_going_pipe_list_name - if ( - (link.cv == False and link.initial_status != LinkStatus.Closed) # noqa: E712 - or (link.cv == True and link.end_node_name != node_name) # noqa: E712 - ) - ] - out_going_link_list_name.extend(out_going_pipe_list_name) - if len(out_going_link_list_name) < 1: - continue - node_id = self._node_name_to_id[node_name] - self._source_ids.append(node_id) - self._source_ids = np.array(self._source_ids, dtype=self._int_dtype) - - def _update_internal_graph(self): - data = self._internal_graph.data - ndx_map = self._map_link_to_internal_graph_data_ndx - for mgr in [self._presolve_controls, self._rules, self._postsolve_controls]: - for obj, attr in mgr.get_changes(): - if attr == 'status': - if obj.status == wntrfr.network.LinkStatus.closed: - ndx1, ndx2 = ndx_map[obj] - data[ndx1] = 0 - data[ndx2] = 0 - else: - ndx1, ndx2 = ndx_map[obj] - data[ndx1] = 1 - data[ndx2] = 1 - - for key, link_list in self._node_pairs_with_multiple_links.items(): # noqa: B007, PERF102 - first_link = link_list[0] - ndx1, ndx2 = ndx_map[first_link] - data[ndx1] = 0 - data[ndx2] = 0 - for link in link_list: - if link.status != wntrfr.network.LinkStatus.closed: - ndx1, ndx2 = ndx_map[link] - data[ndx1] = 1 - data[ndx2] = 1 - - def _initialize_name_id_maps(self): - n = 0 - for link_name, link in self._wn.links(): # noqa: B007 - self._link_name_to_id[link_name] = n - self._link_id_to_name[n] = link_name - n += 1 # noqa: SIM113 - n = 0 - for node_name, node in self._wn.nodes(): # noqa: B007 - self._node_name_to_id[node_name] = n - self._node_id_to_name[n] = node_name - n += 1 - - def now_temp( # noqa: D102 - self, - rr, - isolated_link_list, - alread_closed_pipes, - _prev_isolated_junctions, - already_done_nodes, - ): - check_nodes = [ - node_name - for node_name in self._wn.junction_name_list - if node_name not in _prev_isolated_junctions - and node_name not in already_done_nodes - ] - junctions_pressure = (rr.node['pressure'][check_nodes]).iloc[-1] - negative_junctions_pressure = junctions_pressure[(junctions_pressure < -10)] # noqa: PLR2004 - negative_junctions_pressure = negative_junctions_pressure.sort_values( - ascending=False - ) - negative_junctions_name_list = negative_junctions_pressure.index.to_list() - print('size= ' + repr(len(negative_junctions_name_list))) # noqa: T201 - - pipes_to_be_closed = [] - closed_pipes = [] - # closed_nodes = [] - ifinish = False - - if len(negative_junctions_name_list) > 0: - i = 0 - c = 0 - while i < np.ceil( - len(negative_junctions_name_list) / len(negative_junctions_name_list) - ): - # for i in np.arange(0, ,1 ): - if i + c >= len(negative_junctions_name_list): - break - node_name = negative_junctions_name_list[i + c] - already_done_nodes.append(node_name) - # for node_name in negative_junctions_name_list: - pipe_linked_to_node = self._wn.get_links_for_node(node_name) - # get_checked_pipe_bool = self.check_pipes_sin(self, pipe_linked_to_node) - checked_pipe_list = [ - checked_pipe - for checked_pipe in pipe_linked_to_node - if self._wn.get_link(checked_pipe).link_type == 'Pipe' - and checked_pipe not in isolated_link_list - and self._wn.get_link(checked_pipe).cv == False # noqa: E712 - and self._wn.get_link(checked_pipe).initial_status == 1 - and self._wn.get_link(checked_pipe).start_node.node_type - == 'Junction' - and self._wn.get_link(checked_pipe).end_node.node_type - == 'Junction' - and checked_pipe not in alread_closed_pipes - ] - pipes_to_be_closed.extend(checked_pipe_list) - - flag = False - for pipe_name in pipes_to_be_closed: - # pipe = self.wn.get_link(pipe_name) - flow = rr.link['flowrate'][pipe_name].iloc[-1] - - if abs(flow) > 0.01: # noqa: PLR2004 - flag = True - # pipe.initial_status = LinkStatus(0) - closed_pipes.append(pipe_name) - if not flag: - i = i - 1 - c = c + 1 - i = i + 1 - else: - ifinish = True - return closed_pipes, already_done_nodes, ifinish - - def alterPipeKmNNN( # noqa: N802, D102 - self, - rr, - isolated_link_list, - _prev_isolated_junctions, - flow_criteria, - negative_pressure_limit, - ): - # t1 = time.time() - - closed_pipes = {} - - check_nodes = [ - node_name - for node_name in self._wn.junction_name_list - if node_name not in _prev_isolated_junctions - ] # not isolated junctions - junctions_pressure = (rr.node['pressure'][check_nodes]).iloc[ - -1 - ] # latest pressure result for not-isolated junctions - negative_junctions_pressure = junctions_pressure[ - (junctions_pressure < negative_pressure_limit) - ] # not-isolated junctions that have pressure less than specified amount - - negative_junctions_pressure = negative_junctions_pressure.sort_values( - ascending=False - ) - negative_junctions_name_list = negative_junctions_pressure.index.to_list() - - last_flow_row = rr.link['flowrate'].iloc[-1] - - pipe_found = False - while pipe_found == False: # noqa: E712 - if len(negative_junctions_name_list) == 0: - ifinish = True - return closed_pipes, ifinish - - pipe_name_list = [] - pipe_name_list_temp = self._wn.get_links_for_node( - negative_junctions_name_list[-1] - ) # new: the most negative - pipe_name_list.extend(pipe_name_list_temp) - - pipe_name_list = set(pipe_name_list) - set(isolated_link_list) - pipe_name_list = [ - pipe_name - for pipe_name in pipe_name_list - if pipe_name in self._wn.pipe_name_list - ] - most_recent_flow_for_pipes = last_flow_row[pipe_name_list] - abs_most_recent_flow_for_pipes = most_recent_flow_for_pipes.abs() - abs_most_recent_flow_for_pipes = abs_most_recent_flow_for_pipes[ - abs_most_recent_flow_for_pipes >= flow_criteria - ] - - if len(abs_most_recent_flow_for_pipes) == 0: - negative_junctions_pressure.drop( - negative_junctions_name_list[-1], - inplace=True, # noqa: PD002 - ) - negative_junctions_name_list = ( - negative_junctions_pressure.index.to_list() - ) - else: - pipe_found = True - ifinish = False - abs_most_recent_flow_for_pipes = abs_most_recent_flow_for_pipes.sort_values( - ascending=False - ) - biggest_flow_pipe_name = abs_most_recent_flow_for_pipes.index[0] - biggest_flow_pipe_abs_flow = abs_most_recent_flow_for_pipes.iloc[0] - pipe = self._wn.get_link(biggest_flow_pipe_name) - # n1 = pipe.start_node_name - # n2 = pipe.end_node_name - # n1_pressure = rr.node['pressure'][n1].iloc[-1] - # n2_pressure = rr.node['pressure'][n2].iloc[-1] - already_C = pipe.minor_loss # noqa: N806 - # if already_C < 0.001: - # already_C = 1 - new_C = (1000 * 2 * 9.81 * (pipe.diameter**2 * math.pi / 4) ** 2) / ( # noqa: N806 - (biggest_flow_pipe_abs_flow) ** 2 - ) + already_C # the last of 100 is to magnify the c choosing - pipe.minor_loss = new_C - closed_pipes[biggest_flow_pipe_name] = already_C - - # t2 = time.time() - # print(t2-t1) - # print('size closed: '+repr(len(closed_pipes)) ) - return closed_pipes, ifinish - - # if pipe.cv == True: - # continue - # if pipe._is_isolated == True: - # continue - # node_A = pipe.start_node - # node_B = pipe.end_node - - # if node_A.node_type != "Junction" or node_B.node_type != "Junction": - # continue - - # if node_A.name in already_nodes or node_B.name in already_nodes: - # continue - - # if pipe.initial_status != 1: - # continue - - # for - # flow = rr.link['flowrate'] - - # i_possitive_rate = True - - # if flow > 0.01: - # i_possitive_rate = True - # chosen_node = node_A - # elif flow < 0.01: - # i_possitive_rate = False - # chosen_node = node_B - # else: - # continue - - # def check_pipes_sin(self, pipe_list): - # for pipe_name in pipe_list: - def closePipeNNN( # noqa: N802, D102 - self, - rr, - isolated_link_list, - _prev_isolated_junctions, - flow_criteria, - negative_pressure_limit, - ): - closed_pipes = {} - - check_nodes = [ - node_name - for node_name in self._wn.junction_name_list - if node_name not in _prev_isolated_junctions - ] # not isolated junctions - junctions_pressure = (rr.node['pressure'][check_nodes]).iloc[ - -1 - ] # latest pressure result for not-isolated junctions - negative_junctions_pressure = junctions_pressure[ - (junctions_pressure < negative_pressure_limit) - ] # not-isolated junctions that have pressure less than specified amount - - negative_junctions_pressure = negative_junctions_pressure.sort_values( - ascending=False - ) - negative_junctions_name_list = negative_junctions_pressure.index.to_list() - - last_flow_row = rr.link['flowrate'].iloc[-1] - - pipe_found = False - while pipe_found == False: # noqa: E712 - if len(negative_junctions_name_list) == 0: - ifinish = True - return closed_pipes, ifinish - - pipe_name_list = [] - pipe_name_list_temp = self._wn.get_links_for_node( - negative_junctions_name_list[-1] - ) # new: the most negative - pipe_name_list.extend(pipe_name_list_temp) - - pipe_name_list = set(pipe_name_list) - set(isolated_link_list) - pipe_name_list = [ - pipe_name - for pipe_name in pipe_name_list - if pipe_name in self._wn.pipe_name_list - ] - most_recent_flow_for_pipes = last_flow_row[pipe_name_list] - abs_most_recent_flow_for_pipes = most_recent_flow_for_pipes.abs() - abs_most_recent_flow_for_pipes = abs_most_recent_flow_for_pipes[ - abs_most_recent_flow_for_pipes >= flow_criteria - ] - - if len(abs_most_recent_flow_for_pipes) == 0: - negative_junctions_pressure.drop( - negative_junctions_name_list[-1], - inplace=True, # noqa: PD002 - ) - negative_junctions_name_list = ( - negative_junctions_pressure.index.to_list() - ) - else: - pipe_found = True - ifinish = False - abs_most_recent_flow_for_pipes = abs_most_recent_flow_for_pipes.sort_values( - ascending=False - ) - biggest_flow_pipe_name = abs_most_recent_flow_for_pipes.index[0] - biggest_flow_pipe_abs_flow = abs_most_recent_flow_for_pipes.iloc[0] # noqa: F841 - pipe = self._wn.get_link(biggest_flow_pipe_name) - - already_C = pipe.minor_loss # noqa: N806, F841 - initial_status = pipe.initial_status - closed_pipes[biggest_flow_pipe_name] = initial_status - pipe.initial_status = LinkStatus.Closed - - return closed_pipes, ifinish - - # if pipe.cv == True: - # continue - # if pipe._is_isolated == True: - # continue - # node_A = pipe.start_node - # node_B = pipe.end_node - - # if node_A.node_type != "Junction" or node_B.node_type != "Junction": - # continue - - # if node_A.name in already_nodes or node_B.name in already_nodes: - # continue - - # if pipe.initial_status != 1: - # continue - - # for - # flow = rr.link['flowrate'] - - # i_possitive_rate = True - - # if flow > 0.01: - # i_possitive_rate = True - # chosen_node = node_A - # elif flow < 0.01: - # i_possitive_rate = False - # chosen_node = node_B - # else: - # continue - - # def check_pipes_sin(self, pipe_list): - # for pipe_name in pipe_list: diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/io.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/io.py deleted file mode 100644 index 0422e1318..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/io.py +++ /dev/null @@ -1,1703 +0,0 @@ -"""The wntrfr.epanet.io module contains methods for reading/writing EPANET input and output files. - -.. rubric:: Contents - -.. autosummary:: - - InpFile - BinFile - ----- - - -""" - -import logging -import re - -import numpy as np -import pandas as pd - -# from .time_utils import run_lineprofile -import wntrfr.network -import wntrfr.sim -from wntrfr.network.base import Link -from wntrfr.network.controls import ( - Comparison, - Control, - SimTimeCondition, - TimeOfDayCondition, - ValueCondition, - _ControlType, -) -from wntrfr.network.elements import Junction, Pipe, Pump, Tank, Valve -from wntrfr.network.model import LinkStatus - -from .util import ( - EN, - FlowUnits, - HydParam, - MassUnits, - MixType, - PressureUnits, - QualParam, - QualType, - ResultType, - StatisticsType, - from_si, - to_si, -) - -logger = logging.getLogger(__name__) - -_INP_SECTIONS = [ - '[OPTIONS]', - '[TITLE]', - '[JUNCTIONS]', - '[RESERVOIRS]', - '[TANKS]', - '[PIPES]', - '[PUMPS]', - '[VALVES]', - '[EMITTERS]', - '[CURVES]', - '[PATTERNS]', - '[ENERGY]', - '[STATUS]', - '[CONTROLS]', - '[RULES]', - '[DEMANDS]', - '[QUALITY]', - '[REACTIONS]', - '[SOURCES]', - '[MIXING]', - '[TIMES]', - '[REPORT]', - '[COORDINATES]', - '[VERTICES]', - '[LABELS]', - '[BACKDROP]', - '[TAGS]', -] - -_JUNC_ENTRY = ' {name:20} {elev:15.11g} {dem:15.11g} {pat:24} {com:>3s}\n' -_JUNC_LABEL = '{:21} {:>12s} {:>12s} {:24}\n' - -_RES_ENTRY = ' {name:20s} {head:15.11g} {pat:>24s} {com:>3s}\n' -_RES_LABEL = '{:21s} {:>20s} {:>24s}\n' - -_TANK_ENTRY = ' {name:20s} {elev:15.11g} {initlev:15.11g} {minlev:15.11g} {maxlev:15.11g} {diam:15.11g} {minvol:15.11g} {curve:20s} {com:>3s}\n' -_TANK_LABEL = '{:21s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s} {:20s}\n' - -_PIPE_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {len:15.11g} {diam:15.11g} {rough:15.11g} {mloss:15.11g} {status:>20s} {com:>3s}\n' -_PIPE_LABEL = '{:21s} {:20s} {:20s} {:>20s} {:>20s} {:>20s} {:>20s} {:>20s}\n' - -_PUMP_ENTRY = ( - ' {name:20s} {node1:20s} {node2:20s} {ptype:8s} {params:20s} {com:>3s}\n' -) -_PUMP_LABEL = '{:21s} {:20s} {:20s} {:20s}\n' - -_VALVE_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {diam:15.11g} {vtype:4s} {set:15.11g} {mloss:15.11g} {com:>3s}\n' -_GPV_ENTRY = ' {name:20s} {node1:20s} {node2:20s} {diam:15.11g} {vtype:4s} {set:20s} {mloss:15.11g} {com:>3s}\n' -_VALVE_LABEL = '{:21s} {:20s} {:20s} {:>20s} {:4s} {:>20s} {:>20s}\n' - -_CURVE_ENTRY = ' {name:10s} {x:12f} {y:12f} {com:>3s}\n' -_CURVE_LABEL = '{:11s} {:12s} {:12s}\n' - - -def _split_line(line): - _vc = line.split(';', 1) - _cmnt = None - _vals = None - if len(_vc) == 0: - pass - elif len(_vc) == 1: - _vals = _vc[0].split() - elif _vc[0] == '': - _cmnt = _vc[1] - else: - _vals = _vc[0].split() - _cmnt = _vc[1] - return _vals, _cmnt - - -def _is_number(s): - """Checks if input is a number - - Parameters - ---------- - s : anything - - """ # noqa: D400, D401 - try: - float(s) - return True # noqa: DOC201, RUF100, TRY300 - except ValueError: - return False - - -def _str_time_to_sec(s): - """Converts EPANET time format to seconds. - - Parameters - ---------- - s : string - EPANET time string. Options are 'HH:MM:SS', 'HH:MM', 'HH' - - - Returns - ------- - Integer value of time in seconds. - - """ # noqa: D401 - pattern1 = re.compile(r'^(\d+):(\d+):(\d+)$') - time_tuple = pattern1.search(s) - if bool(time_tuple): - return ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - + int(round(float(time_tuple.groups()[2]))) - ) - else: # noqa: RET505 - pattern2 = re.compile(r'^(\d+):(\d+)$') - time_tuple = pattern2.search(s) - if bool(time_tuple): - return ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - ) - else: # noqa: RET505 - pattern3 = re.compile(r'^(\d+)$') - time_tuple = pattern3.search(s) - if bool(time_tuple): - return int(time_tuple.groups()[0]) * 60 * 60 - else: # noqa: RET505 - raise RuntimeError('Time format in ' 'INP file not recognized. ') # noqa: EM101, TRY003 - - -def _clock_time_to_sec(s, am_pm): # noqa: C901 - """Converts EPANET clocktime format to seconds. - - Parameters - ---------- - s : string - EPANET time string. Options are 'HH:MM:SS', 'HH:MM', HH' - - am : string - options are AM or PM - - - Returns - ------- - Integer value of time in seconds - - """ # noqa: D401 - if am_pm.upper() == 'AM': - am = True - elif am_pm.upper() == 'PM': - am = False - else: - raise RuntimeError('am_pm option not recognized; options are AM or PM') # noqa: EM101, TRY003 - - pattern1 = re.compile(r'^(\d+):(\d+):(\d+)$') - time_tuple = pattern1.search(s) - if bool(time_tuple): - time_sec = ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - + int(round(float(time_tuple.groups()[2]))) - ) - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - pattern2 = re.compile(r'^(\d+):(\d+)$') - time_tuple = pattern2.search(s) - if bool(time_tuple): - time_sec = ( - int(time_tuple.groups()[0]) * 60 * 60 - + int(time_tuple.groups()[1]) * 60 - ) - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - pattern3 = re.compile(r'^(\d+)$') - time_tuple = pattern3.search(s) - if bool(time_tuple): - time_sec = int(time_tuple.groups()[0]) * 60 * 60 - if s.startswith('12'): - time_sec -= 3600 * 12 - if not am: - if time_sec >= 3600 * 12: - raise RuntimeError( # noqa: TRY003 - 'Cannot specify am/pm for times greater than 12:00:00' # noqa: EM101 - ) - time_sec += 3600 * 12 - return time_sec - else: # noqa: RET505 - raise RuntimeError('Time format in ' 'INP file not recognized. ') # noqa: EM101, TRY003 - - -def _sec_to_string(sec): - hours = int(sec / 3600.0) - sec -= hours * 3600 - mm = int(sec / 60.0) - sec -= mm * 60 - return (hours, mm, int(sec)) - - -class InpFile(wntrfr.epanet.InpFile): - """EPANET INP file reader and writer class. - - This class provides read and write functionality for EPANET INP files. - The EPANET Users Manual provides full documentation for the INP file format. - """ - - def __init__(self): - super().__init__() - - def _write_junctions(self, f, wn): - f.write('[JUNCTIONS]\n'.encode('ascii')) - f.write( - _JUNC_LABEL.format(';ID', 'Elevation', 'Demand', 'Pattern').encode( - 'ascii' - ) - ) - nnames = list(wn.junction_name_list) - # nnames.sort() - for junction_name in nnames: - junction = wn.nodes[junction_name] - # sina added this - if junction._is_isolated == True: # noqa: SLF001, E712 - continue - if junction.demand_timeseries_list: - base_demands = junction.demand_timeseries_list.base_demand_list() - demand_patterns = junction.demand_timeseries_list.pattern_list() - if base_demands: - base_demand = base_demands[0] - else: - base_demand = 0.0 - if demand_patterns: - if demand_patterns[0] == wn.options.hydraulic.pattern: - demand_pattern = None - else: - demand_pattern = demand_patterns[0] - else: - demand_pattern = None - else: - base_demand = 0.0 - demand_pattern = None - E = { # noqa: N806 - 'name': junction_name, - 'elev': from_si( - self.flow_units, junction.elevation, HydParam.Elevation - ), - 'dem': from_si(self.flow_units, base_demand, HydParam.Demand), - 'pat': '', - 'com': ';', - } - if demand_pattern is not None: - E['pat'] = str(demand_pattern) - f.write(_JUNC_ENTRY.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_reservoirs(self, f, wn): - f.write('[RESERVOIRS]\n'.encode('ascii')) - f.write(_RES_LABEL.format(';ID', 'Head', 'Pattern').encode('ascii')) - nnames = list(wn.reservoir_name_list) - # nnames.sort() - for reservoir_name in nnames: - reservoir = wn.nodes[reservoir_name] - # sina added this - if reservoir._is_isolated == True: # noqa: SLF001, E712 - continue - E = { # noqa: N806 - 'name': reservoir_name, - 'head': from_si( - self.flow_units, - reservoir.head_timeseries.base_value, - HydParam.HydraulicHead, - ), - 'com': ';', - } - if reservoir.head_timeseries.pattern is None: - E['pat'] = '' - else: - E['pat'] = reservoir.head_timeseries.pattern.name - f.write(_RES_ENTRY.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_tanks(self, f, wn): - f.write('[TANKS]\n'.encode('ascii')) - f.write( - _TANK_LABEL.format( - ';ID', - 'Elevation', - 'Init Level', - 'Min Level', - 'Max Level', - 'Diameter', - 'Min Volume', - 'Volume Curve', - ).encode('ascii') - ) - nnames = list(wn.tank_name_list) - # nnames.sort() - for tank_name in nnames: - tank = wn.nodes[tank_name] - if tank._is_isolated == True: # sina added this # noqa: SLF001, E712 - continue - E = { # noqa: N806 - 'name': tank_name, - 'elev': from_si(self.flow_units, tank.elevation, HydParam.Elevation), - 'initlev': from_si( - self.flow_units, tank.init_level, HydParam.HydraulicHead - ), - 'minlev': from_si( - self.flow_units, tank.min_level, HydParam.HydraulicHead - ), - 'maxlev': from_si( - self.flow_units, tank.max_level, HydParam.HydraulicHead - ), - 'diam': from_si( - self.flow_units, tank.diameter, HydParam.TankDiameter - ), - 'minvol': from_si(self.flow_units, tank.min_vol, HydParam.Volume), - 'curve': '', - 'com': ';', - } - if tank.vol_curve is not None: - E['curve'] = tank.vol_curve.name - f.write(_TANK_ENTRY.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_pipes(self, f, wn): - f.write('[PIPES]\n'.encode('ascii')) - f.write( - _PIPE_LABEL.format( - ';ID', - 'Node1', - 'Node2', - 'Length', - 'Diameter', - 'Roughness', - 'Minor Loss', - 'Status', - ).encode('ascii') - ) - lnames = list(wn.pipe_name_list) - # lnames.sort() - for pipe_name in lnames: - pipe = wn.links[pipe_name] - if pipe._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - E = { # noqa: N806 - 'name': pipe_name, - 'node1': pipe.start_node_name, - 'node2': pipe.end_node_name, - 'len': from_si(self.flow_units, pipe.length, HydParam.Length), - 'diam': from_si( - self.flow_units, pipe.diameter, HydParam.PipeDiameter - ), - 'rough': pipe.roughness, - 'mloss': pipe.minor_loss, - 'status': str(pipe.initial_status), - 'com': ';', - } - if pipe.cv: - E['status'] = 'CV' - f.write(_PIPE_ENTRY.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_pumps(self, f, wn): - f.write('[PUMPS]\n'.encode('ascii')) - f.write( - _PUMP_LABEL.format(';ID', 'Node1', 'Node2', 'Properties').encode('ascii') - ) - lnames = list(wn.pump_name_list) - # lnames.sort() - for pump_name in lnames: - pump = wn.links[pump_name] - if pump._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - E = { # noqa: N806 - 'name': pump_name, - 'node1': pump.start_node_name, - 'node2': pump.end_node_name, - 'ptype': pump.pump_type, - 'params': '', - # 'speed_keyword': 'SPEED', - # 'speed': pump.speed_timeseries.base_value, - 'com': ';', - } - if pump.pump_type == 'HEAD': - E['params'] = pump.pump_curve_name - elif pump.pump_type == 'POWER': - E['params'] = str( - from_si(self.flow_units, pump.power, HydParam.Power) - ) - else: - raise RuntimeError('Only head or power info is supported of pumps.') # noqa: EM101, TRY003 - tmp_entry = _PUMP_ENTRY - if pump.speed_timeseries.base_value != 1: - E['speed_keyword'] = 'SPEED' - E['speed'] = pump.speed_timeseries.base_value - tmp_entry = ( - tmp_entry.rstrip('\n').rstrip('}').rstrip('com:>3s').rstrip(' {') - + ' {speed_keyword:8s} {speed:15.11g} {com:>3s}\n' - ) - if pump.speed_timeseries.pattern is not None: - tmp_entry = ( - tmp_entry.rstrip('\n').rstrip('}').rstrip('com:>3s').rstrip(' {') - + ' {pattern_keyword:10s} {pattern:20s} {com:>3s}\n' - ) - E['pattern_keyword'] = 'PATTERN' - E['pattern'] = pump.speed_timeseries.pattern.name - f.write(tmp_entry.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_valves(self, f, wn): - f.write('[VALVES]\n'.encode('ascii')) - f.write( - _VALVE_LABEL.format( - ';ID', 'Node1', 'Node2', 'Diameter', 'Type', 'Setting', 'Minor Loss' - ).encode('ascii') - ) - lnames = list(wn.valve_name_list) - # lnames.sort() - for valve_name in lnames: - valve = wn.links[valve_name] - if valve._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - E = { # noqa: N806 - 'name': valve_name, - 'node1': valve.start_node_name, - 'node2': valve.end_node_name, - 'diam': from_si( - self.flow_units, valve.diameter, HydParam.PipeDiameter - ), - 'vtype': valve.valve_type, - 'set': valve._initial_setting, # noqa: SLF001 - 'mloss': valve.minor_loss, - 'com': ';', - } - valve_type = valve.valve_type - formatter = _VALVE_ENTRY - if valve_type in ['PRV', 'PSV', 'PBV']: - valve_set = from_si( - self.flow_units, - valve._initial_setting, # noqa: SLF001 - HydParam.Pressure, - ) - elif valve_type == 'FCV': - valve_set = from_si( - self.flow_units, - valve._initial_setting, # noqa: SLF001 - HydParam.Flow, - ) - elif valve_type == 'TCV': - valve_set = valve._initial_setting # noqa: SLF001 - elif valve_type == 'GPV': - valve_set = valve.headloss_curve_name - formatter = _GPV_ENTRY - E['set'] = valve_set - f.write(formatter.format(**E).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_emitters(self, f, wn): - f.write('[EMITTERS]\n'.encode('ascii')) - entry = '{:10s} {:10s}\n' - label = '{:10s} {:10s}\n' - f.write(label.format(';ID', 'Flow coefficient').encode('ascii')) - njunctions = list(wn.junction_name_list) - # njunctions.sort() - for junction_name in njunctions: - junction = wn.nodes[junction_name] - # Sina added this - if junction._is_isolated == True: # noqa: SLF001, E712 - continue - if junction._emitter_coefficient: # noqa: SLF001 - val = from_si( - self.flow_units, - junction._emitter_coefficient, # noqa: SLF001 - HydParam.Flow, - ) - f.write(entry.format(junction_name, str(val)).encode('ascii')) - f.write('\n'.encode('ascii')) - - # System Operation - - def _write_status(self, f, wn): - f.write('[STATUS]\n'.encode('ascii')) - f.write('{:10s} {:10s}\n'.format(';ID', 'Setting').encode('ascii')) - for link_name, link in wn.links(): - if link._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if isinstance(link, Pipe): - continue - if isinstance(link, Pump): - setting = link.initial_setting - if type(setting) is float and setting != 1.0: - f.write(f'{link_name:10s} {setting:10.10g}\n'.encode('ascii')) - if link.initial_status == LinkStatus.Closed: - f.write( - f'{link_name:10s} {LinkStatus(link.initial_status).name:10s}\n'.encode( - 'ascii' - ) - ) - if isinstance(link, wntrfr.network.Valve) and link.initial_status in ( - LinkStatus.Open, - LinkStatus.Opened, - ): - # if link.initial_status in (LinkStatus.Closed,): - f.write( - f'{link_name:10s} {LinkStatus(link.initial_status).name:10s}\n'.encode( - 'ascii' - ) - ) - - # if link.initial_status is LinkStatus.Active: - # valve_type = link.valve_type - # if valve_type in ['PRV', 'PSV', 'PBV']: - # setting = from_si(self.flow_units, link.initial_setting, HydParam.Pressure) - # elif valve_type == 'FCV': - # setting = from_si(self.flow_units, link.initial_setting, HydParam.Flow) - # elif valve_type == 'TCV': - # setting = link.initial_setting - # else: - # continue - # continue - # elif isinstance(link, wntrfr.network.Pump): - # setting = link.initial_setting - # else: continue - # f.write('{:10s} {:10.10g}\n'.format(link_name, - # setting).encode('ascii')) - # f.write('\n'.encode('ascii')) - - def _write_controls(self, f, wn): # noqa: C901 - def get_setting(control_action, control_name): - value = control_action._value # noqa: SLF001 - attribute = control_action._attribute.lower() # noqa: SLF001 - if attribute == 'status': - setting = LinkStatus(value).name - elif attribute == 'base_speed': - setting = str(value) - elif attribute == 'setting' and isinstance( - control_action._target_obj, # noqa: SLF001 - Valve, - ): - valve = control_action._target_obj # noqa: SLF001 - valve_type = valve.valve_type - if valve_type == 'PRV' or valve_type == 'PSV' or valve_type == 'PBV': # noqa: PLR1714 - setting = str(from_si(self.flow_units, value, HydParam.Pressure)) - elif valve_type == 'FCV': - setting = str(from_si(self.flow_units, value, HydParam.Flow)) - elif valve_type == 'TCV': - setting = str(value) - elif valve_type == 'GPV': - setting = value - else: - raise ValueError('Valve type not recognized' + str(valve_type)) - elif attribute == 'setting': - setting = value - else: - setting = None - logger.warning( - 'Could not write control ' + str(control_name) + ' - skipping' # noqa: G003 - ) - - return setting - - f.write('[CONTROLS]\n'.encode('ascii')) - # Time controls and conditional controls only - for text, all_control in wn.controls(): - control_action = all_control._then_actions[0] # noqa: SLF001 - # Sina added this - if control_action._target_obj._is_isolated == True: # noqa: SLF001, E712 - continue - if all_control.epanet_control_type is not _ControlType.rule: - if ( - len(all_control._then_actions) != 1 # noqa: SLF001 - or len(all_control._else_actions) != 0 # noqa: SLF001 - ): - logger.error('Too many actions on CONTROL "%s"' % text) # noqa: G002, UP031 - raise RuntimeError('Too many actions on CONTROL "%s"' % text) # noqa: UP031 - if not isinstance(control_action.target()[0], Link): - continue - if isinstance( - all_control._condition, # noqa: SLF001 - (SimTimeCondition, TimeOfDayCondition), - ): - entry = '{ltype} {link} {setting} AT {compare} {time:g}\n' - vals = { - 'ltype': control_action._target_obj.link_type, # noqa: SLF001 - 'link': control_action._target_obj.name, # noqa: SLF001 - 'setting': get_setting(control_action, text), - 'compare': 'TIME', - 'time': all_control._condition._threshold / 3600.0, # noqa: SLF001 - } - if vals['setting'] is None: - continue - if isinstance(all_control._condition, TimeOfDayCondition): # noqa: SLF001 - vals['compare'] = 'CLOCKTIME' - f.write(entry.format(**vals).encode('ascii')) - elif ( - all_control._condition._source_obj._is_isolated == True # noqa: SLF001, E712 - ): # Sina added this - continue - elif isinstance(all_control._condition, (ValueCondition)): # noqa: SLF001 - entry = '{ltype} {link} {setting} IF {ntype} {node} {compare} {thresh}\n' - vals = { - 'ltype': control_action._target_obj.link_type, # noqa: SLF001 - 'link': control_action._target_obj.name, # noqa: SLF001 - 'setting': get_setting(control_action, text), - 'ntype': all_control._condition._source_obj.node_type, # noqa: SLF001 - 'node': all_control._condition._source_obj.name, # noqa: SLF001 - 'compare': 'above', - 'thresh': 0.0, - } - if vals['setting'] is None: - continue - if all_control._condition._relation in [ # noqa: SLF001 - np.less, - np.less_equal, - Comparison.le, - Comparison.lt, - ]: - vals['compare'] = 'below' - threshold = all_control._condition._threshold # noqa: SLF001 - if isinstance(all_control._condition._source_obj, Tank): # noqa: SLF001 - vals['thresh'] = from_si( - self.flow_units, threshold, HydParam.HydraulicHead - ) - elif isinstance(all_control._condition._source_obj, Junction): # noqa: SLF001 - vals['thresh'] = from_si( - self.flow_units, threshold, HydParam.Pressure - ) - else: - raise RuntimeError( # noqa: TRY004 - 'Unknown control for EPANET INP files: %s' # noqa: UP031 - % type(all_control) - ) - f.write(entry.format(**vals).encode('ascii')) - elif not isinstance(all_control, Control): - raise RuntimeError( - 'Unknown control for EPANET INP files: %s' # noqa: UP031 - % type(all_control) - ) - f.write('\n'.encode('ascii')) - - def _write_rules(self, f, wn): - f.write('[RULES]\n'.encode('ascii')) - for text, all_control in wn.controls(): # noqa: B007 - entry = '{}\n' - if all_control.epanet_control_type == _ControlType.rule: - # Sina added this begin - try: - if all_control._then_actions[0]._target_obj._is_isolated == True: # noqa: SLF001, E712 - continue - except: # noqa: S110, E722 - pass - - try: - if all_control.condition._source_obj._is_isolated == True: # noqa: SLF001, E712 - continue - except: # noqa: S110, E722 - pass - - # Sina added this end - rule = _EpanetRule('blah', self.flow_units, self.mass_units) # noqa: F821 - rule.from_if_then_else(all_control) - f.write(entry.format(str(rule)).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_demands(self, f, wn): - f.write('[DEMANDS]\n'.encode('ascii')) - entry = '{:10s} {:10s} {:10s}{:s}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';ID', 'Demand', 'Pattern').encode('ascii')) - nodes = list(wn.junction_name_list) - # nodes.sort() - for node in nodes: - # Sina added this - if wn.get_node(node)._is_isolated == True: # noqa: SLF001, E712 - continue - demands = wn.get_node(node).demand_timeseries_list - # leak = - if len(demands) > 1: - for ct, demand in enumerate(demands): # noqa: B007 - cat = str(demand.category) - # if cat == 'EN2 base': - # cat = '' - if cat.lower() == 'none': - cat = '' - else: - cat = ' ;' + demand.category - E = { # noqa: N806 - 'node': node, - 'base': from_si( - self.flow_units, demand.base_value, HydParam.Demand - ), - 'pat': '', - 'cat': cat, - } - if demand.pattern_name in wn.pattern_name_list: - E['pat'] = demand.pattern_name - f.write( - entry.format( - E['node'], str(E['base']), E['pat'], E['cat'] - ).encode('ascii') - ) - f.write('\n'.encode('ascii')) - - # Water Quality - - def _write_quality(self, f, wn): - f.write('[QUALITY]\n'.encode('ascii')) - entry = '{:10s} {:10s}\n' - label = '{:10s} {:10s}\n' # noqa: F841 - nnodes = list(wn.nodes.keys()) - # nnodes.sort() - for node_name in nnodes: - node = wn.nodes[node_name] - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if node.initial_quality: - if wn.options.quality.mode == 'CHEMICAL': - quality = from_si( - self.flow_units, - node.initial_quality, - QualParam.Concentration, - mass_units=self.mass_units, - ) - elif wn.options.quality.mode == 'AGE': - quality = from_si( - self.flow_units, node.initial_quality, QualParam.WaterAge - ) - else: - quality = node.initial_quality - f.write(entry.format(node_name, str(quality)).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_reactions(self, f, wn): - f.write('[REACTIONS]\n'.encode('ascii')) - f.write( - ';Type Pipe/Tank Coefficient\n'.encode('ascii') - ) - entry_int = ' {:s} {:s} {:d}\n' - entry_float = ' {:s} {:s} {:<10.4f}\n' - for tank_name, tank in wn.nodes(Tank): - if tank._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if tank.bulk_rxn_coeff is not None: - f.write( - entry_float.format( - 'TANK', - tank_name, - from_si( - self.flow_units, - tank.bulk_rxn_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.quality.bulk_rxn_order, - ), - ).encode('ascii') - ) - for pipe_name, pipe in wn.links(Pipe): - if pipe._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if pipe.bulk_rxn_coeff is not None: - f.write( - entry_float.format( - 'BULK', - pipe_name, - from_si( - self.flow_units, - pipe.bulk_rxn_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.quality.bulk_rxn_order, - ), - ).encode('ascii') - ) - if pipe.wall_rxn_coeff is not None: - f.write( - entry_float.format( - 'WALL', - pipe_name, - from_si( - self.flow_units, - pipe.wall_rxn_coeff, - QualParam.WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.quality.wall_rxn_order, - ), - ).encode('ascii') - ) - f.write('\n'.encode('ascii')) - # f.write('[REACTIONS]\n'.encode('ascii')) # EPANET GUI puts this line in here - f.write( - entry_int.format( - 'ORDER', 'BULK', int(wn.options.quality.bulk_rxn_order) - ).encode('ascii') - ) - f.write( - entry_int.format( - 'ORDER', 'TANK', int(wn.options.quality.tank_rxn_order) - ).encode('ascii') - ) - f.write( - entry_int.format( - 'ORDER', 'WALL', int(wn.options.quality.wall_rxn_order) - ).encode('ascii') - ) - f.write( - entry_float.format( - 'GLOBAL', - 'BULK', - from_si( - self.flow_units, - wn.options.quality.bulk_rxn_coeff, - QualParam.BulkReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.quality.bulk_rxn_order, - ), - ).encode('ascii') - ) - f.write( - entry_float.format( - 'GLOBAL', - 'WALL', - from_si( - self.flow_units, - wn.options.quality.wall_rxn_coeff, - QualParam.WallReactionCoeff, - mass_units=self.mass_units, - reaction_order=wn.options.quality.wall_rxn_order, - ), - ).encode('ascii') - ) - if wn.options.quality.limiting_potential is not None: - f.write( - entry_float.format( - 'LIMITING', 'POTENTIAL', wn.options.quality.limiting_potential - ).encode('ascii') - ) - if wn.options.quality.roughness_correl is not None: - f.write( - entry_float.format( - 'ROUGHNESS', 'CORRELATION', wn.options.quality.roughness_correl - ).encode('ascii') - ) - f.write('\n'.encode('ascii')) - - def _write_sources(self, f, wn): - f.write('[SOURCES]\n'.encode('ascii')) - entry = '{:10s} {:10s} {:10s} {:10s}\n' - label = '{:10s} {:10s} {:10s} {:10s}\n' - f.write(label.format(';Node', 'Type', 'Quality', 'Pattern').encode('ascii')) - nsources = list(wn._sources.keys()) # noqa: SLF001 - # nsources.sort() - for source_name in nsources: - source = wn._sources[source_name] # noqa: SLF001 - if source._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - - if source.source_type.upper() == 'MASS': - strength = from_si( - self.flow_units, - source.strength_timeseries.base_value, - QualParam.SourceMassInject, - self.mass_units, - ) - else: # CONC, SETPOINT, FLOWPACED - strength = from_si( - self.flow_units, - source.strength_timeseries.base_value, - QualParam.Concentration, - self.mass_units, - ) - - E = { # noqa: N806 - 'node': source.node_name, - 'type': source.source_type, - 'quality': str(strength), - 'pat': '', - } - if source.strength_timeseries.pattern_name is not None: - E['pat'] = source.strength_timeseries.pattern_name - f.write( - entry.format( - E['node'], E['type'], str(E['quality']), E['pat'] - ).encode('ascii') - ) - f.write('\n'.encode('ascii')) - - def _write_mixing(self, f, wn): - f.write('[MIXING]\n'.encode('ascii')) - f.write( - '{:20s} {:5s} {}\n'.format(';Tank ID', 'Model', 'Fraction').encode( - 'ascii' - ) - ) - lnames = list(wn.tank_name_list) - # lnames.sort() - for tank_name in lnames: - tank = wn.nodes[tank_name] - if tank._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if tank._mix_model is not None: # noqa: SLF001 - if tank._mix_model in [MixType.Mixed, MixType.Mix1, 0]: # noqa: SLF001 - f.write(f' {tank_name:19s} MIXED\n'.encode('ascii')) - elif tank._mix_model in [ # noqa: SLF001 - MixType.TwoComp, - MixType.Mix2, - '2comp', - '2COMP', - 1, - ]: - f.write( - f' {tank_name:19s} 2COMP {tank._mix_frac}\n'.encode('ascii') # noqa: SLF001 - ) - elif tank._mix_model in [MixType.FIFO, 2]: # noqa: SLF001 - f.write(f' {tank_name:19s} FIFO\n'.encode('ascii')) - elif tank._mix_model in [MixType.LIFO, 3]: # noqa: SLF001 - f.write(f' {tank_name:19s} LIFO\n'.encode('ascii')) - elif isinstance(tank._mix_model, str) and tank._mix_frac is not None: # noqa: SLF001 - f.write( - f' {tank_name:19s} {tank._mix_model} {tank._mix_frac}\n'.encode( # noqa: SLF001 - 'ascii' - ) - ) - elif isinstance(tank._mix_model, str): # noqa: SLF001 - f.write(f' {tank_name:19s} {tank._mix_model}\n'.encode('ascii')) # noqa: SLF001 - else: - logger.warning('Unknown mixing model: %s', tank._mix_model) # noqa: SLF001 - f.write('\n'.encode('ascii')) - - # Options and Reporting - - def _write_options(self, f, wn): - f.write('[OPTIONS]\n'.encode('ascii')) - entry_string = '{:20s} {:20s}\n' - entry_float = '{:20s} {:.11g}\n' - f.write(entry_string.format('UNITS', self.flow_units.name).encode('ascii')) - - f.write( - entry_string.format('HEADLOSS', wn.options.hydraulic.headloss).encode( - 'ascii' - ) - ) - - f.write( - entry_float.format( - 'SPECIFIC GRAVITY', wn.options.hydraulic.specific_gravity - ).encode('ascii') - ) - - f.write( - entry_float.format('VISCOSITY', wn.options.hydraulic.viscosity).encode( - 'ascii' - ) - ) - - f.write( - entry_float.format('TRIALS', wn.options.solver.trials).encode('ascii') - ) - - f.write( - entry_float.format('ACCURACY', wn.options.solver.accuracy).encode( - 'ascii' - ) - ) - - f.write( - entry_float.format('CHECKFREQ', wn.options.solver.checkfreq).encode( - 'ascii' - ) - ) - - f.write( - entry_float.format('MAXCHECK', wn.options.solver.maxcheck).encode( - 'ascii' - ) - ) - - if wn.options.solver.damplimit != 0: - f.write( - entry_float.format('DAMPLIMIT', wn.options.solver.damplimit).encode( - 'ascii' - ) - ) - - if wn.options.solver.unbalanced_value is None: - f.write( - entry_string.format( - 'UNBALANCED', wn.options.solver.unbalanced - ).encode('ascii') - ) - else: - f.write( - '{:20s} {:s} {:d}\n'.format( - 'UNBALANCED', - wn.options.solver.unbalanced, - wn.options.solver.unbalanced_value, - ).encode('ascii') - ) - - # Sina Added here - if wn.options.hydraulic.pattern is not None: - f.write( - entry_string.format('PATTERN', wn.options.hydraulic.pattern).encode( - 'ascii' - ) - ) - else: - f.write(entry_string.format('PATTERN', '1').encode('ascii')) - - f.write( - entry_float.format( - 'DEMAND MULTIPLIER', wn.options.hydraulic.demand_multiplier - ).encode('ascii') - ) - - f.write( - entry_string.format( - 'DEMAND MODEL', wn.options.hydraulic.demand_model - ).encode('ascii') - ) - - f.write( - entry_float.format( - 'MINIMUM PRESSURE', wn.options.hydraulic.minimum_pressure - ).encode('ascii') - ) - - f.write( - entry_float.format( - 'REQUIRED PRESSURE', wn.options.hydraulic.required_pressure - ).encode('ascii') - ) - - f.write( - entry_float.format( - 'PRESSURE EXPONENT', wn.options.hydraulic.pressure_exponent - ).encode('ascii') - ) - - f.write( - entry_float.format( - 'EMITTER EXPONENT', wn.options.hydraulic.emitter_exponent - ).encode('ascii') - ) - - if wn.options.quality.mode.upper() in ['NONE', 'AGE']: - f.write( - entry_string.format('QUALITY', wn.options.quality.mode).encode( - 'ascii' - ) - ) - elif wn.options.quality.mode.upper() == 'TRACE': - f.write( - '{:20s} {} {}\n'.format( - 'QUALITY', wn.options.quality.mode, wn.options.quality.trace_node - ).encode('ascii') - ) - else: - f.write( - '{:20s} {} {}\n'.format( - 'QUALITY', - wn.options.quality.chemical_name, - wn.options.quality.wq_units, - ).encode('ascii') - ) - - f.write( - entry_float.format('DIFFUSIVITY', wn.options.quality.diffusivity).encode( - 'ascii' - ) - ) - - f.write( - entry_float.format('TOLERANCE', wn.options.solver.tolerance).encode( - 'ascii' - ) - ) - - if wn.options.hydraulic.hydraulics is not None: - f.write( - '{:20s} {:s} {:<30s}\n'.format( - 'HYDRAULICS', - wn.options.hydraulic.hydraulics, - wn.options.hydraulic.hydraulics_filename, - ).encode('ascii') - ) - - if wn.options.graphics.map_filename is not None: - f.write( - entry_string.format('MAP', wn.options.graphics.map_filename).encode( - 'ascii' - ) - ) - f.write('\n'.encode('ascii')) - - def _write_times(self, f, wn): - f.write('[TIMES]\n'.encode('ascii')) - entry = '{:20s} {:10s}\n' - time_entry = '{:20s} {:02d}:{:02d}:{:02d}\n' - - hrs, mm, sec = _sec_to_string(wn.options.time.duration) - f.write(time_entry.format('DURATION', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.hydraulic_timestep) - f.write( - time_entry.format('HYDRAULIC TIMESTEP', hrs, mm, sec).encode('ascii') - ) - - hrs, mm, sec = _sec_to_string(wn.options.time.quality_timestep) - f.write(time_entry.format('QUALITY TIMESTEP', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.pattern_timestep) - f.write(time_entry.format('PATTERN TIMESTEP', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.pattern_start) - f.write(time_entry.format('PATTERN START', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.report_timestep) - f.write(time_entry.format('REPORT TIMESTEP', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.report_start) - f.write(time_entry.format('REPORT START', hrs, mm, sec).encode('ascii')) - - hrs, mm, sec = _sec_to_string(wn.options.time.start_clocktime) - - # Sina - day = int(hrs / 24) - hrs -= day * 24 - - if hrs < 12: # noqa: PLR2004 - time_format = ' AM' - else: - hrs -= 12 - time_format = ' PM' - f.write( - '{:20s} {:02d}:{:02d}:{:02d}{:s}\n'.format( - 'START CLOCKTIME', hrs, mm, sec, time_format - ).encode('ascii') - ) - - hrs, mm, sec = _sec_to_string(wn.options.time.rule_timestep) - - # TODO: RULE TIMESTEP is not written?! # noqa: TD002 - # f.write(time_entry.format('RULE TIMESTEP', hrs, mm, int(sec)).encode('ascii')) - f.write( - entry.format('STATISTIC', wn.options.results.statistic).encode('ascii') - ) - f.write('\n'.encode('ascii')) - - def _write_coordinates(self, f, wn): - f.write('[COORDINATES]\n'.encode('ascii')) - entry = '{:10s} {:20.9f} {:20.9f}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';Node', 'X-Coord', 'Y-Coord').encode('ascii')) - for name, node in wn.nodes(): - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - val = node.coordinates - f.write(entry.format(name, val[0], val[1]).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_vertices(self, f, wn): - f.write('[VERTICES]\n'.encode('ascii')) - entry = '{:10s} {:20.9f} {:20.9f}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';Link', 'X-Coord', 'Y-Coord').encode('ascii')) - lnames = list(wn.pipe_name_list) - # lnames.sort() - for pipe_name in lnames: - pipe = wn.links[pipe_name] - if pipe._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - for vert in pipe._vertices: # noqa: SLF001 - f.write(entry.format(pipe_name, vert[0], vert[1]).encode('ascii')) - f.write('\n'.encode('ascii')) - - def _write_tags(self, f, wn): - f.write('[TAGS]\n'.encode('ascii')) - entry = '{:10s} {:10s} {:10s}\n' - label = '{:10s} {:10s} {:10s}\n' - f.write(label.format(';type', 'name', 'tag').encode('ascii')) - nnodes = list(wn.node_name_list) - # nnodes.sort() - for node_name in nnodes: - node = wn.nodes[node_name] - if node._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if node.tag: - f.write(entry.format('NODE', node_name, node.tag).encode('ascii')) - nlinks = list(wn.link_name_list) - nlinks.sort() - for link_name in nlinks: - link = wn.links[link_name] - if link._is_isolated == True: # Sina added this # noqa: SLF001, E712 - continue - if link.tag: - f.write(entry.format('LINK', link_name, link.tag).encode('ascii')) - f.write('\n'.encode('ascii')) - - # End of File - - -class BinFile(wntrfr.epanet.io.BinFile): - """EPANET binary output file reader class. - - This class provides read functionality for EPANET binary output files. - - Parameters - ---------- - results_type : list of :class:`~wntrfr.epanet.util.ResultType`, default=None - This parameter is *only* active when using a subclass of the BinFile that implements - a custom reader or writer. - If ``None``, then all results will be saved (node quality, demand, link flow, etc.). - Otherwise, a list of result types can be passed to limit the memory used. - network : bool, default=False - Save a new WaterNetworkModel from the description in the output binary file. Certain - elements may be missing, such as patterns and curves, if this is done. - energy : bool, default=False - Save the pump energy results. - statistics : bool, default=False - Save the statistics lines (different from the stats flag in the inp file) that are - automatically calculated regarding hydraulic conditions. - convert_status : bool, default=True - Convert the EPANET link status (8 values) to simpler WNTR status (3 values). By - default, this is done, and the encoded-cause status values are converted simple state - values, instead. - - Returns - ------- - :class:`~wntrfr.sim.results.SimulationResults` - A WNTR results object will be created and added to the instance after read. - - """ - - def __init__( - self, - result_types=None, # noqa: ARG002 - network=False, # noqa: FBT002, ARG002 - energy=False, # noqa: FBT002, ARG002 - statistics=False, # noqa: FBT002, ARG002 - convert_status=True, # noqa: FBT002, ARG002 - ): - super().__init__() - - def read(self, filename, custom_handlers=False, start_time=None): # noqa: FBT002, C901, PLR0915 - """Read a binary file and create a results object. - - Parameters - ---------- - filename : str - An EPANET BIN output file - custom_handlers : bool, optional - If true, then the the custom, by-line handlers will be used. (:func:`~save_ep_line`, - :func:`~setup_ep_results`, :func:`~finalize_save`, etc.) Otherwise read will use - a faster, all-at-once reader that reads all results. - start_time : int - If the simulation is interval based, then start_time can identify the time passed after - the last simulation. Start_time will be added to all th timings in the result. - - Returns - ------- - object - returns a WaterNetworkResults object - - .. note:: Overloading - This function should **not** be overloaded. Instead, overload the other functions - to change how it saves the results. Specifically, overload :func:`~setup_ep_results`, - :func:`~save_ep_line` and :func:`~finalize_save` to change how extended period - simulation results in a different format (such as directly to a file or database). - - """ - self.results = wntrfr.sim.SimulationResults() - logger.debug(start_time) - if start_time == None: # noqa: E711 - start_time = 0 - logger.debug('Read binary EPANET data from %s', filename) - dt_str = f'|S{self.idlen}' - with open(filename, 'rb') as fin: # noqa: PTH123 - ftype = self.ftype - idlen = self.idlen # noqa: F841 - logger.debug('... read prolog information ...') - prolog = np.fromfile(fin, dtype=np.int32, count=15) - magic1 = prolog[0] - version = prolog[1] - nnodes = prolog[2] - ntanks = prolog[3] - nlinks = prolog[4] - npumps = prolog[5] - nvalve = prolog[6] - wqopt = QualType(prolog[7]) - srctrace = prolog[8] - flowunits = FlowUnits(prolog[9]) - presunits = PressureUnits(prolog[10]) - statsflag = StatisticsType(prolog[11]) - reportstart = prolog[12] - reportstep = prolog[13] - duration = prolog[14] - logger.debug('EPANET/Toolkit version %d', version) - logger.debug( - 'Nodes: %d; Tanks/Resrv: %d Links: %d; Pumps: %d; Valves: %d', - nnodes, - ntanks, - nlinks, - npumps, - nvalve, - ) - logger.debug( - 'WQ opt: %s; Trace Node: %s; Flow Units %s; Pressure Units %s', - wqopt, - srctrace, - flowunits, - presunits, - ) - logger.debug( - 'Statistics: %s; Report Start %d, step %d; Duration=%d sec', - statsflag, - reportstart, - reportstep, - duration, - ) - - # Ignore the title lines - np.fromfile(fin, dtype=np.uint8, count=240) - inpfile = np.fromfile(fin, dtype=np.uint8, count=260) - rptfile = np.fromfile(fin, dtype=np.uint8, count=260) - chemical = str(np.fromfile(fin, dtype=dt_str, count=1)[0]) - # wqunits = ''.join([chr(f) for f in np.fromfile(fin, dtype=np.uint8, count=idlen) if f!=0 ]) - wqunits = str(np.fromfile(fin, dtype=dt_str, count=1)[0]) - mass = wqunits.split('/', 1)[0] - if mass in ['mg', 'ug', 'mg', 'ug']: - massunits = MassUnits[mass] - else: - massunits = MassUnits.mg - self.flow_units = flowunits - self.pres_units = presunits - self.quality_type = wqopt - self.mass_units = massunits - self.num_nodes = nnodes - self.num_tanks = ntanks - self.num_links = nlinks - self.num_pumps = npumps - self.num_valves = nvalve - self.report_start = reportstart - self.report_step = reportstep - self.duration = duration - self.chemical = chemical - self.chem_units = wqunits - self.inp_file = inpfile - self.rpt_file = rptfile - nodenames = [] - linknames = [] - nodenames = np.array( - np.fromfile(fin, dtype=dt_str, count=nnodes), dtype=str - ).tolist() - linknames = np.array( - np.fromfile(fin, dtype=dt_str, count=nlinks), dtype=str - ).tolist() - self.node_names = nodenames - self.link_names = linknames - linkstart = np.array( # noqa: F841 - np.fromfile(fin, dtype=np.int32, count=nlinks), dtype=int - ) - linkend = np.array( # noqa: F841 - np.fromfile(fin, dtype=np.int32, count=nlinks), dtype=int - ) - linktype = np.fromfile(fin, dtype=np.int32, count=nlinks) - tankidxs = np.fromfile(fin, dtype=np.int32, count=ntanks) # noqa: F841 - tankarea = np.fromfile(fin, dtype=np.dtype(ftype), count=ntanks) # noqa: F841 - elevation = np.fromfile(fin, dtype=np.dtype(ftype), count=nnodes) # noqa: F841 - linklen = np.fromfile(fin, dtype=np.dtype(ftype), count=nlinks) # noqa: F841 - diameter = np.fromfile(fin, dtype=np.dtype(ftype), count=nlinks) # noqa: F841 - """ - self.save_network_desc_line('link_start', linkstart) - self.save_network_desc_line('link_end', linkend) - self.save_network_desc_line('link_type', linktype) - self.save_network_desc_line('tank_node_index', tankidxs) - self.save_network_desc_line('tank_area', tankarea) - self.save_network_desc_line('node_elevation', elevation) - self.save_network_desc_line('link_length', linklen) - self.save_network_desc_line('link_diameter', diameter) - """ - logger.debug('... read energy data ...') - for i in range(npumps): # noqa: B007 - pidx = int(np.fromfile(fin, dtype=np.int32, count=1)) - energy = np.fromfile(fin, dtype=np.dtype(ftype), count=6) - self.save_energy_line(pidx, linknames[pidx - 1], energy) - peakenergy = np.fromfile(fin, dtype=np.dtype(ftype), count=1) - self.peak_energy = peakenergy - - logger.debug('... read EP simulation data ...') - reporttimes = ( - np.arange(reportstart, duration + reportstep, reportstep) - + start_time - ) - nrptsteps = len(reporttimes) - statsN = nrptsteps # noqa: N806, F841 - if statsflag in [ - StatisticsType.Maximum, - StatisticsType.Minimum, - StatisticsType.Range, - ]: - nrptsteps = 1 - reporttimes = [reportstart + reportstep] - self.num_periods = nrptsteps - self.report_times = reporttimes - - # set up results metadata dictionary - """ - if wqopt == QualType.Age: - self.results.meta['quality_mode'] = 'AGE' - self.results.meta['quality_units'] = 's' - elif wqopt == QualType.Trace: - self.results.meta['quality_mode'] = 'TRACE' - self.results.meta['quality_units'] = '%' - self.results.meta['quality_trace'] = srctrace - elif wqopt == QualType.Chem: - self.results.meta['quality_mode'] = 'CHEMICAL' - self.results.meta['quality_units'] = wqunits - self.results.meta['quality_chem'] = chemical - self.results.time = reporttimes - self.save_network_desc_line('report_times', reporttimes) - self.save_network_desc_line('node_elevation', pd.Series(data=elevation, index=nodenames)) - self.save_network_desc_line('link_length', pd.Series(data=linklen, index=linknames)) - self.save_network_desc_line('link_diameter', pd.Series(data=diameter, index=linknames)) - self.save_network_desc_line('stats_mode', statsflag) - self.save_network_desc_line('stats_N', statsN) - nodetypes = np.array(['Junction']*self.num_nodes, dtype='|S10') - nodetypes[tankidxs-1] = 'Tank' - nodetypes[tankidxs[tankarea==0]-1] = 'Reservoir' - linktypes = np.array(['Pipe']*self.num_links) - linktypes[ linktype == EN.PUMP ] = 'Pump' - linktypes[ linktype > EN.PUMP ] = 'Valve' - self.save_network_desc_line('link_type', pd.Series(data=linktypes, index=linknames, copy=True)) - linktypes[ linktype == EN.CVPIPE ] = 'CV' - linktypes[ linktype == EN.FCV ] = 'FCV' - linktypes[ linktype == EN.PRV ] = 'PRV' - linktypes[ linktype == EN.PSV ] = 'PSV' - linktypes[ linktype == EN.PBV ] = 'PBV' - linktypes[ linktype == EN.TCV ] = 'TCV' - linktypes[ linktype == EN.GPV ] = 'GPV' - self.save_network_desc_line('link_subtype', pd.Series(data=linktypes, index=linknames, copy=True)) - self.save_network_desc_line('node_type', pd.Series(data=nodetypes, index=nodenames, copy=True)) - self.save_network_desc_line('node_names', np.array(nodenames, dtype=str)) - self.save_network_desc_line('link_names', np.array(linknames, dtype=str)) - names = np.array(nodenames, dtype=str) - self.save_network_desc_line('link_start', pd.Series(data=names[linkstart-1], index=linknames, copy=True)) - self.save_network_desc_line('link_end', pd.Series(data=names[linkend-1], index=linknames, copy=True)) - """ - if custom_handlers is True: - logger.debug('... set up results object ...') - # self.setup_ep_results(reporttimes, nodenames, linknames) - # print(nodenames[5712]+' '+nodenames[5717]+' '+nodenames[5718]+' ') - for ts in range(nrptsteps): - try: - demand = np.fromfile( - fin, dtype=np.dtype(ftype), count=nnodes - ) - # print(repr(demand[5712])+' '+repr(demand[5717])+' '+repr(demand[5718])) - head = np.fromfile(fin, dtype=np.dtype(ftype), count=nnodes) - pressure = np.fromfile( - fin, dtype=np.dtype(ftype), count=nnodes - ) - quality = np.fromfile( - fin, dtype=np.dtype(ftype), count=nnodes - ) - flow = np.fromfile(fin, dtype=np.dtype(ftype), count=nlinks) - velocity = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - headloss = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - linkquality = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - linkstatus = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - linksetting = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - reactionrate = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - frictionfactor = np.fromfile( - fin, dtype=np.dtype(ftype), count=nlinks - ) - self.save_ep_line(ts, ResultType.demand, demand) - self.save_ep_line(ts, ResultType.head, head) - self.save_ep_line(ts, ResultType.pressure, pressure) - self.save_ep_line(ts, ResultType.quality, quality) - self.save_ep_line(ts, ResultType.flowrate, flow) - self.save_ep_line(ts, ResultType.velocity, velocity) - self.save_ep_line(ts, ResultType.headloss, headloss) - self.save_ep_line(ts, ResultType.linkquality, linkquality) - self.save_ep_line(ts, ResultType.status, linkstatus) - self.save_ep_line(ts, ResultType.setting, linksetting) - self.save_ep_line(ts, ResultType.rxnrate, reactionrate) - self.save_ep_line( - ts, ResultType.frictionfact, frictionfactor - ) - except Exception as e: # noqa: PERF203 - logger.exception('Error reading or writing EP line: %s', e) # noqa: TRY401 - logger.warning('Missing results from report period %d', ts) - else: - # type_list = 4*nnodes*['node'] + 8*nlinks*['link'] - name_list = nodenames * 4 + linknames * 8 - valuetype = ( - nnodes * ['demand'] - + nnodes * ['head'] - + nnodes * ['pressure'] - + nnodes * ['quality'] - + nlinks * ['flow'] - + nlinks * ['velocity'] - + nlinks * ['headloss'] - + nlinks * ['linkquality'] - + nlinks * ['linkstatus'] - + nlinks * ['linksetting'] - + nlinks * ['reactionrate'] - + nlinks * ['frictionfactor'] - ) - - # tuples = zip(type_list, valuetype, name_list) - tuples = list(zip(valuetype, name_list)) - # tuples = [(valuetype[i], v) for i, v in enumerate(name_list)] - index = pd.MultiIndex.from_tuples(tuples, names=['value', 'name']) - try: - data = np.fromfile( - fin, - dtype=np.dtype(ftype), - count=(4 * nnodes + 8 * nlinks) * nrptsteps, - ) - data = np.reshape(data, (nrptsteps, (4 * nnodes + 8 * nlinks))) - except Exception as e: - logger.exception('Failed to process file: %s', e) # noqa: TRY401 - - df = pd.DataFrame(data.transpose(), index=index, columns=reporttimes) # noqa: PD901 - df = df.transpose() # noqa: PD901 - - self.results.node = {} - self.results.link = {} - self.results.network_name = self.inp_file - - # Node Results - self.results.node['demand'] = HydParam.Demand._to_si( # noqa: SLF001 - self.flow_units, df['demand'] - ) - self.results.node['head'] = HydParam.HydraulicHead._to_si( # noqa: SLF001 - self.flow_units, df['head'] - ) - self.results.node['pressure'] = HydParam.Pressure._to_si( # noqa: SLF001 - self.flow_units, df['pressure'] - ) - - # Water Quality Results (node and link) - if self.quality_type is QualType.Chem: - self.results.node['quality'] = QualParam.Concentration._to_si( # noqa: SLF001 - self.flow_units, df['quality'], mass_units=self.mass_units - ) - self.results.link['linkquality'] = ( - QualParam.Concentration._to_si( # noqa: SLF001 - self.flow_units, - df['linkquality'], - mass_units=self.mass_units, - ) - ) - elif self.quality_type is QualType.Age: - self.results.node['quality'] = QualParam.WaterAge._to_si( # noqa: SLF001 - self.flow_units, df['quality'], mass_units=self.mass_units - ) - self.results.link['linkquality'] = QualParam.WaterAge._to_si( # noqa: SLF001 - self.flow_units, - df['linkquality'], - mass_units=self.mass_units, - ) - else: - self.results.node['quality'] = df['quality'] - self.results.link['linkquality'] = df['linkquality'] - - # Link Results - self.results.link['flowrate'] = HydParam.Flow._to_si( # noqa: SLF001 - self.flow_units, df['flow'] - ) - self.results.link['headloss'] = df['headloss'] # Unit is per 1000 - self.results.link['velocity'] = HydParam.Velocity._to_si( # noqa: SLF001 - self.flow_units, df['velocity'] - ) - - # self.results.link['status'] = df['linkstatus'] - status = np.array(df['linkstatus']) - if self.convert_status: - status[status <= 2] = 0 # noqa: PLR2004 - status[status == 3] = 1 # noqa: PLR2004 - status[status >= 5] = 1 # noqa: PLR2004 - status[status == 4] = 2 # noqa: PLR2004 - self.results.link['status'] = pd.DataFrame( - data=status, columns=linknames, index=reporttimes - ) - - settings = np.array(df['linksetting']) - settings[:, linktype == EN.PRV] = to_si( - self.flow_units, - settings[:, linktype == EN.PRV], - HydParam.Pressure, - ) - settings[:, linktype == EN.PSV] = to_si( - self.flow_units, - settings[:, linktype == EN.PSV], - HydParam.Pressure, - ) - settings[:, linktype == EN.PBV] = to_si( - self.flow_units, - settings[:, linktype == EN.PBV], - HydParam.Pressure, - ) - settings[:, linktype == EN.FCV] = to_si( - self.flow_units, settings[:, linktype == EN.FCV], HydParam.Flow - ) - self.results.link['setting'] = pd.DataFrame( - data=settings, columns=linknames, index=reporttimes - ) - self.results.link['frictionfact'] = df['frictionfactor'] - self.results.link['rxnrate'] = df['reactionrate'] - - logger.debug('... read epilog ...') - # Read the averages and then the number of periods for checks - averages = np.fromfile(fin, dtype=np.dtype(ftype), count=4) - self.averages = averages - np.fromfile(fin, dtype=np.int32, count=1) - warnflag = np.fromfile(fin, dtype=np.int32, count=1) - magic2 = np.fromfile(fin, dtype=np.int32, count=1) - if magic1 != magic2: - logger.critical( - 'The magic number did not match -- binary incomplete or incorrectly read. If you believe this file IS complete, please try a different float type. Current type is "%s"', - ftype, - ) - # print numperiods, warnflag, magic - if warnflag != 0: - logger.warning('Warnings were issued during simulation') - self.finalize_save(magic1 == magic2, warnflag) - - return self.results diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/results.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/results.py deleted file mode 100644 index 9162dcefa..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/results.py +++ /dev/null @@ -1,9 +0,0 @@ -from wntrfr.sim.results import SimulationResults # noqa: D100 - - -class SimulationResults(SimulationResults): - """Water network simulation results class.""" - - def __init__(self): - super().__init__() - self.maximum_trial_time = [] diff --git a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/toolkit.py b/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/toolkit.py deleted file mode 100644 index 04da60b09..000000000 --- a/modules/systemPerformance/REWET/REWET/EnhancedWNTR/sim/toolkit.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Created on Wed May 26 16:11:36 2021 - -@author: snaeimi -""" # noqa: D400 - -import ctypes -import logging -import os -import platform -import sys - -import numpy as np -import wntrfr.epanet.toolkit -from pkg_resources import resource_filename - -logger = logging.getLogger(__name__) - - -class EpanetException(Exception): # noqa: N818, D101 - pass - - -class ENepanet(wntrfr.epanet.toolkit.ENepanet): # noqa: D101 - def __init__( # noqa: C901 - self, - inpfile='', - rptfile='', - binfile='', - changed_epanet=False, # noqa: FBT002 - version=2.2, - ): - if changed_epanet == False or changed_epanet == True: # noqa: E712, PLR1714 - self.changed_epanet = changed_epanet - else: - raise ValueError('changed_epanet must be a boolean value') # noqa: EM101, TRY003 - - if changed_epanet == False: # noqa: E712 - try: # noqa: SIM105 - super().__init__(inpfile, rptfile, binfile, version=version) - except: # noqa: S110, E722 - pass # to add robustness for the time when for the WNTR - # cannot load the umodified DLLs for any reason - else: - if float(version) != 2.2: # noqa: PLR2004 - raise ValueError( # noqa: TRY003 - 'EPANET version must be 2.2 when using tegh changed version' # noqa: EM101 - ) - - elif float(version) == 2.2: # noqa: RET506, PLR2004 - libnames = ['epanet22_mod', 'epanet22_win32_mod'] - if '64' in platform.machine(): - libnames.insert(0, 'epanet22_amd64_mod') - for lib in libnames: - try: - if os.name in ['nt', 'dos']: - libepanet = resource_filename( - __name__, - 'Windows/%s.dll' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.windll.LoadLibrary(libepanet) - elif sys.platform == 'darwin': - libepanet = resource_filename( - __name__, - 'Darwin/lib%s.dylib' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.cdll.LoadLibrary(libepanet) - else: - libepanet = resource_filename( - __name__, - 'Linux/lib%s.so' % lib, # noqa: UP031 - ) - self.ENlib = ctypes.cdll.LoadLibrary(libepanet) - return # noqa: TRY300 - except Exception as E1: # noqa: PERF203 - if lib == libnames[-1]: - raise E1 # noqa: TRY201 - finally: - if version >= 2.2 and '32' not in lib: # noqa: PLR2004 - self._project = ctypes.c_uint64() - elif version >= 2.2: # noqa: PLR2004 - self._project = ctypes.c_uint32() - else: - self._project = None - - def ENn(self, inpfile=None, rptfile=None, binfile=None): # noqa: N802 - """Opens an EPANET input file and reads in network data - - Parameters - ---------- - inpfile : str - EPANET INP file (default to constructor value) - rptfile : str - Output file to create (default to constructor value) - binfile : str - Binary output file to create (default to constructor value) - - """ # noqa: D400, D401 - inpfile = inpfile.encode('ascii') - rptfile = rptfile.encode('ascii') # ''.encode('ascii') - binfile = binfile.encode('ascii') - s = 's' - self.errcode = self.ENlib.EN_runproject(inpfile, rptfile, binfile, s) - self._error() - if self.errcode < 100: # noqa: PLR2004 - self.fileLoaded = True - - def ENSetIgnoreFlag(self, ignore_flag=0): # noqa: N802, D102 - if abs(ignore_flag - np.round(ignore_flag)) > 0.00001 or ignore_flag < 0: # noqa: PLR2004 - logger.error( - 'ignore_flag must be int value and bigger than zero' # noqa: G003 - + str(ignore_flag) - ) - flag = ctypes.c_int(int(ignore_flag)) # noqa: F841 - # print('++++++++++++++++++++++') - # self.ENlib.ENEXTENDEDsetignoreflag(flag) diff --git a/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3DA.txt b/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3DA.txt deleted file mode 100644 index e9196ea9b..000000000 --- a/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3DA.txt +++ /dev/null @@ -1,3 +0,0 @@ -DistYardID,Curr.-X-Coord,Curr.-Y-Coord,Home-X-Coord,Home-Y-Coord,Number,Shift -Northern,10,10,10,10,1,D -Northern,10,10,10,10,1,N diff --git a/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3RA.txt b/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3RA.txt deleted file mode 100644 index 040be19d4..000000000 --- a/modules/systemPerformance/REWET/REWET/Example/Crew_Data/Net3RA.txt +++ /dev/null @@ -1,3 +0,0 @@ -DistYardID,Curr.-X-Coord,Curr.-Y-Coord,Home-X-Coord,Home-Y-Coord,Number,Shift -Northern,20,20,20,20,1,D -Northern,20,20,20,20,1,N diff --git a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-PumpDamage.xlsx b/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-PumpDamage.xlsx deleted file mode 100644 index 35b383ddb..000000000 Binary files a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-PumpDamage.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-node-damage.xlsx b/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-node-damage.xlsx deleted file mode 100644 index 11c991035..000000000 Binary files a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-node-damage.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-pipe-damage.xlsx b/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-pipe-damage.xlsx deleted file mode 100644 index 6e4e7406a..000000000 Binary files a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3-pipe-damage.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3_tank_damage.xlsx b/modules/systemPerformance/REWET/REWET/Example/Damages/Net3_tank_damage.xlsx deleted file mode 100644 index 8b50d4159..000000000 Binary files a/modules/systemPerformance/REWET/REWET/Example/Damages/Net3_tank_damage.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/Example/Net3.inp b/modules/systemPerformance/REWET/REWET/Example/Net3.inp deleted file mode 100644 index 3be1e9673..000000000 --- a/modules/systemPerformance/REWET/REWET/Example/Net3.inp +++ /dev/null @@ -1,481 +0,0 @@ -[TITLE] -EPANET Example Network 3 -Example showing how the percent of Lake water in a dual-source -system changes over time. - -[JUNCTIONS] -;ID Elev Demand Pattern - 10 147 0 ; - 15 32 1 3 ; - 20 129 0 ; - 35 12.5 1 4 ; - 40 131.9 0 ; - 50 116.5 0 ; - 60 0 0 ; - 601 0 0 ; - 61 0 0 ; - 101 42 189.95 ; - 103 43 133.2 ; - 105 28.5 135.37 ; - 107 22 54.64 ; - 109 20.3 231.4 ; - 111 10 141.94 ; - 113 2 20.01 ; - 115 14 52.1 ; - 117 13.6 117.71 ; - 119 2 176.13 ; - 120 0 0 ; - 121 -2 41.63 ; - 123 11 1 2 ; - 125 11 45.6 ; - 127 56 17.66 ; - 129 51 0 ; - 131 6 42.75 ; - 139 31 5.89 ; - 141 4 9.85 ; - 143 -4.5 6.2 ; - 145 1 27.63 ; - 147 18.5 8.55 ; - 149 16 27.07 ; - 151 33.5 144.48 ; - 153 66.2 44.17 ; - 157 13.1 51.79 ; - 159 6 41.32 ; - 161 4 15.8 ; - 163 5 9.42 ; - 164 5 0 ; - 166 -2 2.6 ; - 167 -5 14.56 ; - 169 -5 0 ; - 171 -4 39.34 ; - 173 -4 0 ; - 177 8 58.17 ; - 179 8 0 ; - 181 8 0 ; - 183 11 0 ; - 184 16 0 ; - 185 16 25.65 ; - 187 12.5 0 ; - 189 4 107.92 ; - 191 25 81.9 ; - 193 18 71.31 ; - 195 15.5 0 ; - 197 23 17.04 ; - 199 -2 119.32 ; - 201 0.1 44.61 ; - 203 2 1 5 ; - 204 21 0 ; - 205 21 65.36 ; - 206 1 0 ; - 207 9 69.39 ; - 208 16 0 ; - 209 -2 0.87 ; - 211 7 8.67 ; - 213 7 13.94 ; - 215 7 92.19 ; - 217 6 24.22 ; - 219 4 41.32 ; - 225 8 22.8 ; - 229 10.5 64.18 ; - 231 5 16.48 ; - 237 14 15.61 ; - 239 13 44.61 ; - 241 13 0 ; - 243 14 4.34 ; - 247 18 70.38 ; - 249 18 0 ; - 251 30 24.16 ; - 253 36 54.52 ; - 255 27 40.39 ; - 257 17 0 ; - 259 25 0 ; - 261 0 0 ; - 263 0 0 ; - 265 0 0 ; - 267 21 0 ; - 269 0 0 ; - 271 6 0 ; - 273 8 0 ; - 275 10 0 ; - -[RESERVOIRS] -;ID Head Pattern - River 220.0 ; - Lake 167.0 ; - -[TANKS] -;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve - 1 131.9 13.1 .1 32.1 85 0 ; - 2 116.5 23.5 6.5 40.3 50 0 ; - 3 129.0 29.0 4.0 35.5 164 0 ; - -[PIPES] -;ID Node1 Node2 Length Diameter Roughness MinorLoss Status - 20 3 20 99 99 199 0 Open ; - 40 1 40 99 99 199 0 Open ; - 50 2 50 99 99 199 0 Open ; - 60 River 60 1231 24 140 0 Open ; - 101 10 101 14200 18 110 0 Open ; - 103 101 103 1350 16 130 0 Open ; - 105 101 105 2540 12 130 0 Open ; - 107 105 107 1470 12 130 0 Open ; - 109 103 109 3940 16 130 0 Open ; - 111 109 111 2000 12 130 0 Open ; - 112 115 111 1160 12 130 0 Open ; - 113 111 113 1680 12 130 0 Open ; - 114 115 113 2000 8 130 0 Open ; - 115 107 115 1950 8 130 0 Open ; - 116 113 193 1660 12 130 0 Open ; - 117 263 105 2725 12 130 0 Open ; - 119 115 117 2180 12 130 0 Open ; - 120 119 120 730 12 130 0 Open ; - 121 120 117 1870 12 130 0 Open ; - 122 121 120 2050 8 130 0 Open ; - 123 121 119 2000 30 141 0 Open ; - 125 123 121 1500 30 141 0 Open ; - 129 121 125 930 24 130 0 Open ; - 131 125 127 3240 24 130 0 Open ; - 133 20 127 785 20 130 0 Open ; - 135 127 129 900 24 130 0 Open ; - 137 129 131 6480 16 130 0 Open ; - 145 129 139 2750 8 130 0 Open ; - 147 139 141 2050 8 130 0 Open ; - 149 143 141 1400 8 130 0 Open ; - 151 15 143 1650 8 130 0 Open ; - 153 145 141 3510 12 130 0 Open ; - 155 147 145 2200 12 130 0 Open ; - 159 147 149 880 12 130 0 Open ; - 161 149 151 1020 8 130 0 Open ; - 163 151 153 1170 12 130 0 Open ; - 169 125 153 4560 8 130 0 Open ; - 171 119 151 3460 12 130 0 Open ; - 173 119 157 2080 30 141 0 Open ; - 175 157 159 2910 30 141 0 Open ; - 177 159 161 2000 30 141 0 Open ; - 179 161 163 430 30 141 0 Open ; - 180 163 164 150 14 130 0 Open ; - 181 164 166 490 14 130 0 Open ; - 183 265 169 590 30 141 0 Open ; - 185 167 169 60 8 130 0 Open ; - 186 187 204 99.9 8 130 0 Open ; - 187 169 171 1270 30 141 0 Open ; - 189 171 173 50 30 141 0 Open ; - 191 271 171 760 24 130 0 Open ; - 193 35 181 30 24 130 0 Open ; - 195 181 177 30 12 130 0 Open ; - 197 177 179 30 12 130 0 Open ; - 199 179 183 210 12 130 0 Open ; - 201 40 179 1190 12 130 0 Open ; - 202 185 184 99.9 8 130 0 Open ; - 203 183 185 510 8 130 0 Open ; - 204 184 205 4530. 12 130 0 Open ; - 205 204 185 1325. 12 130 0 Open ; - 207 189 183 1350 12 130 0 Open ; - 209 189 187 500 8 130 0 Open ; - 211 169 269 646 12 130 0 Open ; - 213 191 187 2560 12 130 0 Open ; - 215 267 189 1230 12 130 0 Open ; - 217 191 193 520 12 130 0 Open ; - 219 193 195 360 12 130 0 Open ; - 221 161 195 2300 8 130 0 Open ; - 223 197 191 1150 12 130 0 Open ; - 225 111 197 2790 12 130 0 Open ; - 229 173 199 4000 24 141 0 Open ; - 231 199 201 630 24 141 0 Open ; - 233 201 203 120 24 130 0 Open ; - 235 199 273 725 12 130 0 Open ; - 237 205 207 1200 12 130 0 Open ; - 238 207 206 450 12 130 0 Open ; - 239 275 207 1430 12 130 0 Open ; - 240 206 208 510 12 130 0 Open ; - 241 208 209 885 12 130 0 Open ; - 243 209 211 1210 16 130 0 Open ; - 245 211 213 990 16 130 0 Open ; - 247 213 215 4285 16 130 0 Open ; - 249 215 217 1660 16 130 0 Open ; - 251 217 219 2050 14 130 0 Open ; - 257 217 225 1560 12 130 0 Open ; - 261 213 229 2200 8 130 0 Open ; - 263 229 231 1960 12 130 0 Open ; - 269 211 237 2080 12 130 0 Open ; - 271 237 229 790 8 130 0 Open ; - 273 237 239 510 12 130 0 Open ; - 275 239 241 35 12 130 0 Open ; - 277 241 243 2200 12 130 0 Open ; - 281 241 247 445 10 130 0 Open ; - 283 239 249 430 12 130 0 Open ; - 285 247 249 10 12 130 0 Open ; - 287 247 255 1390 10 130 0 Open ; - 289 50 255 925 10 130 0 Open ; - 291 255 253 1100 10 130 0 Open ; - 293 255 251 1100 8 130 0 Open ; - 295 249 251 1450 12 130 0 Open ; - 297 120 257 645 8 130 0 Open ; - 299 257 259 350 8 130 0 Open ; - 301 259 263 1400 8 130 0 Open ; - 303 257 261 1400 8 130 0 Open ; - 305 117 261 645 12 130 0 Open ; - 307 261 263 350 12 130 0 Open ; - 309 265 267 1580 8 130 0 Open ; - 311 193 267 1170 12 130 0 Open ; - 313 269 189 646 12 130 0 Open ; - 315 181 271 260 24 130 0 Open ; - 317 273 275 2230 8 130 0 Open ; - 319 273 205 645 12 130 0 Open ; - 321 163 265 1200 30 141 0 Open ; - 323 201 275 300 12 130 0 Open ; - 325 269 271 1290 8 130 0 Open ; - 329 61 123 45500 30 140 0 Open ; - 330 60 601 1 30 140 0 Closed ; - 333 601 61 1 30 140 0 Open ; - -[PUMPS] -;ID Node1 Node2 Parameters - 10 Lake 10 HEAD 1 ; - 335 60 61 HEAD 2 ; - -[VALVES] -;ID Node1 Node2 Diameter Type Setting MinorLoss - -[TAGS] - -[DEMANDS] -;Junction Demand Pattern Category - -[STATUS] -;ID Status/Setting - 10 Closed - -[PATTERNS] -;ID Multipliers -;General Default Demand Pattern - 1 1.34 1.94 1.46 1.44 .76 .92 - 1 .85 1.07 .96 1.1 1.08 1.19 - 1 1.16 1.08 .96 .83 .79 .74 - 1 .64 .64 .85 .96 1.24 1.67 -;Demand Pattern for Node 123 - 2 0 0 0 0 0 1219 - 2 0 0 0 1866 1836 1818 - 2 1818 1822 1822 1817 1824 1816 - 2 1833 1817 1830 1814 1840 1859 -;Demand Pattern for Node 15 - 3 620 620 620 620 620 360 - 3 360 0 0 0 0 360 - 3 360 360 360 360 0 0 - 3 0 0 0 0 360 360 -;Demand Pattern for Node 35 - 4 1637 1706 1719 1719 1791 1819 - 4 1777 1842 1815 1825 1856 1801 - 4 1819 1733 1664 1620 1613 1620 - 4 1616 1647 1627 1627 1671 1668 -;Demand Pattern for Node 203 - 5 4439 4531 4511 4582 4531 4582 - 5 4572 4613 4643 4643 4592 4613 - 5 4531 4521 4449 4439 4449 4460 - 5 4439 4419 4368 4399 4470 4480 - -[CURVES] -;ID X-Value Y-Value -;PUMP: Pump Curve for Pump 10 (Lake Source) - 1 0 104. - 1 2000. 92. - 1 4000. 63. -;PUMP: Pump Curve for Pump 335 (River Source) - 2 0 200. - 2 8000. 138. - 2 14000. 86. - -[CONTROLS] -;Lake source operates only part of the day -Link 10 OPEN AT TIME 1 -Link 10 CLOSED AT TIME 15 - -;Pump 335 controlled by level in Tank 1 -;When pump is closed, bypass pipe is opened -Link 335 OPEN IF Node 1 BELOW 17.1 -Link 335 CLOSED IF Node 1 ABOVE 19.1 -Link 330 CLOSED IF Node 1 BELOW 17.1 -Link 330 OPEN IF Node 1 ABOVE 19.1 - - -[RULES] - -[ENERGY] - Global Efficiency 75 - Global Price 0.0 - Demand Charge 0.0 - -[EMITTERS] -;Junction Coefficient - -[QUALITY] -;Node InitQual - -[SOURCES] -;Node Type Quality Pattern - -[REACTIONS] -;Type Pipe/Tank Coefficient - - -[REACTIONS] - Order Bulk 1 - Order Tank 1 - Order Wall 1 - Global Bulk 0.0 - Global Wall 0.0 - Limiting Potential 0.0 - Roughness Correlation 0.0 - -[MIXING] -;Tank Model - -[TIMES] - Duration 24:00 - Hydraulic Timestep 1:00 - Quality Timestep 0:05 - Pattern Timestep 1:00 - Pattern Start 0:00 - Report Timestep 1:00 - Report Start 0:00 - Start ClockTime 12 am - Statistic None - -[REPORT] - Status Yes - Summary No - Page 0 - -[OPTIONS] - Units GPM - Headloss H-W - Specific Gravity 1.0 - Viscosity 1.0 - Trials 40 - Accuracy 0.001 - CHECKFREQ 2 - MAXCHECK 10 - DAMPLIMIT 0 - Unbalanced Continue 10 - Pattern 1 - Demand Multiplier 1.0 - Emitter Exponent 0.5 - Quality Trace Lake - Diffusivity 1.0 - Tolerance 0.01 - -[COORDINATES] -;Node X-Coord Y-Coord - 10 9.00 27.85 - 15 38.68 23.76 - 20 29.44 26.91 - 35 25.46 10.52 - 40 27.02 9.81 - 50 33.01 3.01 - 60 23.90 29.94 - 601 23.00 29.49 - 61 23.71 29.03 - 101 13.81 22.94 - 103 12.96 21.31 - 105 16.97 21.28 - 107 18.45 20.46 - 109 17.64 18.92 - 111 20.21 17.53 - 113 22.04 16.61 - 115 20.98 19.18 - 117 21.69 21.28 - 119 23.70 22.76 - 120 22.08 23.10 - 121 23.54 25.50 - 123 23.37 27.31 - 125 24.59 25.64 - 127 29.29 26.40 - 129 30.32 26.39 - 131 37.89 29.55 - 139 33.28 24.54 - 141 35.68 23.08 - 143 37.47 21.97 - 145 33.02 19.29 - 147 30.24 20.38 - 149 29.62 20.74 - 151 28.29 21.39 - 153 28.13 22.63 - 157 24.85 20.16 - 159 23.12 17.50 - 161 25.10 15.28 - 163 25.39 14.98 - 164 25.98 15.14 - 166 26.48 15.13 - 167 25.88 12.98 - 169 25.68 12.74 - 171 26.65 11.80 - 173 26.87 11.59 - 177 25.92 10.59 - 179 25.71 10.40 - 181 25.72 10.74 - 183 25.45 10.18 - 184 25.15 9.52 - 185 25.01 9.67 - 187 23.64 11.04 - 189 24.15 11.37 - 191 22.10 14.07 - 193 22.88 14.35 - 195 23.18 14.72 - 197 20.97 15.18 - 199 29.42 8.44 - 201 30.89 8.57 - 203 31.14 8.89 - 204 23.80 10.90 - 205 29.20 6.46 - 206 31.66 6.64 - 207 31.00 6.61 - 208 32.54 6.81 - 209 33.76 6.59 - 211 34.20 5.54 - 213 35.26 6.16 - 215 39.95 8.73 - 217 42.11 8.67 - 219 44.86 9.32 - 225 43.53 7.38 - 229 36.16 3.49 - 231 38.38 2.54 - 237 35.37 3.08 - 239 35.76 2.31 - 241 35.87 2.11 - 243 37.04 0.00 - 247 35.02 2.05 - 249 35.02 1.81 - 251 34.15 1.10 - 253 32.17 1.88 - 255 33.51 2.45 - 257 21.17 23.32 - 259 20.80 23.40 - 261 20.79 21.45 - 263 20.32 21.57 - 265 25.39 13.60 - 267 23.38 12.95 - 269 25.03 12.14 - 271 25.97 11.00 - 273 29.16 7.38 - 275 31.07 8.29 - River 24.15 31.06 - Lake 8.00 27.53 - 1 27.46 9.84 - 2 32.99 3.45 - 3 29.41 27.27 - -[VERTICES] -;Link X-Coord Y-Coord - -[LABELS] -;X-Coord Y-Coord Label & Anchor Node - 8.00 29.42 "LAKE" - 25.00 31.10 "RIVER" - -[BACKDROP] - DIMENSIONS 6.16 -1.55 46.70 32.61 - UNITS None - FILE - OFFSET 0.00 0.00 - -[END] diff --git a/modules/systemPerformance/REWET/REWET/Example/exampe_config.txt b/modules/systemPerformance/REWET/REWET/Example/exampe_config.txt deleted file mode 100644 index 17fbac57b..000000000 --- a/modules/systemPerformance/REWET/REWET/Example/exampe_config.txt +++ /dev/null @@ -1,87 +0,0 @@ -[FILES] -Net3RA Crew_Data/Net3RA.txt -Net3DA Crew_Data/Net3DA.txt - -[SHIFTS] -;name beginning end -D 8 20 -N 20 8 - - -[ENTITIES] -;entity_name type Condition Condition Value -trunk PIPE -distr DISTNODE Number_of_damages BG:0 - -pipe_break PIPE damage_type EQ:break -pipe_leak PIPE damage_type EQ:leak - -[SEQUENCES] -;element_name action1 action2 action3 -PIPE inspect reroute repair -DISTNODE inspect isolate repair - -[AGENTS] -;agent_type -RepairAgent FILE Net3RA ;G1:DistYardID -DistrAgent FILE Net3DA ;G3:DistYardID - -[POINTS] -EPICENTERDIST 100.00:100.00 -WaterSource 8.00:27.53 24.15:31.06 32.99:32.990 - -[PRIORITIES] -;agent_type priority step 1 step 2 step 3 step 4 step 5 step 6 - -RepairAgent 1 inspect:trunk reroute:pipe_break reroute:pipe_leak repair:pipe_break repair:pipe_leak -RepairAgent 2 EPICENTERDIST EPICENTERDIST EPICENTERDIST EPICENTERDIST EPICENTERDIST - -DistrAgent 1 inspect:distr isolate:distr repair:distr -DistrAgent 2 EPICENTERDIST EPICENTERDIST EPICENTERDIST - -[JOBS] -;agent_type action:entity time END -;---------- Inspection Phase ---------- -RepairAgent inspect:trunk FIXED:1800 CHECK -RepairAgent inspect:distr FIXED:1800 CHECK -DistrAgent inspect:distr FIXED:1800 CHECK - -;---------- Reroute Phase ---------- -RepairAgent reroute:pipe_break FIXED:14400 MJTRreroute -RepairAgent reroute:pipe_leak FIXED:14400 MJTRreroute - -;---------- Isolation Phase ---------- -;RepairAgent isolate:distr FIXED:72000 DistrIsolate -DistrAgent isolate:distr FIXED:72000 DistrIsolate - - -;---------- Repair Phase ---------- -RepairAgent repair:pipe_break FIXED:144000 trunk_break_repair -RepairAgent repair:pipe_leak FIXED:144000 trunk_leak_repair - -DistrAgent repair:distr FIXED:144000 DN_repair - - -[DEFINE] -;END -;---------- Reroute for Major-Trunkline Definition ---------- -MJTRreroute DEFAULT METHOD_PROBABILITY:1:1 -MJTRreroute 1 RECONNECT:PIPESIZEFACTOR:0.05 REMOVE_LEAK:LEAKFACTOR:1 -MJTRreroute 2 REMOVE_LEAK:LEAKFACTOR:1 - -;---------- Reroute for Minor-Trunkline Definition ---------- -DistrIsolate DEFAULT METHOD_PROBABILITY:2:1; METHOD_PROBABILITY:2:1 PIDR_TYPE:1:ASSIGNED_DEMAND ; PIDR_TYPE:1:Demand10000 -DistrIsolate 1 ISOLATE_DN:PIDR:(BG-EQ,3) -DistrIsolate 2 FASTCHECK - -;---------- Repair for Trunkline Break Definition ---------- -trunk_break_repair DEFAULT METHOD_PROBABILITY:1:1 -trunk_break_repair 1 REPAIR - -;---------- Repair for Trunkline Leak Definition ---------- -trunk_leak_repair DEFAULT METHOD_PROBABILITY:1:1 -trunk_leak_repair 1 REPAIR - -;---------- Reroute for Distribution Node Definition ---------- -DN_repair DEFAULT METHOD_PROBABILITY:1:1 -DN_repair 1 REPAIR diff --git a/modules/systemPerformance/REWET/REWET/Example/example_list.xlsx b/modules/systemPerformance/REWET/REWET/Example/example_list.xlsx deleted file mode 100644 index 1464d06f1..000000000 Binary files a/modules/systemPerformance/REWET/REWET/Example/example_list.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Designer.py deleted file mode 100644 index cb3e5665f..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Designer.py +++ /dev/null @@ -1,239 +0,0 @@ -"""Created on Tue Nov 1 23:25:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import pandas as pd -from PyQt5 import QtCore, QtGui, QtWidgets - -from .Damage_Discovery_Window import Ui_damage_discovery - - -class Damage_Discovery_Designer(Ui_damage_discovery): # noqa: D101 - def __init__(self, damage_discovery_model): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.damage_discovery_model = damage_discovery_model.copy() - - """ - Field Validators - """ - self.leak_amount_line.setValidator( - QtGui.QDoubleValidator( - 0, 1000000, 20, notation=QtGui.QDoubleValidator.StandardNotation - ) - ) - self.leak_time_line.setValidator(QtGui.QIntValidator(0, 10000 * 3600)) - self.time_line.setValidator(QtGui.QIntValidator(0, 10000 * 3600)) - - if self.damage_discovery_model['method'] == 'leak_based': - self.enableLeakBased() - leak_amount = self.damage_discovery_model['leak_amount'] - leak_time = self.damage_discovery_model['leak_time'] - self.leak_amount_line.setText(str(leak_amount)) - self.leak_time_line.setText(str(leak_time)) - - elif self.damage_discovery_model['method'] == 'time_based': - self.enableTimeBased() - time_discovery_ratio = self.damage_discovery_model[ - 'time_discovery_ratio' - ] - self.populateTimeDiscoveryRatioTable(time_discovery_ratio) - - """ - Signal Connections - """ - self.discovery_ratio_line.setValidator( - QtGui.QDoubleValidator( - 0, 1, 20, notation=QtGui.QDoubleValidator.StandardNotation - ) - ) - self.discovery_ratio_line.textChanged.connect( - self.discoveryRatioValidatorHelper - ) - self.leak_based_radio.toggled.connect(self.methodRadioButtonToggled) - self.time_based_radio.toggled.connect(self.methodRadioButtonToggled) - self.add_button.clicked.connect(self.addTimeDiscoveryRatioByButton) - self.remove_button.clicked.connect(self.removeTimeDiscoveryRatioByButton) - self.buttonBox.accepted.connect(self.okButtonPressed) - - def discoveryRatioValidatorHelper(self, x): # noqa: ARG002, N802, D102 - discovery_ratio = float(self.discovery_ratio_line.text()) - - if discovery_ratio > 1: - self.discovery_ratio_line.setText(str(1.0)) - - def enableLeakBased(self): # noqa: N802, D102 - self.leak_based_radio.setChecked(True) - - self.leak_anount_label.setEnabled(True) - self.leak_amount_line.setEnabled(True) - self.leak_time_label.setEnabled(True) - self.leak_time_line.setEnabled(True) - - self.time_line.setEnabled(False) - self.discovery_ratio_line.setEnabled(False) - self.time_discovery_ratio_table.setEnabled(False) - self.add_button.setEnabled(False) - self.remove_button.setEnabled(False) - - def enableTimeBased(self): # noqa: N802, D102 - self.time_based_radio.setChecked(True) - - self.leak_anount_label.setEnabled(False) - self.leak_amount_line.setEnabled(False) - self.leak_time_label.setEnabled(False) - self.leak_time_line.setEnabled(False) - - self.time_line.setEnabled(True) - self.discovery_ratio_line.setEnabled(True) - self.time_discovery_ratio_table.setEnabled(True) - self.add_button.setEnabled(True) - self.remove_button.setEnabled(True) - - def clearTimeDiscoveryRatioTable(self): # noqa: N802, D102 - for i in range(self.time_discovery_ratio_table.rowCount()): # noqa: B007 - self.time_discovery_ratio_table.removeRow(0) - - def okButtonPressed(self): # noqa: C901, N802, D102 - if self.leak_based_radio.isChecked(): - leak_amount = self.leak_amount_line.text() - leak_time = self.leak_time_line.text() - - if leak_amount == '': - self.errorMSG('Empty Vlaue', "Please fill the 'Leak Amont' field.") - return - elif leak_time == '': # noqa: RET505 - self.errorMSG('Empty Vlaue', "Please fill the 'Leak Time' field.") - return - - leak_amount = float(leak_amount) - leak_time = int(float(leak_amount)) - - self.damage_discovery_model['leak_amount'] = leak_amount - self.damage_discovery_model['leak_time'] = leak_time - - elif self.time_based_radio.isChecked(): - if 'time_discovery_ratio' not in self.damage_discovery_model: - self.errorMSG( - 'Discovery Ratio Error', 'Discovery Ratio Table is empty' - ) - return - - if self.damage_discovery_model['time_discovery_ratio'].empty: - self.errorMSG( - 'Discovery Ratio Error', 'Discovery Ratio Table is empty' - ) - return - - if ( - self.damage_discovery_model[ # noqa: E712 - 'time_discovery_ratio' - ].is_monotonic_increasing - == False - ): - self.errorMSG( - 'Discovery Ratio Error', - 'Discovery Ratio data must be monotonic through time', - ) - return - if self.leak_based_radio.isChecked(): - if 'time_discovery_ratio' in self.damage_discovery_model: - self.damage_discovery_model.pop('time_discovery_ratio') - - self.damage_discovery_model['method'] = 'leak_based' - elif self.time_based_radio.isChecked(): - if 'leak_amount' in self.damage_discovery_model: - self.damage_discovery_model.pop('leak_amount') - - if 'leak_time' in self.damage_discovery_model: - self.damage_discovery_model.pop('leak_time') - - self.damage_discovery_model['method'] = 'time_based' - - self._window.accept() - - def populateTimeDiscoveryRatioTable(self, time_discovery_ratio): # noqa: N802, D102 - for time, discovery_ratio in time_discovery_ratio.iteritems(): - number_of_rows = self.time_discovery_ratio_table.rowCount() - self.time_discovery_ratio_table.insertRow(number_of_rows) - - time_item = QtWidgets.QTableWidgetItem(str(time)) - discovery_ratio_item = QtWidgets.QTableWidgetItem(str(discovery_ratio)) - - time_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - discovery_ratio_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - - self.time_discovery_ratio_table.setItem(number_of_rows, 0, time_item) - self.time_discovery_ratio_table.setItem( - number_of_rows, 1, discovery_ratio_item - ) - - def addTimeDiscoveryRatioByButton(self): # noqa: N802, D102 - time = self.time_line.text() - discovery_ratio = self.discovery_ratio_line.text() - - if time == '' or discovery_ratio == '': - return - if 'time_discovery_ratio' not in self.damage_discovery_model: - self.damage_discovery_model['time_discovery_ratio'] = pd.Series() - time_discovery_ratio = self.damage_discovery_model['time_discovery_ratio'] - - if int(float(time)) in time_discovery_ratio.index: - self.errorMSG( - 'Duplicate Time', - 'There is a duplicate time. Please remove the time first', - ) - return - - time = int(float(time)) - discovery_ratio = float(discovery_ratio) - - time_discovery_ratio.loc[time] = discovery_ratio - - self.damage_discovery_model['time_discovery_ratio'] = ( - time_discovery_ratio.sort_index() - ) - self.clearTimeDiscoveryRatioTable() - self.populateTimeDiscoveryRatioTable( - self.damage_discovery_model['time_discovery_ratio'] - ) - - def removeTimeDiscoveryRatioByButton(self): # noqa: N802, D102 - items = self.time_discovery_ratio_table.selectedItems() - if len(items) < 1: - return - - row_number = [] - for i in range(len(items)): - selected_row = items[i].row() - row_number.append(selected_row) - - row_number = list(set(row_number)) - - time_discovery_ratio = self.damage_discovery_model['time_discovery_ratio'] - - for selected_row in row_number: - time = self.time_discovery_ratio_table.item(selected_row, 0).text() - time_discovery_ratio = time_discovery_ratio.drop(time) - self.damage_discovery_model['time_discovery_ratio'] = time_discovery_ratio - self.clearTimeDiscoveryRatioTable() - self.populateTimeDiscoveryRatioTable # noqa: B018 - - def methodRadioButtonToggled(self): # noqa: N802, D102 - if self.leak_based_radio.isChecked(): - self.enableLeakBased() - elif self.time_based_radio.isChecked(): - self.enableTimeBased() - - def errorMSG(self, error_title, error_msg, error_more_msg=None): # noqa: N802, D102 - error_widget = QtWidgets.QMessageBox() - error_widget.setIcon(QtWidgets.QMessageBox.Critical) - error_widget.setText(error_msg) - error_widget.setWindowTitle(error_title) - error_widget.setStandardButtons(QtWidgets.QMessageBox.Ok) - if error_more_msg != None: # noqa: E711 - error_widget.setInformativeText(error_more_msg) - error_widget.exec_() diff --git a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.py deleted file mode 100644 index c43c038f9..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.py +++ /dev/null @@ -1,108 +0,0 @@ -# Form implementation generated from reading ui file 'Damage_Discovery_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_damage_discovery: # noqa: D101 - def setupUi(self, damage_discovery): # noqa: N802, D102 - damage_discovery.setObjectName('damage_discovery') - damage_discovery.resize(450, 400) - damage_discovery.setMinimumSize(QtCore.QSize(450, 400)) - damage_discovery.setMaximumSize(QtCore.QSize(450, 400)) - self.buttonBox = QtWidgets.QDialogButtonBox(damage_discovery) - self.buttonBox.setGeometry(QtCore.QRect(350, 20, 81, 61)) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.groupBox = QtWidgets.QGroupBox(damage_discovery) - self.groupBox.setGeometry(QtCore.QRect(19, 19, 311, 351)) - self.groupBox.setObjectName('groupBox') - self.leak_amount_line = QtWidgets.QLineEdit(self.groupBox) - self.leak_amount_line.setGeometry(QtCore.QRect(80, 50, 51, 20)) - self.leak_amount_line.setObjectName('leak_amount_line') - self.leak_anount_label = QtWidgets.QLabel(self.groupBox) - self.leak_anount_label.setGeometry(QtCore.QRect(10, 50, 71, 16)) - self.leak_anount_label.setObjectName('leak_anount_label') - self.leak_time_line = QtWidgets.QLineEdit(self.groupBox) - self.leak_time_line.setGeometry(QtCore.QRect(210, 50, 81, 20)) - self.leak_time_line.setObjectName('leak_time_line') - self.time_discovery_ratio_table = QtWidgets.QTableWidget(self.groupBox) - self.time_discovery_ratio_table.setGeometry(QtCore.QRect(10, 141, 211, 191)) - self.time_discovery_ratio_table.setSelectionMode( - QtWidgets.QAbstractItemView.ExtendedSelection - ) - self.time_discovery_ratio_table.setSelectionBehavior( - QtWidgets.QAbstractItemView.SelectRows - ) - self.time_discovery_ratio_table.setRowCount(0) - self.time_discovery_ratio_table.setObjectName('time_discovery_ratio_table') - self.time_discovery_ratio_table.setColumnCount(2) - item = QtWidgets.QTableWidgetItem() - self.time_discovery_ratio_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.time_discovery_ratio_table.setHorizontalHeaderItem(1, item) - self.time_discovery_ratio_table.horizontalHeader().setStretchLastSection( - True - ) - self.time_discovery_ratio_table.verticalHeader().setVisible(False) - self.time_discovery_ratio_table.verticalHeader().setStretchLastSection(False) - self.leak_time_label = QtWidgets.QLabel(self.groupBox) - self.leak_time_label.setGeometry(QtCore.QRect(150, 50, 61, 16)) - self.leak_time_label.setObjectName('leak_time_label') - self.leak_based_radio = QtWidgets.QRadioButton(self.groupBox) - self.leak_based_radio.setGeometry(QtCore.QRect(10, 20, 111, 17)) - self.leak_based_radio.setObjectName('leak_based_radio') - self.time_based_radio = QtWidgets.QRadioButton(self.groupBox) - self.time_based_radio.setGeometry(QtCore.QRect(10, 90, 111, 17)) - self.time_based_radio.setObjectName('time_based_radio') - self.time_line = QtWidgets.QLineEdit(self.groupBox) - self.time_line.setGeometry(QtCore.QRect(10, 120, 101, 20)) - self.time_line.setObjectName('time_line') - self.discovery_ratio_line = QtWidgets.QLineEdit(self.groupBox) - self.discovery_ratio_line.setGeometry(QtCore.QRect(110, 120, 111, 20)) - self.discovery_ratio_line.setObjectName('discovery_ratio_line') - self.add_button = QtWidgets.QPushButton(self.groupBox) - self.add_button.setGeometry(QtCore.QRect(230, 120, 51, 23)) - self.add_button.setObjectName('add_button') - self.remove_button = QtWidgets.QPushButton(self.groupBox) - self.remove_button.setGeometry(QtCore.QRect(230, 150, 51, 23)) - self.remove_button.setObjectName('remove_button') - - self.retranslateUi(damage_discovery) - self.buttonBox.rejected.connect(damage_discovery.reject) - QtCore.QMetaObject.connectSlotsByName(damage_discovery) - - def retranslateUi(self, damage_discovery): # noqa: N802, D102 - _translate = QtCore.QCoreApplication.translate - damage_discovery.setWindowTitle( - _translate('damage_discovery', 'Damage Discovery') - ) - self.groupBox.setTitle(_translate('damage_discovery', 'Leak Model')) - self.leak_anount_label.setText(_translate('damage_discovery', 'Leak Amount')) - item = self.time_discovery_ratio_table.horizontalHeaderItem(0) - item.setText(_translate('damage_discovery', 'Time')) - item = self.time_discovery_ratio_table.horizontalHeaderItem(1) - item.setText(_translate('damage_discovery', 'Discovery Ratio')) - self.leak_time_label.setText(_translate('damage_discovery', 'leak time')) - self.leak_based_radio.setText(_translate('damage_discovery', 'Leak Based')) - self.time_based_radio.setText(_translate('damage_discovery', 'Time Based')) - self.add_button.setText(_translate('damage_discovery', 'add')) - self.remove_button.setText(_translate('damage_discovery', 'Remove')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - damage_discovery = QtWidgets.QDialog() - ui = Ui_damage_discovery() - ui.setupUi(damage_discovery) - damage_discovery.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.ui deleted file mode 100644 index f7ccaf055..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Damage_Discovery_Window.ui +++ /dev/null @@ -1,233 +0,0 @@ - - - damage_discovery - - - - 0 - 0 - 450 - 400 - - - - - 450 - 400 - - - - - 450 - 400 - - - - Damage Discovery - - - - - 350 - 20 - 81 - 61 - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 19 - 19 - 311 - 351 - - - - Leak Model - - - - - 80 - 50 - 51 - 20 - - - - - - - 10 - 50 - 71 - 16 - - - - Leak Amount - - - - - - 210 - 50 - 81 - 20 - - - - - - - 10 - 141 - 211 - 191 - - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - 0 - - - true - - - false - - - false - - - - Time - - - - - Discovery Ratio - - - - - - - 150 - 50 - 61 - 16 - - - - leak time - - - - - - 10 - 20 - 111 - 17 - - - - Leak Based - - - - - - 10 - 90 - 111 - 17 - - - - Time Based - - - - - - 10 - 120 - 101 - 20 - - - - - - - 110 - 120 - 111 - 20 - - - - - - - 230 - 120 - 51 - 23 - - - - add - - - - - - 230 - 150 - 51 - 23 - - - - Remove - - - - - - - - buttonBox - rejected() - damage_discovery - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Damage_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Damage_Tab_Designer.py deleted file mode 100644 index cfb70c997..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Damage_Tab_Designer.py +++ /dev/null @@ -1,578 +0,0 @@ -"""Created on Fri Oct 28 12:50:24 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os -import pickle - -import pandas as pd -from PyQt5 import QtCore, QtWidgets - -from .Node_Damage_Model_Designer import Node_Damage_Model_Designer -from .Pipe_Damage_Model_Designer import Pipe_Damage_Model_Designer -from .Scenario_Dialog_Designer import Scenario_Dialog_Designer - - -class Damage_Tab_Designer: # noqa: D101 - def __init__(self): - # self.pipe_damage_model = {"CI":{"alpha":-0.0038, "beta":0.1096, "gamma":0.0196, "a":2, "b":1 }, "DI":{"alpha":-0.0038, "beta":0.05, "gamma":0.04, "a":2, "b":1 } } - # self.node_damage_model = {'a':0.0036, 'aa':1, 'b':0, 'bb':0, 'c':-0.877, 'cc':1, 'd':0, 'dd':0, 'e':0.0248, 'ee1':1, 'ee2':1, 'f':0, 'ff1':0, 'ff2':0, "damage_node_model": "equal_diameter_emitter"} - """These are variables that are shared between ui and settings.""" # noqa: D401 - self.setDamageSettings(self.settings, self.scenario_list) - - """ - Reassignment of shared variables. - """ - self.damage_input_directory = os.getcwd() # noqa: PTH109 - self.current_xlsx_directory = os.getcwd() # noqa: PTH109 - if self.scenario_list == None: # noqa: E711 - self.scenario_list = pd.DataFrame( - columns=[ - 'Scenario Name', - 'Pipe Damage', - 'Nodal Damage', - 'Pump Damage', - 'Tank Damage', - 'Probability', - ] - ) - self.scneraio_validated = False - self.damage_pipe_model_reviewed = False - - """ - ui value assignments. - """ - self.setDamageUI() - - """ - Signals connection. - """ - self.add_scenario_button.clicked.connect(self.addNewScenarioByButton) - self.damage_directory_browse_button.clicked.connect( - self.browseDamageDirectoryByButton - ) - self.remove_scenario_button.clicked.connect(self.removeScenarioByButton) - self.load_scenario_button.clicked.connect(self.loadScenarioByButton) - self.save_scenario_button.clicked.connect(self.saveScenarioByButton) - self.validate_scenario_button.clicked.connect(self.validateScenarioByButton) - self.pipe_damage_modeling_button.clicked.connect( - self.pipeDamageSettingByButton - ) - self.node_damage_modeling_button.clicked.connect( - self.nodeDamageSettingByButton - ) - self.file_type_excel_radio.toggled.connect(self.fileTypeChanged) - self.file_type_pickle_radio.toggled.connect(self.fileTypeChanged) - - def getDamageSettings(self): # noqa: N802, D102 - if len(self.scenario_list) < 1: - self.errorMSG('REWET', 'Damage scenario list is empty.') - return False - if self.damage_input_directory == '': - self.errorMSG('REWET', 'No Damage Input Directory is selected.') - return False - - self.settings.scenario['pipe_damage_model'] = self.pipe_damage_model - self.settings.scenario['node_damage_model'] = self.node_damage_model - self.settings.scenario['Pipe_damage_input_method'] = ( - self.pipe_damage_input_method - ) - self.settings.process['pipe_damage_file_directory'] = ( - self.damage_input_directory - ) - # self.scenario_list -- already set - return True - - def setDamageUI(self): # noqa: N802, D102 - self.damage_direcotry_line.setText(self.damage_input_directory) - self.clearScnearioTable() - self.populateScenarioTable() - - def setDamageSettings(self, settings, scenario_list): # noqa: N802, D102 - self.pipe_damage_model = settings.scenario['pipe_damage_model'] - self.node_damage_model = settings.scenario['node_damage_model'] - self.pipe_damage_input_method = settings.scenario['Pipe_damage_input_method'] - self.damage_input_directory = settings.process['pipe_damage_file_directory'] - self.scenario_list = scenario_list - - def addNewScenarioByButton(self): # noqa: N802, D102 - new_scenario_dialoge = Scenario_Dialog_Designer() - - error = True - while error: - error = False - return_value = new_scenario_dialoge._window.exec_() # noqa: SLF001 - - if return_value == 0: - return - - scenario_name = new_scenario_dialoge.scenario_name_line.text() - pipe_damage_name = new_scenario_dialoge.pipe_damage_line.text() - node_damage_name = new_scenario_dialoge.node_damage_line.text() - pump_damage_name = new_scenario_dialoge.pump_damage_line.text() - tank_damage_name = new_scenario_dialoge.tank_damage_line.text() - probability = new_scenario_dialoge.probability_line.text() - probability = float(probability) - - if len(scenario_name) < 1: - self.errorMSG('Empty Scenario Name', 'Please enter a scenario name') - error = True - - if len(pipe_damage_name) < 1: - self.errorMSG( - 'Empty Pipe Damage Name', 'Please enter a pipe damage name' - ) - error = True - - if len(node_damage_name) < 1: - self.errorMSG( - 'Empty Node Damage Name', 'Please enter a node damage name' - ) - error = True - - if len(pump_damage_name) < 1: - self.errorMSG( - 'Empty Pump Damage Name', 'Please enter a pump damage name' - ) - error = True - - if len(tank_damage_name) < 1: - self.errorMSG( - 'Empty Tank Damage Name', 'Please enter a tank damage name' - ) - error = True - - if (self.scenario_list['Scenario Name'] == scenario_name).any(): - self.errorMSG( - 'Duplicate Scenario Name', - 'Please Have the Scenario Name changed', - ) - error = True - new_row = { - 'Scenario Name': scenario_name, - 'Pipe Damage': pipe_damage_name, - 'Nodal Damage': node_damage_name, - 'Pump Damage': pump_damage_name, - 'Tank Damage': tank_damage_name, - 'Probability': probability, - } - self.scenario_list = self.scenario_list.append(new_row, ignore_index=True) - self.clearScnearioTable() - self.populateScenarioTable() - self.scneraio_validated = False - self.damage_pipe_model_reviewed = False - - def fileTypeChanged(self, checked): # noqa: ARG002, N802, D102 - if self.file_type_excel_radio.isChecked(): - self.pipe_damage_input_method = 'excel' - else: - self.pipe_damage_input_method = 'pickle' - - def removeScenarioByButton(self): # noqa: N802, D102 - items = self.scenario_table.selectedItems() - if len(items) < 1: - return - - row_number = [] - for i in range(len(items)): - selected_row = items[i].row() - row_number.append(selected_row) - - row_number = list(set(row_number)) - - for selected_row in row_number: - scenario_name = self.scenario_table.item(selected_row, 0).text() - to_be_removed_index = ( - self.scenario_list[self.scenario_list == scenario_name] - ).index[0] - self.scenario_list = self.scenario_list.drop(to_be_removed_index) - self.scenario_list = self.scenario_list.reset_index(drop=True) - self.clearScnearioTable() - self.populateScenarioTable() - self.scneraio_validated = False - self.damage_pipe_model_reviewed = False - - def loadScenarioByButton(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getOpenFileName( - self.asli_MainWindow, - 'Open file', - self.current_xlsx_directory, - 'scenrario file (*.xlsx)', - ) - if file[0] == '': - return - split_addr = os.path.split(file[0]) - - temp = self.getScnearioListFromXLSX(file[0]) - if temp is None: - return - self.scenario_list = temp - - self.current_xlsx_directory = split_addr[0] - self.wdn_addr_line.setText(file[0]) - self.clearScnearioTable() - self.populateScenarioTable() - self.scneraio_validated = False - self.damage_pipe_model_reviewed = False - - def saveScenarioByButton(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getSaveFileName( - self.asli_MainWindow, - 'Save file', - self.current_xlsx_directory, - 'Excel file (*.xlsx)', - ) - split_addr = os.path.split(file[0]) - self.current_xlsx_directory = split_addr[0] - - self.scenario_list.to_excel(file[0]) - - def validateScenarioByButton(self): # noqa: C901, N802, D102 - self.status_text.setText('Validating Damage Scnearios') - if_validate_successful = True - text_output = '' - scneario_list = self.scenario_list - - all_pipe_material = set() - - damage_pipe_not_exist_List = [] # noqa: N806 - damage_nodal_not_exist_List = [] # noqa: N806 - damage_pump_not_exist_List = [] # noqa: N806 - damage_tank_not_exist_List = [] # noqa: N806 - - for index, row in scneario_list.iterrows(): # noqa: B007 - damage_pipe_name = row['Pipe Damage'] - damage_pipe_addr = os.path.join( # noqa: PTH118 - self.damage_input_directory, damage_pipe_name - ) - if not os.path.exists(damage_pipe_addr): # noqa: PTH110 - damage_pipe_not_exist_List.append(damage_pipe_name) - - damage_node_name = row['Nodal Damage'] - damage_nodal_addr = os.path.join( # noqa: PTH118 - self.damage_input_directory, damage_node_name - ) - if not os.path.exists(damage_nodal_addr): # noqa: PTH110 - damage_nodal_not_exist_List.append(damage_node_name) - - damage_pump_name = row['Pump Damage'] - damage_pump_addr = os.path.join( # noqa: PTH118 - self.damage_input_directory, damage_pump_name - ) - if not os.path.exists(damage_pump_addr): # noqa: PTH110 - damage_pump_not_exist_List.append(damage_pump_name) - - damage_tank_name = row['Tank Damage'] - damage_tank_addr = os.path.join( # noqa: PTH118 - self.damage_input_directory, damage_tank_name - ) - if not os.path.exists(damage_tank_addr): # noqa: PTH110 - damage_tank_not_exist_List.append(damage_tank_name) - - if len(damage_pipe_not_exist_List) > 0: - text_output += ( - 'The following pipe damage files could not be found.\n' - + repr(damage_pipe_not_exist_List) - + '\n' - ) - if_validate_successful = False - if len(damage_nodal_not_exist_List) > 0: - text_output += ( - 'The following node damage files could not be found.\n' - + repr(damage_nodal_not_exist_List) - + '\n' - ) - if_validate_successful = False - if len(damage_pump_not_exist_List) > 0: - text_output += ( - 'The following pump damage files could not be found.\n' - + repr(damage_pump_not_exist_List) - + '\n' - ) - if_validate_successful = False - if len(damage_tank_not_exist_List) > 0: - text_output += ( - 'The following tank damage files could not be found.\n' - + repr(damage_tank_not_exist_List) - + '\n' - ) - if_validate_successful = False - - try: - must_have_pipe_columns = set( # noqa: C405 - ['time', 'pipe_id', 'damage_loc', 'type', 'Material'] - ) - for index, row in scneario_list.iterrows(): # noqa: B007 - damage_pipe_name = row['Pipe Damage'] - if self.pipe_damage_input_method == 'excel': - pipe_damage = pd.read_excel( - os.path.join(self.damage_input_directory, damage_pipe_name) # noqa: PTH118 - ) - elif self.pipe_damage_input_method == 'pickle': - with open( # noqa: PTH123 - os.path.join(self.damage_input_directory, damage_pipe_name), # noqa: PTH118 - 'rb', - ) as f: - pipe_damage = pickle.load(f) # noqa: S301 - index_list = pipe_damage.index - pipe_damage = pd.DataFrame.from_dict(pipe_damage.to_list()) - pipe_damage.loc[:, 'time'] = index_list - if len(index_list) == 0: - available_columns = set(pipe_damage.columns) - not_available_columns = ( - must_have_pipe_columns - available_columns - ) - pipe_damage.loc[:, not_available_columns] = None - # print(pipe_damage) - # pipe_damage = pd.DataFrame.from_dict( ) - # pipe_damage.index.name = 'time' - # pipe_damage = pipe_damage.reset_index(drop=False) - # print(pipe_damage) - available_columns = set(pipe_damage.columns) - not_available_columns = must_have_pipe_columns - available_columns - if len(not_available_columns) > 0: - text_output += ( - 'In pipe damage file= ' - + repr(damage_pipe_name) - + 'the following headers are missing: ' - + repr(not_available_columns) - + '\n' - ) - if_validate_successful = False - - new_material_set = set(pipe_damage['Material'].unique()) - all_pipe_material = all_pipe_material.union(new_material_set) - - must_have_node_columns = set( # noqa: C405 - ['time', 'node_name', 'Number_of_damages', 'node_Pipe_Length'] - ) - for index, row in scneario_list.iterrows(): # noqa: B007 - damage_node_name = row['Nodal Damage'] - if self.pipe_damage_input_method == 'excel': - node_damage = pd.read_excel( - os.path.join(self.damage_input_directory, damage_node_name) # noqa: PTH118 - ) - elif self.pipe_damage_input_method == 'pickle': - with open( # noqa: PTH123 - os.path.join(self.damage_input_directory, damage_node_name), # noqa: PTH118 - 'rb', - ) as f: - node_damage = pickle.load(f) # noqa: S301 - index_list = node_damage.index - node_damage = pd.DataFrame.from_dict(node_damage.to_list()) - node_damage.loc[:, 'time'] = index_list - if len(index_list) == 0: - available_columns = set(node_damage.columns) - not_available_columns = ( - must_have_node_columns - available_columns - ) - pipe_damage.loc[:, not_available_columns] = None - available_columns = set(node_damage.columns) - not_available_columns = must_have_node_columns - available_columns - if len(not_available_columns) > 0: - text_output += ( - 'In node damage file= ' - + repr(damage_node_name) - + 'the following headers are missing: ' - + repr(not_available_columns) - + '\n' - ) - if_validate_successful = False - - must_have_pump_columns = set(['time', 'Pump_ID', 'Restore_time']) # noqa: C405 - for index, row in scneario_list.iterrows(): # noqa: B007 - damage_pump_name = row['Pump Damage'] - if self.pipe_damage_input_method == 'excel': - pump_damage = pd.read_excel( - os.path.join(self.damage_input_directory, damage_pump_name) # noqa: PTH118 - ) - elif self.pipe_damage_input_method == 'pickle': - with open( # noqa: PTH123 - os.path.join(self.damage_input_directory, damage_pump_name), # noqa: PTH118 - 'rb', - ) as f: - pump_damage = pickle.load(f) # noqa: S301 - pump_damage = pump_damage.reset_index(drop=False) - available_columns = set(pump_damage.columns) - not_available_columns = ( - must_have_pump_columns - available_columns - ) - pump_damage.loc[:, not_available_columns] = None - # index_list = pump_damage.index - # pump_damage = pd.DataFrame.from_dict(pump_damage.to_list() ) - - available_columns = set(pump_damage.columns) - not_available_columns = must_have_pump_columns - available_columns - - if len(not_available_columns) > 0 and len(pump_damage) > 0: - text_output += ( - 'In pump damage file= ' - + repr(damage_pump_name) - + 'the following headers are missing: ' - + repr(not_available_columns) - + '\n' - ) - if_validate_successful = False - - must_have_tank_columns = set(['time', 'Tank_ID', 'Restore_time']) # noqa: C405 - for index, row in scneario_list.iterrows(): # noqa: B007 - damage_tank_name = row['Tank Damage'] - if self.pipe_damage_input_method == 'excel': - tank_damage = pd.read_excel( - os.path.join(self.damage_input_directory, damage_tank_name) # noqa: PTH118 - ) - elif self.pipe_damage_input_method == 'pickle': - with open( # noqa: PTH123 - os.path.join(self.damage_input_directory, damage_tank_name), # noqa: PTH118 - 'rb', - ) as f: - tank_damage = pickle.load(f) # noqa: S301 - tank_damage = tank_damage.reset_index(drop=False) - available_columns = set(tank_damage.columns) - not_available_columns = ( - must_have_tank_columns - available_columns - ) - tank_damage.loc[:, not_available_columns] = None - - available_columns = set(tank_damage.columns) - not_available_columns = must_have_tank_columns - available_columns - if len(not_available_columns) > 0 and len(damage_tank_name) > 0: - text_output += ( - 'In tank damage file= ' - + repr(damage_tank_name) - + 'the following headers are missing: ' - + repr(not_available_columns) - + '\n' - ) - if_validate_successful = False - except Exception as exp: # noqa: TRY302 - raise exp # noqa: TRY201 - if_validate_successful = False - text_output += ( - 'An error happened. File type might be wrong in addition to other problems. More information:\n' - + repr(exp) - ) - - if if_validate_successful == True: # noqa: E712 - text_output += 'Damage Scenario List Validated Sucessfully' - not_defined_materials = all_pipe_material - set( - self.pipe_damage_model.keys() - ) - if len(not_defined_materials) > 0: - default_material_model = self.settings.scenario[ - 'default_pipe_damage_model' - ] - new_material_model = dict( - zip( - not_defined_materials, - [ - default_material_model - for i in range(len(not_defined_materials)) - ], - ) - ) - self.pipe_damage_model.update(new_material_model) - self.scneraio_validated = True - - self.status_text.setText(text_output) - - def pipeDamageSettingByButton(self): # noqa: N802, D102 - if self.scneraio_validated == False: # noqa: E712 - self.errorMSG( - 'REWET', - 'You must validate damage scenarios successfully before reviewing pipe damage models.', - ) - return - pipe_designer = Pipe_Damage_Model_Designer(self.pipe_damage_model) - return_value = pipe_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.pipe_damage_model = pipe_designer.pipe_damage_model - - self.damage_pipe_model_reviewed = True - - def nodeDamageSettingByButton(self): # noqa: N802, D102 - node_designer = Node_Damage_Model_Designer(self.node_damage_model) - return_value = node_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.node_damage_model = node_designer.node_damage_model - - def browseDamageDirectoryByButton(self): # noqa: N802, D102 - directory = QtWidgets.QFileDialog.getExistingDirectory( - self.asli_MainWindow, 'Select Directory', self.current_xlsx_directory - ) - if directory == '': - return - self.current_xlsx_directory = self.current_xlsx_directory - self.damage_input_directory = directory - self.damage_direcotry_line.setText(directory) - - def getScnearioListFromXLSX(self, scenario_file_addr): # noqa: N802, D102 - scn_list = pd.read_excel(scenario_file_addr) - - must_be_headers = [ - 'Scenario Name', - 'Pipe Damage', - 'Nodal Damage', - 'Pump Damage', - 'Tank Damage', - 'Probability', - ] - available_headers = scn_list.columns.tolist() - - not_available_headers = set(must_be_headers) - set(available_headers) - if len(not_available_headers) > 1: - self.status_text.setText( - 'failed to open the scenario file. the following columns are missing and need to be in the file: ' - + repr(not_available_headers) - ) - return None - else: # noqa: RET505 - self.status_text.setText('Opened file Successfully.') - scn_list = scn_list[must_be_headers] - - return scn_list # noqa: RET504 - - def populateScenarioTable(self): # noqa: N802, D102 - for index, row in self.scenario_list.iterrows(): # noqa: B007 - number_of_rows = self.scenario_table.rowCount() - self.scenario_table.insertRow(number_of_rows) - - scenario_item = QtWidgets.QTableWidgetItem(row['Scenario Name']) - pipe_damage_item = QtWidgets.QTableWidgetItem(row['Pipe Damage']) - node_damage_item = QtWidgets.QTableWidgetItem(row['Nodal Damage']) - pump_damage_item = QtWidgets.QTableWidgetItem(row['Pump Damage']) - tank_damage_item = QtWidgets.QTableWidgetItem(row['Tank Damage']) - probability_item = QtWidgets.QTableWidgetItem(str(row['Probability'])) - - scenario_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - pipe_damage_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - node_damage_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - pump_damage_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - tank_damage_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - probability_item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - - self.scenario_table.setItem(number_of_rows, 0, scenario_item) - self.scenario_table.setItem(number_of_rows, 1, pipe_damage_item) - self.scenario_table.setItem(number_of_rows, 2, node_damage_item) - self.scenario_table.setItem(number_of_rows, 3, pump_damage_item) - self.scenario_table.setItem(number_of_rows, 4, tank_damage_item) - self.scenario_table.setItem(number_of_rows, 5, probability_item) - - def clearScnearioTable(self): # noqa: N802, D102 - for i in range(self.scenario_table.rowCount()): # noqa: B007 - self.scenario_table.removeRow(0) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Hydraulic_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Hydraulic_Tab_Designer.py deleted file mode 100644 index 2c4b8e8ac..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Hydraulic_Tab_Designer.py +++ /dev/null @@ -1,122 +0,0 @@ -"""Created on Thu Oct 27 19:19:02 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os - -from PyQt5 import QtGui, QtWidgets - - -class Hydraulic_Tab_Designer: # noqa: D101 - def __init__(self): - """These are variables that are shared between ui and settings.""" # noqa: D401 - self.setHydraulicSettings(self.settings) - - """ - ui value assignments. - """ - self.setHydraulicUI() - """ - Field Validators. - """ - self.demand_ratio_line.setValidator( - QtGui.QDoubleValidator( - 0.0, 1.0, 3, notation=QtGui.QDoubleValidator.StandardNotation - ) - ) - self.minimum_pressure_line.setValidator(QtGui.QIntValidator(0.0, 2147483647)) - self.required_pressure_line.setValidator( - QtGui.QIntValidator(0.0, 2147483647) - ) - self.hydraulic_time_step_line.setValidator( - QtGui.QIntValidator(0.0, 2147483647) - ) - - """ - Signals connection. - """ - self.demand_ratio_line.textChanged.connect(self.demandRatioValidatorHelper) - self.wdn_browse_button.clicked.connect(self.wdnFileBroweserClicked) - self.hydraulic_time_step_line.textEdited.connect( - self.hydraulicTimeStepValidatorHelper - ) - self.current_inp_directory = os.getcwd() # noqa: PTH109 - - def getHydraulicSettings(self): # noqa: N802, D102 - if self.wn_inp == '': - self.errorMSG( - 'REWET', 'Water distribution network File must be provided' - ) - return False - - # self.wn_inp -- already set - self.demand_ratio = float(self.demand_ratio_line.text()) - self.minimum_pressure = float(self.minimum_pressure_line.text()) - self.required_pressure = float(self.required_pressure_line.text()) - self.hydraulic_time_step = int(float(self.hydraulic_time_step_line.text())) - - self.settings.process['WN_INP'] = self.wn_inp - self.settings.process['demand_ratio'] = self.demand_ratio - self.settings.process['solver_type'] = self.solver - self.settings.scenario['minimum_pressure'] = self.minimum_pressure - self.settings.scenario['required_pressure'] = self.required_pressure - self.settings.scenario['hydraulic_time_step'] = self.hydraulic_time_step - - return True - - def setHydraulicUI(self): # noqa: N802, D102 - self.wdn_addr_line.setText(self.wn_inp) - self.last_demand_ratio_value = self.demand_ratio - self.demand_ratio_line.setText(str(self.last_demand_ratio_value)) - - if self.solver == 'ModifiedEPANETV2.2': - self.modified_epanet_radio.setChecked(True) - elif self.solver == 'WNTR': - self.wntr_solver_radio.setChecked(True) - else: - raise ValueError('Unknown value for solver: ' + repr(self.solver)) - - self.minimum_pressure_line.setText(str(self.minimum_pressure)) - self.required_pressure_line.setText(str(self.required_pressure)) - self.hydraulic_time_step_line.setText(str(self.hydraulic_time_step)) - - def setHydraulicSettings(self, settings): # noqa: N802, D102 - self.wn_inp = settings.process['WN_INP'] - self.demand_ratio = settings.process['demand_ratio'] - self.solver = settings.process['solver_type'] - self.minimum_pressure = settings.scenario['minimum_pressure'] - self.required_pressure = settings.scenario['required_pressure'] - self.hydraulic_time_step = settings.scenario['hydraulic_time_step'] - - def demandRatioValidatorHelper(self, x): # noqa: N802, D102 - if float(x) > 1: - self.demand_ratio_line.setText(self.last_demand_ratio_value) - else: - self.last_demand_ratio_value = x - # print(x) - - def hydraulicTimeStepValidatorHelper(self, x): # noqa: ARG002, N802, D102 - try: - hydraulic_time_step = int(float(self.hydraulic_time_step_line.text())) - except: # noqa: E722 - hydraulic_time_step = 0 - simulation_time_step = int(float(self.simulation_time_step_line.text())) - - if hydraulic_time_step > simulation_time_step: - self.hydraulic_time_step_line.setText(str(simulation_time_step)) - - def wdnFileBroweserClicked(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getOpenFileName( - self.asli_MainWindow, - 'Open file', - self.current_inp_directory, - 'inp file (*.inp)', - ) - if file[0] == '': - return - split_addr = os.path.split(file[0]) - self.current_inp_directory = split_addr[0] - self.wn_inp = file[0] - - self.wdn_addr_line.setText(file[0]) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Input_IO.py b/modules/systemPerformance/REWET/REWET/GUI/Input_IO.py deleted file mode 100644 index bbdb83776..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Input_IO.py +++ /dev/null @@ -1,124 +0,0 @@ -import os # noqa: N999, D100 -import pickle - -import pandas as pd - - -# Read files From Pickle ##################### -def read_pipe_damage_seperate_pickle_file(directory, all_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, all_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _all_damages = pickle.load(f) # noqa: S301 - - return _all_damages # noqa: RET504 - - -def read_node_damage_seperate_pickle_file(directory, all_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, all_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _node_damages = pickle.load(f) # noqa: S301 - - return _node_damages # noqa: RET504 - - -def read_tank_damage_seperate_pickle_file(directory, tank_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, tank_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _tank_damages = pickle.load(f) # noqa: S301 - - return _tank_damages # noqa: RET504 - - -def read_pump_damage_seperate_pickle_file(directory, pump_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, pump_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _pump_damages = pickle.load(f) # noqa: S301 - - return _pump_damages # noqa: RET504 - - -# Read files From Excel ##################### - - -def read_pipe_damage_seperate_EXCEL_file(directory, pipe_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, pipe_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.sort_values( - ['pipe_id', 'damage_time', 'damage_loc'], - ascending=[True, True, False], - ignore_index=True, - inplace=True, # noqa: PD002 - ) - unique_time = ss.groupby(['pipe_id']).time.unique() - if 1 in [ - 0 if len(i) <= 1 else 1 for i in unique_time - ]: # checks if there are any pipe id with more than two unique time values - raise ValueError( # noqa: TRY003 - 'All damage location for one pipe should happen at the same time' # noqa: EM101 - ) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.pipe_id = ss.pipe_id.astype(str) - return pd.Series(ss.to_dict('records'), index=ss.index) - - -def read_node_damage_seperate_EXCEL_file(directory, node_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, node_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.node_name = ss.node_name.astype(str) - return pd.Series(ss.to_dict('records'), index=ss.index) - - -def read_tank_damage_seperate_EXCEL_file(directory, tank_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, tank_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - # ss.set_index('Tank_ID', inplace=True) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.Tank_ID = ss.Tank_ID.astype(str) - # ss = ss['Tank_ID'] - - return ss - - -def read_pump_damage_seperate_EXCEL_file(directory, pump_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, pump_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.Pump_ID = ss.Pump_ID.astype(str) - return ss - - -# Save Results ##################### - - -def save_single(settings, result, name, restoration_data): # noqa: D103 - result_file_directory = settings.process['result_directory'] - result_name = name + '.res' - settings_name = name + '.xlsx' - - file_dest = os.path.join(result_file_directory, result_name) # noqa: PTH118 - print('Saving: ' + str(file_dest)) # noqa: T201 - with open(file_dest, 'wb') as f: # noqa: PTH123 - pickle.dump(result, f) - - process_set = pd.Series(settings.process.settings) - scenario_set = pd.Series(settings.scenario.settings) - _set = pd.Series( - process_set.to_list() + scenario_set.to_list(), - index=process_set.index.to_list() + scenario_set.index.to_list(), - ) - file_dest = os.path.join(result_file_directory, settings_name) # noqa: PTH118 - _set.to_excel(file_dest) - - if settings.process['dmg_rst_data_save']: - # file_dest = os.path.join(result_file_directory, 'restoration_file.pkl') - # rest_data_out = pd.DataFrame.from_dict(restoration_data) - # rest_data_out.to_pickle(file_dest) - file_dest = os.path.join(result_file_directory, name + '_registry.pkl') # noqa: PTH118 - print('Saving: ' + str(file_dest)) # noqa: T201 - with open(file_dest, 'wb') as f: # noqa: PTH123 - pickle.dump(restoration_data, f) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Designer.py deleted file mode 100644 index 84e70e8ac..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Designer.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Created on Wed Nov 2 13:25:40 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from PyQt5 import QtWidgets - -from .Main_Help_Window import Ui_Main_Help_Window - - -class Main_Help_Designer(Ui_Main_Help_Window): # noqa: D101 - def __init__(self): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - - self.buttonBox.rejected.connect(self._window.close) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.py deleted file mode 100644 index 5c4a8c5f6..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.py +++ /dev/null @@ -1,87 +0,0 @@ -# Form implementation generated from reading ui file 'Main_Help_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Main_Help_Window: # noqa: D101 - def setupUi(self, Main_Help_Window): # noqa: N802, N803, D102 - Main_Help_Window.setObjectName('Main_Help_Window') - Main_Help_Window.resize(680, 320) - Main_Help_Window.setMinimumSize(QtCore.QSize(680, 320)) - Main_Help_Window.setMaximumSize(QtCore.QSize(680, 320)) - self.layoutWidget = QtWidgets.QWidget(Main_Help_Window) - self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 641, 281)) - self.layoutWidget.setObjectName('layoutWidget') - self.main_layout = QtWidgets.QVBoxLayout(self.layoutWidget) - self.main_layout.setContentsMargins(0, 0, 0, 0) - self.main_layout.setObjectName('main_layout') - self.label = QtWidgets.QLabel(self.layoutWidget) - font = QtGui.QFont() - font.setFamily('Times New Roman') - font.setPointSize(11) - self.label.setFont(font) - self.label.setWordWrap(True) - self.label.setObjectName('label') - self.main_layout.addWidget(self.label) - self.gridLayout_4 = QtWidgets.QGridLayout() - self.gridLayout_4.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) - self.gridLayout_4.setObjectName('gridLayout_4') - spacerItem = QtWidgets.QSpacerItem( # noqa: N806 - 50, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum - ) - self.gridLayout_4.addItem(spacerItem, 1, 1, 1, 1) - spacerItem1 = QtWidgets.QSpacerItem( # noqa: N806 - 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum - ) - self.gridLayout_4.addItem(spacerItem1, 0, 0, 1, 1) - self.label_4 = QtWidgets.QLabel(self.layoutWidget) - self.label_4.setText('') - self.label_4.setPixmap(QtGui.QPixmap(':/resources/resources/both_logos.jpg')) - self.label_4.setObjectName('label_4') - self.gridLayout_4.addWidget(self.label_4, 0, 1, 1, 1) - spacerItem2 = QtWidgets.QSpacerItem( # noqa: N806 - 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum - ) - self.gridLayout_4.addItem(spacerItem2, 0, 2, 1, 1) - self.main_layout.addLayout(self.gridLayout_4) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName('horizontalLayout_2') - spacerItem3 = QtWidgets.QSpacerItem( # noqa: N806 - 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum - ) - self.horizontalLayout_2.addItem(spacerItem3) - self.buttonBox = QtWidgets.QDialogButtonBox(self.layoutWidget) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close) - self.buttonBox.setObjectName('buttonBox') - self.horizontalLayout_2.addWidget(self.buttonBox) - self.main_layout.addLayout(self.horizontalLayout_2) - - self.retranslateUi(Main_Help_Window) - QtCore.QMetaObject.connectSlotsByName(Main_Help_Window) - - def retranslateUi(self, Main_Help_Window): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Main_Help_Window.setWindowTitle(_translate('Main_Help_Window', 'Help')) - self.label.setText( - _translate( - 'Main_Help_Window', - 'REstoration of Water after an Event Tool (REWET) is created by Sina Naeimi and Rachel Davidson at University of Delaware. REWET is as it as and developers guarantee neither the usability of the software nor the validity of data it produce in any way.', - ) - ) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Main_Help_Window = QtWidgets.QDialog() - ui = Ui_Main_Help_Window() - ui.setupUi(Main_Help_Window) - Main_Help_Window.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.ui deleted file mode 100644 index f1625ce40..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Main_Help_Window.ui +++ /dev/null @@ -1,144 +0,0 @@ - - - Main_Help_Window - - - - 0 - 0 - 680 - 320 - - - - - 680 - 320 - - - - - 680 - 320 - - - - Help - - - - - 20 - 20 - 641 - 281 - - - - - - - - Times New Roman - 11 - - - - REstoration of Water after an Event Tool (REWET) is created by Sina Naeimi and Rachel Davidson at University of Delaware. REWET is as it as and developers guarantee neither the usability of the software nor the validity of data it produce in any way. - - - true - - - - - - - QLayout::SetDefaultConstraint - - - - - Qt::Horizontal - - - - 50 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - :/resources/resources/both_logos.jpg - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - QDialogButtonBox::Close - - - - - - - - - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Map_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Map_Designer.py deleted file mode 100644 index d5b0b00a5..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Map_Designer.py +++ /dev/null @@ -1,808 +0,0 @@ -"""Created on Thu Nov 10 18:29:50 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import geopandas as gpd -import matplotlib.pyplot as plt -import numpy as np -import pandas as pd -from GUI.Subsitute_Layer_Designer import Subsitute_Layer_Designer -from GUI.Symbology_Designer import Symbology_Designer -from PyQt5 import QtGui, QtWidgets -from shapely.geometry import Point - -single_scenario_map_options = [ - '', - 'Quantity Return', - 'Delivery Return', -] -multi_scenario_map_options = [ - '', - 'Quantity Outage vs. Exceedance', - 'Delivery Outage vs. Exceedance', - 'Quantity Exceedance vs. Time', - 'Delivery Exceedance vs. Time', -] -map_settings = { - 'Quantity Return': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '0.75'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - ], - 'Delivery Return': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - ], - 'Quantity Outage vs. Exceedance': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - { - 'Label': 'Ex. Prob.', - 'Type': 'Float Line', - 'Default': '0.09', - 'Validator': {'Min': 0, 'Max': 1}, - }, - ], - 'Delivery Outage vs. Exceedance': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - { - 'Label': 'Ex. Prob.', - 'Type': 'Int Line', - 'Default': str(24 * 3600), - 'Validator': {'Min': 0, 'Max': 1000 * 24 * 3600}, - }, - ], - 'Quantity Exceedance vs. Time': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - { - 'Label': 'Outage Time', - 'Type': 'Float Line', - 'Default': '0.09', - 'Validator': {'Min': 0, 'Max': 1}, - }, - ], - 'Delivery Exceedance vs. Time': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - {'Label': 'Time Window', 'Type': 'Int Line', 'Default': '7200'}, - { - 'Label': 'Outage Time', - 'Type': 'Int Line', - 'Default': str(24 * 3600), - 'Validator': {'Min': 0, 'Max': 1000 * 24 * 3600}, - }, - ], -} -norm = plt.Normalize(1, 4) -cmap = plt.cm.RdYlGn - - -class Time_Unit_Combo(QtWidgets.QComboBox): # noqa: D101 - def __init__(self): - super().__init__() - time_units = ['second', 'hour', 'day'] - - self.addItems(time_units) - - def changeMapTimeUnit(self, raw_time_map, value_columns_name): # noqa: N802, D102 - time_justified_map = raw_time_map.copy() - - time_unit = self.currentText() - data = time_justified_map[value_columns_name] - - # time_justified_map = time_justified_map.reset_index() - - if time_unit == 'second': - return raw_time_map.copy() - elif time_unit == 'hour': # noqa: RET505 - data = data / 3600 - elif time_unit == 'day': - data = data / 3600 / 24 - else: - raise ValueError('Unknown unit time: ' + repr(time_unit)) - - for ind in data.index.to_list(): - time_justified_map.loc[ind, value_columns_name] = data.loc[ind] - return time_justified_map - - -class Yes_No_Combo(QtWidgets.QComboBox): # noqa: D101 - def __init__(self): - super().__init__() - self.addItems(['No', 'Yes']) - - -class Map_Designer: # noqa: D101 - def __init__(self): - self.current_raw_map = None - self.current_map = None - self.annotation_map = None - self.plotted_map = None - self.subsitute_layer_addr = None - self.subsitute_layer = None - self.iUse_substitute_layer = False - self.map_settings_widgets = {} - self.symbology = {'Method': 'FisherJenks', 'kw': {'k': 5}, 'Color': 'Blues'} - - self.main_tab.currentChanged.connect(self.tabChangedMap) - self.map_all_scenarios_checkbox.stateChanged.connect( - self.mapAllScenarioCheckboxChanged - ) - self.save_map_button.clicked.connect(self.saveCurrentMapByButton) - self.map_scenario_combo.currentTextChanged.connect( - self.resultScenarioChanged - ) - self.map_type_combo.currentTextChanged.connect(self.mapTypeChanegd) - self.annotation_checkbox.stateChanged.connect(self.AnnotationCheckboxChanged) - self.annotation_event_combo.currentTextChanged.connect( - self.getAnnotationtype - ) - self.mpl_map.canvas.fig.canvas.mpl_connect( - 'motion_notify_event', self.mouseHovered - ) - self.mpl_map.canvas.fig.canvas.mpl_connect( - 'button_press_event', self.mouseClicked - ) - - """ - Signals - """ - self.annotation_radius_line.editingFinished.connect( - self.annotationRadiusChanegd - ) - self.spatial_join_button.clicked.connect(self.openSubsituteLayerWindow) - self.major_tick_size_line.editingFinished.connect(self.majorTickSet) - self.symbology_button.clicked.connect(self.symbologyByButton) - - """ - Validators - """ - self.annotation_radius_line.setValidator( - QtGui.QDoubleValidator( - 0, 1000000, 20, notation=QtGui.QDoubleValidator.StandardNotation - ) - ) - self.major_tick_size_line.setValidator(QtGui.QIntValidator(0, 64)) - - self.map_value_columns_name = None - self.anottation_type = 'None' - self.annotation_column = None - - self.initializeMap() - - def initializeMap(self): # noqa: N802, D102 - self.setMapAllScenarios(True) - self.map_all_scenarios_checkbox.setChecked(True) - self.map_scenario_combo.clear() - self.map_scenario_combo.addItems(self.result_scenarios) - # self.current_map_data = None - - def symbologyByButton(self): # noqa: N802, D102 - sym = Symbology_Designer( - self.symbology, self.plotted_map, self.map_value_columns_name - ) - val = sym._window.exec_() # noqa: SLF001 - - if val == 1: - self.symbology = sym.sym - self.plotMap(self.map_value_columns_name) - - def majorTickSet(self): # noqa: N802, D102 - major_tick_fond_size = self.major_tick_size_line.text() - major_tick_fond_size = float(major_tick_fond_size) - - self.mpl_map.canvas.ax.tick_params( - axis='both', which='major', labelsize=major_tick_fond_size - ) - self.mpl_map.canvas.fig.canvas.draw_idle() - - def openSubsituteLayerWindow(self): # noqa: N802, D102 - demand_node_temporary_layer = ( - self.project_result.createGeopandasPointDataFrameForNodes() - ) - sub_layer = Subsitute_Layer_Designer( - self.subsitute_layer_addr, - self.subsitute_layer, - self.iUse_substitute_layer, - demand_node_temporary_layer, - ) - val = sub_layer._window.exec_() # noqa: SLF001 - - if val == 1: - self.subsitute_layer_addr = sub_layer.subsitute_layer_addr - self.subsitute_layer = sub_layer.subsitute_layer - self.iUse_substitute_layer = sub_layer.iUse_substitute_layer - self.plotMap(self.map_value_columns_name) - - def annotationRadiusChanegd(self): # noqa: N802, D102 - annotation_radius = self.annotation_radius_line.text() - self.annotation_map = self.plotted_map.copy(deep=True) - if annotation_radius == '': - annotation_radius = 0 - self.annotation_radius_line.settext('0') - annotation_radius = float(annotation_radius) - for ind, val in self.current_map.geometry.iteritems(): - self.annotation_map.geometry.loc[ind] = val.buffer(annotation_radius) - - def AnnotationCheckboxChanged(self, state): # noqa: N802, D102 - if state == 0: - self.annotation_event_combo.setEnabled(False) - self.annotation_radius_line.setEnabled(False) - self.anottation_type = 'None' - self.annot.set_visible(False) - elif state == 2: # noqa: PLR2004 - self.annotation_event_combo.setEnabled(True) - self.annotation_radius_line.setEnabled(True) - self.getAnnotationtype() - - def mapAllScenarioCheckboxChanged(self, state): # noqa: N802, D102 - if state == 0: - self.setMapAllScenarios(False) - elif state == 2: # noqa: PLR2004 - self.setMapAllScenarios(True) - - def getAnnotationtype(self, text=None): # noqa: ARG002, N802, D102 - combo_value = self.annotation_event_combo.currentText() - if combo_value == 'Mouse hover' or combo_value == 'Mouse click': # noqa: PLR1714 - self.anottation_type = combo_value - else: - raise ValueError('unknown annotation type: ' + repr(combo_value)) - - def mouseHovered(self, event): # noqa: N802, D102 - if self.anottation_type != 'Mouse hover': - return - - if type(self.current_map) == type(None): # noqa: E721 - return - self.putAnnotation(event) - - def mouseClicked(self, event): # noqa: N802, D102 - if self.anottation_type != 'Mouse click': - return - - if type(self.current_map) == type(None): # noqa: E721 - return - - if event.button != 1: - return - - self.putAnnotation(event) - - def putAnnotation(self, event): # noqa: N802, D102 - vis = self.annot.get_visible() - if event.inaxes == self.mpl_map.canvas.ax: - # print((event.xdata, event.ydata) ) - mouse_point = Point(event.xdata, event.ydata) - - s = self.annotation_map.geometry.contains(mouse_point) - s_index_list = s[s == True].index # noqa: E712 - - if len(s_index_list) >= 1: - cont = True - s_index = s_index_list[0] - elif len(s_index_list) == 0: - cont = False - - if cont: - # print(len(s_index_list)) - data = self.annotation_map.loc[s_index, self.map_value_columns_name] - if type(data) == pd.core.series.Series: # noqa: E721 - data = data.iloc[0] - text = repr(data) - self.update_annot(text, event) - self.annot.set_visible(True) - self.mpl_map.canvas.fig.canvas.draw_idle() - elif vis: - self.annot.set_visible(False) - self.mpl_map.canvas.fig.canvas.draw_idle() - - def update_annot(self, text, event): # noqa: D102 - self.annot.xy = (event.xdata, event.ydata) - - self.annot.set_text(text) - self.annot.get_bbox_patch().set_facecolor(cmap(norm(1))) - self.annot.get_bbox_patch().set_alpha(0.4) - - def clearMapPlot(self): # noqa: N802, D102 - self.mpl_map.canvas.ax.cla() - - def plotMap(self, value_columns_name): # noqa: N802, D102 - self.clearMapPlot() - self.mpl_map.canvas.ax.clear() - # for ind, val in self.current_map.geometry.iteritems(): - # self.current_map.geometry.loc[ind] = val.buffer(2000) - # self.mpl_map.canvas.ax.clear() - data = self.current_map - # print(data.head() ) - - self.annot = self.mpl_map.canvas.ax.annotate( - '', - xy=(0, 0), - xytext=(20, 20), - textcoords='offset points', - bbox=dict(boxstyle='round', fc='w'), # noqa: C408 - arrowprops=dict(arrowstyle='->'), # noqa: C408 - ) - self.annot.set_visible(False) - - if self.iUse_substitute_layer == True: # noqa: E712 - data = data.set_crs(crs=self.subsitute_layer.crs) - joined_map = gpd.sjoin(self.subsitute_layer, data) - # joined_map.plot(ax=self.mpl_map.canvas.ax, column=value_columns_name, cmap="Blues", legend=True) - data = joined_map - else: - pass - self.annotation_map = data.copy(deep=True) - # data.to_file("Northridge/ss2.shp") - self.plotted_map = self.prepareForLegend(data, value_columns_name) - self.plotted_map.plot( - ax=self.mpl_map.canvas.ax, - column=value_columns_name, - cmap=self.symbology['Color'], - categorical=True, - legend='True', - scheme=self.symbology['Method'], - classification_kwds=self.symbology['kw'], - ) - self.mpl_map.canvas.ax.ticklabel_format(axis='both', style='plain') - # self.majorTickSet() - - # labels = self.mpl_map.canvas.ax.get_xticks() - # self.mpl_map.canvas.ax.set_xticklabels(labels, rotation=45, ha='right') - # self.mpl_map.canvas.ax.plot(self.current_map.index, self.current_map.to_list()) - - self.mpl_map.canvas.draw() - self.mpl_map.canvas.fig.tight_layout() - - def prepareForLegend(self, data, value_columns_name): # noqa: N802, D102 - return data.copy(deep=True) - data = data.copy(deep=True) - min_value = data[value_columns_name].min() - max_value = data[value_columns_name].max() - step = (max_value - min_value) / 5 - - step_array = np.arange(min_value, max_value, step) - step_array = step_array.tolist() - step_array.append(max_value) - - for i in range(len(step_array) - 1): - step_max = step_array[i + 1] - step_min = step_array[i] - index_list = data[ - (data[value_columns_name] < step_max) - & (data[value_columns_name] > step_min) - ].index - # print(index_list) - for ind in index_list: - data.loc[ind, value_columns_name] = step_max - - return data - - def setMapAllScenarios(self, flag): # noqa: N802, D102 - if flag == True: # noqa: E712 - self.map_all_scenarios_checkbox.setChecked(True) - self.map_scenario_combo.setEnabled(False) - self.map_type_combo.clear() - self.map_type_combo.addItems(multi_scenario_map_options) - self.clearMapPlot() - elif flag == False: # noqa: E712 - self.map_all_scenarios_checkbox.setChecked(False) - self.map_scenario_combo.setEnabled(True) - self.map_type_combo.clear() - self.map_type_combo.addItems(single_scenario_map_options) - self.clearMapPlot() - else: - raise ValueError('Unknown flag: ' + repr(flag)) - - def resultScenarioChanged(self, text): # noqa: N802, D102 - self.map_result_current_scenario = text # self.map_scenario_combo.getText() - - def mapTypeChanegd(self, text): # noqa: N802, D102 - if self.project_result == None: # noqa: E711 - return - self.current_map_type = text - self.setMapSettingBox(text) - self.calculateCurrentMap() - - def calculateCurrentMap(self): # noqa: C901, N802, D102 - map_type = self.current_map_type - if map_type == 'Quantity Outage vs. Exceedance': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - exeedance_probability = self.map_settings_widgets['Ex. Prob.'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - exeedance_probability = float(exeedance_probability) - - self.map_value_columns_name = 'res' - map_data = self.project_result.AS_getOutage_4( - LOS='QN', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - # print(map_data) - self.current_raw_map = ( - self.project_result.getDLQNExceedenceProbabilityMap( - map_data, ihour=True, param=exeedance_probability - ) - ) - # self.current_map = self.current_raw_map.copy() - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, self.map_value_columns_name - ) - - # print(exeedance_probability) - self.plotMap(self.map_value_columns_name) - - elif map_type == 'Delivery Outage vs. Exceedance': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - exeedance_probability = self.map_settings_widgets['Ex. Prob.'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - exeedance_probability = float(exeedance_probability) - - self.map_value_columns_name = 'res' - map_data = self.project_result.AS_getOutage_4( - LOS='DL', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - # print(map_data) - self.current_raw_map = ( - self.project_result.getDLQNExceedenceProbabilityMap( - map_data, ihour=True, param=exeedance_probability - ) - ) - # self.current_map = self.current_raw_map.copy() - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, self.map_value_columns_name - ) - - # print(exeedance_probability) - self.plotMap(self.map_value_columns_name) - - elif map_type == 'Quantity Exceedance vs. Time': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - outage_time = self.map_settings_widgets['Outage Time'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - outage_time = int(float(outage_time)) - - self.map_value_columns_name = 'res' - map_data = self.project_result.AS_getOutage_4( - LOS='QN', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - # print(map_data) - self.current_raw_map = ( - self.project_result.getDLQNExceedenceProbabilityMap( - map_data, ihour=False, param=outage_time - ) - ) - # self.current_map = self.current_raw_map.copy() - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, self.map_value_columns_name - ) - - # print(exeedance_probability) - self.plotMap(self.map_value_columns_name) - - elif map_type == 'Delivery Exceedance vs. Time': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - outage_time = self.map_settings_widgets['Outage Time'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - outage_time = int(float(outage_time)) - - self.map_value_columns_name = 'res' - map_data = self.project_result.AS_getOutage_4( - LOS='DL', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - # print(map_data) - self.current_raw_map = ( - self.project_result.getDLQNExceedenceProbabilityMap( - map_data, ihour=False, param=outage_time - ) - ) - # self.current_map = self.current_raw_map.copy() - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, self.map_value_columns_name - ) - - # print(exeedance_probability) - self.plotMap(self.map_value_columns_name) - - elif map_type == 'Quantity Return': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - - scn_name = self.map_scenario_combo.currentText() - self.current_raw_map = self.project_result.getOutageTimeGeoPandas_4( - scn_name, - LOS='QN', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - value_column_label = 'restoration_time' - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, value_column_label - ) - self.plotMap(value_column_label) - - self.map_value_columns_name = value_column_label - - elif map_type == 'Delivery Return': - iConsider_leak = self.map_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.map_settings_widgets['leak Criteria'].text() - time_window = self.map_settings_widgets['Time Window'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - leak_ratio = float(leak_ratio) - time_window = int(float(time_window)) - - scn_name = self.map_scenario_combo.currentText() - self.current_raw_map = self.project_result.getOutageTimeGeoPandas_4( - scn_name, - LOS='DL', - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=time_window, - ) - value_column_label = 'restoration_time' - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, value_column_label - ) - self.plotMap(value_column_label) - - self.map_value_columns_name = value_column_label - - elif map_type == 'SSI': - return - # self.current_map_data = (map_type, pd.DataFrame()) - iPopulation = self.map_settings_widgets['Population'].currentText() # noqa: N806 - scn_name = self.map_scenario_combo.currentText() - self.current_raw_map = ( - self.project_result.getSystemServiceabilityIndexMap( - scn_name, iPopulation=iPopulation - ) - ) - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map - ) - self.plotMap('SSI', 'Time') - elif map_type == '': - return - else: - raise # noqa: PLE0704 - - # self.annotation_map = self.current_raw_map.copy() - self.annotationRadiusChanegd() - - def setMapSettingBox(self, map_type): # noqa: N802, D102 - for i in range(self.map_settings_table.rowCount()): # noqa: B007 - self.map_settings_table.removeRow(0) - - if map_type in map_settings: - self.populateMapSettingsTable(map_settings[map_type]) - else: - pass - # raise ValueError("Unknown Map type: "+repr(map_type)) - - def populateMapSettingsTable(self, settings_content): # noqa: C901, N802, D102 - self.map_settings_widgets.clear() - vertical_header = [] - cell_type_list = [] - default_list = [] - content_list = [] - validator_list = [] - for row in settings_content: - for k in row: - if k == 'Label': - vertical_header.append(row[k]) - elif k == 'Type': - cell_type_list.append(row[k]) - elif k == 'Default': - default_list.append(row[k]) - - if 'Content' in row: - content_list.append(row['Content']) - else: - content_list.append(None) - - if 'Validator' in row: - validator_list.append(row['Validator']) - else: - validator_list.append(None) - - self.map_settings_table.setColumnCount(1) - self.map_settings_table.setRowCount(len(settings_content)) - self.map_settings_table.setVerticalHeaderLabels(vertical_header) - - i = 0 - for cell_type in cell_type_list: - if cell_type == 'Time': - self.time_combo = Time_Unit_Combo() - self.map_settings_table.setCellWidget(i, 0, self.time_combo) - self.time_combo.currentTextChanged.connect( - self.mapTimeSettingsChanged - ) - - elif cell_type == 'Yes-No_Combo': - current_widget = Yes_No_Combo() - self.map_settings_table.setCellWidget(i, 0, current_widget) - current_widget.currentTextChanged.connect(self.mapSettingChanged) - - default_value = default_list[i] - current_widget.setCurrentText(default_value) - - self.map_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Custom_Combo': - current_widget = QtWidgets.QComboBox() - contents = content_list[i] - current_widget.addItems(contents) - self.map_settings_table.setCellWidget(i, 0, current_widget) - current_widget.currentTextChanged.connect(self.mapSettingChanged) - - default_value = default_list[i] - current_widget.setCurrentText(default_value) - - self.map_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Float Line': - current_widget = QtWidgets.QLineEdit() - self.map_settings_table.setCellWidget(i, 0, current_widget) - current_widget.editingFinished.connect(self.mapSettingChanged) - if validator_list[i] == None: # noqa: E711 - current_widget.setValidator( - QtGui.QDoubleValidator( - 0, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - else: - current_widget.setValidator( - QtGui.QDoubleValidator( - validator_list[i]['Min'], - validator_list[i]['Max'], - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - - default_value = default_list[i] - current_widget.setText(default_value) - self.map_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Int Line': - current_widget = QtWidgets.QLineEdit() - self.map_settings_table.setCellWidget(i, 0, current_widget) - current_widget.editingFinished.connect(self.mapSettingChanged) - - if validator_list[i] == None: # noqa: E711 - current_widget.setValidator( - QtGui.QIntValidator(0, 3600 * 24 * 1000) - ) - else: - current_widget.setValidator( - QtGui.QIntValidator( - validator_list[i]['Min'], validator_list[i]['Max'] - ) - ) - - default_value = default_list[i] - current_widget.setText(default_value) - self.map_settings_widgets[vertical_header[i]] = current_widget - else: - raise ValueError(repr(cell_type)) - - i += 1 # noqa: SIM113 - # for label in settings_content: - - def mapTimeSettingsChanged(self, x): # noqa: ARG002, N802, D102 - self.current_map = self.time_combo.changeMapTimeUnit( - self.current_raw_map, self.map_value_columns_name - ) - self.plotMap(self.map_value_columns_name) - - def mapSettingChanged(self): # noqa: N802, D102 - if 'Population' in self.map_settings_widgets: - new_population_setting = self.map_settings_widgets[ - 'Population' - ].currentText() - if new_population_setting == 'Yes' and type( # noqa: E721 - self.project_result._population_data # noqa: SLF001 - ) == type(None): - self.errorMSG('Error', 'Population data is not loaded') - self.map_settings_widgets['Population'].setCurrentText('No') - return - self.calculateCurrentMap() - - def tabChangedMap(self, index): # noqa: N802, D102 - if index == 1: - self.initializeMap() - - def saveCurrentMapByButton(self): # noqa: N802, D102 - # if self.current_map_data == None: - if type(self.current_map) == type(None): # noqa: E721 - self.errorMSG('REWET', 'No map is ploted') - return - - file_addr = QtWidgets.QFileDialog.getSaveFileName( - self.asli_MainWindow, - 'Save File', - self.project_file_addr, - 'Shapefile (*.shp)', - ) - if file_addr[0] == '': - return - - # self.current_map_data[1].to_excel(file_addr[0]) - self.current_map.to_file(file_addr[0]) diff --git a/modules/systemPerformance/REWET/REWET/GUI/MplWidget.py b/modules/systemPerformance/REWET/REWET/GUI/MplWidget.py deleted file mode 100644 index 5d1c71e27..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/MplWidget.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Created on Thu Nov 10 18:26:02 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -# Imports -from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas -from matplotlib.backends.backend_qt5agg import ( - NavigationToolbar2QT as NavigationToolbar, -) -from matplotlib.figure import Figure -from PyQt5 import QtWidgets - - -class MplCanvas(Canvas): # noqa: D101 - def __init__(self): - self.fig = Figure(figsize=(100, 40), dpi=100, tight_layout=True) - self.ax = self.fig.add_subplot(111) - Canvas.__init__(self, self.fig) - Canvas.setSizePolicy( - self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding - ) - Canvas.updateGeometry(self) - - -# Matplotlib widget -class MplWidget(QtWidgets.QWidget): # noqa: D101 - def __init__(self, parent=None): - QtWidgets.QWidget.__init__(self, parent) # Inherit from QWidget - self.canvas = MplCanvas() # Create canvas object - toolbar = NavigationToolbar(self.canvas, self) - self.vbl = QtWidgets.QVBoxLayout() # Set box for plotting - self.vbl.addWidget(toolbar) - self.vbl.addWidget(self.canvas) - self.setLayout(self.vbl) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Discovery_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Discovery_Designer.py deleted file mode 100644 index d2679d7e7..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Discovery_Designer.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Created on Tue Nov 1 23:25:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from .Damage_Discovery_Designer import Damage_Discovery_Designer - - -class Node_Damage_Discovery_Designer(Damage_Discovery_Designer): # noqa: D101 - def __init__(self, node_damage_discovery_model): - super().__init__(node_damage_discovery_model) - self._window.setWindowTitle('Node Damage Discovery') diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Designer.py deleted file mode 100644 index 4cae2f921..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Designer.py +++ /dev/null @@ -1,271 +0,0 @@ -"""Created on Tue Nov 1 20:36:29 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from PyQt5 import QtGui, QtWidgets - -from .Node_Damage_Model_Help_Designer import Node_Damage_Model_Help_Designer -from .Node_Damage_Model_Window import Ui_Node_Damage_Model - - -class Node_Damage_Model_Designer(Ui_Node_Damage_Model): # noqa: D101 - def __init__(self, node_damage_model): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.node_damage_model = node_damage_model.copy() - - self.a_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.b_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.c_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.d_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.e_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.f_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - - self.aa_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.bb_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.cc_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.dd_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.ee1_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.ff1_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.ee2_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.ff2_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - - a = self.node_damage_model['a'] - b = self.node_damage_model['b'] - c = self.node_damage_model['c'] - d = self.node_damage_model['d'] - e = self.node_damage_model['e'] - f = self.node_damage_model['f'] - aa = self.node_damage_model['aa'] - bb = self.node_damage_model['bb'] - cc = self.node_damage_model['cc'] - dd = self.node_damage_model['dd'] - ee1 = self.node_damage_model['ee1'] - ff1 = self.node_damage_model['ff1'] - ee2 = self.node_damage_model['ee2'] - ff2 = self.node_damage_model['ff2'] - - if self.node_damage_model['damage_node_model'] == 'equal_diameter_emitter': - self.equal_emitter_button.setChecked(True) - elif ( - self.node_damage_model['damage_node_model'] == 'equal_diameter_reservoir' - ): - self.equal_reservoir_button.setChecked(True) - - self.a_line.setText(str(a)) - self.b_line.setText(str(b)) - self.c_line.setText(str(c)) - self.d_line.setText(str(d)) - self.e_line.setText(str(e)) - self.f_line.setText(str(f)) - - self.aa_line.setText(str(aa)) - self.bb_line.setText(str(bb)) - self.cc_line.setText(str(cc)) - self.dd_line.setText(str(dd)) - self.ee1_line.setText(str(ee1)) - self.ff1_line.setText(str(ff1)) - self.ee2_line.setText(str(ee2)) - self.ff2_line.setText(str(ff2)) - - self.buttonBox.accepted.connect(self.okButtonPressed) - self.help_button.clicked.connect(self.showHelpByButton) - - def showHelpByButton(self): # noqa: N802, D102 - help_dialog_box = Node_Damage_Model_Help_Designer() - help_dialog_box._window.exec_() # noqa: SLF001 - - def okButtonPressed(self): # noqa: C901, N802, D102 - a = self.a_line.text() - b = self.b_line.text() - c = self.c_line.text() - d = self.d_line.text() - e = self.e_line.text() - f = self.f_line.text() - aa = self.aa_line.text() - bb = self.bb_line.text() - cc = self.cc_line.text() - dd = self.dd_line.text() - ee1 = self.ee1_line.text() - ff1 = self.ff1_line.text() - ee2 = self.ee2_line.text() - ff2 = self.ff2_line.text() - - if_failed = False - - if a == '': - self.errorMSG('Cannot Save data', 'A Field cannot be left empty') - if_failed = True - elif aa == '': - self.errorMSG('Cannot Save data', 'AA Field cannot be left empty') - if_failed = True - elif b == '': - self.errorMSG('Cannot Save data', 'B Field cannot be left empty') - if_failed = True - elif bb == '': - self.errorMSG('Cannot Save data', 'BB Field cannot be left empty') - if_failed = True - elif c == '': - self.errorMSG('Cannot Save data', 'C Field cannot be left empty') - if_failed = True - elif cc == '': - self.errorMSG('Cannot Save data', 'CC Field cannot be left empty') - if_failed = True - elif d == '': - self.errorMSG('Cannot Save data', 'D Field cannot be left empty') - if_failed = True - elif dd == '': - self.errorMSG('Cannot Save data', 'DD Field cannot be left empty') - if_failed = True - elif e == '': - self.errorMSG('Cannot Save data', 'E Field cannot be left empty') - if_failed = True - elif ee1 == '': - self.errorMSG('Cannot Save data', 'EE1 Field cannot be left empty') - if_failed = True - elif ee2 == '': - self.errorMSG('Cannot Save data', 'EE2 Field cannot be left empty') - if_failed = True - elif f == '': - self.errorMSG('Cannot Save data', 'F Field cannot be left empty') - if_failed = True - elif ff1 == '': - self.errorMSG('Cannot Save data', 'FF1 Field cannot be left empty') - if_failed = True - elif ff2 == '': - self.errorMSG('Cannot Save data', 'FF2 Field cannot be left empty') - if_failed = True - - if if_failed: - return - - self.node_damage_model['a'] = float(a) - self.node_damage_model['b'] = float(b) - self.node_damage_model['c'] = float(c) - self.node_damage_model['d'] = float(d) - self.node_damage_model['e'] = float(e) - self.node_damage_model['f'] = float(f) - self.node_damage_model['aa'] = float(aa) - self.node_damage_model['bb'] = float(bb) - self.node_damage_model['cc'] = float(cc) - self.node_damage_model['dd'] = float(dd) - self.node_damage_model['ee1'] = float(ee1) - self.node_damage_model['ff1'] = float(ff1) - self.node_damage_model['ee2'] = float(ee2) - self.node_damage_model['ff2'] = float(ff2) - - if self.equal_emitter_button.isChecked(): - self.node_damage_model['damage_node_model'] = 'equal_diameter_emitter' - elif self.equal_reservoir_button.isChecked(): - self.node_damage_model['damage_node_model'] = 'equal_diameter_reservoir' - - self._window.accept() - - def errorMSG(self, error_title, error_msg, error_more_msg=None): # noqa: N802, D102 - error_widget = QtWidgets.QMessageBox() - error_widget.setIcon(QtWidgets.QMessageBox.Critical) - error_widget.setText(error_msg) - error_widget.setWindowTitle(error_title) - error_widget.setStandardButtons(QtWidgets.QMessageBox.Ok) - if error_more_msg != None: # noqa: E711 - error_widget.setInformativeText(error_more_msg) - error_widget.exec_() diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Designer.py deleted file mode 100644 index f50f8c3aa..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Designer.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Created on Tue Nov 1 21:35:02 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from PyQt5 import QtWidgets - -from .Node_Damage_Model_Help_Window import Ui_Node_Damage_Model_Help - - -class Node_Damage_Model_Help_Designer(Ui_Node_Damage_Model_Help): # noqa: D101 - def __init__(self): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.buttonBox.rejected.connect(self._window.close) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.py deleted file mode 100644 index 399534c4f..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.py +++ /dev/null @@ -1,70 +0,0 @@ -# Form implementation generated from reading ui file 'Node_Damage_Model_Help_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Node_Damage_Model_Help: # noqa: D101 - def setupUi(self, Node_Damage_Model_Help): # noqa: N802, N803, D102 - Node_Damage_Model_Help.setObjectName('Node_Damage_Model_Help') - Node_Damage_Model_Help.resize(340, 130) - Node_Damage_Model_Help.setMinimumSize(QtCore.QSize(340, 130)) - Node_Damage_Model_Help.setMaximumSize(QtCore.QSize(340, 130)) - self.layoutWidget = QtWidgets.QWidget(Node_Damage_Model_Help) - self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 291, 101)) - self.layoutWidget.setObjectName('layoutWidget') - self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget) - self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_2.setObjectName('verticalLayout_2') - self.label = QtWidgets.QLabel(self.layoutWidget) - self.label.setObjectName('label') - self.verticalLayout_2.addWidget(self.label) - self.label_2 = QtWidgets.QLabel(self.layoutWidget) - self.label_2.setObjectName('label_2') - self.verticalLayout_2.addWidget(self.label_2) - self.label_3 = QtWidgets.QLabel(self.layoutWidget) - self.label_3.setObjectName('label_3') - self.verticalLayout_2.addWidget(self.label_3) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName('horizontalLayout_2') - spacerItem = QtWidgets.QSpacerItem( # noqa: N806 - 40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum - ) - self.horizontalLayout_2.addItem(spacerItem) - self.buttonBox = QtWidgets.QDialogButtonBox(self.layoutWidget) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close) - self.buttonBox.setObjectName('buttonBox') - self.horizontalLayout_2.addWidget(self.buttonBox) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - - self.retranslateUi(Node_Damage_Model_Help) - QtCore.QMetaObject.connectSlotsByName(Node_Damage_Model_Help) - - def retranslateUi(self, Node_Damage_Model_Help): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Node_Damage_Model_Help.setWindowTitle( - _translate('Node_Damage_Model_Help', 'Help') - ) - self.label.setText( - _translate('Node_Damage_Model_Help', 'ND = Number of Nodal damage') - ) - self.label_2.setText( - _translate('Node_Damage_Model_Help', 'MP = Pressure at the node') - ) - self.label_3.setText(_translate('Node_Damage_Model_Help', 'RR =Repair Rate')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Node_Damage_Model_Help = QtWidgets.QDialog() - ui = Ui_Node_Damage_Model_Help() - ui.setupUi(Node_Damage_Model_Help) - Node_Damage_Model_Help.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.ui deleted file mode 100644 index afc97fbb3..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Help_Window.ui +++ /dev/null @@ -1,91 +0,0 @@ - - - Node_Damage_Model_Help - - - - 0 - 0 - 340 - 130 - - - - - 340 - 130 - - - - - 340 - 130 - - - - Help - - - - - 20 - 20 - 291 - 101 - - - - - - - ND = Number of Nodal damage - - - - - - - MP = Pressure at the node - - - - - - - RR =Repair Rate - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - QDialogButtonBox::Close - - - - - - - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.py deleted file mode 100644 index d1523836d..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.py +++ /dev/null @@ -1,225 +0,0 @@ -# Form implementation generated from reading ui file 'Node_Damage_Model_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Node_Damage_Model: # noqa: D101 - def setupUi(self, Node_Damage_Model): # noqa: N802, N803, D102, PLR0915 - Node_Damage_Model.setObjectName('Node_Damage_Model') - Node_Damage_Model.resize(396, 296) - palette = QtGui.QPalette() - brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) - brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush) - brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) - brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush) - brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) - brush = QtGui.QBrush(QtGui.QColor(240, 240, 240)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush) - Node_Damage_Model.setPalette(palette) - self.buttonBox = QtWidgets.QDialogButtonBox(Node_Damage_Model) - self.buttonBox.setGeometry(QtCore.QRect(300, 230, 81, 51)) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.groupBox = QtWidgets.QGroupBox(Node_Damage_Model) - self.groupBox.setGeometry(QtCore.QRect(20, 230, 261, 51)) - self.groupBox.setObjectName('groupBox') - self.equal_emitter_button = QtWidgets.QRadioButton(self.groupBox) - self.equal_emitter_button.setGeometry(QtCore.QRect(20, 20, 91, 17)) - self.equal_emitter_button.setChecked(True) - self.equal_emitter_button.setObjectName('equal_emitter_button') - self.equal_reservoir_button = QtWidgets.QRadioButton(self.groupBox) - self.equal_reservoir_button.setGeometry(QtCore.QRect(120, 20, 131, 17)) - self.equal_reservoir_button.setObjectName('equal_reservoir_button') - self.a_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.a_line.setGeometry(QtCore.QRect(40, 80, 41, 20)) - self.a_line.setObjectName('a_line') - self.label = QtWidgets.QLabel(Node_Damage_Model) - self.label.setGeometry(QtCore.QRect(20, 80, 21, 16)) - self.label.setObjectName('label') - self.label_2 = QtWidgets.QLabel(Node_Damage_Model) - self.label_2.setGeometry(QtCore.QRect(20, 100, 21, 16)) - self.label_2.setObjectName('label_2') - self.label_3 = QtWidgets.QLabel(Node_Damage_Model) - self.label_3.setGeometry(QtCore.QRect(20, 120, 21, 16)) - self.label_3.setObjectName('label_3') - self.label_4 = QtWidgets.QLabel(Node_Damage_Model) - self.label_4.setGeometry(QtCore.QRect(20, 140, 21, 16)) - self.label_4.setObjectName('label_4') - self.label_5 = QtWidgets.QLabel(Node_Damage_Model) - self.label_5.setGeometry(QtCore.QRect(20, 160, 21, 16)) - self.label_5.setObjectName('label_5') - self.label_6 = QtWidgets.QLabel(Node_Damage_Model) - self.label_6.setGeometry(QtCore.QRect(20, 180, 21, 16)) - self.label_6.setObjectName('label_6') - self.b_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.b_line.setGeometry(QtCore.QRect(40, 100, 41, 20)) - self.b_line.setObjectName('b_line') - self.c_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.c_line.setGeometry(QtCore.QRect(40, 120, 41, 20)) - self.c_line.setObjectName('c_line') - self.d_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.d_line.setGeometry(QtCore.QRect(40, 140, 41, 20)) - self.d_line.setObjectName('d_line') - self.e_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.e_line.setGeometry(QtCore.QRect(40, 160, 41, 20)) - self.e_line.setObjectName('e_line') - self.f_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.f_line.setGeometry(QtCore.QRect(40, 180, 41, 20)) - self.f_line.setObjectName('f_line') - self.label_10 = QtWidgets.QLabel(Node_Damage_Model) - self.label_10.setGeometry(QtCore.QRect(170, 80, 71, 20)) - self.label_10.setText('') - self.label_10.setPixmap(QtGui.QPixmap(':/resources/resources/node_A.png')) - self.label_10.setObjectName('label_10') - self.label_11 = QtWidgets.QLabel(Node_Damage_Model) - self.label_11.setGeometry(QtCore.QRect(170, 100, 71, 20)) - self.label_11.setText('') - self.label_11.setPixmap(QtGui.QPixmap(':/resources/resources/node_B.png')) - self.label_11.setObjectName('label_11') - self.label_12 = QtWidgets.QLabel(Node_Damage_Model) - self.label_12.setGeometry(QtCore.QRect(170, 120, 71, 20)) - self.label_12.setText('') - self.label_12.setPixmap(QtGui.QPixmap(':/resources/resources/node_C.png')) - self.label_12.setObjectName('label_12') - self.label_13 = QtWidgets.QLabel(Node_Damage_Model) - self.label_13.setGeometry(QtCore.QRect(170, 140, 71, 20)) - self.label_13.setText('') - self.label_13.setPixmap(QtGui.QPixmap(':/resources/resources/node_D.png')) - self.label_13.setObjectName('label_13') - self.label_14 = QtWidgets.QLabel(Node_Damage_Model) - self.label_14.setGeometry(QtCore.QRect(170, 160, 131, 20)) - self.label_14.setText('') - self.label_14.setPixmap(QtGui.QPixmap(':/resources/resources/node_E.png')) - self.label_14.setObjectName('label_14') - self.label_15 = QtWidgets.QLabel(Node_Damage_Model) - self.label_15.setGeometry(QtCore.QRect(170, 180, 131, 20)) - self.label_15.setText('') - self.label_15.setPixmap(QtGui.QPixmap(':/resources/resources/node_F.png')) - self.label_15.setObjectName('label_15') - self.label_16 = QtWidgets.QLabel(Node_Damage_Model) - self.label_16.setGeometry(QtCore.QRect(90, 180, 21, 16)) - self.label_16.setObjectName('label_16') - self.aa_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.aa_line.setGeometry(QtCore.QRect(120, 80, 41, 20)) - self.aa_line.setObjectName('aa_line') - self.label_17 = QtWidgets.QLabel(Node_Damage_Model) - self.label_17.setGeometry(QtCore.QRect(90, 120, 21, 16)) - self.label_17.setObjectName('label_17') - self.ff1_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.ff1_line.setGeometry(QtCore.QRect(120, 180, 41, 20)) - self.ff1_line.setObjectName('ff1_line') - self.cc_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.cc_line.setGeometry(QtCore.QRect(120, 120, 41, 20)) - self.cc_line.setObjectName('cc_line') - self.label_18 = QtWidgets.QLabel(Node_Damage_Model) - self.label_18.setGeometry(QtCore.QRect(90, 80, 21, 16)) - self.label_18.setObjectName('label_18') - self.label_19 = QtWidgets.QLabel(Node_Damage_Model) - self.label_19.setGeometry(QtCore.QRect(90, 100, 21, 16)) - self.label_19.setObjectName('label_19') - self.bb_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.bb_line.setGeometry(QtCore.QRect(120, 100, 41, 20)) - self.bb_line.setObjectName('bb_line') - self.ee1_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.ee1_line.setGeometry(QtCore.QRect(120, 160, 41, 20)) - self.ee1_line.setObjectName('ee1_line') - self.dd_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.dd_line.setGeometry(QtCore.QRect(120, 140, 41, 20)) - self.dd_line.setObjectName('dd_line') - self.label_20 = QtWidgets.QLabel(Node_Damage_Model) - self.label_20.setGeometry(QtCore.QRect(90, 160, 21, 16)) - self.label_20.setObjectName('label_20') - self.label_21 = QtWidgets.QLabel(Node_Damage_Model) - self.label_21.setGeometry(QtCore.QRect(90, 140, 21, 16)) - self.label_21.setObjectName('label_21') - self.ff2_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.ff2_line.setGeometry(QtCore.QRect(340, 180, 41, 20)) - self.ff2_line.setObjectName('ff2_line') - self.ee2_line = QtWidgets.QLineEdit(Node_Damage_Model) - self.ee2_line.setGeometry(QtCore.QRect(340, 160, 41, 20)) - self.ee2_line.setObjectName('ee2_line') - self.label_22 = QtWidgets.QLabel(Node_Damage_Model) - self.label_22.setGeometry(QtCore.QRect(310, 180, 21, 16)) - self.label_22.setObjectName('label_22') - self.label_23 = QtWidgets.QLabel(Node_Damage_Model) - self.label_23.setGeometry(QtCore.QRect(310, 160, 21, 16)) - self.label_23.setObjectName('label_23') - self.first_formula = QtWidgets.QLabel(Node_Damage_Model) - self.first_formula.setGeometry(QtCore.QRect(20, 20, 361, 20)) - self.first_formula.setText('') - self.first_formula.setPixmap( - QtGui.QPixmap(':/resources/resources/first_damage.png') - ) - self.first_formula.setObjectName('first_formula') - self.second_formula = QtWidgets.QLabel(Node_Damage_Model) - self.second_formula.setGeometry(QtCore.QRect(90, 40, 291, 20)) - self.second_formula.setText('') - self.second_formula.setPixmap( - QtGui.QPixmap(':/resources/resources/second_damage.png') - ) - self.second_formula.setObjectName('second_formula') - self.help_button = QtWidgets.QPushButton(Node_Damage_Model) - self.help_button.setGeometry(QtCore.QRect(310, 100, 75, 23)) - self.help_button.setObjectName('help_button') - - self.retranslateUi(Node_Damage_Model) - self.buttonBox.rejected.connect(Node_Damage_Model.reject) - QtCore.QMetaObject.connectSlotsByName(Node_Damage_Model) - - def retranslateUi(self, Node_Damage_Model): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Node_Damage_Model.setWindowTitle( - _translate('Node_Damage_Model', 'Node Damage Model') - ) - self.groupBox.setTitle(_translate('Node_Damage_Model', 'Node Damage Type')) - self.equal_emitter_button.setText( - _translate('Node_Damage_Model', 'Equal Emitter') - ) - self.equal_reservoir_button.setText( - _translate('Node_Damage_Model', 'Equal Pipe & Reservoir') - ) - self.label.setText(_translate('Node_Damage_Model', 'A')) - self.label_2.setText(_translate('Node_Damage_Model', 'B')) - self.label_3.setText(_translate('Node_Damage_Model', 'C')) - self.label_4.setText(_translate('Node_Damage_Model', 'D')) - self.label_5.setText(_translate('Node_Damage_Model', 'E')) - self.label_6.setText(_translate('Node_Damage_Model', 'F')) - self.label_16.setText(_translate('Node_Damage_Model', 'FF1')) - self.label_17.setText(_translate('Node_Damage_Model', 'CC')) - self.label_18.setText(_translate('Node_Damage_Model', 'AA')) - self.label_19.setText(_translate('Node_Damage_Model', 'BB')) - self.label_20.setText(_translate('Node_Damage_Model', 'EE1')) - self.label_21.setText(_translate('Node_Damage_Model', 'DD')) - self.label_22.setText(_translate('Node_Damage_Model', 'FF2')) - self.label_23.setText(_translate('Node_Damage_Model', 'EE2')) - self.help_button.setText(_translate('Node_Damage_Model', 'Help')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Node_Damage_Model = QtWidgets.QDialog() - ui = Ui_Node_Damage_Model() - ui.setupUi(Node_Damage_Model) - Node_Damage_Model.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.ui deleted file mode 100644 index 76ad54070..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Node_Damage_Model_Window.ui +++ /dev/null @@ -1,624 +0,0 @@ - - - Node_Damage_Model - - - - 0 - 0 - 396 - 296 - - - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - - - 240 - 240 - 240 - - - - - - - 240 - 240 - 240 - - - - - - - - Node Damage Model - - - - - 300 - 230 - 81 - 51 - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 20 - 230 - 261 - 51 - - - - Node Damage Type - - - - - 20 - 20 - 91 - 17 - - - - Equal Emitter - - - true - - - - - - 120 - 20 - 131 - 17 - - - - Equal Pipe & Reservoir - - - - - - - 40 - 80 - 41 - 20 - - - - - - - 20 - 80 - 21 - 16 - - - - A - - - - - - 20 - 100 - 21 - 16 - - - - B - - - - - - 20 - 120 - 21 - 16 - - - - C - - - - - - 20 - 140 - 21 - 16 - - - - D - - - - - - 20 - 160 - 21 - 16 - - - - E - - - - - - 20 - 180 - 21 - 16 - - - - F - - - - - - 40 - 100 - 41 - 20 - - - - - - - 40 - 120 - 41 - 20 - - - - - - - 40 - 140 - 41 - 20 - - - - - - - 40 - 160 - 41 - 20 - - - - - - - 40 - 180 - 41 - 20 - - - - - - - 170 - 80 - 71 - 20 - - - - - - - :/resources/resources/node_A.png - - - - - - 170 - 100 - 71 - 20 - - - - - - - :/resources/resources/node_B.png - - - - - - 170 - 120 - 71 - 20 - - - - - - - :/resources/resources/node_C.png - - - - - - 170 - 140 - 71 - 20 - - - - - - - :/resources/resources/node_D.png - - - - - - 170 - 160 - 131 - 20 - - - - - - - :/resources/resources/node_E.png - - - - - - 170 - 180 - 131 - 20 - - - - - - - :/resources/resources/node_F.png - - - - - - 90 - 180 - 21 - 16 - - - - FF1 - - - - - - 120 - 80 - 41 - 20 - - - - - - - 90 - 120 - 21 - 16 - - - - CC - - - - - - 120 - 180 - 41 - 20 - - - - - - - 120 - 120 - 41 - 20 - - - - - - - 90 - 80 - 21 - 16 - - - - AA - - - - - - 90 - 100 - 21 - 16 - - - - BB - - - - - - 120 - 100 - 41 - 20 - - - - - - - 120 - 160 - 41 - 20 - - - - - - - 120 - 140 - 41 - 20 - - - - - - - 90 - 160 - 21 - 16 - - - - EE1 - - - - - - 90 - 140 - 21 - 16 - - - - DD - - - - - - 340 - 180 - 41 - 20 - - - - - - - 340 - 160 - 41 - 20 - - - - - - - 310 - 180 - 21 - 16 - - - - FF2 - - - - - - 310 - 160 - 21 - 16 - - - - EE2 - - - - - - 20 - 20 - 361 - 20 - - - - - - - :/resources/resources/first_damage.png - - - - - - 90 - 40 - 291 - 20 - - - - - - - :/resources/resources/second_damage.png - - - - - - 310 - 100 - 75 - 23 - - - - Help - - - - - - - - - - buttonBox - rejected() - Node_Damage_Model - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Opening.ui b/modules/systemPerformance/REWET/REWET/GUI/Opening.ui deleted file mode 100644 index 6033d7993..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Opening.ui +++ /dev/null @@ -1,2580 +0,0 @@ - - - Opening_Window - - - - 0 - 0 - 830 - 780 - - - - REWET - - - - - - 0 - 0 - 801 - 741 - - - - 0 - - - - Process - - - - - 0 - 0 - 811 - 681 - - - - - 9 - 50 - false - - - - QTabWidget::West - - - QTabWidget::Triangular - - - 4 - - - - 16 - 16 - - - - - - 8 - 50 - false - - - - Simulation - - - - - 50 - 220 - 711 - 101 - - - - Temp File Settings - - - - - 20 - 70 - 101 - 16 - - - - - 8 - 75 - true - - - - Save time step - - - - - - 120 - 70 - 41 - 17 - - - - Yes - - - false - - - - - - 250 - 60 - 301 - 31 - - - - - - - - - 170 - 85 - 0 - - - - - - - 170 - 85 - 0 - - - - - - - 170 - 85 - 0 - - - - - - - - - 170 - 85 - 0 - - - - - - - 170 - 85 - 0 - - - - - - - 170 - 85 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 0 - 0 - 0 - - - - - - - - WARNING: Producing INP files for each event time can produce too many files - - - true - - - - - - 190 - 70 - 41 - 17 - - - - No - - - true - - - - - - 20 - 32 - 91 - 16 - - - - - 8 - 75 - true - - - - Temp Folder - - - - - - 120 - 30 - 331 - 20 - - - - true - - - - - - 460 - 28 - 75 - 23 - - - - Browse - - - - - - - 50 - 40 - 711 - 171 - - - - Settings - - - - - 150 - 20 - 81 - 20 - - - - 36000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 20 - 22 - 101 - 16 - - - - - 8 - 75 - true - - - - Simulation time - - - - - - 20 - 100 - 101 - 16 - - - - - 8 - 75 - true - - - - Run Type - - - - - - 190 - 100 - 101 - 17 - - - - Multiple Serial - - - - - - 120 - 100 - 51 - 17 - - - - Single - - - true - - - - - - 20 - 52 - 121 - 16 - - - - - 8 - 75 - true - - - - Simulation time step - - - - - - 150 - 50 - 81 - 20 - - - - 3600 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 240 - 20 - 61 - 16 - - - - - 8 - 50 - false - - - - seconds - - - Qt::PlainText - - - - - - 240 - 50 - 61 - 16 - - - - - 8 - 50 - false - - - - seconds - - - Qt::PlainText - - - - - - 120 - 130 - 331 - 20 - - - - true - - - - - - 460 - 130 - 75 - 23 - - - - Browse - - - - - - 20 - 130 - 91 - 16 - - - - - 8 - 75 - true - - - - Result Folder - - - - - - - Hydraulics - - - - - 10 - 210 - 761 - 241 - - - - Solver Options - - - - - 20 - 50 - 47 - 13 - - - - - 8 - 75 - true - - - - Solver: - - - Qt::PlainText - - - - - false - - - - 240 - 50 - 82 - 17 - - - - WNTR - - - - - true - - - - 80 - 50 - 151 - 17 - - - - Modified EPANET V2.2 - - - true - - - - - - 80 - 90 - 61 - 20 - - - - 8 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 80 - 130 - 61 - 20 - - - - 25 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 20 - 90 - 47 - 13 - - - - - 8 - 75 - true - - - - P(min): - - - Qt::PlainText - - - - - - 150 - 90 - 61 - 16 - - - - - 8 - 50 - false - - - - h (water) - - - Qt::PlainText - - - - - - 150 - 130 - 61 - 16 - - - - - 8 - 50 - false - - - - h (water) - - - Qt::PlainText - - - - - - 20 - 130 - 47 - 13 - - - - - 8 - 75 - true - - - - P(req): - - - Qt::PlainText - - - - - - 10 - 145 - 61 - 41 - - - - - 8 - 75 - true - - - - Hydraulic time step - - - true - - - - - - 80 - 160 - 61 - 20 - - - - 3600 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 150 - 160 - 61 - 16 - - - - - 8 - 50 - false - - - - seconds - - - Qt::PlainText - - - - - - - 10 - 30 - 761 - 171 - - - - Water Distribution Network - - - - - 130 - 30 - 481 - 20 - - - - true - - - - - - 630 - 30 - 75 - 23 - - - - Browse - - - - - - 10 - 30 - 101 - 16 - - - - - 9 - 75 - true - - - - System INP File - - - - - - 130 - 70 - 41 - 21 - - - - 1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 10 - 70 - 111 - 16 - - - - - 9 - 75 - true - - - - Calibrate Demand - - - - - - 180 - 70 - 91 - 21 - - - - QFrame::Box - - - QFrame::Raised - - - 0<Ratio=<1 - - - 0 - - - - - - - Damage - - - - - 80 - 100 - 691 - 192 - - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - 60 - - - 110 - - - - Name - - - - - Pipe - - - - - Node - - - - - Pump - - - - - Tank - - - - - Probability - - - - - - - 80 - 70 - 111 - 16 - - - - - 9 - 75 - true - - - - Damage Scenario - - - - - - 20 - 100 - 51 - 23 - - - - Add - - - - - true - - - - 0 - 550 - 791 - 121 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - - 20 - 130 - 51 - 23 - - - - Remove - - - - - - 80 - 310 - 481 - 80 - - - - File Headers Correction - - - - false - - - - 30 - 30 - 91 - 23 - - - - Pipe - - - - - false - - - - 140 - 30 - 91 - 23 - - - - Node - - - - - false - - - - 360 - 30 - 91 - 23 - - - - Tanks - - - - - false - - - - 250 - 30 - 91 - 23 - - - - Pump - - - - - - - 80 - 420 - 691 - 80 - - - - Damage Modeling - - - - - 30 - 40 - 101 - 23 - - - - Pipe - - - - - - 150 - 40 - 101 - 23 - - - - Nodal - - - - - - - 200 - 50 - 141 - 16 - - - - - 9 - 75 - true - - - - Damage File Directory - - - - - - 580 - 70 - 75 - 23 - - - - Browse - - - - - - 200 - 70 - 371 - 20 - - - - true - - - - - - 20 - 230 - 51 - 23 - - - - Load - - - - - - 20 - 260 - 51 - 23 - - - - Save - - - - - - 570 - 350 - 171 - 41 - - - - Validate Damage Scenarios - - - - - - 560 - 300 - 171 - 51 - - - - File Type - - - - - 10 - 20 - 82 - 17 - - - - Excel - - - true - - - - - - 90 - 20 - 82 - 17 - - - - Pickle - - - - - - - Restoration - - - - - 30 - 40 - 191 - 80 - - - - On/Off - - - - - 20 - 40 - 61 - 17 - - - - On - - - true - - - - - - 90 - 40 - 82 - 17 - - - - Off - - - - - - - 30 - 120 - 731 - 231 - - - - Restoration Definition - - - - - 460 - 100 - 91 - 23 - - - - Browse - - - - - - 290 - 60 - 111 - 17 - - - - Policy File (*.rrp) - - - - - - 180 - 60 - 101 - 17 - - - - Script (*.txt) - - - true - - - - - - 30 - 100 - 131 - 16 - - - - - 9 - 75 - true - - - - Policy Definition File - - - - - - 170 - 100 - 281 - 20 - - - - - - - true - - - - - - 460 - 60 - 91 - 23 - - - - Policy Designer - - - - - - 30 - 180 - 131 - 16 - - - - - 9 - 75 - true - - - - Minimum Job Time - - - - - - 170 - 180 - 51 - 20 - - - - 3600 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - false - - - - 30 - 140 - 131 - 16 - - - - - 9 - 75 - true - - - - Crew Availability - - - - - false - - - - 460 - 140 - 91 - 23 - - - - Browse - - - - - false - - - - 170 - 140 - 281 - 20 - - - - - - - - - - 230 - 180 - 61 - 16 - - - - - 8 - 50 - false - - - - seconds - - - Qt::PlainText - - - - - - 30 - 60 - 131 - 16 - - - - - 9 - 75 - true - - - - File Type - - - - - - - 30 - 370 - 721 - 91 - - - - Damage Discovery - - - - - 30 - 40 - 75 - 23 - - - - Pipe - - - - - - 120 - 40 - 75 - 23 - - - - Node - - - - - - 210 - 40 - 75 - 23 - - - - Pump - - - - - - 290 - 40 - 75 - 23 - - - - Tank - - - - - - - 30 - 470 - 211 - 51 - - - - Crew out-of-zone Travel - - - - - 10 - 20 - 82 - 17 - - - - Allowed - - - - - - 90 - 20 - 101 - 17 - - - - Not Allowed - - - true - - - - - - - Run - - - - - 50 - 50 - 181 - 31 - - - - - 12 - 50 - false - - - - RUN - - - - - - 50 - 520 - 181 - 31 - - - - - 12 - 50 - false - - - - Stop - - - - - - 50 - 110 - 651 - 391 - - - - true - - - - - - 50 - 80 - 51 - 31 - - - - - 11 - 50 - false - - - - Log - - - - - - - - Post-Process - - - - - 0 - 0 - 801 - 721 - - - - - 9 - - - - QTabWidget::West - - - QTabWidget::Triangular - - - 2 - - - - Data - - - - true - - - - 130 - 70 - 331 - 421 - - - - QAbstractItemView::NoSelection - - - 200 - - - false - - - - Scenario Name - - - - - Status - - - - - - - 130 - 30 - 91 - 23 - - - - Load - - - - - - 30 - 30 - 101 - 16 - - - - - 8 - 75 - true - - - - Load Result Files - - - - - - 250 - 30 - 121 - 17 - - - - Read Files - - - true - - - - - - 470 - 550 - 91 - 23 - - - - Browse - - - - - - 130 - 530 - 141 - 16 - - - - - 8 - 75 - true - - - - Population Data - - - - - - 130 - 550 - 331 - 20 - - - - true - - - - - - 130 - 600 - 111 - 22 - - - - - - - 250 - 600 - 111 - 22 - - - - - - - 470 - 600 - 91 - 23 - - - - Load - - - - - - 130 - 580 - 101 - 16 - - - - - 8 - 50 - false - - - - Node ID Header - - - - - - 250 - 580 - 101 - 16 - - - - - 8 - 50 - false - - - - Population Header - - - - - - Curve - - - - - 30 - 80 - 351 - 22 - - - - - Quantity Exceedance - - - - - Delivery Exceedance - - - - - - - 190 - 30 - 121 - 17 - - - - All Scenarios - - - false - - - - - - 30 - 412 - 47 - 21 - - - - Settings - - - - - - 380 - 440 - 91 - 23 - - - - Browse - - - - - - 30 - 440 - 231 - 271 - - - - QAbstractItemView::NoSelection - - - QAbstractItemView::SelectItems - - - true - - - - Percentage - - - - - Leak Ratio - - - - - Time Unit - - - - - Time Shift - - - - - Values - - - - - - - - - - - - - - - - - - - - - - 30 - 30 - 141 - 22 - - - - - - - 30 - 110 - 531 - 291 - - - - - - - 30 - 10 - 81 - 16 - - - - Scenario - - - - - - 30 - 55 - 81 - 21 - - - - Curve Type - - - - - - 380 - 420 - 101 - 21 - - - - Save Curve Data - - - - - - Map - - - - - 20 - 110 - 560 - 560 - - - - - - - 20 - 25 - 81 - 21 - - - - Curve Type - - - - - - 20 - 50 - 351 - 22 - - - - - - - 590 - 110 - 181 - 201 - - - - QAbstractItemView::NoSelection - - - QAbstractItemView::SelectItems - - - true - - - - Percentage - - - - - Leak Ratio - - - - - Time Unit - - - - - Time Shift - - - - - Values - - - - - - - - - - - - - - - - - - - - - - 590 - 80 - 47 - 21 - - - - Settings - - - - - - 20 - 90 - 81 - 21 - - - - Map - - - - - - 600 - 680 - 131 - 23 - - - - Browse - - - - - - 600 - 660 - 131 - 21 - - - - Save Map Shape File - - - Qt::AlignCenter - - - - - - 400 - 30 - 81 - 16 - - - - Scenario - - - - - - 400 - 10 - 121 - 17 - - - - All Scenarios - - - false - - - - - - 400 - 50 - 181 - 22 - - - - - - - 590 - 330 - 171 - 131 - - - - Annotation - - - - - 10 - 20 - 91 - 31 - - - - On - - - - - false - - - - 10 - 50 - 141 - 22 - - - - - Mouse hover - - - - - Mouse click - - - - - - - 10 - 80 - 81 - 21 - - - - Radius - - - - - false - - - - 10 - 100 - 113 - 20 - - - - 0 - - - - - - - 590 - 470 - 171 - 51 - - - - Substitute Layer - - - - - 20 - 20 - 121 - 21 - - - - Setup - - - - - - - 590 - 540 - 171 - 111 - - - - Map Appearance - - - - - 20 - 20 - 121 - 31 - - - - Symbology - - - - - - 110 - 60 - 31 - 20 - - - - 10 - - - - - - 20 - 60 - 81 - 21 - - - - Grid Font Size - - - Qt::AlignCenter - - - - - - - - - - - - 0 - 0 - 830 - 21 - - - - - File - - - - - - - - - - - Help - - - - - - - - - - - Open Project - - - - - Save - - - - - Save Project As - - - - - Exit - - - - - About - - - - - REWET GITHUB - - - - - - MplWidget - QWidget -
MplWidget
- 1 -
-
- - -
diff --git a/modules/systemPerformance/REWET/REWET/GUI/Opening_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Opening_Designer.py deleted file mode 100644 index 6e80ebe39..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Opening_Designer.py +++ /dev/null @@ -1,211 +0,0 @@ -"""Created on Thu Oct 27 18:06:01 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os -import pickle -import sys - -from Input.Settings import Settings -from Project import Project -from PyQt5 import QtWidgets -from PyQt5.Qt import QDesktopServices, QUrl - -from .Damage_Tab_Designer import Damage_Tab_Designer -from .Hydraulic_Tab_Designer import Hydraulic_Tab_Designer -from .Main_Help_Designer import Main_Help_Designer -from .Map_Designer import Map_Designer -from .Opening_Window import Ui_Opening_Window -from .PP_Data_Tab_Designer import PP_Data_Tab -from .Restoration_Tab_Designer import Restoration_Tab_Designer -from .Result_Designer import Result_Designer -from .Run_Tab_Designer import Run_Tab_Designer -from .Simulation_Tab_Designer import Simulation_Tab_Designer - - -class Opening_Designer( # noqa: D101 - Ui_Opening_Window, - Simulation_Tab_Designer, - Hydraulic_Tab_Designer, - Damage_Tab_Designer, - Run_Tab_Designer, - Restoration_Tab_Designer, - PP_Data_Tab, - Result_Designer, - Map_Designer, -): - def __init__(self): - self.project = None - self.scenario_list = None - self.settings = Settings() - self.settings.initializeScenarioSettings(None) - self.current_project_directory = os.getcwd() # noqa: PTH109 - self.project_file_addr = None - - self.asli_app = QtWidgets.QApplication([]) - self.asli_MainWindow = QtWidgets.QMainWindow() - - self.setupUi(self.asli_MainWindow) - - Simulation_Tab_Designer.__init__(self) - Hydraulic_Tab_Designer.__init__(self) - Damage_Tab_Designer.__init__(self) - Restoration_Tab_Designer.__init__(self) - Run_Tab_Designer.__init__(self) - PP_Data_Tab.__init__(self, self.project) - Result_Designer.__init__(self) - Map_Designer.__init__(self) - - """ - Action Triggers. - """ - self.action_Open_Project.triggered.connect(self.openProject) - self.action_Save.triggered.connect(self.saveProject) - self.action_Save_Project_As.triggered.connect(self.saveProjectAs) - self.action_REWET_GITHUB.triggered.connect( - lambda: QDesktopServices.openUrl( - QUrl('https://github.com/snaeimi/REWET') - ) - ) - self.action_About.triggered.connect(self.showHelpWindow) - self.action_Exit.triggered.connect(self.asli_MainWindow.close) - - """ - Native signal overwrite - """ - self.asli_MainWindow.closeEvent = self.exitApp - - def run(self): # noqa: D102 - self.asli_MainWindow.show() - sys.exit(self.asli_app.exec_()) - - def errorMSG(self, error_title, error_msg, error_more_msg=None): # noqa: N802, D102 - error_widget = QtWidgets.QMessageBox() - error_widget.setIcon(QtWidgets.QMessageBox.Critical) - error_widget.setText(error_msg) - error_widget.setWindowTitle(error_title) - error_widget.setStandardButtons(QtWidgets.QMessageBox.Ok) - if error_more_msg != None: # noqa: E711 - error_widget.setInformativeText(error_more_msg) - error_widget.exec_() - - def questionPrompt(self, title, msg, more_msg=None): # noqa: N802, D102 - prompt_widget = QtWidgets.QMessageBox() - prompt_widget.setIcon(QtWidgets.QMessageBox.Question) - prompt_widget.setText(msg) - prompt_widget.setWindowTitle(title) - prompt_widget.setStandardButtons( - QtWidgets.QMessageBox.Yes - | QtWidgets.QMessageBox.No - | QtWidgets.QMessageBox.Cancel - ) - if more_msg != None: # noqa: E711 - prompt_widget.setInformativeText(more_msg) - return prompt_widget.exec_() - - def openProject(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getOpenFileName( - self.asli_MainWindow, - 'Select project file', - self.current_project_directory, - 'REWET Project File (*.prj)', - ) - if file[0] == '': - return - split_addr = os.path.split(file[0]) - self.current_project_directory = split_addr - - self.project_file_addr = file[0] - with open(file[0], 'rb') as f: # noqa: PTH123 - project = pickle.load(f) # noqa: S301 - self.project = project - # sina put a possible check of result version here - self.setSimulationSettings(project.project_settings) - self.setHydraulicSettings(project.project_settings) - self.setDamageSettings(project.project_settings, project.scenario_list) - self.setRestorationSettings(project.project_settings) - self.setSimulationUI() - self.setHydraulicUI() - self.setDamageUI() - self.setRestorationUI() - - def saveProject(self, save_as=False): # noqa: FBT002, N802, D102 - data_retrived = False - if self.getSimulationSettings(): - if self.getHydraulicSettings(): - if self.getDamageSettings(): - if self.getRestorationSettings(): - data_retrived = True - - if data_retrived == False: # noqa: E712 - return False - - if save_as == False: # noqa: E712 - if self.project_file_addr == None: # noqa: E711 - file_addr = QtWidgets.QFileDialog.getSaveFileName( - self.asli_MainWindow, - 'Save project file', - self.project_file_addr, - 'Project file (*.prj)', - ) - if file_addr[0] == '': - return False - split_addr = os.path.split(file_addr[0]) - self.current_project_directory = split_addr[0] - self.project_file_addr = file_addr[0] - - project = Project(self.settings, self.scenario_list) - self.project = project - with open(self.project_file_addr, 'wb') as f: # noqa: PTH123 - pickle.dump(project, f) - - return True - - def saveProjectAs(self): # noqa: N802, D102 - if_saved = self.saveProject(save_as=True) - if if_saved == False: # noqa: E712 - return - - file_addr = QtWidgets.QFileDialog.getSaveFileName( - self.asli_MainWindow, - 'Save project file', - self.project_file_addr, - 'Project file (*.prj)', - ) - if file_addr[0] == '': - return - split_addr = os.path.split(file_addr[0]) - self.current_project_directory = split_addr[0] - self.project_file_addr = file_addr[0] - - project = Project(self.settings, self.scenario_list) - self.project = project - with open(self.project_file_addr, 'wb') as f: # noqa: PTH123 - pickle.dump(project, f) - - def showHelpWindow(self): # noqa: N802, D102 - help_window = Main_Help_Designer() - help_window._window.exec_() # noqa: SLF001 - - def exitApp(self, event): # noqa: N802, D102 - return_value = self.questionPrompt( - 'REWET', 'Do you want to save the project before you leave?' - ) - - if return_value == 16384: # Yes # noqa: PLR2004 - if_saved = self.saveProject() - if if_saved: - event.accept() - else: - event.ignore() - elif return_value == 65536: # None # noqa: PLR2004 - event.accept() - elif return_value == 4194304: # Cancel # noqa: PLR2004 - event.ignore() - return - - -if __name__ == '__main__': - opening_designer = Opening_Designer() - opening_designer.run() diff --git a/modules/systemPerformance/REWET/REWET/GUI/Opening_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Opening_Window.py deleted file mode 100644 index b7eaf7ff3..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Opening_Window.py +++ /dev/null @@ -1,1187 +0,0 @@ -# Form implementation generated from reading ui file 'Opening.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Opening_Window: # noqa: D101 - def setupUi(self, Opening_Window): # noqa: N802, N803, D102, PLR0915 - Opening_Window.setObjectName('Opening_Window') - Opening_Window.resize(830, 780) - self.centralwidget = QtWidgets.QWidget(Opening_Window) - self.centralwidget.setObjectName('centralwidget') - self.main_tab = QtWidgets.QTabWidget(self.centralwidget) - self.main_tab.setGeometry(QtCore.QRect(0, 0, 801, 741)) - self.main_tab.setObjectName('main_tab') - self.main_process = QtWidgets.QWidget() - self.main_process.setObjectName('main_process') - self.main_process1 = QtWidgets.QTabWidget(self.main_process) - self.main_process1.setGeometry(QtCore.QRect(0, 0, 811, 681)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(False) - font.setWeight(50) - self.main_process1.setFont(font) - self.main_process1.setTabPosition(QtWidgets.QTabWidget.West) - self.main_process1.setTabShape(QtWidgets.QTabWidget.Triangular) - self.main_process1.setIconSize(QtCore.QSize(16, 16)) - self.main_process1.setObjectName('main_process1') - self.simulation_tab = QtWidgets.QWidget() - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.simulation_tab.setFont(font) - self.simulation_tab.setObjectName('simulation_tab') - self.groupBox_4 = QtWidgets.QGroupBox(self.simulation_tab) - self.groupBox_4.setGeometry(QtCore.QRect(50, 220, 711, 101)) - self.groupBox_4.setObjectName('groupBox_4') - self.label_29 = QtWidgets.QLabel(self.groupBox_4) - self.label_29.setGeometry(QtCore.QRect(20, 70, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_29.setFont(font) - self.label_29.setObjectName('label_29') - self.save_time_step_yes_radio = QtWidgets.QRadioButton(self.groupBox_4) - self.save_time_step_yes_radio.setGeometry(QtCore.QRect(120, 70, 41, 17)) - self.save_time_step_yes_radio.setChecked(False) - self.save_time_step_yes_radio.setObjectName('save_time_step_yes_radio') - self.label_30 = QtWidgets.QLabel(self.groupBox_4) - self.label_30.setGeometry(QtCore.QRect(250, 60, 301, 31)) - palette = QtGui.QPalette() - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0, 128)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush( - QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush - ) - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) - brush = QtGui.QBrush(QtGui.QColor(170, 85, 0, 128)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush( - QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush - ) - brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) - brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) - brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush( - QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush - ) - self.label_30.setPalette(palette) - self.label_30.setWordWrap(True) - self.label_30.setObjectName('label_30') - self.save_time_step_no_radio = QtWidgets.QRadioButton(self.groupBox_4) - self.save_time_step_no_radio.setGeometry(QtCore.QRect(190, 70, 41, 17)) - self.save_time_step_no_radio.setChecked(True) - self.save_time_step_no_radio.setObjectName('save_time_step_no_radio') - self.label_15 = QtWidgets.QLabel(self.groupBox_4) - self.label_15.setGeometry(QtCore.QRect(20, 32, 91, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_15.setFont(font) - self.label_15.setObjectName('label_15') - self.temp_folder_addr_line = QtWidgets.QLineEdit(self.groupBox_4) - self.temp_folder_addr_line.setGeometry(QtCore.QRect(120, 30, 331, 20)) - self.temp_folder_addr_line.setReadOnly(True) - self.temp_folder_addr_line.setObjectName('temp_folder_addr_line') - self.temp_browser_button = QtWidgets.QPushButton(self.groupBox_4) - self.temp_browser_button.setGeometry(QtCore.QRect(460, 28, 75, 23)) - self.temp_browser_button.setObjectName('temp_browser_button') - self.groupBox_5 = QtWidgets.QGroupBox(self.simulation_tab) - self.groupBox_5.setGeometry(QtCore.QRect(50, 40, 711, 171)) - self.groupBox_5.setObjectName('groupBox_5') - self.simulation_time_line = QtWidgets.QLineEdit(self.groupBox_5) - self.simulation_time_line.setGeometry(QtCore.QRect(150, 20, 81, 20)) - self.simulation_time_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.simulation_time_line.setObjectName('simulation_time_line') - self.label = QtWidgets.QLabel(self.groupBox_5) - self.label.setGeometry(QtCore.QRect(20, 22, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label.setFont(font) - self.label.setObjectName('label') - self.label_32 = QtWidgets.QLabel(self.groupBox_5) - self.label_32.setGeometry(QtCore.QRect(20, 100, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_32.setFont(font) - self.label_32.setObjectName('label_32') - self.multiple_radio = QtWidgets.QRadioButton(self.groupBox_5) - self.multiple_radio.setGeometry(QtCore.QRect(190, 100, 101, 17)) - self.multiple_radio.setObjectName('multiple_radio') - self.single_radio = QtWidgets.QRadioButton(self.groupBox_5) - self.single_radio.setGeometry(QtCore.QRect(120, 100, 51, 17)) - self.single_radio.setChecked(True) - self.single_radio.setObjectName('single_radio') - self.label_3 = QtWidgets.QLabel(self.groupBox_5) - self.label_3.setGeometry(QtCore.QRect(20, 52, 121, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_3.setFont(font) - self.label_3.setObjectName('label_3') - self.simulation_time_step_line = QtWidgets.QLineEdit(self.groupBox_5) - self.simulation_time_step_line.setGeometry(QtCore.QRect(150, 50, 81, 20)) - self.simulation_time_step_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.simulation_time_step_line.setObjectName('simulation_time_step_line') - self.label_17 = QtWidgets.QLabel(self.groupBox_5) - self.label_17.setGeometry(QtCore.QRect(240, 20, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_17.setFont(font) - self.label_17.setTextFormat(QtCore.Qt.PlainText) - self.label_17.setObjectName('label_17') - self.label_18 = QtWidgets.QLabel(self.groupBox_5) - self.label_18.setGeometry(QtCore.QRect(240, 50, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_18.setFont(font) - self.label_18.setTextFormat(QtCore.Qt.PlainText) - self.label_18.setObjectName('label_18') - self.result_folder_addr_line = QtWidgets.QLineEdit(self.groupBox_5) - self.result_folder_addr_line.setGeometry(QtCore.QRect(120, 130, 331, 20)) - self.result_folder_addr_line.setReadOnly(True) - self.result_folder_addr_line.setObjectName('result_folder_addr_line') - self.result_directory_browser_button = QtWidgets.QPushButton(self.groupBox_5) - self.result_directory_browser_button.setGeometry( - QtCore.QRect(460, 130, 75, 23) - ) - self.result_directory_browser_button.setObjectName( - 'result_directory_browser_button' - ) - self.label_22 = QtWidgets.QLabel(self.groupBox_5) - self.label_22.setGeometry(QtCore.QRect(20, 130, 91, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_22.setFont(font) - self.label_22.setObjectName('label_22') - self.main_process1.addTab(self.simulation_tab, '') - self.hudrauics_tab = QtWidgets.QWidget() - self.hudrauics_tab.setObjectName('hudrauics_tab') - self.groupBox_3 = QtWidgets.QGroupBox(self.hudrauics_tab) - self.groupBox_3.setGeometry(QtCore.QRect(10, 210, 761, 241)) - self.groupBox_3.setObjectName('groupBox_3') - self.label_9 = QtWidgets.QLabel(self.groupBox_3) - self.label_9.setGeometry(QtCore.QRect(20, 50, 47, 13)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_9.setFont(font) - self.label_9.setTextFormat(QtCore.Qt.PlainText) - self.label_9.setObjectName('label_9') - self.wntr_solver_radio = QtWidgets.QRadioButton(self.groupBox_3) - self.wntr_solver_radio.setEnabled(False) - self.wntr_solver_radio.setGeometry(QtCore.QRect(240, 50, 82, 17)) - self.wntr_solver_radio.setObjectName('wntr_solver_radio') - self.modified_epanet_radio = QtWidgets.QRadioButton(self.groupBox_3) - self.modified_epanet_radio.setEnabled(True) - self.modified_epanet_radio.setGeometry(QtCore.QRect(80, 50, 151, 17)) - self.modified_epanet_radio.setChecked(True) - self.modified_epanet_radio.setObjectName('modified_epanet_radio') - self.minimum_pressure_line = QtWidgets.QLineEdit(self.groupBox_3) - self.minimum_pressure_line.setGeometry(QtCore.QRect(80, 90, 61, 20)) - self.minimum_pressure_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.minimum_pressure_line.setObjectName('minimum_pressure_line') - self.required_pressure_line = QtWidgets.QLineEdit(self.groupBox_3) - self.required_pressure_line.setGeometry(QtCore.QRect(80, 130, 61, 20)) - self.required_pressure_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.required_pressure_line.setObjectName('required_pressure_line') - self.label_10 = QtWidgets.QLabel(self.groupBox_3) - self.label_10.setGeometry(QtCore.QRect(20, 90, 47, 13)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_10.setFont(font) - self.label_10.setTextFormat(QtCore.Qt.PlainText) - self.label_10.setObjectName('label_10') - self.label_11 = QtWidgets.QLabel(self.groupBox_3) - self.label_11.setGeometry(QtCore.QRect(150, 90, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_11.setFont(font) - self.label_11.setTextFormat(QtCore.Qt.PlainText) - self.label_11.setObjectName('label_11') - self.label_12 = QtWidgets.QLabel(self.groupBox_3) - self.label_12.setGeometry(QtCore.QRect(150, 130, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_12.setFont(font) - self.label_12.setTextFormat(QtCore.Qt.PlainText) - self.label_12.setObjectName('label_12') - self.label_13 = QtWidgets.QLabel(self.groupBox_3) - self.label_13.setGeometry(QtCore.QRect(20, 130, 47, 13)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_13.setFont(font) - self.label_13.setTextFormat(QtCore.Qt.PlainText) - self.label_13.setObjectName('label_13') - self.label_4 = QtWidgets.QLabel(self.groupBox_3) - self.label_4.setGeometry(QtCore.QRect(10, 145, 61, 41)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_4.setFont(font) - self.label_4.setWordWrap(True) - self.label_4.setObjectName('label_4') - self.hydraulic_time_step_line = QtWidgets.QLineEdit(self.groupBox_3) - self.hydraulic_time_step_line.setGeometry(QtCore.QRect(80, 160, 61, 20)) - self.hydraulic_time_step_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.hydraulic_time_step_line.setObjectName('hydraulic_time_step_line') - self.label_16 = QtWidgets.QLabel(self.groupBox_3) - self.label_16.setGeometry(QtCore.QRect(150, 160, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_16.setFont(font) - self.label_16.setTextFormat(QtCore.Qt.PlainText) - self.label_16.setObjectName('label_16') - self.groupBox_6 = QtWidgets.QGroupBox(self.hudrauics_tab) - self.groupBox_6.setGeometry(QtCore.QRect(10, 30, 761, 171)) - self.groupBox_6.setObjectName('groupBox_6') - self.wdn_addr_line = QtWidgets.QLineEdit(self.groupBox_6) - self.wdn_addr_line.setGeometry(QtCore.QRect(130, 30, 481, 20)) - self.wdn_addr_line.setReadOnly(True) - self.wdn_addr_line.setObjectName('wdn_addr_line') - self.wdn_browse_button = QtWidgets.QPushButton(self.groupBox_6) - self.wdn_browse_button.setGeometry(QtCore.QRect(630, 30, 75, 23)) - self.wdn_browse_button.setObjectName('wdn_browse_button') - self.label_2 = QtWidgets.QLabel(self.groupBox_6) - self.label_2.setGeometry(QtCore.QRect(10, 30, 101, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_2.setFont(font) - self.label_2.setObjectName('label_2') - self.demand_ratio_line = QtWidgets.QLineEdit(self.groupBox_6) - self.demand_ratio_line.setGeometry(QtCore.QRect(130, 70, 41, 21)) - self.demand_ratio_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.demand_ratio_line.setObjectName('demand_ratio_line') - self.label_7 = QtWidgets.QLabel(self.groupBox_6) - self.label_7.setGeometry(QtCore.QRect(10, 70, 111, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_7.setFont(font) - self.label_7.setObjectName('label_7') - self.label_8 = QtWidgets.QLabel(self.groupBox_6) - self.label_8.setGeometry(QtCore.QRect(180, 70, 91, 21)) - self.label_8.setFrameShape(QtWidgets.QFrame.Box) - self.label_8.setFrameShadow(QtWidgets.QFrame.Raised) - self.label_8.setObjectName('label_8') - self.main_process1.addTab(self.hudrauics_tab, '') - self.damage_tab = QtWidgets.QWidget() - self.damage_tab.setObjectName('damage_tab') - self.scenario_table = QtWidgets.QTableWidget(self.damage_tab) - self.scenario_table.setGeometry(QtCore.QRect(80, 100, 691, 192)) - self.scenario_table.setSelectionMode( - QtWidgets.QAbstractItemView.ExtendedSelection - ) - self.scenario_table.setSelectionBehavior( - QtWidgets.QAbstractItemView.SelectRows - ) - self.scenario_table.setObjectName('scenario_table') - self.scenario_table.setColumnCount(6) - self.scenario_table.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(2, item) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(3, item) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(4, item) - item = QtWidgets.QTableWidgetItem() - self.scenario_table.setHorizontalHeaderItem(5, item) - self.scenario_table.horizontalHeader().setDefaultSectionSize(110) - self.scenario_table.horizontalHeader().setMinimumSectionSize(60) - self.label_31 = QtWidgets.QLabel(self.damage_tab) - self.label_31.setGeometry(QtCore.QRect(80, 70, 111, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_31.setFont(font) - self.label_31.setObjectName('label_31') - self.add_scenario_button = QtWidgets.QPushButton(self.damage_tab) - self.add_scenario_button.setGeometry(QtCore.QRect(20, 100, 51, 23)) - self.add_scenario_button.setObjectName('add_scenario_button') - self.status_text = QtWidgets.QTextBrowser(self.damage_tab) - self.status_text.setEnabled(True) - self.status_text.setGeometry(QtCore.QRect(0, 550, 791, 121)) - self.status_text.setObjectName('status_text') - self.remove_scenario_button = QtWidgets.QPushButton(self.damage_tab) - self.remove_scenario_button.setGeometry(QtCore.QRect(20, 130, 51, 23)) - self.remove_scenario_button.setObjectName('remove_scenario_button') - self.groupBox_7 = QtWidgets.QGroupBox(self.damage_tab) - self.groupBox_7.setGeometry(QtCore.QRect(80, 310, 481, 80)) - self.groupBox_7.setObjectName('groupBox_7') - self.pushButton_13 = QtWidgets.QPushButton(self.groupBox_7) - self.pushButton_13.setEnabled(False) - self.pushButton_13.setGeometry(QtCore.QRect(30, 30, 91, 23)) - self.pushButton_13.setObjectName('pushButton_13') - self.pushButton_17 = QtWidgets.QPushButton(self.groupBox_7) - self.pushButton_17.setEnabled(False) - self.pushButton_17.setGeometry(QtCore.QRect(140, 30, 91, 23)) - self.pushButton_17.setObjectName('pushButton_17') - self.pushButton_16 = QtWidgets.QPushButton(self.groupBox_7) - self.pushButton_16.setEnabled(False) - self.pushButton_16.setGeometry(QtCore.QRect(360, 30, 91, 23)) - self.pushButton_16.setObjectName('pushButton_16') - self.pushButton_15 = QtWidgets.QPushButton(self.groupBox_7) - self.pushButton_15.setEnabled(False) - self.pushButton_15.setGeometry(QtCore.QRect(250, 30, 91, 23)) - self.pushButton_15.setObjectName('pushButton_15') - self.groupBox_8 = QtWidgets.QGroupBox(self.damage_tab) - self.groupBox_8.setGeometry(QtCore.QRect(80, 420, 691, 80)) - self.groupBox_8.setObjectName('groupBox_8') - self.pipe_damage_modeling_button = QtWidgets.QPushButton(self.groupBox_8) - self.pipe_damage_modeling_button.setGeometry(QtCore.QRect(30, 40, 101, 23)) - self.pipe_damage_modeling_button.setObjectName('pipe_damage_modeling_button') - self.node_damage_modeling_button = QtWidgets.QPushButton(self.groupBox_8) - self.node_damage_modeling_button.setGeometry(QtCore.QRect(150, 40, 101, 23)) - self.node_damage_modeling_button.setObjectName('node_damage_modeling_button') - self.label_20 = QtWidgets.QLabel(self.damage_tab) - self.label_20.setGeometry(QtCore.QRect(200, 50, 141, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_20.setFont(font) - self.label_20.setObjectName('label_20') - self.damage_directory_browse_button = QtWidgets.QPushButton(self.damage_tab) - self.damage_directory_browse_button.setGeometry( - QtCore.QRect(580, 70, 75, 23) - ) - self.damage_directory_browse_button.setObjectName( - 'damage_directory_browse_button' - ) - self.damage_direcotry_line = QtWidgets.QLineEdit(self.damage_tab) - self.damage_direcotry_line.setGeometry(QtCore.QRect(200, 70, 371, 20)) - self.damage_direcotry_line.setReadOnly(True) - self.damage_direcotry_line.setObjectName('damage_direcotry_line') - self.load_scenario_button = QtWidgets.QPushButton(self.damage_tab) - self.load_scenario_button.setGeometry(QtCore.QRect(20, 230, 51, 23)) - self.load_scenario_button.setObjectName('load_scenario_button') - self.save_scenario_button = QtWidgets.QPushButton(self.damage_tab) - self.save_scenario_button.setGeometry(QtCore.QRect(20, 260, 51, 23)) - self.save_scenario_button.setObjectName('save_scenario_button') - self.validate_scenario_button = QtWidgets.QPushButton(self.damage_tab) - self.validate_scenario_button.setGeometry(QtCore.QRect(570, 350, 171, 41)) - self.validate_scenario_button.setObjectName('validate_scenario_button') - self.groupBox_11 = QtWidgets.QGroupBox(self.damage_tab) - self.groupBox_11.setGeometry(QtCore.QRect(560, 300, 171, 51)) - self.groupBox_11.setObjectName('groupBox_11') - self.file_type_excel_radio = QtWidgets.QRadioButton(self.groupBox_11) - self.file_type_excel_radio.setGeometry(QtCore.QRect(10, 20, 82, 17)) - self.file_type_excel_radio.setChecked(True) - self.file_type_excel_radio.setObjectName('file_type_excel_radio') - self.file_type_pickle_radio = QtWidgets.QRadioButton(self.groupBox_11) - self.file_type_pickle_radio.setGeometry(QtCore.QRect(90, 20, 82, 17)) - self.file_type_pickle_radio.setObjectName('file_type_pickle_radio') - self.main_process1.addTab(self.damage_tab, '') - self.restoration_tab = QtWidgets.QWidget() - self.restoration_tab.setObjectName('restoration_tab') - self.groupBox = QtWidgets.QGroupBox(self.restoration_tab) - self.groupBox.setGeometry(QtCore.QRect(30, 40, 191, 80)) - self.groupBox.setObjectName('groupBox') - self.restoration_on_radio = QtWidgets.QRadioButton(self.groupBox) - self.restoration_on_radio.setGeometry(QtCore.QRect(20, 40, 61, 17)) - self.restoration_on_radio.setChecked(True) - self.restoration_on_radio.setObjectName('restoration_on_radio') - self.restoration_off_radio = QtWidgets.QRadioButton(self.groupBox) - self.restoration_off_radio.setGeometry(QtCore.QRect(90, 40, 82, 17)) - self.restoration_off_radio.setObjectName('restoration_off_radio') - self.groupBox_2 = QtWidgets.QGroupBox(self.restoration_tab) - self.groupBox_2.setGeometry(QtCore.QRect(30, 120, 731, 231)) - self.groupBox_2.setObjectName('groupBox_2') - self.policy_browse_button = QtWidgets.QPushButton(self.groupBox_2) - self.policy_browse_button.setGeometry(QtCore.QRect(460, 100, 91, 23)) - self.policy_browse_button.setObjectName('policy_browse_button') - self.script_rrp_radio = QtWidgets.QRadioButton(self.groupBox_2) - self.script_rrp_radio.setGeometry(QtCore.QRect(290, 60, 111, 17)) - self.script_rrp_radio.setObjectName('script_rrp_radio') - self.script_txt_radio = QtWidgets.QRadioButton(self.groupBox_2) - self.script_txt_radio.setGeometry(QtCore.QRect(180, 60, 101, 17)) - self.script_txt_radio.setChecked(True) - self.script_txt_radio.setObjectName('script_txt_radio') - self.label_5 = QtWidgets.QLabel(self.groupBox_2) - self.label_5.setGeometry(QtCore.QRect(30, 100, 131, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_5.setFont(font) - self.label_5.setObjectName('label_5') - self.policy_definition_addr_line = QtWidgets.QLineEdit(self.groupBox_2) - self.policy_definition_addr_line.setGeometry(QtCore.QRect(170, 100, 281, 20)) - self.policy_definition_addr_line.setText('') - self.policy_definition_addr_line.setReadOnly(True) - self.policy_definition_addr_line.setObjectName('policy_definition_addr_line') - self.policy_designer = QtWidgets.QPushButton(self.groupBox_2) - self.policy_designer.setGeometry(QtCore.QRect(460, 60, 91, 23)) - self.policy_designer.setObjectName('policy_designer') - self.label_6 = QtWidgets.QLabel(self.groupBox_2) - self.label_6.setGeometry(QtCore.QRect(30, 180, 131, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_6.setFont(font) - self.label_6.setObjectName('label_6') - self.minimum_job_time_line = QtWidgets.QLineEdit(self.groupBox_2) - self.minimum_job_time_line.setGeometry(QtCore.QRect(170, 180, 51, 20)) - self.minimum_job_time_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.minimum_job_time_line.setObjectName('minimum_job_time_line') - self.label_14 = QtWidgets.QLabel(self.groupBox_2) - self.label_14.setEnabled(False) - self.label_14.setGeometry(QtCore.QRect(30, 140, 131, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_14.setFont(font) - self.label_14.setObjectName('label_14') - self.crew_availability_browse_button = QtWidgets.QPushButton(self.groupBox_2) - self.crew_availability_browse_button.setEnabled(False) - self.crew_availability_browse_button.setGeometry( - QtCore.QRect(460, 140, 91, 23) - ) - self.crew_availability_browse_button.setObjectName( - 'crew_availability_browse_button' - ) - self.lineEdit_8 = QtWidgets.QLineEdit(self.groupBox_2) - self.lineEdit_8.setEnabled(False) - self.lineEdit_8.setGeometry(QtCore.QRect(170, 140, 281, 20)) - self.lineEdit_8.setText('') - self.lineEdit_8.setObjectName('lineEdit_8') - self.label_19 = QtWidgets.QLabel(self.groupBox_2) - self.label_19.setGeometry(QtCore.QRect(230, 180, 61, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_19.setFont(font) - self.label_19.setTextFormat(QtCore.Qt.PlainText) - self.label_19.setObjectName('label_19') - self.label_21 = QtWidgets.QLabel(self.groupBox_2) - self.label_21.setGeometry(QtCore.QRect(30, 60, 131, 16)) - font = QtGui.QFont() - font.setPointSize(9) - font.setBold(True) - font.setWeight(75) - self.label_21.setFont(font) - self.label_21.setObjectName('label_21') - self.groupBox_9 = QtWidgets.QGroupBox(self.restoration_tab) - self.groupBox_9.setGeometry(QtCore.QRect(30, 370, 721, 91)) - self.groupBox_9.setObjectName('groupBox_9') - self.pipe_damage_discovery_button = QtWidgets.QPushButton(self.groupBox_9) - self.pipe_damage_discovery_button.setGeometry(QtCore.QRect(30, 40, 75, 23)) - self.pipe_damage_discovery_button.setObjectName( - 'pipe_damage_discovery_button' - ) - self.node_damage_discovery_button = QtWidgets.QPushButton(self.groupBox_9) - self.node_damage_discovery_button.setGeometry(QtCore.QRect(120, 40, 75, 23)) - self.node_damage_discovery_button.setObjectName( - 'node_damage_discovery_button' - ) - self.pump_damage_discovery_button = QtWidgets.QPushButton(self.groupBox_9) - self.pump_damage_discovery_button.setGeometry(QtCore.QRect(210, 40, 75, 23)) - self.pump_damage_discovery_button.setObjectName( - 'pump_damage_discovery_button' - ) - self.tank_damage_discovery_button = QtWidgets.QPushButton(self.groupBox_9) - self.tank_damage_discovery_button.setGeometry(QtCore.QRect(290, 40, 75, 23)) - self.tank_damage_discovery_button.setObjectName( - 'tank_damage_discovery_button' - ) - self.groupBox_10 = QtWidgets.QGroupBox(self.restoration_tab) - self.groupBox_10.setGeometry(QtCore.QRect(30, 470, 211, 51)) - self.groupBox_10.setObjectName('groupBox_10') - self.out_of_zone_travel_yes = QtWidgets.QRadioButton(self.groupBox_10) - self.out_of_zone_travel_yes.setGeometry(QtCore.QRect(10, 20, 82, 17)) - self.out_of_zone_travel_yes.setObjectName('out_of_zone_travel_yes') - self.out_of_zone_travel_no = QtWidgets.QRadioButton(self.groupBox_10) - self.out_of_zone_travel_no.setGeometry(QtCore.QRect(90, 20, 101, 17)) - self.out_of_zone_travel_no.setChecked(True) - self.out_of_zone_travel_no.setObjectName('out_of_zone_travel_no') - self.main_process1.addTab(self.restoration_tab, '') - self.run_tab = QtWidgets.QWidget() - self.run_tab.setObjectName('run_tab') - self.run_button = QtWidgets.QPushButton(self.run_tab) - self.run_button.setGeometry(QtCore.QRect(50, 50, 181, 31)) - font = QtGui.QFont() - font.setPointSize(12) - font.setBold(False) - font.setWeight(50) - self.run_button.setFont(font) - self.run_button.setObjectName('run_button') - self.stop_button = QtWidgets.QPushButton(self.run_tab) - self.stop_button.setGeometry(QtCore.QRect(50, 520, 181, 31)) - font = QtGui.QFont() - font.setPointSize(12) - font.setBold(False) - font.setWeight(50) - self.stop_button.setFont(font) - self.stop_button.setObjectName('stop_button') - self.ouput_textedit = QtWidgets.QPlainTextEdit(self.run_tab) - self.ouput_textedit.setGeometry(QtCore.QRect(50, 110, 651, 391)) - self.ouput_textedit.setReadOnly(True) - self.ouput_textedit.setObjectName('ouput_textedit') - self.label_42 = QtWidgets.QLabel(self.run_tab) - self.label_42.setGeometry(QtCore.QRect(50, 80, 51, 31)) - font = QtGui.QFont() - font.setPointSize(11) - self.label_42.setFont(font) - self.label_42.setObjectName('label_42') - self.main_process1.addTab(self.run_tab, '') - self.main_tab.addTab(self.main_process, '') - self.post_process = QtWidgets.QWidget() - self.post_process.setObjectName('post_process') - self.results_tabs_widget = QtWidgets.QTabWidget(self.post_process) - self.results_tabs_widget.setGeometry(QtCore.QRect(0, 0, 801, 721)) - font = QtGui.QFont() - font.setPointSize(9) - self.results_tabs_widget.setFont(font) - self.results_tabs_widget.setTabPosition(QtWidgets.QTabWidget.West) - self.results_tabs_widget.setTabShape(QtWidgets.QTabWidget.Triangular) - self.results_tabs_widget.setObjectName('results_tabs_widget') - self.data_tab = QtWidgets.QWidget() - self.data_tab.setObjectName('data_tab') - self.result_file_status_table = QtWidgets.QTableWidget(self.data_tab) - self.result_file_status_table.setEnabled(True) - self.result_file_status_table.setGeometry(QtCore.QRect(130, 70, 331, 421)) - self.result_file_status_table.setSelectionMode( - QtWidgets.QAbstractItemView.NoSelection - ) - self.result_file_status_table.setObjectName('result_file_status_table') - self.result_file_status_table.setColumnCount(2) - self.result_file_status_table.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - self.result_file_status_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.result_file_status_table.setHorizontalHeaderItem(1, item) - self.result_file_status_table.horizontalHeader().setDefaultSectionSize(200) - self.result_file_status_table.horizontalHeader().setStretchLastSection(False) - self.load_results_button = QtWidgets.QPushButton(self.data_tab) - self.load_results_button.setGeometry(QtCore.QRect(130, 30, 91, 23)) - self.load_results_button.setObjectName('load_results_button') - self.label_27 = QtWidgets.QLabel(self.data_tab) - self.label_27.setGeometry(QtCore.QRect(30, 30, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_27.setFont(font) - self.label_27.setObjectName('label_27') - self.read_files_check_box = QtWidgets.QCheckBox(self.data_tab) - self.read_files_check_box.setGeometry(QtCore.QRect(250, 30, 121, 17)) - self.read_files_check_box.setChecked(True) - self.read_files_check_box.setObjectName('read_files_check_box') - self.population_browser_button = QtWidgets.QPushButton(self.data_tab) - self.population_browser_button.setGeometry(QtCore.QRect(470, 550, 91, 23)) - self.population_browser_button.setObjectName('population_browser_button') - self.label_28 = QtWidgets.QLabel(self.data_tab) - self.label_28.setGeometry(QtCore.QRect(130, 530, 141, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(True) - font.setWeight(75) - self.label_28.setFont(font) - self.label_28.setObjectName('label_28') - self.population_addr_line = QtWidgets.QLineEdit(self.data_tab) - self.population_addr_line.setGeometry(QtCore.QRect(130, 550, 331, 20)) - self.population_addr_line.setReadOnly(True) - self.population_addr_line.setObjectName('population_addr_line') - self.population_node_ID_header_combo = QtWidgets.QComboBox(self.data_tab) - self.population_node_ID_header_combo.setGeometry( - QtCore.QRect(130, 600, 111, 22) - ) - self.population_node_ID_header_combo.setObjectName( - 'population_node_ID_header_combo' - ) - self.population_population_header_combo = QtWidgets.QComboBox(self.data_tab) - self.population_population_header_combo.setGeometry( - QtCore.QRect(250, 600, 111, 22) - ) - self.population_population_header_combo.setObjectName( - 'population_population_header_combo' - ) - self.population_load_button = QtWidgets.QPushButton(self.data_tab) - self.population_load_button.setGeometry(QtCore.QRect(470, 600, 91, 23)) - self.population_load_button.setObjectName('population_load_button') - self.label_33 = QtWidgets.QLabel(self.data_tab) - self.label_33.setGeometry(QtCore.QRect(130, 580, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_33.setFont(font) - self.label_33.setObjectName('label_33') - self.label_34 = QtWidgets.QLabel(self.data_tab) - self.label_34.setGeometry(QtCore.QRect(250, 580, 101, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_34.setFont(font) - self.label_34.setObjectName('label_34') - self.results_tabs_widget.addTab(self.data_tab, '') - self.curve_tab = QtWidgets.QWidget() - self.curve_tab.setObjectName('curve_tab') - self.curve_type_combo = QtWidgets.QComboBox(self.curve_tab) - self.curve_type_combo.setGeometry(QtCore.QRect(30, 80, 351, 22)) - self.curve_type_combo.setObjectName('curve_type_combo') - self.curve_type_combo.addItem('') - self.curve_type_combo.addItem('') - self.all_scenarios_checkbox = QtWidgets.QCheckBox(self.curve_tab) - self.all_scenarios_checkbox.setGeometry(QtCore.QRect(190, 30, 121, 17)) - self.all_scenarios_checkbox.setChecked(False) - self.all_scenarios_checkbox.setObjectName('all_scenarios_checkbox') - self.label_23 = QtWidgets.QLabel(self.curve_tab) - self.label_23.setGeometry(QtCore.QRect(30, 412, 47, 21)) - self.label_23.setObjectName('label_23') - self.save_curve_button = QtWidgets.QPushButton(self.curve_tab) - self.save_curve_button.setGeometry(QtCore.QRect(380, 440, 91, 23)) - self.save_curve_button.setObjectName('save_curve_button') - self.curve_settings_table = QtWidgets.QTableWidget(self.curve_tab) - self.curve_settings_table.setGeometry(QtCore.QRect(30, 440, 231, 271)) - self.curve_settings_table.setSelectionMode( - QtWidgets.QAbstractItemView.NoSelection - ) - self.curve_settings_table.setSelectionBehavior( - QtWidgets.QAbstractItemView.SelectItems - ) - self.curve_settings_table.setObjectName('curve_settings_table') - self.curve_settings_table.setColumnCount(1) - self.curve_settings_table.setRowCount(4) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setVerticalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setVerticalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setVerticalHeaderItem(2, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setVerticalHeaderItem(3, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setItem(0, 0, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setItem(2, 0, item) - item = QtWidgets.QTableWidgetItem() - self.curve_settings_table.setItem(3, 0, item) - self.curve_settings_table.horizontalHeader().setStretchLastSection(True) - self.scenario_combo = QtWidgets.QComboBox(self.curve_tab) - self.scenario_combo.setGeometry(QtCore.QRect(30, 30, 141, 22)) - self.scenario_combo.setObjectName('scenario_combo') - self.mpl_curve = MplWidget(self.curve_tab) - self.mpl_curve.setGeometry(QtCore.QRect(30, 110, 531, 291)) - self.mpl_curve.setObjectName('mpl_curve') - self.label_25 = QtWidgets.QLabel(self.curve_tab) - self.label_25.setGeometry(QtCore.QRect(30, 10, 81, 16)) - self.label_25.setObjectName('label_25') - self.label_26 = QtWidgets.QLabel(self.curve_tab) - self.label_26.setGeometry(QtCore.QRect(30, 55, 81, 21)) - self.label_26.setObjectName('label_26') - self.label_24 = QtWidgets.QLabel(self.curve_tab) - self.label_24.setGeometry(QtCore.QRect(380, 420, 101, 21)) - self.label_24.setObjectName('label_24') - self.results_tabs_widget.addTab(self.curve_tab, '') - self.tab = QtWidgets.QWidget() - self.tab.setObjectName('tab') - self.mpl_map = MplWidget(self.tab) - self.mpl_map.setGeometry(QtCore.QRect(20, 110, 560, 560)) - self.mpl_map.setObjectName('mpl_map') - self.label_35 = QtWidgets.QLabel(self.tab) - self.label_35.setGeometry(QtCore.QRect(20, 25, 81, 21)) - self.label_35.setObjectName('label_35') - self.map_type_combo = QtWidgets.QComboBox(self.tab) - self.map_type_combo.setGeometry(QtCore.QRect(20, 50, 351, 22)) - self.map_type_combo.setObjectName('map_type_combo') - self.map_settings_table = QtWidgets.QTableWidget(self.tab) - self.map_settings_table.setGeometry(QtCore.QRect(590, 110, 181, 201)) - self.map_settings_table.setSelectionMode( - QtWidgets.QAbstractItemView.NoSelection - ) - self.map_settings_table.setSelectionBehavior( - QtWidgets.QAbstractItemView.SelectItems - ) - self.map_settings_table.setObjectName('map_settings_table') - self.map_settings_table.setColumnCount(1) - self.map_settings_table.setRowCount(4) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setVerticalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setVerticalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setVerticalHeaderItem(2, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setVerticalHeaderItem(3, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setItem(0, 0, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setItem(2, 0, item) - item = QtWidgets.QTableWidgetItem() - self.map_settings_table.setItem(3, 0, item) - self.map_settings_table.horizontalHeader().setStretchLastSection(True) - self.label_36 = QtWidgets.QLabel(self.tab) - self.label_36.setGeometry(QtCore.QRect(590, 80, 47, 21)) - self.label_36.setObjectName('label_36') - self.label_37 = QtWidgets.QLabel(self.tab) - self.label_37.setGeometry(QtCore.QRect(20, 90, 81, 21)) - self.label_37.setObjectName('label_37') - self.save_map_button = QtWidgets.QPushButton(self.tab) - self.save_map_button.setGeometry(QtCore.QRect(600, 680, 131, 23)) - self.save_map_button.setObjectName('save_map_button') - self.label_38 = QtWidgets.QLabel(self.tab) - self.label_38.setGeometry(QtCore.QRect(600, 660, 131, 21)) - self.label_38.setAlignment(QtCore.Qt.AlignCenter) - self.label_38.setObjectName('label_38') - self.label_39 = QtWidgets.QLabel(self.tab) - self.label_39.setGeometry(QtCore.QRect(400, 30, 81, 16)) - self.label_39.setObjectName('label_39') - self.map_all_scenarios_checkbox = QtWidgets.QCheckBox(self.tab) - self.map_all_scenarios_checkbox.setGeometry(QtCore.QRect(400, 10, 121, 17)) - self.map_all_scenarios_checkbox.setChecked(False) - self.map_all_scenarios_checkbox.setObjectName('map_all_scenarios_checkbox') - self.map_scenario_combo = QtWidgets.QComboBox(self.tab) - self.map_scenario_combo.setGeometry(QtCore.QRect(400, 50, 181, 22)) - self.map_scenario_combo.setObjectName('map_scenario_combo') - self.groupBox_12 = QtWidgets.QGroupBox(self.tab) - self.groupBox_12.setGeometry(QtCore.QRect(590, 330, 171, 131)) - self.groupBox_12.setObjectName('groupBox_12') - self.annotation_checkbox = QtWidgets.QCheckBox(self.groupBox_12) - self.annotation_checkbox.setGeometry(QtCore.QRect(10, 20, 91, 31)) - self.annotation_checkbox.setObjectName('annotation_checkbox') - self.annotation_event_combo = QtWidgets.QComboBox(self.groupBox_12) - self.annotation_event_combo.setEnabled(False) - self.annotation_event_combo.setGeometry(QtCore.QRect(10, 50, 141, 22)) - self.annotation_event_combo.setObjectName('annotation_event_combo') - self.annotation_event_combo.addItem('') - self.annotation_event_combo.addItem('') - self.label_40 = QtWidgets.QLabel(self.groupBox_12) - self.label_40.setGeometry(QtCore.QRect(10, 80, 81, 21)) - self.label_40.setObjectName('label_40') - self.annotation_radius_line = QtWidgets.QLineEdit(self.groupBox_12) - self.annotation_radius_line.setEnabled(False) - self.annotation_radius_line.setGeometry(QtCore.QRect(10, 100, 113, 20)) - self.annotation_radius_line.setObjectName('annotation_radius_line') - self.groupBox_13 = QtWidgets.QGroupBox(self.tab) - self.groupBox_13.setGeometry(QtCore.QRect(590, 470, 171, 51)) - self.groupBox_13.setObjectName('groupBox_13') - self.spatial_join_button = QtWidgets.QPushButton(self.groupBox_13) - self.spatial_join_button.setGeometry(QtCore.QRect(20, 20, 121, 21)) - self.spatial_join_button.setObjectName('spatial_join_button') - self.groupBox_14 = QtWidgets.QGroupBox(self.tab) - self.groupBox_14.setGeometry(QtCore.QRect(590, 540, 171, 111)) - self.groupBox_14.setObjectName('groupBox_14') - self.symbology_button = QtWidgets.QPushButton(self.groupBox_14) - self.symbology_button.setGeometry(QtCore.QRect(20, 20, 121, 31)) - self.symbology_button.setObjectName('symbology_button') - self.major_tick_size_line = QtWidgets.QLineEdit(self.groupBox_14) - self.major_tick_size_line.setGeometry(QtCore.QRect(110, 60, 31, 20)) - self.major_tick_size_line.setObjectName('major_tick_size_line') - self.label_41 = QtWidgets.QLabel(self.groupBox_14) - self.label_41.setGeometry(QtCore.QRect(20, 60, 81, 21)) - self.label_41.setAlignment(QtCore.Qt.AlignCenter) - self.label_41.setObjectName('label_41') - self.results_tabs_widget.addTab(self.tab, '') - self.main_tab.addTab(self.post_process, '') - Opening_Window.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(Opening_Window) - self.menubar.setGeometry(QtCore.QRect(0, 0, 830, 21)) - self.menubar.setObjectName('menubar') - self.menuFile = QtWidgets.QMenu(self.menubar) - self.menuFile.setObjectName('menuFile') - self.menuHelp = QtWidgets.QMenu(self.menubar) - self.menuHelp.setObjectName('menuHelp') - Opening_Window.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(Opening_Window) - self.statusbar.setObjectName('statusbar') - Opening_Window.setStatusBar(self.statusbar) - self.action_Open_Project = QtWidgets.QAction(Opening_Window) - self.action_Open_Project.setObjectName('action_Open_Project') - self.action_Save = QtWidgets.QAction(Opening_Window) - self.action_Save.setObjectName('action_Save') - self.action_Save_Project_As = QtWidgets.QAction(Opening_Window) - self.action_Save_Project_As.setObjectName('action_Save_Project_As') - self.action_Exit = QtWidgets.QAction(Opening_Window) - self.action_Exit.setObjectName('action_Exit') - self.action_About = QtWidgets.QAction(Opening_Window) - self.action_About.setObjectName('action_About') - self.action_REWET_GITHUB = QtWidgets.QAction(Opening_Window) - self.action_REWET_GITHUB.setObjectName('action_REWET_GITHUB') - self.menuFile.addAction(self.action_Open_Project) - self.menuFile.addSeparator() - self.menuFile.addAction(self.action_Save) - self.menuFile.addAction(self.action_Save_Project_As) - self.menuFile.addSeparator() - self.menuFile.addAction(self.action_Exit) - self.menuHelp.addAction(self.action_REWET_GITHUB) - self.menuHelp.addAction(self.action_About) - self.menubar.addAction(self.menuFile.menuAction()) - self.menubar.addAction(self.menuHelp.menuAction()) - - self.retranslateUi(Opening_Window) - self.main_tab.setCurrentIndex(0) - self.main_process1.setCurrentIndex(4) - self.results_tabs_widget.setCurrentIndex(0) - QtCore.QMetaObject.connectSlotsByName(Opening_Window) - - def retranslateUi(self, Opening_Window): # noqa: N802, N803, D102, PLR0915 - _translate = QtCore.QCoreApplication.translate - Opening_Window.setWindowTitle(_translate('Opening_Window', 'REWET')) - self.groupBox_4.setTitle(_translate('Opening_Window', 'Temp File Settings')) - self.label_29.setText(_translate('Opening_Window', 'Save time step')) - self.save_time_step_yes_radio.setText(_translate('Opening_Window', 'Yes')) - self.label_30.setText( - _translate( - 'Opening_Window', - 'WARNING: Producing INP files for each event time can produce too many files', - ) - ) - self.save_time_step_no_radio.setText(_translate('Opening_Window', 'No')) - self.label_15.setText(_translate('Opening_Window', 'Temp Folder')) - self.temp_browser_button.setText(_translate('Opening_Window', 'Browse')) - self.groupBox_5.setTitle(_translate('Opening_Window', 'Settings')) - self.simulation_time_line.setText(_translate('Opening_Window', '36000')) - self.label.setText(_translate('Opening_Window', 'Simulation time')) - self.label_32.setText(_translate('Opening_Window', 'Run Type')) - self.multiple_radio.setText(_translate('Opening_Window', 'Multiple Serial')) - self.single_radio.setText(_translate('Opening_Window', 'Single')) - self.label_3.setText(_translate('Opening_Window', 'Simulation time step')) - self.simulation_time_step_line.setText(_translate('Opening_Window', '3600')) - self.label_17.setText(_translate('Opening_Window', 'seconds')) - self.label_18.setText(_translate('Opening_Window', 'seconds')) - self.result_directory_browser_button.setText( - _translate('Opening_Window', 'Browse') - ) - self.label_22.setText(_translate('Opening_Window', 'Result Folder')) - self.main_process1.setTabText( - self.main_process1.indexOf(self.simulation_tab), - _translate('Opening_Window', 'Simulation'), - ) - self.groupBox_3.setTitle(_translate('Opening_Window', 'Solver Options')) - self.label_9.setText(_translate('Opening_Window', 'Solver:')) - self.wntr_solver_radio.setText(_translate('Opening_Window', 'WNTR')) - self.modified_epanet_radio.setText( - _translate('Opening_Window', 'Modified EPANET V2.2') - ) - self.minimum_pressure_line.setText(_translate('Opening_Window', '8')) - self.required_pressure_line.setText(_translate('Opening_Window', '25')) - self.label_10.setText(_translate('Opening_Window', 'P(min):')) - self.label_11.setText(_translate('Opening_Window', 'h (water)')) - self.label_12.setText(_translate('Opening_Window', 'h (water)')) - self.label_13.setText(_translate('Opening_Window', 'P(req):')) - self.label_4.setText(_translate('Opening_Window', 'Hydraulic time step')) - self.hydraulic_time_step_line.setText(_translate('Opening_Window', '3600')) - self.label_16.setText(_translate('Opening_Window', 'seconds')) - self.groupBox_6.setTitle( - _translate('Opening_Window', 'Water Distribution Network') - ) - self.wdn_browse_button.setText(_translate('Opening_Window', 'Browse')) - self.label_2.setText(_translate('Opening_Window', 'System INP File')) - self.demand_ratio_line.setText(_translate('Opening_Window', '1')) - self.label_7.setText(_translate('Opening_Window', 'Calibrate Demand')) - self.label_8.setText(_translate('Opening_Window', '0\n' - '\n' - '


', - ) - ) - self.remove_scenario_button.setText(_translate('Opening_Window', 'Remove')) - self.groupBox_7.setTitle( - _translate('Opening_Window', 'File Headers Correction') - ) - self.pushButton_13.setText(_translate('Opening_Window', 'Pipe')) - self.pushButton_17.setText(_translate('Opening_Window', 'Node')) - self.pushButton_16.setText(_translate('Opening_Window', 'Tanks')) - self.pushButton_15.setText(_translate('Opening_Window', 'Pump')) - self.groupBox_8.setTitle(_translate('Opening_Window', 'Damage Modeling')) - self.pipe_damage_modeling_button.setText( - _translate('Opening_Window', 'Pipe') - ) - self.node_damage_modeling_button.setText( - _translate('Opening_Window', 'Nodal') - ) - self.label_20.setText(_translate('Opening_Window', 'Damage File Directory')) - self.damage_directory_browse_button.setText( - _translate('Opening_Window', 'Browse') - ) - self.load_scenario_button.setText(_translate('Opening_Window', 'Load')) - self.save_scenario_button.setText(_translate('Opening_Window', 'Save')) - self.validate_scenario_button.setText( - _translate('Opening_Window', 'Validate Damage Scenarios') - ) - self.groupBox_11.setTitle(_translate('Opening_Window', 'File Type')) - self.file_type_excel_radio.setText(_translate('Opening_Window', 'Excel')) - self.file_type_pickle_radio.setText(_translate('Opening_Window', 'Pickle')) - self.main_process1.setTabText( - self.main_process1.indexOf(self.damage_tab), - _translate('Opening_Window', 'Damage'), - ) - self.groupBox.setTitle(_translate('Opening_Window', 'On/Off')) - self.restoration_on_radio.setText(_translate('Opening_Window', 'On')) - self.restoration_off_radio.setText(_translate('Opening_Window', 'Off')) - self.groupBox_2.setTitle( - _translate('Opening_Window', 'Restoration Definition') - ) - self.policy_browse_button.setText(_translate('Opening_Window', 'Browse')) - self.script_rrp_radio.setText( - _translate('Opening_Window', 'Policy File (*.rrp)') - ) - self.script_txt_radio.setText(_translate('Opening_Window', 'Script (*.txt)')) - self.label_5.setText(_translate('Opening_Window', 'Policy Definition File')) - self.policy_designer.setText(_translate('Opening_Window', 'Policy Designer')) - self.label_6.setText(_translate('Opening_Window', 'Minimum Job Time')) - self.minimum_job_time_line.setText(_translate('Opening_Window', '3600')) - self.label_14.setText(_translate('Opening_Window', 'Crew Availability')) - self.crew_availability_browse_button.setText( - _translate('Opening_Window', 'Browse') - ) - self.label_19.setText(_translate('Opening_Window', 'seconds')) - self.label_21.setText(_translate('Opening_Window', 'File Type')) - self.groupBox_9.setTitle(_translate('Opening_Window', 'Damage Discovery')) - self.pipe_damage_discovery_button.setText( - _translate('Opening_Window', 'Pipe ') - ) - self.node_damage_discovery_button.setText( - _translate('Opening_Window', 'Node') - ) - self.pump_damage_discovery_button.setText( - _translate('Opening_Window', 'Pump') - ) - self.tank_damage_discovery_button.setText( - _translate('Opening_Window', 'Tank') - ) - self.groupBox_10.setTitle( - _translate('Opening_Window', 'Crew out-of-zone Travel') - ) - self.out_of_zone_travel_yes.setText(_translate('Opening_Window', 'Allowed')) - self.out_of_zone_travel_no.setText( - _translate('Opening_Window', 'Not Allowed') - ) - self.main_process1.setTabText( - self.main_process1.indexOf(self.restoration_tab), - _translate('Opening_Window', 'Restoration'), - ) - self.run_button.setText(_translate('Opening_Window', 'RUN')) - self.stop_button.setText(_translate('Opening_Window', 'Stop')) - self.label_42.setText(_translate('Opening_Window', 'Log')) - self.main_process1.setTabText( - self.main_process1.indexOf(self.run_tab), - _translate('Opening_Window', 'Run'), - ) - self.main_tab.setTabText( - self.main_tab.indexOf(self.main_process), - _translate('Opening_Window', 'Process'), - ) - item = self.result_file_status_table.horizontalHeaderItem(0) - item.setText(_translate('Opening_Window', 'Scenario Name')) - item = self.result_file_status_table.horizontalHeaderItem(1) - item.setText(_translate('Opening_Window', 'Status')) - self.load_results_button.setText(_translate('Opening_Window', 'Load')) - self.label_27.setText(_translate('Opening_Window', 'Load Result Files')) - self.read_files_check_box.setText(_translate('Opening_Window', 'Read Files')) - self.population_browser_button.setText( - _translate('Opening_Window', 'Browse') - ) - self.label_28.setText(_translate('Opening_Window', 'Population Data')) - self.population_load_button.setText(_translate('Opening_Window', 'Load')) - self.label_33.setText(_translate('Opening_Window', 'Node ID Header')) - self.label_34.setText(_translate('Opening_Window', 'Population Header')) - self.results_tabs_widget.setTabText( - self.results_tabs_widget.indexOf(self.data_tab), - _translate('Opening_Window', 'Data'), - ) - self.curve_type_combo.setItemText( - 0, _translate('Opening_Window', 'Quantity Exceedance') - ) - self.curve_type_combo.setItemText( - 1, _translate('Opening_Window', 'Delivery Exceedance') - ) - self.all_scenarios_checkbox.setText( - _translate('Opening_Window', 'All Scenarios') - ) - self.label_23.setText(_translate('Opening_Window', 'Settings')) - self.save_curve_button.setText(_translate('Opening_Window', 'Browse')) - item = self.curve_settings_table.verticalHeaderItem(0) - item.setText(_translate('Opening_Window', 'Percentage')) - item = self.curve_settings_table.verticalHeaderItem(1) - item.setText(_translate('Opening_Window', 'Leak Ratio')) - item = self.curve_settings_table.verticalHeaderItem(2) - item.setText(_translate('Opening_Window', 'Time Unit')) - item = self.curve_settings_table.verticalHeaderItem(3) - item.setText(_translate('Opening_Window', 'Time Shift')) - item = self.curve_settings_table.horizontalHeaderItem(0) - item.setText(_translate('Opening_Window', 'Values')) - __sortingEnabled = self.curve_settings_table.isSortingEnabled() # noqa: N806 - self.curve_settings_table.setSortingEnabled(False) - self.curve_settings_table.setSortingEnabled(__sortingEnabled) - self.label_25.setText(_translate('Opening_Window', 'Scenario')) - self.label_26.setText(_translate('Opening_Window', 'Curve Type')) - self.label_24.setText(_translate('Opening_Window', 'Save Curve Data')) - self.results_tabs_widget.setTabText( - self.results_tabs_widget.indexOf(self.curve_tab), - _translate('Opening_Window', 'Curve'), - ) - self.label_35.setText(_translate('Opening_Window', 'Curve Type')) - item = self.map_settings_table.verticalHeaderItem(0) - item.setText(_translate('Opening_Window', 'Percentage')) - item = self.map_settings_table.verticalHeaderItem(1) - item.setText(_translate('Opening_Window', 'Leak Ratio')) - item = self.map_settings_table.verticalHeaderItem(2) - item.setText(_translate('Opening_Window', 'Time Unit')) - item = self.map_settings_table.verticalHeaderItem(3) - item.setText(_translate('Opening_Window', 'Time Shift')) - item = self.map_settings_table.horizontalHeaderItem(0) - item.setText(_translate('Opening_Window', 'Values')) - __sortingEnabled = self.map_settings_table.isSortingEnabled() # noqa: N806 - self.map_settings_table.setSortingEnabled(False) - self.map_settings_table.setSortingEnabled(__sortingEnabled) - self.label_36.setText(_translate('Opening_Window', 'Settings')) - self.label_37.setText(_translate('Opening_Window', 'Map')) - self.save_map_button.setText(_translate('Opening_Window', 'Browse')) - self.label_38.setText(_translate('Opening_Window', 'Save Map Shape File')) - self.label_39.setText(_translate('Opening_Window', 'Scenario')) - self.map_all_scenarios_checkbox.setText( - _translate('Opening_Window', 'All Scenarios') - ) - self.groupBox_12.setTitle(_translate('Opening_Window', 'Annotation')) - self.annotation_checkbox.setText(_translate('Opening_Window', 'On')) - self.annotation_event_combo.setItemText( - 0, _translate('Opening_Window', 'Mouse hover') - ) - self.annotation_event_combo.setItemText( - 1, _translate('Opening_Window', 'Mouse click') - ) - self.label_40.setText(_translate('Opening_Window', 'Radius')) - self.annotation_radius_line.setText(_translate('Opening_Window', '0')) - self.groupBox_13.setTitle(_translate('Opening_Window', 'Substitute Layer')) - self.spatial_join_button.setText(_translate('Opening_Window', 'Setup')) - self.groupBox_14.setTitle(_translate('Opening_Window', 'Map Appearance')) - self.symbology_button.setText(_translate('Opening_Window', 'Symbology')) - self.major_tick_size_line.setText(_translate('Opening_Window', '10')) - self.label_41.setText(_translate('Opening_Window', 'Grid Font Size')) - self.results_tabs_widget.setTabText( - self.results_tabs_widget.indexOf(self.tab), - _translate('Opening_Window', 'Map'), - ) - self.main_tab.setTabText( - self.main_tab.indexOf(self.post_process), - _translate('Opening_Window', 'Post-Process'), - ) - self.menuFile.setTitle(_translate('Opening_Window', 'File')) - self.menuHelp.setTitle(_translate('Opening_Window', 'Help')) - self.action_Open_Project.setText( - _translate('Opening_Window', 'Open Project') - ) - self.action_Save.setText(_translate('Opening_Window', 'Save')) - self.action_Save_Project_As.setText( - _translate('Opening_Window', 'Save Project As') - ) - self.action_Exit.setText(_translate('Opening_Window', 'Exit')) - self.action_About.setText(_translate('Opening_Window', 'About')) - self.action_REWET_GITHUB.setText( - _translate('Opening_Window', 'REWET GITHUB') - ) - - -from .MplWidget import MplWidget # noqa: E402 - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Opening_Window = QtWidgets.QMainWindow() - ui = Ui_Opening_Window() - ui.setupUi(Opening_Window) - Opening_Window.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/PP_Data_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/PP_Data_Tab_Designer.py deleted file mode 100644 index c438176ec..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/PP_Data_Tab_Designer.py +++ /dev/null @@ -1,158 +0,0 @@ -"""Created on Thu Dec 29 15:41:03 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os - -import pandas as pd -from PyQt5 import QtWidgets -from Result_Project import Project_Result - - -class PP_Data_Tab: # noqa: D101 - def __init__(self, project): - self.pp_project = project - # self.__settings = settings - self.result_scenarios = [] - self.population_data = None - # self.pp_result_folder_addr = result_folder_addr - self.load_results_button.clicked.connect(self.resultLoadButtonPressed) - self.population_browser_button.clicked.connect(self.browsePopulationData) - self.population_load_button.clicked.connect(self.loadPopulationData) - # self.results_tabs_widget.setTabEnabled(1, False) - self.project_result = None - self.current_population_directory = '' - - def initalizeResultData(self): # noqa: N802, D102 - if self.project == None: # noqa: E711 - self.errorMSG( - 'Error', 'No project is found. open or save a new project.' - ) - return - result_directory = self.result_folder_addr_line.text() - self.project_result = Project_Result( - self.project, - iObject=True, - result_file_dir=result_directory, - ignore_not_found=True, - ) - self.clearResultData() - - print(self.project_result.scn_name_list_that_result_file_not_found) # noqa: T201 - for index, row in self.scenario_list.iterrows(): # noqa: B007 - number_of_rows = self.result_file_status_table.rowCount() - scenario_name = row['Scenario Name'] - scenario_item = QtWidgets.QTableWidgetItem(scenario_name) - if ( - scenario_name - in self.project_result.scn_name_list_that_result_file_not_found - ): - status_item = QtWidgets.QTableWidgetItem('NOT Available') - else: - self.result_scenarios.append(scenario_name) - status_item = QtWidgets.QTableWidgetItem('Available') - - self.result_file_status_table.insertRow(number_of_rows) - self.result_file_status_table.setItem(number_of_rows, 0, scenario_item) - self.result_file_status_table.setItem(number_of_rows, 1, status_item) - - if self.read_files_check_box.isChecked(): - for scenario_name in self.result_scenarios: - try: - self.project_result.loadScneariodata(scenario_name) - except Exception: # noqa: BLE001, PERF203 - self.errorMSG('Error', 'Error occurred in reading data') - self.clearResultData() - raise Exception # noqa: B904, TRY002 - return - - self.results_tabs_widget.setTabEnabled(1, True) # noqa: FBT003 - - def clearResultData(self): # noqa: N802, D102 - for i in range(self.result_file_status_table.rowCount()): # noqa: B007 - self.result_file_status_table.removeRow(0) - - def resultLoadButtonPressed(self): # noqa: N802, D102 - # data_retrived = False - # if self.getSimulationSettings(): - # if self.getHydraulicSettings(): - # if self.getDamageSettings(): - # if self.getRestorationSettings(): - # data_retrived = True - - # if not data_retrived: - # return - - self.initalizeResultData() - - def browsePopulationData(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getOpenFileName( - self.asli_MainWindow, - 'Open file', - self.current_population_directory, - 'Excel file (*.xlsx);;CSV File (*.csv)', - ) - if file[0] == '': - return - split_addr = os.path.split(file[0]) - self.current_population_directory = split_addr[0] - - self.population_addr_line.setText(file[0]) - - print(file) # noqa: T201 - if file[1] == 'Excel file (*.xlsx)': - self.population_data = pd.read_excel(file[0]) - elif file[1] == 'CSV File (*.csv)': - self.population_data = pd.read_scv(file[0]) - else: - raise ValueError('Unknown population file type: ' + repr(file[1])) - - self.population_node_ID_header_combo.clear() - self.population_node_ID_header_combo.addItems( - self.population_data.columns.to_list() - ) - self.population_population_header_combo.clear() - self.population_population_header_combo.addItems( - self.population_data.columns.to_list() - ) - - if len(self.population_data.columns.to_list()) >= 2: # noqa: PLR2004 - self.population_population_header_combo.setCurrentIndex(1) - - def loadPopulationData(self): # noqa: N802, D102 - node_id_header = self.population_node_ID_header_combo.currentText() - population_header = self.population_population_header_combo.currentText() - - if node_id_header == population_header: - self.errorMSG( - 'Error', 'Node ID Header and Population Header cannot be the same' - ) - return - - if node_id_header == '' or population_header == '': - self.errorMSG( - 'Error', - 'Node ID Header or/and Population Header is not selected. Maybe an empty population file?', - ) - return - - if self.project_result == None: # noqa: E711 - self.errorMSG( - 'Error', 'No project and data is loaded. Please load the data first.' - ) - return - - self.project_result.loadPopulation( - self.population_data, node_id_header, population_header - ) - - def errorMSG(self, error_title, error_msg, error_more_msg=None): # noqa: N802, D102 - error_widget = QtWidgets.QMessageBox() - error_widget.setIcon(QtWidgets.QMessageBox.Critical) - error_widget.setText(error_msg) - error_widget.setWindowTitle(error_title) - error_widget.setStandardButtons(QtWidgets.QMessageBox.Ok) - if error_more_msg != None: # noqa: E711 - error_widget.setInformativeText(error_more_msg) - error_widget.exec_() diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Designer.py deleted file mode 100644 index 7e29f3fa3..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Designer.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Created on Tue Nov 1 23:25:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from .Damage_Discovery_Designer import Damage_Discovery_Designer - - -class Pipe_Damage_Discovery_Designer(Damage_Discovery_Designer): # noqa: D101 - def __init__(self, pipe_damage_discovery_model): - super().__init__(pipe_damage_discovery_model) - self._window.setWindowTitle('Pipe Damage Discovery') diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Window.py deleted file mode 100644 index 16b9a3bf8..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Discovery_Window.py +++ /dev/null @@ -1,116 +0,0 @@ -# Form implementation generated from reading ui file 'Pipe_Damage_Discovery_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_pipe_damage_discovery: # noqa: D101 - def setupUi(self, pipe_damage_discovery): # noqa: N802, D102 - pipe_damage_discovery.setObjectName('pipe_damage_discovery') - pipe_damage_discovery.resize(450, 400) - pipe_damage_discovery.setMinimumSize(QtCore.QSize(450, 400)) - pipe_damage_discovery.setMaximumSize(QtCore.QSize(450, 400)) - self.buttonBox = QtWidgets.QDialogButtonBox(pipe_damage_discovery) - self.buttonBox.setGeometry(QtCore.QRect(350, 20, 81, 61)) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.groupBox = QtWidgets.QGroupBox(pipe_damage_discovery) - self.groupBox.setGeometry(QtCore.QRect(19, 19, 311, 351)) - self.groupBox.setObjectName('groupBox') - self.leak_amount_line = QtWidgets.QLineEdit(self.groupBox) - self.leak_amount_line.setGeometry(QtCore.QRect(80, 50, 51, 20)) - self.leak_amount_line.setObjectName('leak_amount_line') - self.leak_anount_label = QtWidgets.QLabel(self.groupBox) - self.leak_anount_label.setGeometry(QtCore.QRect(10, 50, 71, 16)) - self.leak_anount_label.setObjectName('leak_anount_label') - self.leak_time_line = QtWidgets.QLineEdit(self.groupBox) - self.leak_time_line.setGeometry(QtCore.QRect(210, 50, 81, 20)) - self.leak_time_line.setObjectName('leak_time_line') - self.time_discovery_ratio_table = QtWidgets.QTableWidget(self.groupBox) - self.time_discovery_ratio_table.setGeometry(QtCore.QRect(10, 141, 211, 191)) - self.time_discovery_ratio_table.setSelectionMode( - QtWidgets.QAbstractItemView.ExtendedSelection - ) - self.time_discovery_ratio_table.setSelectionBehavior( - QtWidgets.QAbstractItemView.SelectRows - ) - self.time_discovery_ratio_table.setRowCount(0) - self.time_discovery_ratio_table.setObjectName('time_discovery_ratio_table') - self.time_discovery_ratio_table.setColumnCount(2) - item = QtWidgets.QTableWidgetItem() - self.time_discovery_ratio_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.time_discovery_ratio_table.setHorizontalHeaderItem(1, item) - self.time_discovery_ratio_table.horizontalHeader().setStretchLastSection( - True - ) - self.time_discovery_ratio_table.verticalHeader().setVisible(False) - self.time_discovery_ratio_table.verticalHeader().setStretchLastSection(False) - self.leak_time_label = QtWidgets.QLabel(self.groupBox) - self.leak_time_label.setGeometry(QtCore.QRect(150, 50, 61, 16)) - self.leak_time_label.setObjectName('leak_time_label') - self.leak_based_radio = QtWidgets.QRadioButton(self.groupBox) - self.leak_based_radio.setGeometry(QtCore.QRect(10, 20, 111, 17)) - self.leak_based_radio.setObjectName('leak_based_radio') - self.time_based_radio = QtWidgets.QRadioButton(self.groupBox) - self.time_based_radio.setGeometry(QtCore.QRect(10, 90, 111, 17)) - self.time_based_radio.setObjectName('time_based_radio') - self.time_line = QtWidgets.QLineEdit(self.groupBox) - self.time_line.setGeometry(QtCore.QRect(10, 120, 101, 20)) - self.time_line.setObjectName('time_line') - self.discovery_ratio_line = QtWidgets.QLineEdit(self.groupBox) - self.discovery_ratio_line.setGeometry(QtCore.QRect(110, 120, 111, 20)) - self.discovery_ratio_line.setObjectName('discovery_ratio_line') - self.add_button = QtWidgets.QPushButton(self.groupBox) - self.add_button.setGeometry(QtCore.QRect(230, 120, 51, 23)) - self.add_button.setObjectName('add_button') - self.remove_button = QtWidgets.QPushButton(self.groupBox) - self.remove_button.setGeometry(QtCore.QRect(230, 150, 51, 23)) - self.remove_button.setObjectName('remove_button') - - self.retranslateUi(pipe_damage_discovery) - self.buttonBox.rejected.connect(pipe_damage_discovery.reject) - QtCore.QMetaObject.connectSlotsByName(pipe_damage_discovery) - - def retranslateUi(self, pipe_damage_discovery): # noqa: N802, D102 - _translate = QtCore.QCoreApplication.translate - pipe_damage_discovery.setWindowTitle( - _translate('pipe_damage_discovery', 'Pipe Damaeg Discovery') - ) - self.groupBox.setTitle(_translate('pipe_damage_discovery', 'Leak Model')) - self.leak_anount_label.setText( - _translate('pipe_damage_discovery', 'Leak Amount') - ) - item = self.time_discovery_ratio_table.horizontalHeaderItem(0) - item.setText(_translate('pipe_damage_discovery', 'Time')) - item = self.time_discovery_ratio_table.horizontalHeaderItem(1) - item.setText(_translate('pipe_damage_discovery', 'Discovery Ratio')) - self.leak_time_label.setText( - _translate('pipe_damage_discovery', 'leak time') - ) - self.leak_based_radio.setText( - _translate('pipe_damage_discovery', 'Leak Based') - ) - self.time_based_radio.setText( - _translate('pipe_damage_discovery', 'Time Based') - ) - self.add_button.setText(_translate('pipe_damage_discovery', 'add')) - self.remove_button.setText(_translate('pipe_damage_discovery', 'Remove')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - pipe_damage_discovery = QtWidgets.QDialog() - ui = Ui_pipe_damage_discovery() - ui.setupUi(pipe_damage_discovery) - pipe_damage_discovery.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Designer.py deleted file mode 100644 index 01b6ff657..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Designer.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Created on Tue Nov 1 18:32:32 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from PyQt5 import QtGui, QtWidgets - -from .Pipe_Damage_Model_Window import Ui_Pipe_Damage_Model - - -class Pipe_Damage_Model_Designer(Ui_Pipe_Damage_Model): # noqa: D101 - def __init__(self, pipe_damage_model): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.pipe_damage_model = pipe_damage_model - self.material_list.addItems(pipe_damage_model.keys()) - self.alpha_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.beta_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.gamma_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.a_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - self.b_line.setValidator( - QtGui.QDoubleValidator( - -1000000, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - - self.buttonBox.accepted.connect(self.okButtonPressed) - - self.material_list.currentItemChanged.connect(self.materialChanged) - - def materialChanged(self, current_item, previous_item): # noqa: N802, D102 - if previous_item != None: # noqa: E711 - previous_material = previous_item.text() - - alpha = self.alpha_line.text() - beta = self.beta_line.text() - gamma = self.gamma_line.text() - a = self.a_line.text() - b = self.b_line.text() - - self.pipe_damage_model[previous_material]['alpha'] = float(alpha) - self.pipe_damage_model[previous_material]['beta'] = float(beta) - self.pipe_damage_model[previous_material]['gamma'] = float(gamma) - self.pipe_damage_model[previous_material]['a'] = float(a) - self.pipe_damage_model[previous_material]['b'] = float(b) - - current_material = current_item.text() - alpha = self.pipe_damage_model[current_material]['alpha'] - beta = self.pipe_damage_model[current_material]['beta'] - gamma = self.pipe_damage_model[current_material]['gamma'] - a = self.pipe_damage_model[current_material]['a'] - b = self.pipe_damage_model[current_material]['b'] - - self.alpha_line.setText(str(alpha)) - self.beta_line.setText(str(beta)) - self.gamma_line.setText(str(gamma)) - self.a_line.setText(str(a)) - self.b_line.setText(str(b)) - - def okButtonPressed(self): # noqa: N802, D102 - current_material = self.material_list.selectedItems()[0].text() - - alpha = self.alpha_line.text() - beta = self.beta_line.text() - gamma = self.gamma_line.text() - a = self.a_line.text() - b = self.b_line.text() - - self.pipe_damage_model[current_material]['alpha'] = float(alpha) - self.pipe_damage_model[current_material]['beta'] = float(beta) - self.pipe_damage_model[current_material]['gamma'] = float(gamma) - self.pipe_damage_model[current_material]['a'] = float(a) - self.pipe_damage_model[current_material]['b'] = float(b) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.py deleted file mode 100644 index 5f6253e95..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.py +++ /dev/null @@ -1,124 +0,0 @@ -# Form implementation generated from reading ui file 'Pipe_Damage_Model_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Pipe_Damage_Model: # noqa: D101 - def setupUi(self, Pipe_Damage_Model): # noqa: N802, N803, D102 - Pipe_Damage_Model.setObjectName('Pipe_Damage_Model') - Pipe_Damage_Model.resize(377, 372) - self.buttonBox = QtWidgets.QDialogButtonBox(Pipe_Damage_Model) - self.buttonBox.setGeometry(QtCore.QRect(260, 50, 81, 91)) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.material_list = QtWidgets.QListWidget(Pipe_Damage_Model) - self.material_list.setGeometry(QtCore.QRect(10, 50, 231, 192)) - self.material_list.setObjectName('material_list') - self.label = QtWidgets.QLabel(Pipe_Damage_Model) - self.label.setGeometry(QtCore.QRect(10, 30, 101, 16)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label.setFont(font) - self.label.setObjectName('label') - self.alpha_line = QtWidgets.QLineEdit(Pipe_Damage_Model) - self.alpha_line.setGeometry(QtCore.QRect(60, 300, 50, 20)) - self.alpha_line.setLayoutDirection(QtCore.Qt.RightToLeft) - self.alpha_line.setText('') - self.alpha_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.alpha_line.setObjectName('alpha_line') - self.label_2 = QtWidgets.QLabel(Pipe_Damage_Model) - self.label_2.setGeometry(QtCore.QRect(115, 302, 16, 16)) - font = QtGui.QFont() - font.setBold(False) - font.setWeight(50) - self.label_2.setFont(font) - self.label_2.setObjectName('label_2') - self.a_line = QtWidgets.QLineEdit(Pipe_Damage_Model) - self.a_line.setGeometry(QtCore.QRect(125, 280, 41, 20)) - self.a_line.setText('') - self.a_line.setObjectName('a_line') - self.label_3 = QtWidgets.QLabel(Pipe_Damage_Model) - self.label_3.setGeometry(QtCore.QRect(165, 300, 16, 16)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_3.setFont(font) - self.label_3.setObjectName('label_3') - self.label_4 = QtWidgets.QLabel(Pipe_Damage_Model) - self.label_4.setGeometry(QtCore.QRect(285, 300, 16, 16)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_4.setFont(font) - self.label_4.setObjectName('label_4') - self.beta_line = QtWidgets.QLineEdit(Pipe_Damage_Model) - self.beta_line.setGeometry(QtCore.QRect(180, 300, 50, 20)) - self.beta_line.setText('') - self.beta_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.beta_line.setObjectName('beta_line') - self.label_5 = QtWidgets.QLabel(Pipe_Damage_Model) - self.label_5.setGeometry(QtCore.QRect(235, 300, 16, 16)) - font = QtGui.QFont() - font.setBold(False) - font.setWeight(50) - self.label_5.setFont(font) - self.label_5.setObjectName('label_5') - self.b_line = QtWidgets.QLineEdit(Pipe_Damage_Model) - self.b_line.setGeometry(QtCore.QRect(245, 280, 41, 20)) - self.b_line.setText('') - self.b_line.setObjectName('b_line') - self.gamma_line = QtWidgets.QLineEdit(Pipe_Damage_Model) - self.gamma_line.setGeometry(QtCore.QRect(300, 300, 50, 20)) - self.gamma_line.setText('') - self.gamma_line.setAlignment( - QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter - ) - self.gamma_line.setObjectName('gamma_line') - self.label_6 = QtWidgets.QLabel(Pipe_Damage_Model) - self.label_6.setGeometry(QtCore.QRect(10, 300, 51, 20)) - font = QtGui.QFont() - font.setBold(False) - font.setWeight(50) - self.label_6.setFont(font) - self.label_6.setObjectName('label_6') - - self.retranslateUi(Pipe_Damage_Model) - self.buttonBox.accepted.connect(Pipe_Damage_Model.accept) - self.buttonBox.rejected.connect(Pipe_Damage_Model.reject) - QtCore.QMetaObject.connectSlotsByName(Pipe_Damage_Model) - - def retranslateUi(self, Pipe_Damage_Model): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Pipe_Damage_Model.setWindowTitle( - _translate('Pipe_Damage_Model', 'Pipe Damage Model') - ) - self.label.setText(_translate('Pipe_Damage_Model', 'Pipe Material')) - self.label_2.setText(_translate('Pipe_Damage_Model', 'D')) - self.label_3.setText(_translate('Pipe_Damage_Model', '+')) - self.label_4.setText(_translate('Pipe_Damage_Model', '+')) - self.label_5.setText(_translate('Pipe_Damage_Model', 'D')) - self.label_6.setText(_translate('Pipe_Damage_Model', 'opening=')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Pipe_Damage_Model = QtWidgets.QDialog() - ui = Ui_Pipe_Damage_Model() - ui.setupUi(Pipe_Damage_Model) - Pipe_Damage_Model.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.ui deleted file mode 100644 index 24a419705..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pipe_Damage_Model_Window.ui +++ /dev/null @@ -1,269 +0,0 @@ - - - Pipe_Damage_Model - - - - 0 - 0 - 377 - 372 - - - - Pipe Damage Model - - - - - 260 - 50 - 81 - 91 - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 10 - 50 - 231 - 192 - - - - - - - 10 - 30 - 101 - 16 - - - - - 75 - true - - - - Pipe Material - - - - - - 60 - 300 - 50 - 20 - - - - Qt::RightToLeft - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 115 - 302 - 16 - 16 - - - - - 50 - false - - - - D - - - - - - 125 - 280 - 41 - 20 - - - - - - - - - - 165 - 300 - 16 - 16 - - - - - 75 - true - - - - + - - - - - - 285 - 300 - 16 - 16 - - - - - 75 - true - - - - + - - - - - - 180 - 300 - 50 - 20 - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 235 - 300 - 16 - 16 - - - - - 50 - false - - - - D - - - - - - 245 - 280 - 41 - 20 - - - - - - - - - - 300 - 300 - 50 - 20 - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 10 - 300 - 51 - 20 - - - - - 50 - false - - - - opening= - - - - - - - buttonBox - accepted() - Pipe_Damage_Model - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Pipe_Damage_Model - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Pump_Damage_Discovery_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Pump_Damage_Discovery_Designer.py deleted file mode 100644 index e63358d0a..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Pump_Damage_Discovery_Designer.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Created on Tue Nov 1 23:25:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from .Damage_Discovery_Designer import Damage_Discovery_Designer - - -class Pump_Damage_Discovery_Designer(Damage_Discovery_Designer): # noqa: D101 - def __init__(self, pump_damage_discovery_model): - super().__init__(pump_damage_discovery_model) - self._window.setWindowTitle('Pump Damage Discovery') - self.leak_based_radio.setEnabled(False) diff --git a/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource.qrc b/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource.qrc deleted file mode 100644 index cdf22dff5..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource.qrc +++ /dev/null @@ -1,15 +0,0 @@ - - - resources/both_logos.jpg - resources/us_nsf.jpg - resources/UDPrimaryLogo2945web.jpg - resources/first_damage.png - resources/node_A.png - resources/node_B.png - resources/node_C.png - resources/node_D.png - resources/node_E.png - resources/node_F.png - resources/second_damage.png - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource_rc.py b/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource_rc.py deleted file mode 100644 index 11273d7ec..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/REWET_Resource_rc.py +++ /dev/null @@ -1,6963 +0,0 @@ -# Resource object code # noqa: N999, D100 -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.12.9) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b'\ -\x00\x00\x02\xd7\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x45\x00\x00\x00\x1b\x08\x02\x00\x00\x00\xa5\x6b\xd5\xf9\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x6c\x49\x44\x41\x54\x58\x47\xed\x98\xb1\xce\ -\x29\x51\x10\xc7\xb9\x6f\xe0\xf2\x06\x14\x12\x25\x9d\x8a\x02\x89\ -\xde\x55\x6a\x91\x48\x68\x24\x3c\x01\x85\xda\x1b\xf0\x02\xb4\x0a\ -\x0a\x05\x09\x89\x12\x05\x2d\x11\x4f\xb0\xf7\x97\x9d\x73\x8f\xb5\ -\xbb\xf7\xcb\x0d\xb7\x58\x5f\xf6\x57\x9c\x6f\x66\xf6\xec\xec\xf9\ -\xcf\xcc\x12\x5f\xd0\x30\x8c\xc0\x37\xe2\x87\xfa\xfb\x5d\xf0\xf5\ -\x78\x9b\x0f\xd0\x73\xbd\x5e\x63\xb1\xd8\x78\x3c\x56\xbe\x89\x6b\ -\x10\x3e\x40\xcf\x60\x30\xe0\xe8\xa7\xd3\x49\xf9\x26\xae\x41\x70\ -\xd7\x73\x3c\x1e\x83\xc1\xe0\x62\xb1\x50\xfe\x4b\xf4\xfb\x7d\x92\ -\xd8\xf2\x50\xd7\x9f\x26\xdb\xed\x56\x22\xb2\x47\x20\xce\x5d\x12\ -\x17\xa6\xd3\x29\x6b\x36\x9b\x15\x57\x70\x0d\x2a\xf8\xbc\x76\x92\ -\xcf\xe7\xa3\xd1\xe8\x68\x34\x52\xfe\xab\xa4\x52\x29\x52\x4d\x26\ -\x13\xe5\x1b\x46\xa7\xd3\x09\x85\x42\xac\xca\x37\x0c\xae\x72\x8c\ -\xcb\xe5\x82\xcd\x13\xb1\x37\x9b\x8d\x5c\x22\x48\x06\x56\xf6\x90\ -\xe7\x8b\xa0\xc6\xa5\x3f\x94\x33\x99\x4c\xba\x76\x13\x0a\x85\x82\ -\x2e\xad\xc0\x10\x77\xbb\x5d\xe5\x3c\x43\x51\x58\x77\xbb\x9d\xb8\ -\xdc\xb8\x5e\xaf\x31\xd2\xe9\xb4\x44\xe0\x7c\x3e\x73\xbe\x70\x38\ -\x8c\x5d\x2e\x97\x59\x97\xcb\xa5\x79\x25\x50\xaf\xd7\x57\xab\x55\ -\x24\x12\x29\x16\x8b\x12\x01\xd7\xa0\xc6\x45\x4f\xb3\xd9\x6c\xb5\ -\x5a\xca\x71\x50\xa9\x54\x32\x99\x8c\x96\x84\x98\x5a\xad\x56\x2a\ -\x95\xc4\xb5\xc2\x1e\xf4\x30\x15\xf7\xfb\x5d\x22\xed\x76\xbb\xd1\ -\x68\xdc\x6e\xb7\x78\x3c\x2e\x11\x98\xcd\x66\xb9\x5c\x4e\x6c\xe6\ -\x9c\x35\x91\x48\xb0\x92\xf9\x70\x38\x48\xdf\xe6\xf3\xf9\x7e\xbf\ -\x67\x56\x5d\x83\xe6\xad\x7f\x30\xbb\xf4\xa0\xd7\xeb\xc9\x98\xd1\ -\x4a\x6c\x09\xda\x60\x03\x33\xc3\x54\x68\x43\x5d\x78\x66\x38\x1c\ -\xb2\x81\x24\x32\x15\x62\x13\x44\xa4\x6c\x10\xc8\x20\x03\x49\x1e\ -\x1a\x05\xd8\x9c\x55\x8e\x87\x81\x2b\x7d\xae\x56\xab\xce\xa0\xed\ -\x90\x4f\x7a\xd0\xad\x27\xf2\x97\x89\xd8\x4e\x44\xc9\x17\x62\x80\ -\xdb\xa9\xa5\x4c\xb9\x1e\x7a\x82\x1c\x4b\xed\x30\x35\xc8\x11\x81\ -\x6c\x5c\x92\xda\xbf\xcc\x93\x1e\x5d\x00\xc1\xf9\xb6\x69\xfe\x45\ -\x8f\xf4\x41\x2a\xad\xdb\x4e\x50\x0c\x81\x76\x91\x44\x39\xff\x83\ -\x87\x1e\x1e\x6c\x9d\x04\x3d\x27\x4e\x44\x0c\x4a\xb4\xa1\x2e\x58\ -\x20\x9b\xb4\x97\x7a\xeb\xd2\xd0\x2e\x6c\xeb\x7e\x5b\xbb\xde\xe7\ -\xa1\x87\x79\xb0\x56\x8e\xc7\xc8\x28\xdb\xb0\x69\xf8\x9b\x24\x3e\ -\x91\xf5\x87\xb2\xd6\x40\x8d\xb0\xf5\x44\x89\x54\xdb\x0b\xf0\x26\ -\x4a\x0f\x75\x22\xb5\x2e\x95\x3c\x18\xe4\x4d\xb5\xe2\x1c\x71\x24\ -\x59\xbf\x4f\x40\x66\x0c\xe4\xc5\x15\x74\x50\xb7\x1d\x43\x22\xd6\ -\x6d\x6f\xe2\xff\xfe\xf1\x36\xbe\x1e\x6f\xe3\xeb\xf1\x36\xbe\x1e\ -\x6f\xe3\xeb\xf1\x36\x9f\xa7\x87\x1f\xc8\xb6\xff\x31\x3c\x08\x04\ -\x7e\x03\x32\xd4\x1d\x05\x0b\xb9\xf1\x3b\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x02\xb7\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x44\x00\x00\x00\x17\x08\x02\x00\x00\x00\x3d\x6b\x7e\xbc\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x4c\x49\x44\x41\x54\x58\x47\xed\x96\x31\xb2\ -\x29\x51\x10\x86\xe7\xbe\x1d\x60\x07\x08\x85\x28\x81\x44\x64\x09\ -\xec\x40\xd9\x81\x62\x05\xac\x40\xd9\x00\x1b\x20\x90\xa8\x42\x20\ -\x14\x4a\x24\x02\x11\xb6\xe0\x7d\x6f\xfe\xf3\xda\x99\xe1\xde\xaa\ -\x3b\xd1\x94\xf2\x05\x9c\xd3\x7d\xa6\x4f\xff\xdd\x6d\xee\xfd\xba\ -\xdf\xef\xc1\xbb\xf0\xc7\x7d\xbf\x05\x29\x15\x53\xa9\x54\xbe\x42\ -\xb2\xd9\xec\x68\x34\x92\xf1\x7a\xbd\xca\x08\xc5\x62\x71\xb1\x58\ -\xc8\xfe\x80\x31\x4b\x21\xd3\xe9\xb4\xd5\x6a\xb1\xd8\x6c\x36\x99\ -\x4c\x86\xad\xec\xdd\x6e\x77\x3c\x1e\xb3\xe0\x93\xe4\x8f\xc7\xa3\ -\xec\x22\xd2\x19\xa7\x3a\x04\xe9\x56\x92\xc4\x6c\xb7\x5b\x17\x2e\ -\x84\x98\xb3\xd9\xcc\xf9\xa2\xd7\xd1\x81\xc1\x60\xe0\x1c\x41\xb0\ -\x5e\xaf\x1b\x8d\x06\x8b\x7a\xbd\xde\xeb\xf5\x4e\xa7\x93\xec\xcb\ -\xe5\xb2\x56\xab\xb1\xe8\x74\x3a\xcd\x66\xf3\x7c\x3e\xcb\xee\x70\ -\xa2\x42\xe6\xf3\x39\x96\xcb\xe5\xc2\x9a\x62\x50\x92\x7e\xbf\x2f\ -\x57\x62\x88\x50\x2e\x97\xb5\x1e\x0e\x87\xc4\xb7\x72\xfa\xd7\xd1\ -\x01\xd6\xd6\x81\x42\xa1\xb0\xdf\xef\xb5\x26\x02\x0f\xb2\xe0\x41\ -\x52\x92\x11\x08\xcb\x53\x6e\x13\x12\x11\x43\x2c\xbb\x18\x88\x12\ -\x53\x2b\xb0\xdb\xad\x82\x8b\xa9\x93\xdb\x44\x61\x5a\x98\x0d\xad\ -\xc9\x86\x80\x96\x01\xa3\x42\xd2\x5a\x03\x6b\x25\x4d\x34\xb3\x23\ -\x15\x01\x7a\x84\xf3\x16\x4a\xe3\xa7\x42\x18\x91\x5c\x39\x6a\xa7\ -\x41\xd5\xb2\x0a\x19\x58\xfc\x39\x8e\x6d\x63\xf8\x2e\xb5\xc2\x3a\ -\xe3\xeb\x24\x2d\xeb\x0c\x92\x64\x27\x32\xc5\xb5\x33\xd4\x4b\x07\ -\x88\xf3\xf2\xc6\x88\x18\xea\xe1\x9f\x90\x98\x98\x7a\x61\x02\x7e\ -\x56\x82\xd7\xb2\x57\x06\xfe\xdc\xda\x83\x4a\x5a\x43\x21\x55\xc2\ -\x7a\x05\x2a\x84\xe0\x24\x5b\xd9\x7d\x1e\x62\x34\x03\x56\x36\x20\ -\x10\xf7\xb9\xcd\x13\x92\x61\x09\xbd\x44\xef\x1c\x11\xab\x94\x74\ -\x0a\x82\x70\xd7\xcb\xaa\xfd\x8a\xc7\xdb\xec\x70\x38\x70\x5f\x3e\ -\x9f\x77\xfb\x20\x98\x4c\x26\xed\x76\xdb\x6d\x12\xb1\x5a\xad\xec\ -\x0d\x7b\xbb\xdd\xaa\xd5\xaa\x73\x04\xc1\x6e\xb7\x43\x03\x2e\xb5\ -\xa2\x54\x2a\xe5\x72\x39\xb9\x92\x13\x4a\xfa\x07\x03\xe0\xff\x60\ -\xd4\x16\xbf\x51\x3e\x36\x5d\xb6\x70\x8e\x28\xb8\xf4\x67\x01\xfc\ -\x99\x01\x44\x4a\x27\x70\xef\x77\xef\x8f\x5f\xf1\x10\xc3\x20\xea\ -\x62\xf2\x23\xfa\x0f\x29\xc6\x04\x7c\xa7\x47\x53\xae\x17\x11\xf8\ -\x19\xab\x1b\xa6\x8d\x67\xfd\xb2\x26\xc6\x85\x50\x38\x41\x66\x5c\ -\x4c\x8a\x72\x3d\x43\x12\x31\x2f\xdb\xe7\xd2\xba\x70\xff\xb3\xd4\ -\x15\xaa\x17\x87\xe5\x92\x54\xfd\x5c\xad\x51\x89\xf9\xfc\xd7\x9c\ -\x56\x3e\x62\xd2\xca\x47\x4c\x5a\xf9\x88\x49\x2b\x6f\x24\x26\x08\ -\xfe\x02\x7d\x51\xf9\x70\x59\x9e\xf7\x68\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x07\x42\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x01\x20\x00\x00\x00\x20\x08\x02\x00\x00\x00\x3d\x96\x32\x63\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x06\xd7\x49\x44\x41\x54\x78\x5e\xed\x9c\x3d\x8f\ -\x4e\x5d\x14\x86\x1f\xef\x0f\x18\x41\x37\xd3\xa1\x20\x4c\x33\x83\ -\x86\x28\x11\x95\x42\x42\xb4\x8a\x89\x69\x27\x99\x49\x4c\x4b\x41\ -\xa1\x14\x0a\x35\x11\x85\x86\x04\x85\xc2\x5b\x48\x7c\x64\x84\x44\ -\xc3\x34\x44\x65\x86\x7f\x30\xef\x65\xdf\xdb\x7a\xf7\xb3\xcf\x87\ -\xf3\xcc\x9c\x3d\x92\xc9\xba\x8a\xc7\xfe\xde\xf7\x5a\x6b\xaf\x7d\ -\xce\x11\xb1\x6d\x6d\x6d\x6d\xe0\x38\x4e\x19\xfe\x89\x7f\x3a\x8e\ -\x53\x00\x4f\x30\xc7\x29\x88\x27\x98\xe3\x14\xc4\x13\xcc\x71\x0a\ -\xe2\x09\xe6\x38\x05\xf1\x04\x73\x9c\x82\x78\x82\x39\x4e\x41\x3c\ -\xc1\x1c\xa7\x20\x9e\x60\x8e\x53\x90\xad\x90\x60\x2b\x2b\x2b\xdb\ -\x86\xa1\xf1\xf1\xe3\xc7\xb1\x12\x38\x75\xea\x94\x46\x5e\xbf\x7e\ -\xfd\xfc\xf9\xf3\x61\xde\x5f\x60\x71\x71\x31\x0a\x0a\x20\x86\xc6\ -\xc3\x87\x0f\xc7\x7a\xe0\xdf\x00\x82\x29\xef\xdd\xbb\x77\x79\x79\ -\x59\x73\xb7\x06\x59\x5c\x14\x8b\xcc\x2d\xb7\x6f\xdf\xa6\x11\xc3\ -\x67\x67\x67\xe5\xa2\xcd\x27\x3b\x54\x3b\x77\xee\xa4\xb1\x2a\x5e\ -\x27\x8a\x5e\xaa\xb5\x52\xb7\x42\x82\xed\xda\xb5\xeb\xd2\xa5\x4b\ -\xb7\x6e\xdd\x5a\x0b\x9c\x3c\x79\x92\xc6\xd3\xa7\x4f\xef\xd9\xb3\ -\x67\x69\x69\x89\x16\x7e\xa7\xa7\xa7\xf1\xc5\x8d\x1b\x37\xe8\xfa\ -\xf9\xf3\x67\x98\xf7\x17\xb8\x78\xf1\xe2\x8e\x1d\x3b\xa4\x13\xc1\ -\x07\x0f\x1e\xa4\x71\x6e\x6e\xee\xdc\xb9\x73\x6a\xa4\xb0\x7f\xff\ -\xfe\x2b\x57\xae\x5c\xbb\x76\xed\xfb\xf7\xef\x24\xd8\x83\x07\x0f\ -\x34\x77\x6b\x90\xc6\xe5\xd1\xa3\x47\x53\x53\x53\x34\xa6\x6e\xb9\ -\x7c\xf9\xf2\x81\x03\x07\xde\xbd\x7b\x87\xe1\xab\xab\xab\x9a\xb5\ -\xf9\xa4\x87\x8a\x40\x1c\x39\x72\x84\xc6\xaa\xf8\x8f\x1f\x3f\xbe\ -\x7d\xfb\x16\x9d\x54\x17\x16\x16\x34\x77\x88\x60\xd4\x68\xbc\x78\ -\xf1\x22\x4e\x4e\xe0\x40\xc4\xee\xd1\x61\xae\x16\x61\xe5\xd8\x14\ -\xac\xc2\xe9\x20\x7b\x40\x63\x04\xed\xe9\x8e\x98\xfd\xf9\xf3\x67\ -\x46\x5a\x23\x55\x1a\x29\xe0\xa3\x74\x59\xca\x64\x60\xac\xac\x97\ -\xcc\x03\x6c\x74\xf7\xee\xdd\xd8\xf7\x3b\xc3\x0d\x72\x06\x5b\xd4\ -\xc5\x30\xc2\x46\xc1\x32\x0a\x68\xa1\x9d\x31\xea\x4a\xa1\x25\x15\ -\xbf\x0e\x32\xa9\x22\x55\x3b\x2a\x5d\x82\x55\xf5\x0f\xe7\x4f\x23\ -\x2d\x2e\xac\x63\x2b\x98\x5b\xb2\xd0\x30\x06\x62\x65\xbd\xb0\x42\ -\xd4\x11\x38\x74\xe8\x90\x9d\xa8\xaa\xce\xd4\x33\x54\x51\xcb\x18\ -\xd3\x50\x2b\x5e\xd0\x55\x7b\xae\xda\x12\x8c\x55\x9a\xce\x22\xd7\ -\x0c\x42\x63\x65\x6d\x8d\xb2\x79\x70\x7d\xb0\x02\x7b\xa5\x8b\xb0\ -\x05\x01\xe3\x37\xd6\xc3\x9d\x81\x17\x74\x58\x71\x04\x65\x79\x0a\ -\xdb\x82\x7f\x7e\x61\x2b\x68\x80\xb0\xf3\x0d\xf8\xa5\xc9\xa8\x91\ -\x48\x3d\xa0\x10\x22\x43\x55\xb6\xa3\x2a\x25\x0a\x89\x65\x0e\x85\ -\xa0\xe8\x57\x98\xd5\x02\x0c\x50\x63\x6a\x2c\x60\x5d\xd6\x52\xa5\ -\x25\x46\x46\x2a\x55\x99\x90\x1d\x8e\x51\xe9\x12\xac\x74\x53\xac\ -\xa6\x57\xe5\x34\x2e\x6a\x01\x73\x4b\x66\x0b\xd6\x41\xac\x6c\x00\ -\x94\x48\x1b\xe6\x73\xb5\x29\x49\x44\xaa\x93\xbd\xd0\xa0\x38\xa6\ -\x87\xca\xdc\x55\x2b\x5e\x60\x82\x1d\x80\x94\x75\xbe\x22\xfe\xf8\ -\xf1\xe3\xc4\x89\x13\xb1\x12\x9e\xa7\x13\x13\x13\xb1\xf2\x1b\xbe\ -\x22\x78\xd0\xc7\x4a\xe0\xde\xbd\x7b\xbc\x6d\xc7\xca\x30\x3a\x64\ -\x1f\x3e\x7c\x50\x95\x89\x6f\xde\xbc\xa1\x70\xf4\xe8\x51\xb5\xc0\ -\x97\x2f\x5f\xf0\x05\x7b\x51\xd6\xbb\xfb\xcb\x97\x2f\xf9\x7d\xf6\ -\xec\x99\x1e\x08\x38\x68\x6c\x6c\xec\xd7\xd0\xc1\xe0\xe1\xc3\x87\ -\x7a\xbe\x13\x33\x4d\xf9\x23\x68\x43\x61\xac\x04\x90\xa1\x8f\xb7\ -\x2a\x78\x93\x6f\x27\x95\xcf\x9e\x3d\xcb\xef\xb7\x6f\xdf\x54\xfd\ -\xfa\xf5\x2b\xbf\xfb\xf6\xed\xe3\x77\xf7\xee\xdd\x38\xca\xbe\xa3\ -\x58\x5f\x97\x82\x49\x62\x0b\x5e\x30\x68\x21\x8a\xdb\xb7\x6f\x57\ -\x23\xd0\x7e\xff\xfe\xfd\xab\x57\xaf\xc6\xfa\x06\x40\xaa\x05\x8b\ -\x7d\x79\xdb\x39\x76\xec\x98\xaa\x46\xef\xc1\x4a\x37\xbd\x70\xe1\ -\x02\x07\x46\xeb\x5b\x5c\x2c\xa9\xc0\xdc\x82\xbb\x62\xd3\x9f\x18\ -\x49\x30\x62\x26\x27\x27\x29\x60\xfe\x99\x33\x67\xa8\xaa\x1d\x9a\ -\xe2\x98\x1e\xaa\xf1\xf1\xf1\xd0\x5f\x2f\x1e\xd8\x77\x66\x66\xa6\ -\x5e\x3c\xa3\x9b\x60\xe9\xa6\xdb\x11\x17\x2b\xad\xd9\x4f\x5b\x56\ -\x21\xdd\xed\x9d\xa1\x5a\x4d\xd1\x55\xcd\x76\x76\x05\xea\x82\x44\ -\x1e\xf6\xab\x05\x30\xd8\x06\xc8\x47\xd2\xc0\x60\x69\xe0\x7e\x92\ -\x60\xdd\xd3\xda\x8b\x5f\xdc\x41\x41\x30\xd2\x6e\xac\x0c\x46\x32\ -\x0b\x9d\xb5\xd5\x8c\xb4\x2b\x93\xca\x16\xe9\x1d\xc9\x76\x12\x80\ -\x5a\x66\xa9\x91\xb9\xd2\x8c\xd5\xf6\xba\xc8\x30\xd3\x6c\x37\x2e\ -\x03\x42\x67\x3d\x2d\x31\x32\xcc\x15\x2d\x64\xd1\xc9\xaa\x29\xd2\ -\xf6\xc7\x60\x31\xdd\x1e\x71\xac\xa6\x93\x56\xfb\xfc\xa4\xaa\xde\ -\x2a\x69\xc4\x33\x46\x12\x9c\x6a\x63\xc1\x34\x3a\xcc\x62\xae\xca\ -\xa9\x15\x18\x95\x79\xbe\x56\x3c\xb0\xa0\xf6\xad\x95\xba\x9e\x04\ -\xd3\xe1\x36\x6a\xad\x12\x66\x76\x8b\xfd\xc0\x51\x63\x80\x6d\xa7\ -\x72\x76\x4c\x81\x15\x14\x33\xd6\xe1\xd4\x2a\x4f\xe4\x14\x43\x87\ -\x15\x53\x63\x3d\xa0\xa3\x0c\xb1\x1e\xa8\x7a\x0a\x58\x59\x1e\xb7\ -\x42\xec\x18\x86\x5e\x56\x50\x24\x10\xc0\xc8\xd4\xb9\x68\x50\x46\ -\x31\x80\x02\xbd\x1a\x89\x60\x6d\x2d\x58\x84\x98\xc5\x4a\x80\x91\ -\x61\x81\xff\x5f\x1a\x21\x0b\x73\x46\x53\x8c\x0c\x49\x35\xec\xd0\ -\x57\xb1\x18\x59\x21\x76\x0c\xd3\x25\x58\xda\x14\xeb\x28\xa7\xfe\ -\x51\x5c\x32\xc1\x72\x4b\x66\xa6\xb2\xce\x88\xad\xc3\x74\x17\x2c\ -\x6d\xe8\xa1\xcc\x6a\xe6\x04\xe9\xac\xc6\x91\x72\xd8\x76\x68\xdf\ -\x5a\xf1\x6c\xad\x91\x22\xb6\x26\xe4\x4d\xd8\x19\xc7\x56\x30\x17\ -\xb0\xa8\x79\x53\xa7\xbc\x05\x19\xdf\x62\x3f\x70\x22\x31\x12\xab\ -\x50\x8f\x17\x58\x93\x5f\x3b\xa6\x42\xbe\x10\xac\x46\x97\xe2\xd7\ -\x3b\x6c\x24\xc1\x28\x8f\x4d\x15\x14\x27\x81\x2b\xb2\x91\xcc\x8d\ -\x7d\x83\x01\x3a\x15\xbf\x1e\xe9\x12\x23\x03\xa9\x16\xa3\x4d\x0b\ -\x56\xe6\x9f\xaa\xaa\xbe\xe8\x28\x38\x4a\x09\xe9\x91\x5e\xac\xed\ -\x71\xec\x85\xfc\x1b\x6c\x7e\x7e\x3e\xf6\x54\x6e\x47\xba\x34\xe6\ -\xfd\xfb\xf7\xf6\x7a\xfd\xea\xd5\x2b\x15\x36\xc2\xeb\xd7\xaf\x79\ -\x7f\xe5\xf3\xe9\xc9\x93\x27\x77\xee\xdc\x99\x9b\x9b\xe3\x5d\x99\ -\xc6\xe3\xc7\x8f\xc7\x11\xe1\x73\x0b\x3f\x4a\x09\x1f\x2d\x37\x6f\ -\xde\xec\xf8\x65\x55\x82\xe7\xcf\x9f\x13\x36\x94\x10\x2d\xc4\xe8\ -\xef\x70\x05\x1f\x06\x7c\x6f\x28\xde\x78\x0f\xcd\xdd\xbf\x2b\x3a\ -\xd2\x25\x46\x06\x52\x37\x3f\x58\xe6\x1f\xf8\xf4\xe9\x53\x55\xd5\ -\x66\xf2\xf4\xe9\x53\x12\x09\x25\xf8\x6a\x65\x65\x25\xfd\xfe\x6c\ -\x89\x63\x6f\x04\x27\xd4\x93\x05\xcf\xe0\xd2\x4a\x73\xdd\x9e\x66\ -\x55\x74\xc1\x70\xda\xac\x10\x3b\x12\xb0\x4d\x46\x72\x11\xa2\x47\ -\x3b\x72\x47\x52\x4e\xc7\x33\x26\xbd\x23\x0b\xc1\x8e\xe8\x44\xad\ -\x15\x62\xc7\x30\x74\x29\x66\x90\xdd\xd0\xb4\xd3\xab\x32\xd3\xdb\ -\x3d\xbc\x71\x9a\x62\x64\x20\xc6\xde\x88\xda\xe9\x31\x58\x4c\x6f\ -\x72\x5d\x8f\x74\x11\x4c\xa3\x69\x93\xce\xf4\x09\xc6\xac\xa6\x38\ -\xf6\xc5\xc8\x09\x26\xcf\x9a\x31\x1c\xfa\xa6\x00\x67\x66\x37\x79\ -\x81\x57\x5b\xbd\xf8\x82\xad\xcc\xd6\x94\xd9\x4b\xed\xda\xb4\x84\ -\xfd\x29\x6c\x8d\x42\x3b\x19\x59\xd5\xd0\x0b\xba\xc5\x29\xf3\x00\ -\xb7\x8f\x55\xab\x11\xed\x9d\xf6\x04\x93\xd4\x2e\x09\xd6\x63\xb0\ -\x32\xff\x14\xa2\xbb\x60\xc4\xc4\xca\x70\x16\xb5\xc7\xb1\x2f\x46\ -\x4e\x30\x74\x20\x2b\xa5\xe9\xdc\x33\xd2\x9c\x2e\xf0\x82\x85\x47\ -\x60\x9e\x16\x49\xe3\x61\x8d\xb6\x3b\x05\xb5\x14\x0d\x1b\x86\x64\ -\x11\xa2\x5a\xf5\x80\x94\x80\xaa\x18\x45\xd9\x5e\x42\xd4\x65\x3e\ -\x21\xa2\xa4\x1c\x99\xa6\x6a\xef\xd4\xc6\xc8\x90\x18\x88\xf5\x66\ -\x7a\x0c\x96\xaa\xa0\x6a\x21\x46\x12\x6c\xda\x98\x45\x1e\x4a\xbf\ -\xba\x40\x5d\x69\x1c\x7b\xc4\xff\x57\x29\xc7\x29\x88\xff\x6b\x7a\ -\xc7\x29\x88\x27\x98\xe3\x14\xc4\x13\xcc\x71\x0a\xe2\x09\xe6\x38\ -\x05\xf1\x04\x73\x9c\x82\x78\x82\x39\x4e\x41\x3c\xc1\x1c\xa7\x20\ -\x9e\x60\x8e\x53\x10\x4f\x30\xc7\x29\xc6\x60\xf0\x1f\x89\x59\x21\ -\xd8\x7f\xb3\x61\x57\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ -\x82\ -\x00\x00\x04\x57\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x83\x00\x00\x00\x17\x08\x02\x00\x00\x00\xa7\x08\x6b\x64\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x03\xec\x49\x44\x41\x54\x68\x43\xed\x98\x3d\x2f\ -\x74\x41\x14\xc7\xd7\xf3\x05\xbc\x75\x0a\x05\x8d\x44\x21\x11\x2f\ -\x8d\x4a\x81\xa8\x25\x44\xab\x5a\xad\x84\x84\xf8\x00\x5a\x09\xe1\ -\x13\xac\x42\xa1\xa1\x91\x50\xd0\x69\xa8\xb6\x59\x2a\xd9\xca\xcb\ -\x47\xe0\xb7\xf3\x9f\xe7\xec\xec\xdc\x67\x37\xbb\x5c\x9e\x5b\xdc\ -\x5f\x71\xcd\x9c\x39\x77\xe6\x3f\x73\xce\x9c\xbb\xd1\xf5\xf1\xf1\ -\x51\xc8\xc9\x00\x7f\xfc\xdf\x9c\xff\x4d\x1e\x89\xac\x90\xe9\x48\ -\x5c\x5c\x5c\x74\x05\xac\xac\xac\x60\x9c\x9c\x9c\xf4\x7d\xc7\xc3\ -\xc3\x03\xc6\xdb\xdb\xdb\x85\x85\x05\x9e\xee\xbd\xdf\xe6\xf5\xf5\ -\xd5\xab\x71\xf4\xf5\xf5\x61\xdc\xd9\xd9\xf1\x7d\xc7\xf1\xf1\xf1\ -\xd3\xd3\xd3\xfa\xfa\x3a\x6d\x1c\xd8\x9a\xde\x35\x32\x1d\x89\xc5\ -\xc5\xc5\xe1\xe1\xe1\xfb\xfb\x7b\x3e\x66\xe7\xe7\xe7\xe3\xe3\xe3\ -\x18\x37\x36\x36\x96\x97\x97\xb1\xc0\xc4\xc4\xc4\xd8\xd8\xd8\xc9\ -\xc9\xc9\xf3\xf3\x73\xa5\x52\xd1\x5b\xbf\x4f\x7f\x7f\x7f\xb1\x58\ -\x3c\x3a\x3a\x42\xd2\xcb\xcb\xcb\xd4\xd4\x14\xc6\xb5\xb5\xb5\xde\ -\xde\x5e\xe9\xdc\xde\xde\x1e\x1d\x1d\x3d\x3d\x3d\x45\x2d\x5d\x9c\ -\xf7\xf7\xf7\xf5\x6e\x1d\xb9\x8a\x9b\x9b\x1b\x6f\x0d\x28\x95\x4a\ -\x7e\xb8\x73\xe6\xe7\xe7\x35\x89\xef\x3b\xb4\x0a\x87\x88\x68\xeb\ -\x1a\x1c\x3d\x87\x2e\xcf\xc7\xc7\x47\xba\x34\xf6\xf6\xf6\x70\x93\ -\x91\x6d\x20\x89\x77\x2d\x1e\x82\xb5\xcc\xe7\xcb\x98\x60\xc1\x12\ -\x12\x09\x49\x9d\xe1\xc9\xd0\x45\x2d\x3e\x48\x95\x85\x51\xa4\xd2\ -\x60\x4e\x59\x0c\x86\xcc\xcd\x68\x38\x23\x20\x7a\x9c\x91\xda\x88\ -\x20\xaa\xdf\xd9\x1e\x33\x68\x6f\xb6\x1f\x90\xc5\x8e\x1b\xc2\x45\ -\x51\x6f\xa9\x84\x62\xb7\xeb\x1a\xb2\x00\x7b\x96\x25\xda\x4c\x2a\ -\x91\x40\x27\x33\x4b\x9b\xf2\x40\xa7\x29\x42\x9d\xac\x8e\x27\x3e\ -\xb4\x79\x3a\x45\x35\x4c\x03\x2f\xca\x12\x45\x82\x25\xa2\x1c\x12\ -\x71\x75\x62\xd2\xb9\xb9\x39\xb5\xb9\x74\x5c\xb4\x99\x99\x19\x75\ -\x05\xc5\x8e\x8a\x4c\x65\xf4\x7d\x07\xe5\x2f\x59\xf8\x80\xa2\x31\ -\x3b\x3b\x4b\xa3\x5c\x2e\xcb\x42\xb9\xec\xe9\xe9\xa1\x31\x3d\x3d\ -\x2d\x0b\x84\x8b\xae\xae\xae\xbe\xbf\xbf\xab\xfa\x9f\x9d\x9d\xe9\ -\xca\xdb\xae\xb0\xbf\xbd\xbd\x61\x61\xc3\x83\x83\x83\x32\xb6\xa6\ -\x53\xc1\x3c\x47\x46\x46\x78\x0e\x0d\x0d\xa1\x8a\xd7\xdd\x48\x0d\ -\x74\xf2\x95\x52\x7b\x69\x69\x89\x67\xb5\x5a\xe5\x79\x79\x79\xa9\ -\xc3\x25\x3c\x03\x03\x03\x6e\xbc\x40\xcd\x54\x5d\x65\x1e\x59\x00\ -\x19\xbb\xbb\xbb\x07\x07\x07\xbe\x1f\x82\x6b\x08\xf9\xa8\xf7\x5b\ -\xc0\xb9\x58\x6d\x49\x76\x43\x38\x47\xf2\x8b\xa4\x50\x96\xe1\x83\ -\x27\x46\xd5\x1c\x83\x45\xed\x8a\xe8\x1e\xd0\xc0\x39\x79\x23\xd9\ -\x6a\x94\x62\x02\x67\xe6\x0c\xef\x59\x48\x47\x82\x43\x6d\xb8\xe1\ -\xec\x3b\x4e\xa7\x55\x24\xd6\x42\xa7\xee\x04\x92\xa2\x0b\x8a\xec\ -\xe4\xd9\xb2\x22\xb3\x69\x5d\xae\x97\x8c\x46\x83\x37\x31\xa8\x05\ -\xe7\x2f\xcd\x36\x06\xb6\x99\x16\xbb\x02\x32\x05\xad\x26\x14\x67\ -\x24\x62\x0c\xb7\xa7\x45\x35\x03\x2b\xb2\x5b\xa9\xe4\x89\x3d\x3c\ -\x77\x7c\x9c\xae\x7a\x05\x10\x2a\x14\xe2\x9f\x71\x82\xf6\x05\x4b\ -\x1b\xb2\x69\x20\x46\x67\x0d\xd2\xa9\x6e\xa8\x53\x21\x01\xe7\xe5\ -\x61\x09\x2c\x51\x78\x98\x50\x9e\x90\xd4\xd9\xf0\x3e\x19\xc1\x14\ -\x6a\x5b\xa3\x19\x12\xda\x62\x57\xa0\x49\x50\x8c\x26\x76\xa2\xe5\ -\xc3\xcc\x02\x16\xf5\xea\xdc\x67\x30\x52\x9f\x22\xed\x08\xc6\xc1\ -\x4b\x29\x14\xf0\xb7\x30\x40\xa4\x33\xdc\x42\x2a\x34\x7c\x27\xae\ -\xaf\xaf\xad\x5e\xdf\xdd\xdd\xa9\xf1\x65\xa8\xe9\x28\xa6\xd1\xdd\ -\xdd\x7d\x75\x75\xb5\xb5\xb5\x75\x78\x78\x48\xd9\xe5\x33\xa0\xdf\ -\x79\x82\x45\xed\x0b\xc6\x2f\xd1\xcd\xcd\x4d\x3f\xf0\xeb\x20\x18\ -\x6d\x2a\xce\x24\x0d\x51\x09\x4b\xbc\xe9\xe4\x46\xf2\xad\x0a\xb7\ -\x90\x0e\xee\x04\x3c\xac\xdd\xa2\x22\x85\x90\x2f\x4a\x2e\x6b\xf8\ -\x81\x00\xb2\x9b\x3c\xa2\xa1\xfb\xab\x64\x27\x95\x58\xc5\x8d\x7b\ -\xe8\xa6\x9e\x5f\x49\xda\x11\x8c\x5a\xd3\x86\xa4\xe4\xe1\x68\x3b\ -\xf0\x13\x77\xb7\xbe\x98\xce\xab\x9d\x48\x44\x9b\x69\xb6\x37\x8c\ -\x9a\x8d\x24\x42\xba\x1c\xc8\x35\xec\x6e\xbc\x86\x16\x8d\xea\x7e\ -\xea\xb4\x2f\xd8\xca\x37\x75\x29\x14\x16\xe9\x64\x86\x64\xa1\xff\ -\x26\xf5\x48\xb0\x92\xf0\xfd\x26\x20\x31\xf9\xdd\x47\x59\x14\x42\ -\x52\x26\x39\x9b\x19\x2d\xa1\xd4\x05\x75\x7f\x82\x4e\x05\x9b\x36\ -\xb2\x87\xd8\xe8\x53\xa1\x21\xd0\x90\x6e\x8c\x5d\x91\x54\xc8\xff\ -\x2b\x9e\x15\xf2\xff\xc5\x66\x85\x3c\x12\x59\x21\x8f\x44\x56\xc8\ -\x23\x91\x15\xf2\x48\x64\x85\x3c\x12\x59\x21\x8f\x44\x36\x28\x14\ -\x3e\x01\x89\x4c\x9e\x9b\x1b\x93\x9b\xc9\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x09\xff\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x01\x68\x00\x00\x00\x26\x08\x02\x00\x00\x00\x66\xa2\x96\x2a\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x09\x94\x49\x44\x41\x54\x78\x5e\xed\x9d\xcd\x8b\ -\xce\xdf\x1b\xc7\x67\xbe\xff\x80\xa7\xad\x24\x2c\x28\x22\x19\x0a\ -\x29\xca\xf3\x46\x79\xcc\x4a\x8d\x05\xb6\x53\x33\xe5\x21\x1b\xc5\ -\xcc\x52\x88\x62\x4d\x13\x65\x43\x86\x62\x41\x92\xa7\x48\xb2\xc1\ -\x02\x4b\x4f\xf1\x07\xcc\xf7\x75\x7f\xde\xc7\xd5\xb9\x3f\x4f\xee\ -\xf3\x99\x7b\x16\xa3\xeb\xb5\x98\xdf\xb9\xce\x39\x9f\x73\xae\xa7\ -\x73\xdd\xe7\xa8\x6f\xbf\xde\xf1\xf1\xf1\x1e\xc7\x71\x9c\x14\xfe\ -\x0b\xff\xeb\x38\x8e\xd3\x31\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\xe3\ -\x38\xc9\x78\xe1\x70\x1c\x27\x19\x2f\x1c\x8e\xe3\x24\xe3\x85\xc3\ -\x71\x9c\x64\xbc\x70\x38\x8e\x93\x8c\x17\x0e\xc7\x71\x92\xf1\xc2\ -\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x47\x1a\x97\x2e\x5d\ -\x5a\xb0\x60\x41\x10\xfe\x50\xda\xf9\x0f\xd0\xd7\xd7\xd7\xfb\x87\ -\x7d\xfb\xf6\x7d\xfb\xf6\x8d\xce\x63\xc7\x8e\x85\xae\xde\x5e\x26\ -\xbc\x7e\xfd\x5a\x93\xa7\x3a\x0a\x22\x46\xcd\x9c\x39\x53\x46\x7d\ -\xfc\xf8\x11\xab\x65\xe9\x91\x23\x47\x34\x6d\xaa\x73\xfb\xf6\x6d\ -\x59\x04\x5b\xb6\x6c\xb1\xf0\xc5\x61\xc5\x58\xc5\xba\x06\x2f\x1c\ -\x09\x90\x49\x0f\x1e\x3c\xf8\xf0\xe1\x43\x90\x33\x4a\x3b\xff\x0d\ -\x06\x06\x06\xf6\xee\xdd\x3b\x3e\x3e\xfe\xf5\xeb\xd7\xe7\xcf\x9f\ -\xbf\x7b\xf7\x8e\xce\xfe\xfe\xfe\x19\x33\x66\xd0\x09\xf3\xe7\xcf\ -\x1f\x1b\x1b\xd3\xe4\x29\xcd\xc8\xc8\xc8\xe5\xcb\x97\x6f\xdc\xb8\ -\x21\xa3\x96\x2e\x5d\xca\xc9\x59\xb1\x62\xc5\xf2\xe5\xcb\xe9\xb9\ -\x75\xeb\xd6\xdc\xb9\x73\xc3\xd4\x29\xce\xb6\x6d\xdb\x30\xf0\xd5\ -\xab\x57\xc4\x74\xde\xbc\x79\x3b\x77\xee\x54\xbf\x85\x95\x4c\x7e\ -\xf6\xec\xd9\x89\x13\x27\xd4\x5f\x49\x2b\xfe\x05\x34\x74\xf4\xe8\ -\x51\x89\x0f\x1f\x3e\x54\x0f\x8d\x58\x14\xf8\x17\xcf\x6a\xe6\x64\ -\x70\xf8\xf0\xe1\xcd\x9b\x37\x07\xa1\x29\xac\x20\x6d\x83\x9c\x21\ -\x43\xd0\x1f\x27\x9a\x68\xe0\xdf\x9c\x5d\x2c\xa2\x02\x11\xe4\x8c\ -\xd2\xce\x06\xe4\x76\x07\x0c\x97\x62\xcd\xb0\x05\x87\x87\x87\x43\ -\x57\x86\x5c\x71\xf5\xea\xd5\x58\x34\xe2\x4d\x69\x6b\x1a\x4b\xe1\ -\x0d\xf5\xd3\x43\x3f\x0d\xac\xc6\x75\x0c\xb5\xa6\x4e\x0c\x34\x64\ -\x7d\x29\x80\x3e\xa1\xb7\x11\x5a\x44\x70\x12\x2c\x87\x21\x67\x29\ -\x35\x51\x16\xf1\x17\x91\xb3\xa4\x69\x82\x0f\x55\x34\xbb\x02\x06\ -\x6a\x53\xc1\xca\xb9\xed\x1a\x50\x65\x0e\xe4\xb6\x23\x4c\xb6\x1d\ -\x51\xb3\xba\x0f\x8c\xaa\x41\x58\xcd\x5e\x62\xfa\xd7\x28\x94\xa7\ -\x3b\x07\x86\x2f\x89\x65\x90\xb3\x1c\x8a\x63\x40\x1b\x6d\x68\xa0\ -\xab\xb4\x9c\xa4\xda\xa1\x94\x8d\x35\x69\x06\x7a\xca\xd1\xe6\x5c\ -\x50\x4f\xac\xb9\xd9\x05\x98\x1c\xbb\x18\x33\x2f\x5e\xbc\x48\x23\ -\x3e\x2d\xa5\x9d\xa5\xb0\x17\x93\x83\x50\x41\xbc\x3b\xab\xb1\xbb\ -\x16\x6f\x0c\x0b\xb2\x6f\x1c\x38\x8c\x65\x59\xdb\x05\x74\x6c\xe4\ -\x04\xd2\x2b\xde\x14\xb7\x33\x04\x74\x5a\xe6\xe1\x16\x75\x82\x55\ -\x9f\x2a\x3a\xb1\x1a\x65\x40\xde\x63\x71\x3e\x51\x7f\x33\x30\x04\ -\xc5\x14\x65\xd6\x8c\x95\x8c\x2d\xe5\xfc\x60\x9d\x2a\x20\x13\x62\ -\x87\x08\x46\xe3\xc4\xa8\xa7\x43\x33\x15\x08\xb6\xe6\x88\xe2\x52\ -\x1a\x1a\x6a\x46\x95\x39\xc2\xb6\x63\x1a\xdb\xd9\x09\x8a\x0b\x84\ -\x56\x50\x9b\x6f\x2d\xee\xac\xf9\xd7\x28\x94\x3f\x55\x3e\x7f\xfe\ -\x7c\xfc\xf8\xf1\xef\xdf\xbf\xdb\x13\x88\x0b\xf9\xd6\xad\x5b\xd5\ -\x86\x1f\x3f\x7e\x6c\xda\xb4\x89\xc6\xac\x59\xb3\x06\x07\x07\xd1\ -\xf2\xec\xd9\xb3\x1a\xea\x2e\xe7\xce\x9d\x3b\x75\xea\x14\x7e\x09\ -\x72\x04\x2a\xf1\x48\xcb\x3d\xc6\x78\x9e\xf1\x8a\x0b\x42\xc4\x97\ -\x2f\x5f\x36\x6c\xd8\x40\x43\xf7\x6d\xe0\x4d\x3b\x7d\xfa\x74\x1a\ -\xab\x56\xad\x52\x0f\xb0\x91\xec\x82\xfd\xfb\xf7\x63\xa6\x3c\xc0\ -\xdf\xa1\xa1\xa1\x43\x87\x0e\xf1\x02\xe4\xd2\xae\x09\xa5\x9d\x13\ -\xc1\xbc\x0a\x6b\xd7\xae\xe5\xb1\xad\x76\x0c\x6f\xd1\x6b\xd7\xae\ -\x05\x21\x03\x35\xf0\x43\x10\xda\xc1\x1c\xac\x7e\xf1\xe2\x85\x44\ -\x7c\x75\xf2\xe4\xc9\x95\x2b\x57\xda\x2e\x80\x67\xf8\x2b\x27\x70\ -\x45\x67\x94\x97\x17\x6d\x96\x25\x01\x94\x25\x3c\xf5\x71\x57\x6b\ -\x76\x4f\x0f\xbb\xab\x88\x90\x82\x24\x89\x3a\x1b\xc3\x1b\x01\x25\ -\xef\xdc\xb9\x83\xbd\x88\xf8\x9c\xfb\xb3\x86\x0c\x02\x9a\xfb\x27\ -\x06\x0c\xc1\x64\x12\x20\xc8\x11\xa4\x2e\x87\x84\xb4\xa4\xcd\x9a\ -\xb4\x3f\x7d\xfa\xa4\x21\x59\xba\x70\xe1\x42\xfe\xb2\x0b\x4e\xd0\ -\x0a\x4c\x88\x1d\x22\xd0\x2a\x4e\x8c\x89\x43\x70\xd7\xac\x59\x43\ -\x83\xad\xcf\x9f\x3f\x8f\x78\xfd\xfa\x75\x0d\x19\xa9\x29\xcd\xdf\ -\xa2\x39\x02\xfd\x97\x2c\x59\x42\x03\x57\xec\xd8\xb1\x03\x51\xfd\ -\x37\x6f\xde\x44\x54\xfb\xca\x95\x2b\x14\x08\xb5\x09\xeb\xc6\x8d\ -\x1b\xd5\xe6\x2c\xeb\xb0\xd4\x50\x5e\x38\x48\x9d\x45\x8b\x16\x91\ -\x2e\xa3\xa3\xa3\xea\x79\xfa\xf4\xa9\x42\x2b\xee\xde\xbd\x2b\xb5\ -\xc4\xee\xdd\xbb\x99\x10\x84\xee\x81\x31\x3c\x32\x67\xcf\x9e\x1d\ -\xe4\x76\x70\x16\xc4\x8e\xc6\xc5\x3c\xcf\x4a\xe3\xfd\xe4\xc9\x93\ -\xc5\x8b\x17\xe3\xa6\x5f\xbf\x7e\x21\xf2\x09\x6f\xda\xf5\xeb\xd7\ -\x5b\x92\x09\xec\x52\x74\x41\x81\xd1\x73\xf7\xe0\xc1\x83\xf6\xc3\ -\xc5\x22\x6f\xdf\xbe\x2d\xed\xd4\x87\x8d\x61\x77\x55\x67\x32\x00\ -\x5b\xf8\x51\xda\xb5\x6b\x97\x86\x8c\x3d\x7b\xf6\x30\x64\xb5\x83\ -\xe3\x8d\x15\x07\x0e\x1c\x90\x98\xe3\xe7\xcf\x9f\xab\x57\xaf\x36\ -\xff\x90\x28\x03\x03\x03\x44\x2a\x8e\x1d\x9e\xa1\xee\x9b\x13\xde\ -\xbf\x7f\x8f\xcf\x69\x8c\x8d\x8d\xe9\x38\xa1\x0c\x15\x04\x65\x68\ -\x3f\x7a\xf4\x88\xbf\xf2\x09\xe7\x4d\x9d\x8d\x61\x91\x33\x67\xce\ -\x9c\x3e\x7d\xda\x76\x27\xc7\x2e\x5c\xb8\xa0\xb6\x41\x40\x09\xab\ -\xd5\x0e\xbe\x22\xe8\x8a\xbe\x7a\x62\x48\x5d\xab\x02\xcc\xe4\xc0\ -\xcc\x99\x33\x47\x22\x96\x12\x6e\xfb\x8a\x35\xd5\x66\x02\x9e\x67\ -\xb2\x56\xd6\xf1\x63\xe6\xbd\x7b\xf7\x68\x14\xcb\x56\x03\x58\x13\ -\x4d\x74\xc8\x01\x7b\x49\x98\x97\x2f\x5f\x4a\x34\x32\x9b\x12\x52\ -\xba\xd4\x1c\x20\x2b\x28\x4c\xfc\x06\x48\x7c\xf3\xe6\x0d\x33\x69\ -\xb0\x2c\x96\xd2\x4f\x83\x5f\x02\x9c\xcf\x45\x89\x7e\xc2\xca\xaf\ -\x14\x9f\x2b\xf1\x18\xed\xef\xef\xcf\x3e\xad\x46\x79\x9f\x43\x37\ -\x37\x6e\x2c\xec\x47\x83\x5f\x18\xec\xcc\x46\x5a\xa8\x7a\xf1\x37\ -\xc8\xd9\x8d\x5d\x9f\xe4\xe0\x2b\xed\x52\xa4\xfe\x62\x0f\xdc\xa3\ -\xb4\xa6\x2e\x9c\xea\x2c\xc2\x15\x8b\x69\x4c\xb6\x46\x18\x68\x87\ -\xeb\x19\x0a\xa3\x8f\xae\x94\x4c\x66\x59\x3a\xe3\xdb\x1d\x66\xb2\ -\x91\x56\xc0\x76\x4e\x85\x2e\x7b\xb2\x42\x1e\xa0\x52\xb4\xb4\xcf\ -\xc4\x62\x27\xed\x2a\x6c\xeb\x2a\xe4\x55\x03\xdd\xaa\x6c\xd1\x83\ -\x82\x4d\xad\x11\x06\xda\x61\x54\x66\xb2\x1a\xa2\xcc\x97\x8d\x71\ -\xec\xd8\xc8\xae\xd0\xcc\x67\x41\x1a\x6c\x9d\x69\xd1\x82\x1e\xfa\ -\xa5\x0c\x1e\x0e\xbd\x9d\x3d\xd4\xeb\xad\x96\xdf\xaa\xcc\x8c\x61\ -\x0e\x5b\x4b\x0d\x35\xc2\x40\x01\x73\x08\xba\x31\x13\xd4\x0f\x16\ -\xee\xd8\x52\x44\xd6\x64\x48\x46\xd9\x7c\x16\xd1\x61\xab\xf1\xb0\ -\xf1\xd7\xe0\x6a\xb5\x20\x64\xf0\x49\xfc\x84\x8c\x41\x37\xd4\x40\ -\x2b\x6b\x84\x81\x76\xaa\xcc\x01\x1e\x1d\xda\x8e\x6f\x69\x63\x85\ -\x5e\x34\xec\x98\x59\xd9\x22\x0e\x1f\xbb\xa8\x33\x8e\x75\x3d\x25\ -\xb9\xae\x84\x53\x9b\xb5\x10\xd9\x3b\xf6\x4b\xa9\x17\xd0\x23\x08\ -\x5d\x82\x1d\x65\x2d\x0a\x48\x0d\xf5\x17\x91\xd7\x6a\x5c\x0c\x4a\ -\x08\x1c\xc7\xb2\x2c\x85\xc2\x88\xb9\x9c\x90\x8b\x05\x06\xd6\xa7\ -\x42\x27\xb0\x4b\x58\xae\x40\xb1\x6e\xa2\x89\x94\x04\x9d\xf6\xe2\ -\x1c\x03\x13\x50\x3e\xa7\x7f\x0e\xcc\x61\x14\x9f\xb0\x14\x22\x01\ -\x62\x41\x4b\x29\x83\x45\x32\x8d\x5a\xc4\xc9\xd4\x98\xce\xad\x26\ -\x70\x0a\x44\x27\x60\x08\xfe\x41\x5b\x4b\xce\x22\x4a\x15\xc1\x4c\ -\x22\x18\xa7\x44\x6c\x29\x8b\xd8\x31\x6b\x46\x52\x70\xd9\x2e\xa7\ -\x36\xd3\x88\x45\x10\x0a\x30\x19\x6d\xeb\x53\xba\xc6\x1c\xe2\x18\ -\x06\xb2\xdf\xb6\x9a\x44\x6a\x4c\xc9\x53\x85\x2b\x10\x77\x51\xb5\ -\xd1\x60\x74\x74\x94\xeb\x1f\x37\x5e\xf5\x00\x37\x9f\xf8\x4d\xc8\ -\xf5\x86\x6b\xad\x3d\x9c\xba\x02\x6b\x0e\x0d\x0d\x6d\xdf\xbe\xbd\ -\xb7\xb7\x77\xd9\xb2\x65\xf4\xfc\xfe\xfd\x5b\x43\x0d\xe0\xe6\xc6\ -\x69\xa1\x31\x6d\xda\xb4\xfb\xf7\xef\xb3\x32\xf7\x61\xb6\x88\xaf\ -\x73\x80\x99\x56\xfe\xb8\xb1\x0f\x0e\x0e\x86\x81\xa6\xf0\x74\xd7\ -\x6a\x40\xfc\xe2\x4a\x14\xbf\xfb\x04\x5e\xed\xeb\xeb\x53\x9b\x51\ -\xe6\x3f\x7e\xfc\x58\x62\x33\xf4\xde\xd4\x2b\x60\x64\x64\x84\xbb\ -\x28\xcb\xe2\x8a\x38\x76\xba\xd3\x5a\xb1\xe0\x05\x64\xa1\x6f\x4c\ -\xe7\x56\x13\x02\xbb\x5d\x77\x05\x52\x97\xe3\xc4\x46\x2a\x97\x3c\ -\x4e\xed\x11\x14\x5b\x8a\x56\x4c\x9b\xe0\xd6\x49\xc1\xe5\x1d\xb1\ -\x6e\xdd\xba\x20\x64\x6f\x70\xfe\xda\xbf\x29\x34\xa0\xde\x1c\xde\ -\x23\xaa\x4a\x68\xc5\xbb\xa3\xa8\x4f\x17\xc8\x2c\x6d\x03\x3d\x2c\ -\x93\x74\xb9\x80\xb8\xf2\x51\x08\xe3\x1f\x3a\xe6\xdb\x4f\x65\x0e\ -\x86\xc2\x36\x05\xea\xab\x20\x1f\xc6\x5b\xd4\xcc\xa7\xd6\xaa\x30\ -\x5b\x23\x0c\x44\xe0\x3e\xf9\x91\x2b\x0c\x4b\x29\xc6\xac\xaf\x24\ -\x33\x10\xe3\x4d\xbb\x0b\x16\xc5\xb9\x55\x24\xf6\xaa\xf2\xbe\xea\ -\x17\x89\xe8\x48\x55\x6b\x84\x81\x76\xcc\x3a\x56\xa6\x2d\xcf\x10\ -\xca\x78\x59\xda\xf4\x04\x61\x12\xa8\xb7\x9a\xd1\xdc\xef\x70\x15\ -\x28\x8f\x15\x4c\xb6\x46\x18\x68\x87\xba\x6f\xa5\x9f\x39\xac\xaf\ -\x36\x60\xa9\x39\x04\x8f\xe1\x5e\xb5\xbb\x42\xbd\x99\x8a\xa6\xdd\ -\x08\x10\xd1\xa4\xea\x9d\x02\x96\xc9\xd6\x08\x03\x11\x35\xe6\x90\ -\x15\x88\x3a\xc2\x6c\x4a\x7b\x32\x6e\x1c\x79\xf7\xc9\x48\xd3\x55\ -\x22\xda\x4b\x04\xf5\x48\x2d\xce\x21\x2e\x23\xf3\x24\x76\x0b\x96\ -\x8d\xb3\x59\xc6\xeb\xd9\x92\x23\xe7\xd9\x2a\x47\xd3\xa9\xcf\xf1\ -\xa0\x15\x41\x34\x8f\xed\x52\x4d\x99\x0c\x17\x8b\x4e\x72\xcb\x82\ -\xcd\x64\xd2\x22\xbe\x7c\x1a\xcc\x61\xc8\x8a\x45\x4e\x34\x30\xc7\ -\xac\x63\x35\x15\x0b\xac\xcb\x79\x92\x39\x8c\x06\x61\x12\xa8\xb7\ -\x9a\x21\x33\x13\x43\x50\xa6\xd4\xff\x38\x87\x21\x82\x5b\x2a\x1a\ -\xf2\xa1\x6d\x97\x3b\x4e\xb1\xa5\x5d\x3f\x4e\xf5\x66\xe2\x70\x1d\ -\x72\x34\x44\x2b\x32\x90\xf9\xb4\x35\x9a\xa3\xf3\x94\xae\x32\x47\ -\xff\x90\xa1\x36\xb0\x5d\x8d\x6e\x8d\xc9\x17\x0e\xb4\x61\x57\xd3\ -\x09\x28\xe1\x71\x75\xc4\x12\x26\x08\x74\x62\xa8\xca\x05\xcd\xc0\ -\x7e\xbc\xcc\xca\xe6\x08\xed\x85\xa7\x24\x1a\xf8\xab\x58\xb6\x51\ -\x2f\x3e\x18\x80\xd7\xb4\x42\x90\x33\xac\xd3\x7c\x2a\x11\x24\x76\ -\x9d\xfa\xdc\x8a\xbd\x8a\xf9\xf8\xbc\xb4\x6a\x00\x8b\xe4\xca\x34\ -\x62\x1c\x2f\xa1\xa5\x72\x3b\xaa\x13\x24\x16\x9d\xd0\x75\xea\xad\ -\x26\x73\x62\xc3\x8b\x56\x08\x02\x9a\xab\x8c\x7c\xc8\xe4\x9c\x8b\ -\xe8\xd1\x3a\xca\x1c\x1d\x27\x5d\x40\x8a\x96\x92\x60\x64\x54\x95\ -\x93\x53\xa9\x31\x13\x55\xd9\x48\xbb\x03\xed\xf8\xc6\x97\x23\x35\ -\xa5\x8b\xe6\x60\xbb\x86\xcc\x99\x7c\x4e\x46\xd9\x69\xea\x16\xfe\ -\x7f\x8f\xe0\x38\x4e\x32\xfe\xdf\xaa\x38\x8e\x93\x8c\x17\x0e\xc7\ -\x71\x92\xf1\xc2\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\ -\xe3\x38\xc9\x78\xe1\x70\x1c\x27\x19\x2f\x1c\x8e\xe3\x24\xe3\x85\ -\xc3\x71\x9c\x64\xbc\x70\x38\x8e\x93\x8c\x17\x0e\xc7\x71\x92\xf1\ -\xc2\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\xe3\x38\xc9\ -\x78\xe1\x70\x1c\x27\x91\x9e\x9e\xff\x01\xcb\x50\x49\xc4\xb5\x83\ -\x05\xaf\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\x00\x00\xa8\xfc\ -\xff\ -\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\ -\x48\x00\x00\xff\xe1\x0d\xb0\x45\x78\x69\x66\x00\x00\x4d\x4d\x00\ -\x2a\x00\x00\x00\x08\x00\x07\x01\x12\x00\x03\x00\x00\x00\x01\x00\ -\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x00\x62\x01\ -\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x00\x6a\x01\x28\x00\x03\x00\ -\x00\x00\x01\x00\x02\x00\x00\x01\x31\x00\x02\x00\x00\x00\x1e\x00\ -\x00\x00\x72\x01\x32\x00\x02\x00\x00\x00\x14\x00\x00\x00\x90\x87\ -\x69\x00\x04\x00\x00\x00\x01\x00\x00\x00\xa4\x00\x00\x00\xd0\x00\ -\x0a\xfc\x80\x00\x00\x27\x10\x00\x0a\xfc\x80\x00\x00\x27\x10\x41\ -\x64\x6f\x62\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\ -\x53\x33\x20\x4d\x61\x63\x69\x6e\x74\x6f\x73\x68\x00\x32\x30\x31\ -\x30\x3a\x30\x37\x3a\x32\x38\x20\x31\x33\x3a\x30\x34\x3a\x35\x30\ -\x00\x00\x03\xa0\x01\x00\x03\x00\x00\x00\x01\xff\xff\x00\x00\xa0\ -\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\xb4\xa0\x03\x00\x04\x00\ -\x00\x00\x01\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x06\x01\ -\x03\x00\x03\x00\x00\x00\x01\x00\x06\x00\x00\x01\x1a\x00\x05\x00\ -\x00\x00\x01\x00\x00\x01\x1e\x01\x1b\x00\x05\x00\x00\x00\x01\x00\ -\x00\x01\x26\x01\x28\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x02\ -\x01\x00\x04\x00\x00\x00\x01\x00\x00\x01\x2e\x02\x02\x00\x04\x00\ -\x00\x00\x01\x00\x00\x0c\x79\x00\x00\x00\x00\x00\x00\x00\x48\x00\ -\x00\x00\x01\x00\x00\x00\x48\x00\x00\x00\x01\xff\xd8\xff\xdb\x00\ -\x43\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\x09\x09\x08\x0a\ -\x0c\x14\x0d\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\ -\x1d\x1a\x1c\x1c\x20\x24\x2e\x27\x20\x22\x2c\x23\x1c\x1c\x28\x37\ -\x29\x2c\x30\x31\x34\x34\x34\x1f\x27\x39\x3d\x38\x32\x3c\x2e\x33\ -\x34\x32\xff\xdb\x00\x43\x01\x09\x09\x09\x0c\x0b\x0c\x18\x0d\x0d\ -\x18\x32\x21\x1c\x21\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\ -\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\ -\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\ -\x32\x32\x32\x32\x32\x32\x32\xff\xc0\x00\x11\x08\x00\x43\x00\xa0\ -\x03\x01\x21\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\ -\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\ -\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\xff\xc4\x00\xb5\x10\ -\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7d\ -\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61\x07\ -\x22\x71\x14\x32\x81\x91\xa1\x08\x23\x42\xb1\xc1\x15\x52\xd1\xf0\ -\x24\x33\x62\x72\x82\x09\x0a\x16\x17\x18\x19\x1a\x25\x26\x27\x28\ -\x29\x2a\x34\x35\x36\x37\x38\x39\x3a\x43\x44\x45\x46\x47\x48\x49\ -\x4a\x53\x54\x55\x56\x57\x58\x59\x5a\x63\x64\x65\x66\x67\x68\x69\ -\x6a\x73\x74\x75\x76\x77\x78\x79\x7a\x83\x84\x85\x86\x87\x88\x89\ -\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\ -\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\ -\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\ -\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\ -\xf9\xfa\xff\xc4\x00\x1f\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\ -\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\ -\x09\x0a\x0b\xff\xc4\x00\xb5\x11\x00\x02\x01\x02\x04\x04\x03\x04\ -\x07\x05\x04\x04\x00\x01\x02\x77\x00\x01\x02\x03\x11\x04\x05\x21\ -\x31\x06\x12\x41\x51\x07\x61\x71\x13\x22\x32\x81\x08\x14\x42\x91\ -\xa1\xb1\xc1\x09\x23\x33\x52\xf0\x15\x62\x72\xd1\x0a\x16\x24\x34\ -\xe1\x25\xf1\x17\x18\x19\x1a\x26\x27\x28\x29\x2a\x35\x36\x37\x38\ -\x39\x3a\x43\x44\x45\x46\x47\x48\x49\x4a\x53\x54\x55\x56\x57\x58\ -\x59\x5a\x63\x64\x65\x66\x67\x68\x69\x6a\x73\x74\x75\x76\x77\x78\ -\x79\x7a\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\ -\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\ -\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\ -\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\ -\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xda\x00\x0c\x03\x01\ -\x00\x02\x11\x03\x11\x00\x3f\x00\xf7\xfa\x28\x00\xa2\x80\x0a\x28\ -\x00\xa2\x80\x0a\x28\x00\xa2\x80\x0a\x28\x00\xa2\x80\x0a\x28\x00\ -\xa2\x80\x0a\x28\x00\xa2\x80\x0a\x28\x00\xa2\x80\x0a\x28\x00\xa2\ -\x80\x0a\x86\xe6\x74\x82\xd6\x49\xd9\xd5\x55\x14\xb6\xe6\x3c\x0a\ -\x52\x76\x40\x67\x1d\x55\xae\x34\xcb\x89\x22\x86\x40\xc8\x9b\x59\ -\xf2\x00\x0d\x8e\x71\xce\x78\x07\x35\x14\x3a\xc7\xd9\xf4\x68\x66\ -\x96\x29\x5b\xe5\x28\x24\x2c\x08\x2c\x32\x39\x39\xcf\x38\xcd\x72\ -\xba\xed\x7b\xd6\xd2\xc6\x9c\x8b\x6e\xa6\x95\x8d\xda\x5c\xe9\xf0\ -\xdc\xf9\x88\xe1\xd0\x16\x75\x18\x19\xef\xdc\xe3\x9f\x7a\xb5\x5d\ -\x31\x95\xd5\xc8\x6a\xc1\x45\x50\x82\xa8\x5b\x6b\x9a\x4d\xed\xc7\ -\xd9\xed\x75\x4b\x29\xe7\x39\xfd\xdc\x57\x0a\xcd\xc7\x5e\x01\xcd\ -\x52\x8c\x9a\x6d\x2d\x89\x94\xe3\x16\x93\x76\xb8\xe3\xab\xe9\x82\ -\xfb\xec\x27\x51\xb4\x17\x99\xc7\xd9\xfc\xe5\xf3\x33\x8c\xe3\x6e\ -\x73\xd2\xae\xd0\xe3\x28\xee\x82\x33\x8c\xbe\x17\x70\xa3\x35\x25\ -\x05\x19\xa0\x02\x8a\x00\x28\xa0\x08\x27\xbc\xb7\xb6\x21\x66\x99\ -\x51\x88\x2c\x01\x3c\x90\x3a\xe3\xd7\xa8\xae\x13\x58\xd7\x86\x9b\ -\x70\x89\x63\xe5\x79\xcc\x85\xe3\x8c\x8c\xfd\x98\x37\x43\x8e\x81\ -\x8a\xf3\x8e\xc1\xb9\x18\xc6\x73\x50\x55\x6a\xa8\xa7\xb6\xe1\x39\ -\x72\x41\xb3\x82\xd5\xa4\x9a\x59\x59\xee\x00\x91\xe7\x52\xad\xbd\ -\xf7\x1c\x03\xc7\x1d\xbb\xf4\xa3\x4b\x67\xb4\xb5\x92\x45\x32\x7c\ -\x98\x40\xa8\xdc\x9c\x9e\x98\xff\x00\x3d\x0d\x7b\xfe\xc2\x1e\xc7\ -\x96\xda\x1f\x35\xf5\xa9\x2c\x5d\xba\x9d\x96\x89\xaf\x9f\x11\xde\ -\x34\x17\x05\x56\xee\x14\x49\x65\x85\x90\xa0\xb8\x0a\x46\x41\xce\ -\x17\x76\xdc\xfe\x03\xa6\x33\x8f\x44\xb5\xbf\xb5\xbc\x24\x5b\xce\ -\x92\x32\xa8\x66\x00\xf2\x01\xe9\x91\xdb\xa1\xfc\xab\xc0\x95\x3f\ -\x61\x5a\x50\x93\xdf\x54\x7d\x25\x3a\x9e\xd6\x9a\x92\xe8\x59\xa2\ -\xb4\x18\x57\x13\x61\xa8\xd9\x69\x7e\x38\xf1\x75\xc5\xf5\xc4\x76\ -\xf0\xee\xb2\x5d\xf2\x1c\x0c\xf9\x46\xb7\xa3\x17\x25\x34\xbb\x7e\ -\xa8\xe7\xaf\x25\x17\x06\xf6\xbf\xe8\xca\xfa\xbe\xaf\xa3\x5d\xf8\ -\x8a\x39\xa2\xd5\xe1\xb6\x32\xd8\xf9\x42\xee\x39\x82\x15\xfd\xf2\ -\x11\x86\x3c\x1e\x32\x71\xd0\xf3\x9c\x8a\x65\xdf\xdb\xb5\x3d\x6a\ -\x3b\x3b\x8b\xbb\xdb\x1b\xa7\x64\x82\x43\x6f\x75\x2a\xc6\x58\xc3\ -\x72\x44\x88\xa1\x80\x2a\x76\x44\xd8\xf5\x18\x3c\xe6\xba\x63\x17\ -\x08\xde\x71\xd5\x2e\xa8\xe5\x94\xd4\xe5\x68\x4b\x46\xfa\x32\x49\ -\x9e\x6d\x40\x69\x57\x7e\x6d\xd5\xb9\xb9\x26\x26\x84\x6a\x53\x44\ -\x00\x48\x89\x7c\xe0\xfd\xe5\x70\xc3\xdf\x60\xc9\xe4\xd3\x2c\x24\ -\xb8\x99\x6e\x2d\xa0\xd4\x2e\x11\xe5\x96\x46\x80\x5c\xdd\xca\x7e\ -\xd0\x12\xe6\x40\x51\x58\x92\xc9\x84\x45\x52\x47\xf7\xc6\x47\xaa\ -\xb2\x51\xb5\xaf\x6f\x25\xe7\xfe\x41\x79\x39\x5e\xf6\xbf\x9b\xec\ -\xbf\xcc\x5b\x48\xa3\xbc\xb0\x9e\xed\x6f\xf5\x5d\x86\xf2\xca\x28\ -\x95\xf5\x19\x41\x58\xe4\x4b\x72\xc0\xed\x7c\x12\x7c\xc6\xc9\xfc\ -\xb1\x5a\x70\x46\xfa\x56\xa5\x7b\x0b\x5e\x5c\x4d\x05\x8c\x22\xf1\ -\x5a\xe2\xee\x42\x4e\xf5\x29\xb5\xc9\x24\x15\x06\x27\x63\x90\x70\ -\x58\x60\x0c\x73\x32\x7a\x38\xb4\xbe\xe5\xe5\xfe\x65\xc1\x59\xa9\ -\x26\xfe\x6d\xf9\xff\x00\x91\xa9\x63\xaa\xcd\x77\xad\x5f\x69\xed\ -\x16\x16\xd1\x23\x3e\x76\x30\x25\xdf\xbb\x95\xe7\xa0\xdb\x8f\xa8\ -\x3e\x95\xb1\x5c\xb3\x8a\x8b\xb1\xd9\x4e\x4e\x4a\xef\xcc\x28\xa8\ -\x2c\xc4\xd6\x75\x2d\x3b\x72\xd8\xcb\x3c\x66\x61\x2a\x6f\x40\x72\ -\xc8\x32\x09\xcf\xa6\x57\x23\xd7\x9e\x2b\xcb\x74\x6b\xed\x37\xc4\ -\x57\x1a\x9d\xb4\x61\x6d\xb5\x69\xee\xe5\x7b\x19\xa4\x63\xb2\x65\ -\x5c\x05\x8d\xc1\x3c\x36\xdc\x00\x46\x3a\x0f\xa3\x18\x57\x07\x56\ -\x72\x8e\xeb\x7f\x43\x3c\x42\x7c\x8a\x2f\xa8\x5b\x69\x46\xf3\x53\ -\x86\x3b\xb2\x60\x69\x21\x96\x32\xd3\x90\x8a\x92\x8d\xe1\x37\x1c\ -\xf1\xc8\x51\xfd\x09\x26\xa7\xb4\xd3\x27\xd2\xfc\x43\xa7\x58\x6a\ -\xb6\x8d\x6f\xe7\xc9\xb3\xcc\xce\x7c\xfc\xba\x0d\xb9\x19\x1c\x02\ -\x7e\xee\x3a\x8c\xf6\xaf\x65\xd5\xbc\x79\x14\xba\x7d\xfb\x9f\x3b\ -\x1c\x3f\x2d\x65\x5a\x50\xeb\xae\xfa\x68\xad\xd7\x6b\xdc\xaf\xab\ -\x4c\x34\x9d\x7a\x59\x62\x89\x4c\x2b\x76\xf0\xa8\x0f\x9d\x8b\x1c\ -\x89\xbc\x75\xce\xe2\x8c\x07\x3f\xde\x38\xe7\x18\xf5\x1d\x17\x50\ -\xd2\x92\x69\x2c\x2d\x67\x8c\x48\xd2\x33\x22\x13\x86\x90\x63\x39\ -\xe7\xae\x3a\x7d\x00\xaf\x13\x13\x28\x2a\xb0\x94\xb7\x6a\xc7\xd2\ -\x51\x4f\x95\xa5\xb2\x37\x68\xaa\x28\x2b\xcd\xbc\x5b\x1c\xda\x4d\ -\xd7\x8a\x66\x9a\xda\x67\xb5\xd5\xec\xe3\x31\x5c\x46\x85\x96\x39\ -\x23\x5d\xbb\x1b\x03\xe5\xce\x72\x09\xc0\xfe\x9d\x38\x5b\x73\xf2\ -\xf7\xff\x00\x34\xff\x00\x43\x93\x19\x7f\x67\xcd\xdb\xfc\x9a\xfd\ -\x4d\x6f\x0a\x59\x0d\x57\x4e\xb3\xb8\xbb\xb6\x63\x64\xba\x4c\x16\ -\x49\x1c\xe9\x81\x29\xc0\x32\x36\x0f\xf0\xfd\xd0\x0f\x7c\x12\x38\ -\xc1\x38\xbe\x13\xbf\xb9\xb0\xd5\x27\xf0\xfa\x3c\x8d\x6b\x65\xab\ -\x34\x31\x82\x72\xc6\x26\x8a\x76\x0b\x9f\x66\x8c\x37\xe2\x7b\x71\ -\x5b\xe9\x25\x52\x3d\xb5\xf9\xff\x00\x4c\xc1\x5e\x2e\x9c\xba\xbd\ -\x3e\x5f\xd2\x3a\x66\xd4\xa5\xb7\x92\xef\xcc\xb9\x2a\x89\xa7\xda\ -\xb4\x4d\x70\xa0\x6c\x96\x57\x95\x37\x3e\x07\x1c\xaa\x67\xb0\xc1\ -\xe9\x59\x9a\x5e\xb1\x7d\x34\x3e\x4b\xdd\xf9\xb3\x5c\x5a\x79\x30\ -\xc8\x8a\xb2\x2a\xdc\x47\x2f\x93\x24\x98\x03\x95\x25\xa2\x7e\x7b\ -\x64\xf1\x59\xaa\x71\x69\xbb\x76\xfc\xae\xcd\x25\x56\x49\xa5\x7e\ -\xff\x00\x9d\x90\xb7\x7a\xfd\xdd\xce\x86\xb7\x30\x5c\x0b\x5b\xa7\ -\xb6\x11\x8d\xdb\x02\x2d\xc8\xde\xce\xad\xbb\x90\x41\x8b\x6f\xfd\ -\xb4\x1c\x53\xd3\xc4\x13\xdf\x6b\x2b\x1d\x95\xc4\xe1\x6e\x5e\xce\ -\x5b\x74\x68\x80\x53\x13\xa9\x69\x54\xb6\x30\x0e\xc0\xcd\x8c\xee\ -\xca\xf1\xc6\x69\xfb\x18\xa4\xee\xb6\xff\x00\x81\xff\x00\x04\x9f\ -\x6f\x26\xd5\x9e\xff\x00\xf0\x7f\xe0\x1a\x5e\x13\xbd\xbb\xd4\x2c\ -\xad\xe6\xb9\x96\x66\x61\x01\x2e\x59\x14\x24\x84\xc8\xc0\x10\x47\ -\x70\x10\xe4\x7f\xb4\x2b\xa4\xae\x6a\xa9\x29\xb4\x8e\xba\x0d\xca\ -\x9a\x6c\x28\xac\xcd\x4c\x2f\x13\xcf\xa6\xdb\xda\x40\xf7\xc9\x04\ -\x8e\x26\x53\x14\x72\x00\x4b\x7c\xc3\x70\x00\xf5\xe3\xf5\xc5\x7c\ -\xf3\xe2\x10\x9a\x46\xbd\x71\x6f\x0c\x57\x36\xcc\x2e\x5e\xe6\x0d\ -\xeb\xb3\x11\xbe\x0a\x6d\xef\xc6\x31\x9e\xfe\xd8\xe6\xb0\x55\x52\ -\xc5\x3a\x69\x74\xbb\x33\xc4\xc1\xba\x57\x3a\xe5\xf1\xa3\x6a\xd6\ -\x62\xfa\xfa\x34\xf3\xe3\x80\x43\x33\xa9\x0b\xe6\x30\x39\xdf\x8c\ -\x63\x24\x10\x31\xdc\xfa\x0e\x99\xb2\xf8\xdb\x6c\x9a\x5c\x6b\x1b\ -\x49\x6b\xa7\x5d\xfd\xa6\x30\xe4\x06\x20\x15\xc4\x60\x0f\xb8\xa3\ -\x69\x1d\x4f\x5e\xd8\xc5\x7a\x91\xa0\xd6\x8b\xa1\xe7\xce\x49\xbb\ -\xf7\x21\x4d\x51\x3c\x51\xe2\x95\xfb\x35\xb4\xcd\x25\xcd\xcb\x4b\ -\x24\x09\xb9\xca\x44\x5b\x73\xf2\x06\x39\xc6\x33\x8e\xe2\xbd\xb7\ -\xc3\x17\x7a\x5d\xd2\xdd\xbd\x8c\x71\xc3\x2b\xca\x4c\x91\x0d\xa0\ -\x80\x38\x1c\x0e\x83\xfa\x96\xaf\x27\x15\x51\x46\xbc\x69\x35\xad\ -\xb7\x3d\x2a\x2a\xf4\xdc\x91\xd0\x51\x41\x41\x58\x1e\x37\x65\x5f\ -\x05\x6a\xe5\x88\x19\xb7\x60\x33\xeb\x5a\x52\xfe\x24\x7d\x51\x9d\ -\x6f\xe1\xcb\xd1\x8d\xd1\x75\x4b\x2d\x37\xc0\xda\x4d\xd5\xe5\xd4\ -\x50\xc2\x96\x30\xe5\x99\xbb\x88\xc7\x03\xd4\xfb\x0e\x6b\x27\xc2\ -\xde\x18\x91\xda\xef\x5a\xbd\x17\x16\x77\x77\xb7\xcf\x79\x14\x40\ -\xa8\x68\x94\x86\x08\x18\x10\x7e\x6c\x48\xf9\x1f\xed\x73\xc8\xad\ -\xf9\x9d\x35\x37\xdd\xdb\xfc\xce\x6e\x55\x52\x50\x5d\x95\xff\x00\ -\xc8\xdc\x6f\x0c\xda\xbc\xd2\x48\xf7\x57\x8c\xd2\x0c\x49\x99\x06\ -\x18\x66\x43\x83\xc7\x4f\xde\xbf\xd3\x23\x1d\x06\x26\x8b\xc3\xf6\ -\x11\xea\x5f\x6f\xda\xcd\x70\x26\x79\x90\x92\x30\x8c\xca\x11\xb0\ -\x00\x1d\x40\x1f\x96\x7a\x93\x9c\x9d\x79\x33\x65\x87\x8a\xfc\xc7\ -\xda\x68\x76\x56\x37\xd2\xdd\xdb\x23\x46\xf2\xb4\x8e\xe0\x1e\x0b\ -\x48\x54\xbb\x7d\x4e\xc5\xfc\xaa\x95\xb7\x83\xf4\xcb\x58\x64\x8a\ -\x36\xb8\xda\xe6\x36\x19\x93\xfd\x59\x8d\x8b\x21\x5e\x38\xc1\x27\ -\xdb\x1c\x74\xe2\x85\x5e\x4b\xfa\xec\x0f\x0f\x07\xf8\xfe\x25\xab\ -\x2d\x0a\x1b\x0b\x78\x60\x82\xea\xe8\x43\x09\xca\x21\x71\x81\x97\ -\x0c\x7b\x73\x9c\x63\x9e\xc4\x81\x8a\xd5\xac\xe7\x3e\x67\x76\x69\ -\x08\x28\x2b\x20\xa2\xa4\xb1\xac\xa1\x94\x82\x01\x07\x82\x0d\x79\ -\x7f\x8b\x7c\x1e\x3c\x52\xe9\x1d\xc9\x6d\x36\xda\xd4\xb2\x5a\x5f\ -\xbc\x00\x9c\x67\x84\x7c\x90\x42\x75\xc1\x38\x1d\x31\x9c\xf3\x8d\ -\x49\xce\x9c\xe3\x38\xf4\xdf\xd0\xa4\x94\x93\x4c\xf2\xf3\xe1\x1f\ -\x12\x5a\x43\x73\x18\xb3\xfb\x4d\xb0\x62\xad\x3d\xb2\xb4\xa8\x0a\ -\xf3\x9c\x81\xc0\xe7\xbf\x63\x55\xe3\xf0\x8f\x88\xee\x62\x49\x56\ -\xc8\xc5\x03\xb6\xdf\x3a\x60\xc8\x99\xe7\xb9\x1c\xf4\x3d\x33\x5e\ -\x8f\xf6\x8d\x2f\x65\xcf\x7d\x2d\x73\x9f\xea\xaf\x9a\xc7\xa8\xf8\ -\x67\xc1\xc7\xc2\x4f\x23\xe9\xee\xfa\xa4\x77\x1b\x62\xbc\xbf\x8a\ -\x1e\x42\x6f\x1b\x92\x3c\x12\xd8\xc0\xe4\xae\x79\xeb\xca\x8c\x7a\ -\xb4\x71\xa4\x68\xa9\x1a\x84\x45\x18\x55\x51\x80\x07\xa5\x79\xd4\ -\xe7\x39\xd4\x94\xa7\xf2\xf4\x3a\x1a\x4a\x29\x21\xf4\x56\xc4\x85\ -\x57\xbc\xb0\xb3\xd4\x62\x11\x5f\x5a\x41\x75\x1a\xb6\xe0\x93\xc6\ -\x1c\x03\xeb\x83\xdf\x93\x4d\x37\x17\x74\x29\x45\x49\x59\xab\xa2\ -\x0b\x4d\x13\x49\xb0\x97\xcd\xb3\xd2\xec\xad\xe4\xc6\x37\xc3\x6e\ -\x88\x7f\x30\x2a\xfd\x39\x4e\x52\x77\x93\xb8\xa3\x08\xc1\x5a\x2a\ -\xc1\x45\x49\x41\x45\x00\x14\x50\x03\x5d\xc4\x68\xce\xd9\xda\xa3\ -\x27\x03\x35\x14\x17\x96\xf7\x4a\xcd\x04\xc9\x2a\xa9\x00\x94\x6c\ -\x8e\x54\x30\xfc\xc3\x03\xf8\xd3\xb3\x15\xd5\xec\x4a\x19\x59\x43\ -\x29\x04\x11\x90\x41\xeb\x55\x27\xbc\xb6\x91\x24\xb7\xf3\x42\xbb\ -\x31\x87\x94\x27\x0c\x40\x3d\x3d\x39\x1e\xdc\x81\x9a\x5c\xad\xab\ -\x07\x32\x46\x61\xf0\xd5\x94\x7a\x64\xf6\xd6\x92\xce\x92\x94\xda\ -\xce\x27\x6f\x99\xb0\x3e\xf2\xe7\x6f\x3e\x98\xef\xc6\x2a\x25\xf0\ -\xf5\x84\x3a\x0a\x7f\x69\x3c\xa3\xc8\x84\xc9\x2b\xb5\xc3\xec\x88\ -\xe0\x96\x20\x03\xb7\x03\x9e\xdd\xb9\xcd\x72\x7d\x4e\x1c\xd6\xe9\ -\x6b\x58\xd7\xdb\x3b\x5c\xda\xd3\x23\x58\x34\xcb\x68\x55\xc3\x88\ -\xa3\x58\xf7\x04\xd8\x0e\xd1\x83\xf2\xf6\xe9\xd2\xa5\x6b\x98\x96\ -\xea\x3b\x62\xf8\x9a\x44\x69\x15\x71\xd5\x54\xa8\x27\xf3\x65\xfc\ -\xeb\xad\x2b\x2b\x19\xdf\xa8\xf5\x91\x1c\xb0\x56\x07\x69\xc3\x60\ -\xf4\x3e\x94\xfa\x00\x28\xa0\x02\x8a\x00\x28\xa0\x02\x8a\x00\x28\ -\xa0\x06\xba\xef\x46\x5c\x91\x91\x8c\x8e\xa2\xb1\x63\xf0\x9e\x93\ -\x0e\xa1\x35\xec\x30\x79\x72\x4b\x8d\xca\xb8\xd8\x30\x54\xf0\xa4\ -\x60\x64\xa2\x93\x8f\x4a\xa8\xcd\xc7\x62\x25\x05\x2d\xc8\x87\x82\ -\xf4\x80\xaa\x15\x27\x56\x58\x9e\x25\x75\x99\xb7\x28\x72\x0b\x60\ -\xf6\x3c\x63\x23\x90\x38\xe8\x00\x16\x53\xc3\x5a\x72\x69\xf0\xd9\ -\x05\x97\xc9\x84\xa9\x8f\x12\x10\xcb\xb4\x28\x18\x23\x07\xa2\x81\ -\xee\x32\x0e\x41\x35\x4e\xac\x89\x54\x62\x88\xae\x3c\x23\xa5\x5d\ -\xa5\xd2\x4d\x1b\xb0\xba\x89\x62\x97\x0c\x07\xca\x31\x8d\xa0\x0c\ -\x2f\xdd\x1f\x77\x19\xc0\xcf\x41\x89\xbf\xe1\x1b\xd3\xca\xde\x02\ -\x8e\x7e\xd9\x13\xc3\x31\x2d\xc9\x57\x2c\x5b\x1e\x87\xe6\x3d\x3d\ -\x07\xf7\x46\x17\xb4\x90\xfd\x94\x46\xcf\xe1\x8d\x32\xe2\xed\xae\ -\x5a\x27\x12\xb4\xd1\x4f\xf2\xb9\x00\x34\x7f\x77\x03\xa0\xf7\xf5\ -\xc0\xcf\x41\x50\x43\xe0\xdd\x22\x08\x96\x38\xe3\x91\x42\xc2\xd0\ -\x2f\xcf\xc8\x43\x27\x98\x7f\xf1\xee\x7d\xa9\xaa\xb2\x13\xa3\x16\ -\x2d\xbf\x83\xb4\x7b\x58\xd2\x38\x61\x75\x44\x27\x6a\xef\xe3\x94\ -\x08\x78\xff\x00\x74\x7e\x7c\xf5\xc1\xad\x8b\x2b\x48\xac\x2c\x6d\ -\xec\xe0\x04\x43\x04\x6b\x12\x06\x39\x3b\x54\x60\x64\xf7\xe0\x52\ -\x94\xe5\x2d\xca\x8d\x38\xc7\x62\x7a\x2a\x0b\x0a\x28\x00\xa2\x80\ -\x0a\x28\x00\xa2\x80\x0a\x28\x00\xa2\x80\x0a\x28\x00\xa2\x80\x0a\ -\x28\x03\xff\xd9\x00\xff\xed\x36\x84\x50\x68\x6f\x74\x6f\x73\x68\ -\x6f\x70\x20\x33\x2e\x30\x00\x38\x42\x49\x4d\x04\x04\x00\x00\x00\ -\x00\x00\x07\x1c\x02\x00\x00\x02\x00\x00\x00\x38\x42\x49\x4d\x04\ -\x25\x00\x00\x00\x00\x00\x10\xe8\xf1\x5c\xf3\x2f\xc1\x18\xa1\xa2\ -\x7b\x67\xad\xc5\x64\xd5\xba\x38\x42\x49\x4d\x03\xea\x00\x00\x00\ -\x00\x1c\xe1\x3c\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\ -\x3d\x22\x31\x2e\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\ -\x22\x55\x54\x46\x2d\x38\x22\x3f\x3e\x0a\x3c\x21\x44\x4f\x43\x54\ -\x59\x50\x45\x20\x70\x6c\x69\x73\x74\x20\x50\x55\x42\x4c\x49\x43\ -\x20\x22\x2d\x2f\x2f\x41\x70\x70\x6c\x65\x2f\x2f\x44\x54\x44\x20\ -\x50\x4c\x49\x53\x54\x20\x31\x2e\x30\x2f\x2f\x45\x4e\x22\x20\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\ -\x2e\x63\x6f\x6d\x2f\x44\x54\x44\x73\x2f\x50\x72\x6f\x70\x65\x72\ -\x74\x79\x4c\x69\x73\x74\x2d\x31\x2e\x30\x2e\x64\x74\x64\x22\x3e\ -\x0a\x3c\x70\x6c\x69\x73\x74\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\ -\x22\x31\x2e\x30\x22\x3e\x0a\x3c\x64\x69\x63\x74\x3e\x0a\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x46\ -\x6f\x72\x6d\x61\x74\x74\x69\x6e\x67\x50\x72\x69\x6e\x74\x65\x72\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\ -\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\ -\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\ -\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\ -\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\ -\x65\x46\x6f\x72\x6d\x61\x74\x2e\x46\x6f\x72\x6d\x61\x74\x74\x69\ -\x6e\x67\x50\x72\x69\x6e\x74\x65\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4b\x4f\x4e\x49\ -\x43\x41\x5f\x4d\x49\x4e\x4f\x4c\x54\x41\x5f\x62\x69\x7a\x68\x75\ -\x62\x5f\x43\x35\x35\x30\x5f\x35\x39\x5f\x42\x44\x5f\x33\x38\x5f\ -\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\ -\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\ -\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\ -\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\ -\x61\x74\x2e\x50\x4d\x48\x6f\x72\x69\x7a\x6f\x6e\x74\x61\x6c\x52\ -\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\ -\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x48\x6f\x72\x69\ -\x7a\x6f\x6e\x74\x61\x6c\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x32\x3c\x2f\x72\x65\ -\x61\x6c\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\ -\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\ -\x79\x3e\x0a\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x4f\ -\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\ -\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\ -\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x61\x72\x72\ -\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\ -\x74\x2e\x50\x4d\x4f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\ -\x65\x72\x3e\x31\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\ -\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\ -\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\ -\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x53\x63\x61\x6c\x69\x6e\ -\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\ -\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\ -\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\ -\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\ -\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\ -\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x53\x63\x61\x6c\x69\ -\x6e\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x72\x65\ -\x61\x6c\x3e\x31\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\ -\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\ -\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\x2f\x64\x69\ -\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\ -\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\x74\x69\x63\x61\x6c\x52\ -\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\ -\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\x74\ -\x69\x63\x61\x6c\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x32\x3c\x2f\x72\x65\x61\x6c\ -\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\ -\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\ -\x0a\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\ -\x74\x69\x63\x61\x6c\x53\x63\x61\x6c\x69\x6e\x67\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\ -\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\ -\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x61\ -\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\ -\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\x74\x69\x63\x61\x6c\x53\x63\ -\x61\x6c\x69\x6e\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x3c\x72\x65\x61\x6c\x3e\x31\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\ -\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\ -\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x73\x75\x62\ -\x54\x69\x63\x6b\x65\x74\x2e\x70\x61\x70\x65\x72\x5f\x69\x6e\x66\ -\x6f\x5f\x74\x69\x63\x6b\x65\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x50\x4d\ -\x50\x50\x44\x50\x61\x70\x65\x72\x43\x6f\x64\x65\x4e\x61\x6d\x65\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x50\x4d\x50\x50\x44\x50\x61\x70\x65\x72\x43\x6f\ -\x64\x65\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\x72\ -\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\ -\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\ -\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x50\x4d\ -\x50\x50\x44\x54\x72\x61\x6e\x73\x6c\x61\x74\x69\x6f\x6e\x53\x74\ -\x72\x69\x6e\x67\x50\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\ -\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\ -\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\ -\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\ -\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\ -\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\ -\x3e\x50\x4d\x50\x50\x44\x54\x72\x61\x6e\x73\x6c\x61\x74\x69\x6f\ -\x6e\x53\x74\x72\x69\x6e\x67\x50\x61\x70\x65\x72\x4e\x61\x6d\x65\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x73\x74\x72\ -\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\x72\x20\x2d\x20\x38\x2e\x35\ -\x78\x31\x31\x69\x6e\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\ -\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\ -\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\ -\x65\x79\x3e\x50\x4d\x54\x69\x6f\x67\x61\x50\x61\x70\x65\x72\x4e\ -\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\ -\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\ -\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\ -\x09\x09\x3c\x6b\x65\x79\x3e\x50\x4d\x54\x69\x6f\x67\x61\x50\x61\ -\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x6e\x61\x2d\x6c\x65\ -\x74\x74\x65\x72\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\ -\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\ -\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x41\ -\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x67\x65\x52\x65\x63\x74\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\ -\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\ -\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\ -\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\ -\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x67\x65\x52\x65\x63\x74\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x61\x72\x72\ -\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\ -\x30\x2e\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\ -\x09\x3c\x72\x65\x61\x6c\x3e\x30\x2e\x30\x3c\x2f\x72\x65\x61\x6c\ -\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x36\ -\x38\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\ -\x72\x65\x61\x6c\x3e\x35\x38\x38\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\ -\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\ -\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x41\ -\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x70\x65\x72\x52\x65\x63\x74\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\ -\x4d\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x70\x65\x72\x52\x65\ -\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x61\ -\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\ -\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\ -\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\x65\ -\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\ -\x37\x38\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\ -\x09\x3c\x72\x65\x61\x6c\x3e\x36\x30\x30\x3c\x2f\x72\x65\x61\x6c\ -\x3e\x0a\x09\x09\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\ -\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\ -\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\ -\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\ -\x43\x75\x73\x74\x6f\x6d\x50\x61\x70\x65\x72\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\ -\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\ -\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\ -\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\ -\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x43\x75\x73\x74\x6f\ -\x6d\x50\x61\x70\x65\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x09\x09\x3c\x66\x61\x6c\x73\x65\x2f\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\ -\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\ -\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x50\x61\x70\x65\x72\ -\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\ -\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\ -\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\ -\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\x66\ -\x6f\x2e\x50\x4d\x50\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\ -\x3e\x6e\x61\x2d\x6c\x65\x74\x74\x65\x72\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\ -\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\ -\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\ -\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\x66\ -\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\x64\x50\x61\ -\x67\x65\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\ -\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\ -\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\ -\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\ -\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\x64\ -\x50\x61\x67\x65\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\ -\x09\x09\x3c\x72\x65\x61\x6c\x3e\x30\x2e\x30\x3c\x2f\x72\x65\x61\ -\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x30\ -\x2e\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\ -\x3c\x72\x65\x61\x6c\x3e\x37\x36\x38\x3c\x2f\x72\x65\x61\x6c\x3e\ -\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x35\x38\x38\ -\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x3c\x2f\x61\ -\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\ -\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\ -\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\ -\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\ -\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\x64\ -\x50\x61\x70\x65\x72\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\ -\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\ -\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\ -\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\ -\x74\x65\x64\x50\x61\x70\x65\x72\x52\x65\x63\x74\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x2d\x31\x32\x3c\ -\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\ -\x61\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\ -\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x38\x30\x3c\x2f\x72\ -\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\ -\x3e\x36\x30\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\ -\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\ -\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\ -\x70\x65\x72\x49\x6e\x66\x6f\x2e\x70\x70\x64\x2e\x50\x4d\x50\x61\ -\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\ -\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\ -\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\ -\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\ -\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\ -\x49\x6e\x66\x6f\x2e\x70\x70\x64\x2e\x50\x4d\x50\x61\x70\x65\x72\ -\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\x72\x3c\x2f\ -\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\ -\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\ -\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\ -\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x41\x50\x49\x56\x65\x72\x73\x69\x6f\x6e\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x30\x30\ -\x2e\x32\x30\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x74\x79\x70\x65\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x54\x69\x63\x6b\x65\x74\x3c\ -\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x41\ -\x50\x49\x56\x65\x72\x73\x69\x6f\x6e\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x30\x30\x2e\x32\x30\x3c\x2f\ -\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x74\x79\x70\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\ -\x6d\x61\x74\x54\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\ -\x67\x3e\x0a\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x3c\x2f\x70\x6c\x69\ -\x73\x74\x3e\x0a\x00\x38\x42\x49\x4d\x03\xed\x00\x00\x00\x00\x00\ -\x10\x00\x48\x00\x00\x00\x01\x00\x01\x00\x48\x00\x00\x00\x01\x00\ -\x01\x38\x42\x49\x4d\x04\x26\x00\x00\x00\x00\x00\x0e\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x3f\x80\x00\x00\x38\x42\x49\x4d\x04\ -\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x38\x42\x49\x4d\x04\ -\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x38\x42\x49\x4d\x03\ -\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x00\x38\x42\x49\x4d\x04\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x38\ -\x42\x49\x4d\x27\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\x00\x00\ -\x00\x00\x00\x00\x01\x38\x42\x49\x4d\x03\xf5\x00\x00\x00\x00\x00\ -\x48\x00\x2f\x66\x66\x00\x01\x00\x6c\x66\x66\x00\x06\x00\x00\x00\ -\x00\x00\x01\x00\x2f\x66\x66\x00\x01\x00\xa1\x99\x9a\x00\x06\x00\ -\x00\x00\x00\x00\x01\x00\x32\x00\x00\x00\x01\x00\x5a\x00\x00\x00\ -\x06\x00\x00\x00\x00\x00\x01\x00\x35\x00\x00\x00\x01\x00\x2d\x00\ -\x00\x00\x06\x00\x00\x00\x00\x00\x01\x38\x42\x49\x4d\x03\xf8\x00\ -\x00\x00\x00\x00\x70\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\ -\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\x03\xe8\x00\x00\x38\x42\x49\x4d\x04\x08\x00\x00\x00\x00\x00\ -\x10\x00\x00\x00\x01\x00\x00\x02\x40\x00\x00\x02\x40\x00\x00\x00\ -\x00\x38\x42\x49\x4d\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x00\x38\x42\x49\x4d\x04\x1a\x00\x00\x00\x00\x03\x5d\x00\x00\x00\ -\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x00\x00\ -\xb4\x00\x00\x00\x14\x00\x55\x00\x44\x00\x50\x00\x72\x00\x69\x00\ -\x6d\x00\x61\x00\x72\x00\x79\x00\x4c\x00\x6f\x00\x67\x00\x6f\x00\ -\x32\x00\x39\x00\x34\x00\x35\x00\x77\x00\x65\x00\x62\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\xb4\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00\x6e\x75\x6c\x6c\x00\x00\x00\x02\x00\x00\x00\x06\ -\x62\x6f\x75\x6e\x64\x73\x4f\x62\x6a\x63\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00\x52\x63\x74\x31\x00\x00\x00\x04\x00\x00\x00\x00\ -\x54\x6f\x70\x20\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x00\ -\x4c\x65\x66\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x00\ -\x42\x74\x6f\x6d\x6c\x6f\x6e\x67\x00\x00\x00\x49\x00\x00\x00\x00\ -\x52\x67\x68\x74\x6c\x6f\x6e\x67\x00\x00\x00\xb4\x00\x00\x00\x06\ -\x73\x6c\x69\x63\x65\x73\x56\x6c\x4c\x73\x00\x00\x00\x01\x4f\x62\ -\x6a\x63\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x73\x6c\x69\x63\ -\x65\x00\x00\x00\x12\x00\x00\x00\x07\x73\x6c\x69\x63\x65\x49\x44\ -\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x07\x67\x72\x6f\x75\ -\x70\x49\x44\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x06\x6f\ -\x72\x69\x67\x69\x6e\x65\x6e\x75\x6d\x00\x00\x00\x0c\x45\x53\x6c\ -\x69\x63\x65\x4f\x72\x69\x67\x69\x6e\x00\x00\x00\x0d\x61\x75\x74\ -\x6f\x47\x65\x6e\x65\x72\x61\x74\x65\x64\x00\x00\x00\x00\x54\x79\ -\x70\x65\x65\x6e\x75\x6d\x00\x00\x00\x0a\x45\x53\x6c\x69\x63\x65\ -\x54\x79\x70\x65\x00\x00\x00\x00\x49\x6d\x67\x20\x00\x00\x00\x06\ -\x62\x6f\x75\x6e\x64\x73\x4f\x62\x6a\x63\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00\x52\x63\x74\x31\x00\x00\x00\x04\x00\x00\x00\x00\ -\x54\x6f\x70\x20\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x00\ -\x4c\x65\x66\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x00\ -\x42\x74\x6f\x6d\x6c\x6f\x6e\x67\x00\x00\x00\x49\x00\x00\x00\x00\ -\x52\x67\x68\x74\x6c\x6f\x6e\x67\x00\x00\x00\xb4\x00\x00\x00\x03\ -\x75\x72\x6c\x54\x45\x58\x54\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x6e\x75\x6c\x6c\x54\x45\x58\x54\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x00\x4d\x73\x67\x65\x54\x45\x58\x54\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x06\x61\x6c\x74\x54\x61\x67\x54\x45\x58\x54\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x0e\x63\x65\x6c\x6c\x54\x65\x78\ -\x74\x49\x73\x48\x54\x4d\x4c\x62\x6f\x6f\x6c\x01\x00\x00\x00\x08\ -\x63\x65\x6c\x6c\x54\x65\x78\x74\x54\x45\x58\x54\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x09\x68\x6f\x72\x7a\x41\x6c\x69\x67\x6e\x65\ -\x6e\x75\x6d\x00\x00\x00\x0f\x45\x53\x6c\x69\x63\x65\x48\x6f\x72\ -\x7a\x41\x6c\x69\x67\x6e\x00\x00\x00\x07\x64\x65\x66\x61\x75\x6c\ -\x74\x00\x00\x00\x09\x76\x65\x72\x74\x41\x6c\x69\x67\x6e\x65\x6e\ -\x75\x6d\x00\x00\x00\x0f\x45\x53\x6c\x69\x63\x65\x56\x65\x72\x74\ -\x41\x6c\x69\x67\x6e\x00\x00\x00\x07\x64\x65\x66\x61\x75\x6c\x74\ -\x00\x00\x00\x0b\x62\x67\x43\x6f\x6c\x6f\x72\x54\x79\x70\x65\x65\ -\x6e\x75\x6d\x00\x00\x00\x11\x45\x53\x6c\x69\x63\x65\x42\x47\x43\ -\x6f\x6c\x6f\x72\x54\x79\x70\x65\x00\x00\x00\x00\x4e\x6f\x6e\x65\ -\x00\x00\x00\x09\x74\x6f\x70\x4f\x75\x74\x73\x65\x74\x6c\x6f\x6e\ -\x67\x00\x00\x00\x00\x00\x00\x00\x0a\x6c\x65\x66\x74\x4f\x75\x74\ -\x73\x65\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x0c\x62\ -\x6f\x74\x74\x6f\x6d\x4f\x75\x74\x73\x65\x74\x6c\x6f\x6e\x67\x00\ -\x00\x00\x00\x00\x00\x00\x0b\x72\x69\x67\x68\x74\x4f\x75\x74\x73\ -\x65\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x38\x42\x49\x4d\x04\ -\x28\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x01\x3f\xf0\x00\x00\x00\ -\x00\x00\x00\x38\x42\x49\x4d\x04\x11\x00\x00\x00\x00\x00\x01\x01\ -\x00\x38\x42\x49\x4d\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x04\x38\x42\x49\x4d\x04\x0c\x00\x00\x00\x00\x13\xa7\x00\x00\x00\ -\x01\x00\x00\x00\xa0\x00\x00\x00\x41\x00\x00\x01\xe0\x00\x00\x79\ -\xe0\x00\x00\x13\x8b\x00\x18\x00\x01\xff\xd8\xff\xe0\x00\x10\x4a\ -\x46\x49\x46\x00\x01\x02\x00\x00\x48\x00\x48\x00\x00\xff\xed\x00\ -\x0c\x41\x64\x6f\x62\x65\x5f\x43\x4d\x00\x02\xff\xee\x00\x0e\x41\ -\x64\x6f\x62\x65\x00\x64\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\ -\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\x15\ -\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\ -\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\ -\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\ -\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\xff\xc0\x00\x11\x08\x00\x41\x00\xa0\x03\x01\x22\x00\x02\x11\ -\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x0a\xff\xc4\x01\x3f\x00\x00\ -\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\ -\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\x01\ -\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\ -\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\x04\ -\x02\x05\x07\x06\x08\x05\x03\x0c\x33\x01\x00\x02\x11\x03\x04\x21\ -\x12\x31\x05\x41\x51\x61\x13\x22\x71\x81\x32\x06\x14\x91\xa1\xb1\ -\x42\x23\x24\x15\x52\xc1\x62\x33\x34\x72\x82\xd1\x43\x07\x25\x92\ -\x53\xf0\xe1\xf1\x63\x73\x35\x16\xa2\xb2\x83\x26\x44\x93\x54\x64\ -\x45\xc2\xa3\x74\x36\x17\xd2\x55\xe2\x65\xf2\xb3\x84\xc3\xd3\x75\ -\xe3\xf3\x46\x27\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\ -\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\x37\x47\ -\x57\x67\x77\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\ -\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x05\x35\x01\x00\x02\x11\ -\x03\x21\x31\x12\x04\x41\x51\x61\x71\x22\x13\x05\x32\x81\x91\x14\ -\xa1\xb1\x42\x23\xc1\x52\xd1\xf0\x33\x24\x62\xe1\x72\x82\x92\x43\ -\x53\x15\x63\x73\x34\xf1\x25\x06\x16\xa2\xb2\x83\x07\x26\x35\xc2\ -\xd2\x44\x93\x54\xa3\x17\x64\x45\x55\x36\x74\x65\xe2\xf2\xb3\x84\ -\xc3\xd3\x75\xe3\xf3\x46\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\ -\xb5\xc5\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\ -\x27\x37\x47\x57\x67\x77\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\ -\x01\x00\x02\x11\x03\x11\x00\x3f\x00\xf4\x8e\xa9\x87\x9f\x97\x53\ -\x1b\x83\x9e\xfe\x9d\x63\x4c\x9b\x19\x5d\x76\xee\x11\xf4\x1c\xcc\ -\x86\xbb\xfe\x82\xe1\xfa\x2f\x54\xfa\xdd\xd5\x3a\xd3\xfa\x4b\xba\ -\xb9\xa5\xd4\xfa\xa6\xdb\x45\x34\x3b\xf9\x97\x0a\x5d\xe9\xb4\xd0\ -\xdf\xa5\x63\xbf\x3b\xf3\x17\xa2\xaf\x3a\xfa\x9f\xff\x00\x8b\x8c\ -\xef\x86\x5f\xfe\x7f\xad\x5a\xe5\xc8\xf6\xf2\xdc\x62\x78\x63\x71\ -\xb8\xc6\x4d\x6c\xf7\xee\x62\xa3\x21\xc5\x2a\x95\x48\x8b\x14\xfa\ -\x06\x2d\x57\x53\x8f\x5d\x57\xdc\xec\x9b\x58\xd0\x1f\x7b\x83\x5a\ -\x5e\x7f\x7d\xcc\xa8\x32\xb6\xff\x00\x61\xab\x23\xeb\x35\x1d\x75\ -\xb8\xd6\xe7\xf4\xae\xa2\xec\x5f\xb3\x52\xe7\xbb\x17\xd2\xad\xed\ -\x7e\xc9\xb1\xee\xf5\x2d\xae\xcb\x19\x66\xcf\x6b\x3f\xc1\xad\xc4\ -\x0c\xed\x70\xb2\x01\xff\x00\x44\xff\x00\xfa\x92\xa0\x84\xaa\x60\ -\xd0\x3a\xec\x40\x23\xec\x67\x9c\x6e\x24\x59\x1a\x6e\x0e\xaf\x21\ -\xf5\x6b\xa9\xf5\x6b\xe8\xa7\xaa\xf5\xae\xb8\xcc\x6c\x37\xd8\xe6\ -\x55\x8f\x6b\x31\xeb\xf5\xb6\x0f\x7c\xdc\xea\xea\x77\xd2\xff\x00\ -\x44\xbb\x3f\x5a\x93\x4f\xae\x1e\xd3\x4e\xdd\xfe\xa0\x23\x6e\xd8\ -\xdd\xbf\x7f\xd1\xd9\xb5\x71\x7d\x25\xac\x7f\xf8\xb5\xb4\x3d\xa1\ -\xed\xf4\xed\x30\x75\xe2\xc7\x10\x75\xfc\xe6\xfe\x6a\xbb\xd0\xb2\ -\x6f\xe8\x3d\x50\xfd\x5a\xcf\x71\x38\xb6\xcb\xfa\x3e\x4b\xff\x00\ -\x39\x93\x2e\xc4\x7b\xc7\xb7\xd5\xaf\xfd\x7f\x9c\xc7\xad\x4f\x9a\ -\x02\x46\x66\x34\x0c\x25\x21\xc1\x10\x23\xe8\x87\x6e\x16\x0c\x39\ -\x0c\x44\x04\xac\x89\x46\x27\x8c\x9b\xf5\xcf\xbb\xb2\x3e\xb1\x7d\ -\x5f\x31\x1d\x4f\x10\xcf\x1f\xa7\xaf\xff\x00\x26\xa7\x4f\x5c\xe8\ -\xb7\xd8\xca\xa8\xcf\xc6\xb6\xcb\x0e\xd6\x31\x97\x31\xce\x71\xfd\ -\xd6\xb5\xae\xdc\xe5\xcb\xf5\xc6\xb5\xbf\x56\x3e\xb3\x6d\x00\x4e\ -\x7c\x98\x11\xa9\x38\x5a\xab\xbd\x46\xba\xfa\x6f\xd6\xce\x93\xd4\ -\xda\xd0\xca\xba\x85\x6e\xc0\xc8\x70\x11\xef\x21\xaf\xc5\x3a\x7e\ -\x73\xde\xc6\x53\xfd\x44\xdf\x66\x15\xa5\xd9\xe2\xaf\xf0\x21\x1c\ -\x9f\xf7\x4b\xbd\xe9\x5e\xc2\xbd\x37\xfe\x14\xa5\x0f\xfb\x97\x7b\ -\x2b\xab\x74\xbc\x2b\x05\x59\x99\x94\x63\x58\x5b\xb8\x32\xdb\x18\ -\xc3\xb4\x9d\xbb\xb6\xd8\xe6\xfb\x77\x04\x1f\xf9\xc5\xd0\x37\x06\ -\xfe\xd3\xc4\xdc\x78\x1e\xbd\x73\xff\x00\x56\x80\xe0\xdc\xef\xac\ -\xcc\xd0\x1a\xfa\x45\x25\xd3\xdf\xd7\xca\xf6\x01\xff\x00\x5a\xc4\ -\xad\xff\x00\xfb\x14\xb9\xcf\xab\x99\xbd\x34\xfd\x5b\xab\xa3\xe5\ -\xb1\xcf\x3d\x43\x2a\xcc\x66\xb1\xac\x21\xad\xde\xef\xa6\xdb\x9c\ -\xcf\xb3\xef\xa7\xf9\xe6\x7b\x90\x8e\x28\x98\xdf\xa8\x91\xc3\xc4\ -\x07\xf5\xf8\xbf\xee\x62\xa9\x66\x22\x55\xa5\x1e\x2e\x1b\xfe\xa7\ -\x0f\xfd\xd3\xd6\x59\xd7\xfa\x15\x4f\x75\x76\xf5\x1c\x5a\xde\xc7\ -\x16\x3d\xae\xba\xb0\x43\x9a\x76\xb9\x8e\x6b\x9f\xed\x73\x5c\xad\ -\x8b\xe8\x75\x3f\x68\x6d\x8d\x34\x16\xef\x16\x87\x0d\x9b\x63\x76\ -\xfd\xff\x00\x47\x66\xdf\xce\x5c\xd3\x72\xb0\xb1\x7e\xbb\xf5\x17\ -\xe6\x5d\x55\x15\x3f\x06\x80\x5d\x6b\x9a\xc6\x93\xb9\xfa\x7e\x90\ -\xb7\x77\xb5\x67\x55\xd1\xba\x86\x6f\xd4\xde\xa3\x4e\x13\x1d\x5d\ -\x59\x39\x76\x64\x60\x62\xb8\x6d\xdd\x8d\xbc\x3e\xaa\x9a\xc7\xed\ -\xf4\x9b\x63\x5b\xea\x57\x5f\xfe\x95\x4b\xd9\x8e\x96\x4c\x41\xe0\ -\xd6\x5b\x7e\xb3\xfe\xf5\x5e\xf4\xb5\xa0\x24\x47\x16\x83\x7f\x43\ -\xd5\xd3\xd7\xfa\x25\xfe\xa7\xa5\x9f\x8e\xff\x00\x45\xa6\xcb\x48\ -\xb1\xb0\xd6\x0d\x1d\x6f\x3f\xcd\x7b\xbf\x9d\xfe\x6d\x44\xfd\x62\ -\xfa\xbe\x39\xea\x78\x9f\xf6\xfd\x7f\xf9\x35\x47\xa1\x75\x4e\x97\ -\xd7\x6e\xab\x29\xac\x38\xdd\x4b\xa7\xd6\xfa\x6d\xc4\x77\xb5\xcc\ -\x16\x6c\x16\xb7\x61\x1e\xfa\xb7\xd0\xcd\x9f\xb9\xfe\x11\x53\xfa\ -\x87\x85\x8d\x6f\x4a\xc7\xcc\x7b\x01\xbb\x1a\xdc\x96\x52\x60\x7b\ -\x7d\x57\xb7\xd4\x7f\xfc\x66\xda\xfd\x3d\xff\x00\xe8\xfd\x89\x1c\ -\x51\x02\x46\x42\x40\xc6\x87\x0f\xf7\xb8\xbf\xef\x52\x32\x48\x98\ -\x88\xf0\x9e\x2b\x37\xfd\xde\x1f\xfb\xe7\x6b\xfe\x71\x7d\x5f\xd3\ -\xfc\xa7\x89\xaf\x1f\xa7\xaf\xff\x00\x26\x8b\x47\x57\xe9\x39\x37\ -\x0c\x7c\x7c\xda\x2e\xbc\xcc\x55\x5d\xac\x73\xbd\xbf\x4f\xd8\xc7\ -\x17\x7b\x56\x17\xd5\xcc\x4a\x33\x4f\xd6\x3c\x4c\x96\xef\xa2\xfe\ -\xa1\x7b\x2c\x69\xee\x1d\xa1\x4d\xd4\x03\x3e\xaf\xfd\x64\xc4\xea\ -\x8e\x76\xdc\x1e\xa3\x58\xc3\xcf\xb5\xfd\xad\x60\xdd\x8b\x93\x6b\ -\xff\x00\x79\xfb\x7d\x27\xb9\x23\x8a\x1c\x46\x02\xf8\x80\xb8\xff\ -\x00\x5b\xd3\xc4\x81\x96\x5c\x22\x66\xb8\x49\xd7\xfa\xba\xf0\xbd\ -\x0d\x3d\x4f\xa7\x5f\x92\xec\x4a\x72\xa9\xb7\x26\xbd\xdb\xe8\x65\ -\x8d\x75\x8d\xd8\x76\x59\xbe\xb6\x9d\xed\xd8\xff\x00\x6b\x95\x95\ -\x89\xd2\x5f\x55\x18\x59\x7f\x58\x73\xe3\x1c\xe7\x7e\xb3\x61\x70\ -\x83\x5e\x3b\x1b\xb7\x0e\xa7\xed\xdd\xef\x6e\x38\xf5\x6c\x6f\xfd\ -\xc8\xba\xd4\x47\x75\xdb\x68\x14\x5f\x9d\x85\x66\x2e\x16\x43\x9a\ -\xc1\x7b\xdc\x0b\xab\x75\x84\x36\x8f\xb6\xd2\x3f\xa3\x36\xcd\xdb\ -\x37\xef\xb3\xd1\xb3\xf9\xe4\xc3\x8c\xd9\x11\xd6\xb4\xff\x00\x0b\ -\xf4\x84\x7f\x79\x90\x64\x14\x38\xb4\xbd\x7f\xc1\xfd\x1e\x2f\xdd\ -\x75\xd2\x59\x18\x1d\x72\xec\xcb\x8b\x5b\x86\xf6\xd6\xcc\x9b\x30\ -\xee\xb0\x38\x3b\x65\x95\x35\xce\x7b\xcb\x5a\xdf\xe8\xfb\x99\xe9\ -\xfa\xbf\xcb\xfe\x6d\x6b\xa6\x4a\x26\x26\x8a\xe8\xc8\x48\x58\x7f\ -\xff\xd0\xf5\x55\xe6\xdf\x56\x1d\x73\x3e\xb8\x75\x37\xe3\xb0\x5b\ -\x73\x6b\xcd\x35\x54\x4e\xd0\xe7\x8b\x99\xb1\x85\xff\x00\x99\xbd\ -\xdf\x9e\xbd\x25\x79\xcf\xd5\x77\x7a\x1f\x5f\x72\xea\x7f\xd2\xb1\ -\xf9\x95\x0e\xda\xfa\x9e\xb6\x9f\xd8\xa5\x59\xe5\xbe\x4c\xdf\xdc\ -\x6b\x73\x1f\xce\x60\xfe\xff\x00\xec\x74\xba\x97\xd7\xae\xaf\xd2\ -\xef\x18\xfd\x43\xa3\x8a\x2d\x2d\xde\xd1\xeb\x87\x07\x37\x8d\xcc\ -\x7d\x75\xb9\xaa\xd1\xeb\xdf\x5a\x32\xb0\x0d\xec\xe8\x4d\x38\xf7\ -\xd3\xbd\xb6\x7d\xaa\xbf\xa0\xf6\xee\x6b\xf6\x40\x7f\xd0\x77\xd0\ -\x58\xff\x00\xe3\x3b\xfa\x7e\x07\xfc\x4d\xbf\xf5\x55\xae\x9a\xab\ -\xc6\x37\xd4\x9a\xef\x26\x3d\x3e\x9a\xd7\x0f\x8f\xa0\x36\x8d\x7f\ -\x94\x9f\x28\xe3\x18\xf1\x4c\x63\x8f\x14\xcd\x6f\x3f\xfb\xe5\x91\ -\x96\x43\x97\x2c\x0e\x49\x70\xc0\x58\xd2\x1f\xf7\xaf\x19\x89\xd7\ -\xf2\x30\xfe\xa8\x7e\xce\xb7\xa7\xda\x71\x6f\x6d\x8c\xab\x3d\xa7\ -\xf4\x65\xce\x73\x8c\x3a\x5b\xb5\xae\x6b\xbf\x37\x7a\xea\xae\xc8\ -\xe8\x7f\x5c\xfa\x73\xf1\xf1\x2f\x35\xe6\x53\xfa\x6a\x77\x02\xcb\ -\xa9\xb1\xa7\xf4\x76\xed\xfd\xcd\xdf\x4f\xd2\x77\xfe\x0a\x8d\xf5\ -\x2f\x15\xa3\xea\x9e\x1d\x37\xd6\x1c\xdb\x59\x61\x7b\x1c\x24\x39\ -\xb6\x3e\xc3\xef\x6b\xbe\x93\x5f\x5b\x97\x19\xf5\x9f\xa4\x5b\xf5\ -\x67\xad\x53\x95\xd3\x5e\xea\xaa\xb2\x6d\xc4\x78\xd4\xd6\xf6\xe9\ -\x6e\x3e\xbf\xce\x57\xef\xfc\xff\x00\xe7\x29\xb3\xd1\xb1\x3c\x70\ -\x64\xcb\x28\xc7\xf5\x79\x23\x29\x4a\x12\xbb\x8c\xcf\x5b\x58\x78\ -\xf1\x63\x8c\xe5\xfa\xcc\x72\x8c\x63\x38\xd5\x4a\x11\xe9\xc3\xfe\ -\x33\xa7\x96\x7a\x8b\xfe\xa7\x75\x4c\x7e\xa1\x45\x83\xaa\x65\xe5\ -\x96\x9a\x99\x53\xce\xf7\xd6\x71\xb7\xd8\xcf\x49\x8e\x66\xc7\xd7\ -\x4f\xab\xea\xff\x00\x32\xff\x00\xf0\x6b\x7f\xeb\x2e\x38\xea\xdf\ -\x56\x1f\x76\x16\xf7\x5b\x46\xdc\xac\x63\xb5\xcd\x7e\xfa\x4c\xe9\ -\x53\xda\xdb\x77\xec\x16\x6c\x66\xc4\x1c\xaf\xad\x19\xdf\xf3\x6a\ -\x9f\xac\x18\x35\x52\xe6\x35\xbf\xad\xd3\x69\x70\x70\x7e\xe6\xd0\ -\xe6\xd2\xe6\x6e\xfa\x36\xff\x00\xa4\xff\x00\x04\x96\x47\x58\xfa\ -\xcf\x4f\x43\xfd\xb4\xca\x70\xad\xa7\xd0\x6e\x51\xa4\x1b\x5a\xf1\ -\x59\x6f\xaa\xef\x79\xdc\xc7\x7a\x4c\x51\x9e\x32\x62\x68\x44\xc7\ -\x21\xfd\x2d\x38\xfd\x23\x82\xbf\xc1\x64\x1c\x1a\xc6\xe5\x21\x28\ -\x0e\x9a\xf0\x7a\xa5\x19\xdf\xf8\x4d\xfe\x8b\xbf\x17\xa4\xbf\xa8\ -\xf5\x00\x6b\xc8\xcd\x71\xcc\xc9\x6c\x39\xc5\xbe\xa6\xd1\x55\x3b\ -\x36\xfa\xbf\xab\xe3\x36\x8a\x36\xec\xff\x00\x06\xb0\xfe\xaa\xe6\ -\xe0\xe2\x74\x21\x47\x52\xa6\xf6\x5b\x4d\xef\xbd\xb5\x3b\x1e\xe2\ -\xe9\xdd\xea\x52\xf6\x06\x56\x77\x2b\xfd\x6b\xae\xf5\xbe\x9f\xd5\ -\xf1\x7a\x7d\x35\x62\xd8\xce\xa2\xf2\xcc\x67\xbc\xd8\x1c\xcd\xbb\ -\x37\x7a\xf1\xed\x77\xb9\xff\x00\xe0\xd6\xce\x56\x63\xb0\x3a\x65\ -\x99\x99\x9b\x4b\xf1\xe9\x36\x5c\x2b\xd1\xa5\xcd\x6e\xe7\x36\xad\ -\xff\x00\xbe\xff\x00\x6d\x7b\x93\x09\x20\x6a\x2f\xdd\x22\x51\xe1\ -\x97\xee\xfa\x40\x5f\x40\x9d\x0d\x7b\x40\xc6\x5c\x51\xfd\xed\xde\ -\x5b\xa7\xbe\xae\xad\xd7\xf2\x5d\xd4\x71\xec\x65\x7d\x4f\xa7\xd5\ -\x45\x8c\x35\x5a\x1a\x2d\xf7\xd9\x75\x02\xd7\xd6\x1a\xd7\xd2\xcf\ -\xf0\x9f\xe9\x7e\x82\x2f\x4d\xeb\x9d\x47\xa3\xe2\x8e\x9b\xd4\x71\ -\xee\xb5\xdd\x3b\x21\xb4\x5b\x92\x29\xb1\xe1\xf8\x64\x3c\x55\x99\ -\x5b\xaa\x0e\x6f\xe8\x7f\x43\xeb\xff\x00\xc1\x7f\xc3\xa2\xe1\xfd\ -\x66\xeb\x39\x9f\x56\x9d\xd5\xb1\xe8\xa2\xcc\xac\x47\x58\x33\xa8\ -\x76\xf6\x08\xaf\xdf\xfa\x0f\x73\xdc\xd7\x36\xa2\xd7\xed\xb1\x69\ -\xfd\x59\xea\x79\xdd\x5b\xa6\xb7\xa8\x65\x32\x9a\xd9\x79\x3e\x8b\ -\x2a\x2e\x24\x06\x97\x56\xff\x00\x55\xcf\xfc\xed\xec\xfc\xc4\xec\ -\x96\x04\xb8\xa2\x38\x62\x44\x38\x78\xbe\x59\xc7\xf7\x7f\xc0\x5b\ -\x0a\x24\x70\xc8\xf1\x48\x19\xf1\x70\xe8\x60\x7f\x7b\xfc\x27\x1e\ -\xfb\x30\xb2\xbe\xb5\xe1\x75\x9e\x9a\xd7\x3a\x8c\x6a\x6d\x3d\x4f\ -\x32\xb6\x3b\xd3\x73\x4b\x3d\x3c\x7a\xb7\x06\xfe\xb1\x91\xbd\xdf\ -\x42\xbd\xef\xd9\x5f\xe9\x3f\x9b\x56\x3e\xa2\xda\x28\xe8\x96\x51\ -\x73\x2c\xaa\xda\x2c\xb2\xcb\x1b\x65\x6f\x61\xda\xe2\x5c\xc7\x37\ -\x7b\x1b\xbf\x73\x7f\x71\x68\x74\xdf\xac\x14\xe7\xf5\x9e\xa5\xd2\ -\xd8\xd0\x3e\xc0\x58\x19\x60\x33\xbe\x46\xdb\xfd\xb1\xec\xf4\x2f\ -\xfd\x12\x0f\x55\xea\x5d\x7b\x1b\xab\x63\x60\x61\x55\x8b\x6b\x33\ -\xb7\xfa\x4e\xb0\xd8\x1d\x58\xa9\xad\x7d\xd6\x5e\xd6\x7d\x26\x6e\ -\x77\xe8\xf6\x20\x4c\xa4\x3d\xb3\x1a\xf4\xc4\x8e\x29\x7e\x84\x78\ -\xa7\xff\x00\x76\xb8\x00\x0f\xb8\x0d\xeb\x20\x78\x63\xfa\x53\xf4\ -\xff\x00\xdc\x35\x7e\xa7\xdc\xd3\x99\xd6\x01\x6d\x8c\x39\x39\xb6\ -\xe4\x53\xea\x55\x63\x37\x54\x48\x0d\xb5\xae\xb1\x8d\x6f\xbb\xfc\ -\xf5\x2f\xaf\xff\x00\xa4\xfa\xbf\x6e\x2d\x75\xbe\xec\x8b\x9c\xd3\ -\x4b\x2b\xad\xd6\x12\x5a\xe6\xb9\xe7\xf4\x6d\x7f\xa7\xec\x46\x1f\ -\x59\x5c\x7e\xb7\x1e\x85\xb5\xbf\x67\xf4\x4c\x59\x07\x71\xc8\x0d\ -\xfb\x43\xab\x0e\x9d\x9e\x9b\x71\x8f\xee\xfd\x35\x0e\xbd\xd6\xfa\ -\xcf\x4c\xea\x78\x78\xb4\xd5\x8d\x65\x1d\x46\xd1\x4e\x3b\xde\x5e\ -\x1e\xc7\x7b\x03\x8d\xcd\x6f\xb5\xcd\xdc\xff\x00\xcc\x48\x09\x7b\ -\xd1\x97\x0d\x12\x06\x48\xc4\x9d\xc4\x7c\x7f\xc1\x41\x31\x18\x65\ -\x1b\xb0\x09\xc6\x48\x1b\x5b\x67\xeb\x06\x33\xfa\xe7\xd5\xac\x9a\ -\x7a\x7f\xb9\xf9\x0c\x0e\xa4\x3c\x16\x6e\x2c\x7b\x6c\xf4\xdc\xdb\ -\x83\x36\xfa\x9e\x9f\xa7\xfa\x45\x4b\xad\x65\xd7\xf5\x83\xa1\xfe\ -\xcc\xc3\x65\x83\x33\x3c\xb1\x96\x52\xf6\x39\xae\xc7\xda\xf6\x59\ -\x90\xfc\xcd\xe1\x9e\x93\x68\x6b\x5d\xff\x00\x86\x2c\xfe\x8f\xea\ -\x23\x3f\xaf\x75\x2e\x9b\xd5\x31\x30\x3a\xcd\x14\xfa\x5d\x41\xde\ -\x9e\x36\x5e\x33\x9c\x5a\x2c\x90\xd1\x55\xd4\xda\x37\xb7\x73\x9e\ -\xcf\xd2\x35\xea\xbd\x3d\x73\xeb\x1d\xbd\x72\xee\x87\xe9\xe1\x37\ -\x22\x8a\x85\xee\xbb\xf4\xa5\x85\xa7\x67\xb5\xac\xfa\x6d\x77\xe9\ -\x7f\x79\x28\x46\x42\xa8\x0a\x81\xf7\x60\x78\xbf\xc1\xff\x00\x0b\ -\xe5\x8a\x67\x28\x9d\xc9\xb9\x0f\x6a\x63\x87\xfc\x2f\xf0\x7e\x66\ -\x7f\x56\x71\x5d\x6e\x4e\x66\x5f\xad\x7d\x6d\x66\x7e\x53\xdb\x8e\ -\x41\x65\x6f\x65\xc4\x7a\x77\x6d\x7b\x19\x63\xf8\xfd\x1b\xf7\xec\ -\x5d\x2a\xc9\xe9\x9d\x43\xaa\xbf\xa9\xe5\x74\xee\xa7\x55\x0c\x75\ -\x15\x57\x75\x56\x50\x5c\x43\xdb\x61\xb1\x93\xb6\xcf\x73\x36\x3a\ -\xa5\xac\xa2\xca\x49\x96\xbd\x85\x56\xba\x32\x62\x00\x47\x4e\xe6\ -\xef\xbb\xff\xd1\xf5\x55\xe7\xff\x00\x5c\x3a\x4f\x50\xe9\x3d\x6d\ -\x9f\x59\x7a\x73\x37\xd5\xb9\xb6\xdb\x00\x91\x5d\x8d\x1b\x1f\xeb\ -\x35\x9e\xef\xb3\x64\xd4\x3f\x49\x67\xfc\x6f\xfa\x4a\xd7\xa0\x24\ -\xa4\xc5\x94\xe3\x95\x81\x60\x8e\x19\x44\xfe\x94\x58\xf3\x62\x19\ -\x23\x44\xd1\x07\x8a\x32\x1f\xa3\x20\xf9\x57\xd6\xee\xbf\x87\xd7\ -\x9f\x83\x93\x8a\x1c\xc7\x57\x53\xdb\x7d\x4f\x1a\xb1\xce\x2c\x20\ -\x07\x8f\x6d\x8d\xf6\xbb\xde\xd5\xab\x5e\x5e\x67\xd6\x7e\x9d\x81\ -\xf5\x77\xa6\x31\xf5\xe1\x51\x55\x2d\xea\x99\xae\x10\xd0\x6a\x6b\ -\x37\x51\x54\xfd\x27\xef\x6f\xf6\xdf\xff\x00\x01\xfa\x44\x0f\xf1\ -\x91\x8d\x8f\x47\x50\xc3\x34\x54\xca\x8d\x95\x5a\xeb\x0b\x1a\x1a\ -\x5c\x43\xab\x87\x3f\x68\xf7\xae\xdf\xea\xf8\x03\xa0\xf4\xd8\x11\ -\xfa\xad\x27\xef\xad\x8a\xde\x4c\x91\x8e\x0c\x52\x8c\x7a\x9e\x0e\ -\x23\xf2\x1e\xff\x00\xd6\x69\xe3\xc7\x29\x67\xcb\x19\x4b\xa4\x78\ -\xf8\x45\x71\x86\xe5\x14\xd5\x8f\x4d\x74\x52\xdd\x95\x54\xd0\xca\ -\xd8\x38\x0d\x68\xda\xc6\xff\x00\x9a\xb9\x7f\xf1\x91\x43\x5f\xd1\ -\x29\xba\x25\xd4\xe4\x32\x0f\x80\x7b\x5e\xc7\x7f\xdf\x57\x58\xb9\ -\x6f\xf1\x8d\x66\xcf\xab\xed\x68\x3f\xce\x64\x56\xd8\xf1\x00\x3d\ -\xff\x00\xf7\xc5\x5b\x97\x27\xde\x87\xf7\x9b\x5c\xc8\x1e\xc4\xc7\ -\xf5\x5e\x67\xa5\xdc\xe7\x7d\x43\xeb\x74\x1f\xa3\x55\xd5\xb8\x1f\ -\xeb\xba\x8d\xdf\xf5\x0b\xa4\xc0\xea\xfd\x46\xbc\x3e\x81\x86\x30\ -\xdf\x46\x36\x47\xa3\x4b\xf2\x6c\x35\x3d\x96\x30\x50\xe7\xec\x63\ -\x2b\xb2\xcb\x19\xeb\x6c\xf6\x7a\x8c\x62\xe5\xba\x7b\xe9\xa3\xea\ -\x4f\x57\x37\x5a\xca\xdf\x99\x73\x19\x8f\x5b\x9c\x03\x9e\x6a\x34\ -\x1b\x7d\x26\x1f\x75\x9b\x37\xfb\xb6\xae\xc7\xa4\x75\xef\xab\x8c\ -\xe8\x38\x07\x27\x3b\x14\x3b\x17\x1e\xa2\x58\xf7\xb3\x7b\x1f\x5d\ -\x7b\x1f\xb6\xa2\x7d\x5f\x55\xbe\xf6\xfb\x18\xad\x67\x1f\x35\x43\ -\x8b\xf5\x92\xff\x00\xd2\x71\xff\x00\xba\x6a\xf2\xff\x00\xa3\xea\ -\xe1\xfd\x5c\x7f\xe9\xc9\xad\xf5\xa7\xff\x00\x15\x3f\x57\x3f\xe3\ -\x5f\xf9\x6b\x5a\xbd\x70\x1c\xac\x9e\x9d\xd2\x9a\x25\xb9\x17\x8c\ -\x8c\x8d\x37\x0f\x43\x17\x6e\x43\xb7\xff\x00\x26\xcc\xaf\xb2\x53\ -\xff\x00\x5c\x5c\x9f\x50\xeb\xf8\xd9\xbd\x4f\xea\xe7\x50\xc9\xba\ -\x9a\x88\xb6\xdb\x2e\x60\x78\x3e\x95\x6f\xb1\xbf\x65\xfb\x47\xb9\ -\xde\x9b\xfd\x0f\x4f\xd4\xdd\xfc\xb5\x63\xa9\x75\x4e\x8b\xd5\x3a\ -\x9e\x4d\x8e\x38\xb9\xd6\x8b\x71\xba\x6f\x4b\xa2\xdf\xd2\x34\xba\ -\xc7\x87\x65\xe5\x7a\x6d\x73\x7f\x45\xfa\x5d\x9e\xb7\xd0\xfd\x57\ -\xe9\xfe\x91\x47\xed\x4a\xb1\xd8\x3e\x88\xcb\x5a\xbf\x57\x1c\xa2\ -\x3f\xef\xd9\x7d\xc8\xde\x4a\x20\xf1\xca\x3e\x17\x1e\x0d\x7f\xef\ -\x5b\xfd\x09\xbf\xb3\xfe\xb6\xf5\x9e\x91\x60\x9a\x73\x40\xcd\xa0\ -\x3b\x82\x1e\x7f\x4e\xd6\xb7\xf7\x77\xdb\xe9\xff\x00\xd6\x15\x7f\ -\xaa\xdd\x41\xbd\x17\xa3\xf5\xac\x5b\xce\xf3\xd1\x6e\xb4\xb4\x38\ -\xc6\xe6\xeb\xe9\x35\xbf\xf1\xd6\x57\xed\xff\x00\x8c\x40\xfa\xc5\ -\x5f\x48\xfa\xb3\xd7\x7a\x46\x7e\x10\xab\x18\x35\xce\x6e\x56\x3d\ -\x70\x1d\xe9\x3f\xf4\x6e\xbc\xd4\x3d\xde\xd6\x3a\xef\xfa\xe2\x26\ -\x4e\x19\xc8\xfa\xec\xda\xb1\x9e\xdb\x30\x3a\xad\x54\x67\x64\x39\ -\x90\xe6\xbd\x98\x87\xd9\xb4\xea\xd7\x57\x66\x43\x31\x77\xfe\xff\ -\x00\xa8\x8d\x09\x46\xcf\xcb\x38\x46\x56\x7d\x3e\xac\x1e\x99\x7f\ -\x8d\x8d\x16\x63\x2a\x1f\x34\x27\x28\x80\x3d\x5e\x9c\xde\xa8\xff\ -\x00\x8b\x34\x5f\x63\xb3\xea\xdf\x5e\xe8\x59\x76\xf3\x9d\x51\xc5\ -\xea\x2e\x99\xdd\x91\x61\xf5\x2d\xb5\xef\xfe\x56\x4d\xcc\x76\xef\ -\xf4\x54\x2d\xef\xb4\x54\x7e\xb0\xf5\x2e\xa3\x79\x23\x1f\xa3\xe2\ -\x36\x92\x62\x61\xd6\x0f\xb7\xe5\xb9\xbf\xf5\x86\x62\x28\xfd\x7a\ -\xe9\xdf\x6e\xfa\xbb\x7b\x9a\x3f\x49\x89\x19\x2c\x3c\x68\xcf\xe7\ -\x7f\xf0\x17\x58\xb0\xd9\x9b\x8e\x3a\x26\x16\x16\x76\x45\x75\xe5\ -\xfd\x61\xca\x6e\x56\x68\x73\xf6\x46\x3d\x8f\xf5\x5e\xfe\x7f\x45\ -\x5d\xf8\xf4\x55\x8b\x4f\xfc\x62\x03\xf5\x90\x13\x3f\x36\xb8\xe5\ -\x5b\xd5\xfb\x9c\x5f\xf8\x5a\x4f\xea\xe7\x28\x0f\x97\x4c\x91\xed\ -\x7f\x27\x0f\xf8\xeb\x75\x9c\x4c\xbe\x9f\xd1\xba\x47\x5f\xb1\x84\ -\x66\x63\x65\x1c\xcc\xc6\x34\x16\x99\xcb\x77\xda\x2d\xa9\xff\x00\ -\xb9\xb3\xf4\x78\x8a\xff\x00\xd7\x2b\xeb\x1d\x47\xea\xe6\x40\x25\ -\xf5\x0c\xb1\x60\x2c\x69\x79\x2d\xfd\x13\xbd\x8c\xac\x3a\xcb\x3f\ -\xaa\xc6\xab\x5d\x6f\xea\xbf\xd5\xca\xba\x46\x65\x8d\xc5\xc7\xc4\ -\x78\xa9\xc5\x99\x06\x18\x1a\xff\x00\xf0\x5f\xa4\x3f\x47\x75\xbb\ -\x1a\xb9\x4a\xfa\xe6\x2e\x46\x27\xd5\x71\x6d\xcc\x16\xf4\xfc\xb1\ -\x5e\x40\x73\x9a\xdd\xb5\xb5\xd5\x36\xab\x5d\x27\xdb\x4b\x69\xdb\ -\xfa\x4f\xf8\x37\xa7\x63\xf5\xf0\xcc\x59\xe0\x33\x07\x4a\xd3\x24\ -\x65\x2f\xeb\x2c\xc9\x70\xe2\x81\xa1\xc6\x20\x46\xb7\xea\x84\xa3\ -\x17\xa3\xcc\x73\x3e\xb3\xf5\xec\x2a\x70\xc3\x86\x27\x46\xb4\x64\ -\x67\x59\x6b\x4d\x6e\xf5\x34\x7e\x3e\x33\x71\xef\x0c\xbf\x73\xfd\ -\x3f\xd2\x6f\xaf\xd3\xf4\xd0\x3d\x7b\xf1\xff\x00\xc6\x16\x73\xf1\ -\xf1\x9f\x98\xf3\x86\xc0\x6b\xad\xcc\x69\x03\xf4\x3e\xf9\xbd\xf5\ -\x33\x6f\xe6\xfd\x25\x3f\xac\x57\x0e\x8f\xd5\xb0\xfe\xb6\x61\x11\ -\x76\x16\x43\x46\x3f\x50\xf4\x88\x73\x5f\x59\xfe\x62\xf6\xb8\x1d\ -\xae\x76\xdf\xa0\xff\x00\xf8\x3a\x6b\xff\x00\x0a\xab\x61\xf5\xbe\ -\x8f\xff\x00\x3f\x72\x73\x4e\x65\x23\x16\xfc\x36\xb2\xbb\xcb\xc0\ -\x61\x74\x52\xfd\x9e\xa3\xbd\xac\x7e\xd6\xbb\xe9\xff\x00\xd5\xa1\ -\x10\x78\x6e\x22\xe1\xed\x48\x01\xfd\x7e\x2f\x5c\x64\xba\x64\x71\ -\x00\x4d\x4f\xdd\x89\x27\xfa\xbc\x3e\x89\x45\xe9\x7a\x06\x7e\x57\ -\x50\xc6\xbe\xfc\xba\xfd\x0b\x9b\x91\x6d\x5e\x89\x8d\xd5\xb5\x87\ -\x6b\x2a\x7b\x99\xb9\xaf\x77\xe7\x6f\x5a\x8b\x0a\xcf\xac\x9d\x30\ -\x75\x3c\x6c\x3e\x9f\x75\x17\xb6\xc1\x6e\x4e\x75\x94\x91\x60\x65\ -\x55\x56\x7d\xe7\xd1\x3f\xcf\x3e\xdf\x47\xf7\xff\x00\x46\xb5\x70\ -\x73\xb1\xb3\xe8\xf5\xf1\x9c\x5c\xc9\x2d\x32\x08\x20\xb7\x90\x41\ -\x55\xb2\x44\xdf\x17\x0f\x08\x3d\x3b\x36\x61\x21\xf2\xf1\x71\x11\ -\xf8\xbf\xff\xd2\xf5\x54\x92\x43\xc8\xb8\x63\xe3\xdb\x79\x63\xec\ -\x15\x31\xcf\x2c\xad\xa5\xcf\x76\xd1\xbb\x65\x75\xb7\xe9\xd8\xef\ -\xcc\x62\x4a\x78\x1f\xf1\x9d\xfd\x3f\x03\xfe\x26\xdf\xfa\xaa\xd7\ -\x67\xf5\x7f\xfe\x41\xe9\xbf\xf8\x52\x8f\xfc\xf6\xc5\xc1\x7d\x6e\ -\xc8\xea\x3d\x7b\x36\x8b\x71\xba\x56\x7d\x74\xe3\xd6\xe6\x03\x66\ -\x35\xa1\xce\x2f\x21\xce\x3b\x5a\xc7\x6d\x6f\xb1\x6e\xf4\x4f\xad\ -\x19\x58\x9d\x33\x1f\x0f\x37\xa3\x75\x1f\x57\x1a\xb6\xd4\x1d\x56\ -\x35\x8e\x6b\x9a\xc1\xb1\x8e\xf7\x06\x39\xae\xd8\xdf\x7a\xbb\x93\ -\x1c\x8f\x2f\x8e\x22\xb8\xa2\x4d\x8b\x1d\x5a\x58\xa6\x07\x31\x96\ -\x44\x1e\x19\x01\x47\x86\x5d\x1e\xbd\x79\xff\x00\xf8\xc5\xcf\x39\ -\x59\xf8\x7d\x1f\x18\x1b\x6d\xa8\xef\x7b\x1b\xa9\x36\xdb\xec\xc7\ -\xa7\x6f\xef\xec\xf7\xff\x00\xd7\x6b\x5b\x19\x1f\x58\x3e\xb2\x67\ -\xb0\xd3\xd1\xba\x35\xd8\xee\x76\x9f\x6a\xce\x02\xa6\xb2\x7f\x3d\ -\xb4\x3c\xee\x7f\xfa\xfe\x8e\xc4\x5f\xab\x7f\x54\x2b\xe9\x57\x3b\ -\xa8\x67\xdb\xf6\xce\xa9\x61\x25\xd7\x19\x2d\x61\x77\xf3\x86\xad\ -\xfe\xf7\x5b\x67\xf8\x4b\xdf\xfd\x4f\xd1\xfb\xf7\xc7\x88\x0c\x27\ -\xdc\x99\x1c\x43\xe4\x80\x36\x78\xbf\xad\xfb\xac\x99\xaf\x30\xf6\ -\xe0\x0f\x0c\xbe\x79\x9d\x07\x0f\x68\xba\x1d\x0b\xa3\x55\xd2\xfa\ -\x4e\x36\x0b\xc3\x6c\xb2\xa6\x93\x63\xe0\x10\x6c\x79\xdf\x69\x69\ -\x2d\x6f\xb7\x77\xb5\x9f\xf0\x6a\xff\x00\xd9\xe8\x99\xf4\xd9\x3e\ -\x3b\x42\x22\x4a\xbc\xa4\x64\x49\x27\x52\x6d\x9e\x31\x11\x00\x01\ -\xa0\x14\xc3\xd1\xa6\x67\xd3\x6c\x9e\x74\x09\x0a\x69\x04\x10\xc6\ -\x82\x38\x20\x05\x34\x90\xb2\xba\x83\x17\x57\x5b\x8e\xe7\x31\xa4\ -\xf1\x24\x02\x61\x20\xc6\x36\x36\xb4\x08\x10\x20\x70\x3c\x14\x92\ -\x49\x4b\x10\x08\x83\xc2\x89\xa6\x93\xcb\x1a\x74\x03\x50\x38\x1c\ -\x05\x34\x92\x52\xce\x6b\x5c\x36\xb8\x07\x03\xc8\x3a\x85\x1f\x46\ -\x9f\xf4\x6d\xfb\x82\x9a\x49\x29\x8e\xc6\x6d\xd9\xb4\x6d\xe3\x6c\ -\x69\x1f\x05\x1f\x42\x88\x8f\x4d\xb1\xfd\x50\x88\x92\x56\xaa\x47\ -\xe8\x51\xb4\xb7\xd3\x6e\xd7\x02\xd7\x0d\xa2\x08\x3f\x49\xa5\x36\ -\x3e\x36\x3e\x2d\x2d\xa3\x1a\xa6\xd3\x53\x3e\x8d\x6c\x01\xad\x13\ -\xaf\xd1\x6a\x2a\x48\xd9\xee\x8a\x1b\xd3\xff\xd3\xf5\x54\x97\xca\ -\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\ -\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\ -\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\ -\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\ -\x24\xa7\xff\xd9\x00\x38\x42\x49\x4d\x04\x21\x00\x00\x00\x00\x00\ -\x55\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00\x41\x00\x64\x00\x6f\ -\x00\x62\x00\x65\x00\x20\x00\x50\x00\x68\x00\x6f\x00\x74\x00\x6f\ -\x00\x73\x00\x68\x00\x6f\x00\x70\x00\x00\x00\x13\x00\x41\x00\x64\ -\x00\x6f\x00\x62\x00\x65\x00\x20\x00\x50\x00\x68\x00\x6f\x00\x74\ -\x00\x6f\x00\x73\x00\x68\x00\x6f\x00\x70\x00\x20\x00\x43\x00\x53\ -\x00\x33\x00\x00\x00\x01\x00\x38\x42\x49\x4d\x04\x06\x00\x00\x00\ -\x00\x00\x07\x00\x05\x00\x01\x00\x01\x01\x00\xff\xe1\x0e\x98\x68\ -\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\ -\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x00\x3c\x3f\x78\x70\ -\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\xbb\xbf\ -\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\x68\x69\ -\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\x22\x3f\ -\x3e\x0d\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\x3a\ -\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\x22\ -\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x34\ -\x2e\x31\x2d\x63\x30\x33\x36\x20\x34\x36\x2e\x32\x37\x36\x37\x32\ -\x30\x2c\x20\x4d\x6f\x6e\x20\x46\x65\x62\x20\x31\x39\x20\x32\x30\ -\x30\x37\x20\x32\x32\x3a\x31\x33\x3a\x34\x33\x20\x20\x20\x20\x20\ -\x20\x20\x20\x22\x3e\x0d\x0a\x09\x3c\x72\x64\x66\x3a\x52\x44\x46\ -\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\ -\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\ -\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\ -\x74\x61\x78\x2d\x6e\x73\x23\x22\x3e\x0d\x0a\x09\x09\x3c\x72\x64\ -\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\ -\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3a\x78\x61\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\ -\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\ -\x30\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\ -\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\ -\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3d\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\ -\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x2f\x31\ -\x2e\x30\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x61\x70\x4d\x4d\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\ -\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\ -\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\x66\x66\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\ -\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\x2f\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x65\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\ -\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\ -\x69\x66\x2f\x31\x2e\x30\x2f\x22\x20\x78\x61\x70\x3a\x43\x72\x65\ -\x61\x74\x65\x44\x61\x74\x65\x3d\x22\x32\x30\x30\x39\x2d\x30\x31\ -\x2d\x31\x34\x54\x31\x35\x3a\x33\x31\x3a\x34\x33\x2d\x30\x35\x3a\ -\x30\x30\x22\x20\x78\x61\x70\x3a\x4d\x6f\x64\x69\x66\x79\x44\x61\ -\x74\x65\x3d\x22\x32\x30\x31\x30\x2d\x30\x37\x2d\x32\x38\x54\x31\ -\x33\x3a\x30\x34\x3a\x35\x30\x2d\x30\x34\x3a\x30\x30\x22\x20\x78\ -\x61\x70\x3a\x4d\x65\x74\x61\x64\x61\x74\x61\x44\x61\x74\x65\x3d\ -\x22\x32\x30\x31\x30\x2d\x30\x37\x2d\x32\x38\x54\x31\x33\x3a\x30\ -\x34\x3a\x35\x30\x2d\x30\x34\x3a\x30\x30\x22\x20\x78\x61\x70\x3a\ -\x43\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\x64\x6f\ -\x62\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x53\x33\ -\x20\x4d\x61\x63\x69\x6e\x74\x6f\x73\x68\x22\x20\x64\x63\x3a\x66\ -\x6f\x72\x6d\x61\x74\x3d\x22\x69\x6d\x61\x67\x65\x2f\x6a\x70\x65\ -\x67\x22\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\ -\x6f\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x20\x70\x68\x6f\x74\x6f\ -\x73\x68\x6f\x70\x3a\x48\x69\x73\x74\x6f\x72\x79\x3d\x22\x22\x20\ -\x78\x61\x70\x4d\x4d\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\ -\x3d\x22\x75\x75\x69\x64\x3a\x30\x32\x39\x34\x41\x43\x45\x37\x44\ -\x41\x39\x42\x44\x46\x31\x31\x41\x43\x41\x33\x39\x37\x37\x38\x46\ -\x42\x30\x42\x39\x45\x36\x37\x22\x20\x74\x69\x66\x66\x3a\x58\x52\ -\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x30\x30\x30\ -\x30\x2f\x31\x30\x30\x30\x30\x22\x20\x74\x69\x66\x66\x3a\x59\x52\ -\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x30\x30\x30\ -\x30\x2f\x31\x30\x30\x30\x30\x22\x20\x74\x69\x66\x66\x3a\x52\x65\ -\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x55\x6e\x69\x74\x3d\x22\x32\x22\ -\x20\x74\x69\x66\x66\x3a\x4e\x61\x74\x69\x76\x65\x44\x69\x67\x65\ -\x73\x74\x3d\x22\x32\x35\x36\x2c\x32\x35\x37\x2c\x32\x35\x38\x2c\ -\x32\x35\x39\x2c\x32\x36\x32\x2c\x32\x37\x34\x2c\x32\x37\x37\x2c\ -\x32\x38\x34\x2c\x35\x33\x30\x2c\x35\x33\x31\x2c\x32\x38\x32\x2c\ -\x32\x38\x33\x2c\x32\x39\x36\x2c\x33\x30\x31\x2c\x33\x31\x38\x2c\ -\x33\x31\x39\x2c\x35\x32\x39\x2c\x35\x33\x32\x2c\x33\x30\x36\x2c\ -\x32\x37\x30\x2c\x32\x37\x31\x2c\x32\x37\x32\x2c\x33\x30\x35\x2c\ -\x33\x31\x35\x2c\x33\x33\x34\x33\x32\x3b\x33\x45\x36\x34\x31\x41\ -\x42\x34\x41\x30\x33\x45\x36\x32\x34\x42\x43\x32\x35\x46\x30\x31\ -\x37\x32\x44\x39\x43\x39\x38\x36\x41\x35\x22\x20\x65\x78\x69\x66\ -\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\ -\x3d\x22\x31\x38\x30\x22\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\ -\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x37\x33\x22\ -\x20\x65\x78\x69\x66\x3a\x43\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\ -\x3d\x22\x2d\x31\x22\x20\x65\x78\x69\x66\x3a\x4e\x61\x74\x69\x76\ -\x65\x44\x69\x67\x65\x73\x74\x3d\x22\x33\x36\x38\x36\x34\x2c\x34\ -\x30\x39\x36\x30\x2c\x34\x30\x39\x36\x31\x2c\x33\x37\x31\x32\x31\ -\x2c\x33\x37\x31\x32\x32\x2c\x34\x30\x39\x36\x32\x2c\x34\x30\x39\ -\x36\x33\x2c\x33\x37\x35\x31\x30\x2c\x34\x30\x39\x36\x34\x2c\x33\ -\x36\x38\x36\x37\x2c\x33\x36\x38\x36\x38\x2c\x33\x33\x34\x33\x34\ -\x2c\x33\x33\x34\x33\x37\x2c\x33\x34\x38\x35\x30\x2c\x33\x34\x38\ -\x35\x32\x2c\x33\x34\x38\x35\x35\x2c\x33\x34\x38\x35\x36\x2c\x33\ -\x37\x33\x37\x37\x2c\x33\x37\x33\x37\x38\x2c\x33\x37\x33\x37\x39\ -\x2c\x33\x37\x33\x38\x30\x2c\x33\x37\x33\x38\x31\x2c\x33\x37\x33\ -\x38\x32\x2c\x33\x37\x33\x38\x33\x2c\x33\x37\x33\x38\x34\x2c\x33\ -\x37\x33\x38\x35\x2c\x33\x37\x33\x38\x36\x2c\x33\x37\x33\x39\x36\ -\x2c\x34\x31\x34\x38\x33\x2c\x34\x31\x34\x38\x34\x2c\x34\x31\x34\ -\x38\x36\x2c\x34\x31\x34\x38\x37\x2c\x34\x31\x34\x38\x38\x2c\x34\ -\x31\x34\x39\x32\x2c\x34\x31\x34\x39\x33\x2c\x34\x31\x34\x39\x35\ -\x2c\x34\x31\x37\x32\x38\x2c\x34\x31\x37\x32\x39\x2c\x34\x31\x37\ -\x33\x30\x2c\x34\x31\x39\x38\x35\x2c\x34\x31\x39\x38\x36\x2c\x34\ -\x31\x39\x38\x37\x2c\x34\x31\x39\x38\x38\x2c\x34\x31\x39\x38\x39\ -\x2c\x34\x31\x39\x39\x30\x2c\x34\x31\x39\x39\x31\x2c\x34\x31\x39\ -\x39\x32\x2c\x34\x31\x39\x39\x33\x2c\x34\x31\x39\x39\x34\x2c\x34\ -\x31\x39\x39\x35\x2c\x34\x31\x39\x39\x36\x2c\x34\x32\x30\x31\x36\ -\x2c\x30\x2c\x32\x2c\x34\x2c\x35\x2c\x36\x2c\x37\x2c\x38\x2c\x39\ -\x2c\x31\x30\x2c\x31\x31\x2c\x31\x32\x2c\x31\x33\x2c\x31\x34\x2c\ -\x31\x35\x2c\x31\x36\x2c\x31\x37\x2c\x31\x38\x2c\x32\x30\x2c\x32\ -\x32\x2c\x32\x33\x2c\x32\x34\x2c\x32\x35\x2c\x32\x36\x2c\x32\x37\ -\x2c\x32\x38\x2c\x33\x30\x3b\x32\x34\x44\x41\x30\x37\x46\x44\x41\ -\x35\x39\x32\x37\x43\x36\x37\x32\x32\x34\x31\x36\x31\x35\x45\x41\ -\x37\x36\x34\x44\x32\x41\x42\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x72\ -\x64\x66\x3a\x52\x44\x46\x3e\x0d\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\ -\x6d\x65\x74\x61\x3e\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\x6e\x64\x3d\ -\x27\x77\x27\x3f\x3e\xff\xdb\x00\x43\x00\x02\x01\x01\x02\x01\x01\ -\x02\x02\x02\x02\x02\x02\x02\x02\x03\x05\x03\x03\x03\x03\x03\x06\ -\x04\x04\x03\x05\x07\x06\x07\x07\x07\x06\x07\x07\x08\x09\x0b\x09\ -\x08\x08\x0a\x08\x07\x07\x0a\x0d\x0a\x0a\x0b\x0c\x0c\x0c\x0c\x07\ -\x09\x0e\x0f\x0d\x0c\x0e\x0b\x0c\x0c\x0c\xff\xdb\x00\x43\x01\x02\ -\x02\x02\x03\x03\x03\x06\x03\x03\x06\x0c\x08\x07\x08\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\ -\xc0\x00\x11\x08\x00\xb4\x01\xad\x03\x01\x22\x00\x02\x11\x01\x03\ -\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\ -\x09\x0a\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\ -\x05\x05\x04\x04\x00\x00\x01\x7d\x01\x02\x03\x00\x04\x11\x05\x12\ -\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32\x81\x91\xa1\x08\ -\x23\x42\xb1\xc1\x15\x52\xd1\xf0\x24\x33\x62\x72\x82\x09\x0a\x16\ -\x17\x18\x19\x1a\x25\x26\x27\x28\x29\x2a\x34\x35\x36\x37\x38\x39\ -\x3a\x43\x44\x45\x46\x47\x48\x49\x4a\x53\x54\x55\x56\x57\x58\x59\ -\x5a\x63\x64\x65\x66\x67\x68\x69\x6a\x73\x74\x75\x76\x77\x78\x79\ -\x7a\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\ -\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\ -\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\ -\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\ -\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xc4\x00\x1f\x01\x00\ -\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\ -\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\xff\xc4\x00\xb5\x11\ -\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\ -\x00\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41\x51\x07\x61\x71\ -\x13\x22\x32\x81\x08\x14\x42\x91\xa1\xb1\xc1\x09\x23\x33\x52\xf0\ -\x15\x62\x72\xd1\x0a\x16\x24\x34\xe1\x25\xf1\x17\x18\x19\x1a\x26\ -\x27\x28\x29\x2a\x35\x36\x37\x38\x39\x3a\x43\x44\x45\x46\x47\x48\ -\x49\x4a\x53\x54\x55\x56\x57\x58\x59\x5a\x63\x64\x65\x66\x67\x68\ -\x69\x6a\x73\x74\x75\x76\x77\x78\x79\x7a\x82\x83\x84\x85\x86\x87\ -\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\ -\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\ -\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\ -\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\ -\xf9\xfa\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00\x3f\x00\ -\xfd\xfc\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\ -\x28\x00\xa2\x8a\x31\x40\x05\x19\xe6\x91\xb8\x15\xcb\x5e\x7c\x53\ -\xd3\xf4\xff\x00\x89\x36\xfe\x19\x99\xbe\xcf\x79\x71\x6e\x67\x8e\ -\x49\x58\x22\x4a\xd9\x18\x8d\x33\xcb\x33\x0d\xe4\x63\xb4\x4f\xe8\ -\x6b\x1a\xd8\x8a\x74\xad\xed\x1d\xae\xec\xbd\x4a\x8c\x65\x2f\x84\ -\xea\x89\xc5\x26\xf1\x4c\x46\x62\xb9\x6e\xb5\x9b\xe3\x0d\x79\x3c\ -\x33\xe1\x7d\x4a\xfe\x46\x45\x16\xb6\xf2\x48\x32\x71\xb8\x85\x24\ -\x0f\xa9\x3c\x62\xaa\xa5\x45\x08\xb9\xcb\x64\xae\x11\x8b\x6e\xc8\ -\xd4\xde\x33\x8a\x76\x78\xaf\x9a\x7f\x63\x2d\x72\x3d\x33\xe2\x1f\ -\x88\xad\xaf\x75\x01\xf6\xad\x6a\xce\xcc\xda\x41\x24\x83\x74\xaf\ -\x01\xb8\x32\xec\x1e\xbb\x64\x8c\xe3\xa9\x0a\x4f\x40\x6b\xe9\x28\ -\xf3\x83\xf5\xc5\x70\xe5\x59\x94\x31\xd8\x75\x88\x82\xb6\xe9\xab\ -\xde\xcd\x3b\x7f\xc1\x36\xc4\xe1\xdd\x1a\x8e\x9b\x1f\xba\x97\x39\ -\xac\x1f\x1f\xf8\xde\xdf\xe1\xef\x84\xaf\x35\x6b\xa1\xba\x3b\x50\ -\x30\x81\xb0\xd2\xb1\x20\x05\x1e\xe4\x9a\x4f\x86\xbe\x3d\xb7\xf8\ -\x9f\xe0\x4d\x27\xc4\x36\x76\xd7\xd6\x76\x7a\xcd\xac\x77\x70\x47\ -\x79\x09\x86\x70\x8e\x32\x37\x21\xe5\x78\xc1\xe7\xb1\xae\xbf\xac\ -\x53\xf6\xae\x8d\xfd\xe4\xaf\x6f\x26\x63\xca\xf9\x79\xba\x1b\xf4\ -\x52\x03\xc0\xa5\xad\xc9\x0a\x28\xa0\x1c\xd0\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x43\x74\xa2\x8a\x00\x69\x38\xfa\ -\x51\xe6\x55\x1f\x11\xad\xf3\xe8\x37\x6b\xa6\x49\x6b\x1e\xa1\xe5\ -\x1f\xb3\xb5\xca\x17\x85\x5f\xb6\xf5\x52\x09\x5c\xf5\xc1\x06\xbc\ -\x2b\xe1\xa7\xed\x1f\xe2\x2f\x0c\xdf\x4d\xa7\xf8\xd3\x4b\xb8\x8e\ -\x7b\x79\x1e\x39\x81\x4d\xb2\xc5\x20\x38\x3b\x09\x0a\xb2\xc0\x71\ -\x95\x71\xce\x3a\x93\xd0\x79\x38\xec\xda\x8e\x12\xa4\x21\x5e\xe9\ -\x4b\xad\xb4\x5e\xbe\xa7\x45\x1c\x34\xea\xa6\xe1\xd3\xa1\xf4\x19\ -\x6c\x8a\xf9\xab\xf6\x9d\xba\x86\xeb\xe2\xb4\x37\xb6\x57\x31\x7d\ -\xa3\x4f\xb4\xb7\x0b\x2a\x61\x8d\xb4\xf1\x4b\x34\x80\xe4\xf1\x90\ -\x59\x78\x3e\xe0\xe4\x12\x2b\xa1\xf1\x2f\xc7\xcf\x12\x7c\x50\xf1\ -\x45\xaf\x86\x7c\x05\xa6\xdb\x47\x35\xd1\x57\xd4\xf5\x1b\xe5\x76\ -\x8f\x48\xb3\x24\xab\x4d\xf2\xe1\x4c\xac\x7e\x58\xa3\x2d\x99\x18\ -\x39\xe1\x63\x72\x38\x1f\x8e\x3f\x01\xfc\x33\xfb\x3f\x69\x12\x78\ -\x8a\xeb\xc7\x9a\xbd\xc6\xb1\x75\x75\x1a\x79\x5a\xf6\xab\x04\x71\ -\xcf\x03\xba\x86\x8e\x18\x11\x62\x8f\x31\xe4\xba\xb2\xa1\x7e\x18\ -\x33\x30\x26\xbc\x3c\xfa\x55\x73\x0c\x23\x58\x25\xcc\x93\xbd\xf5\ -\xd6\xdd\x23\xd5\x9d\x78\x3e\x4c\x3d\x5b\xd7\x76\xe9\xe9\xea\x75\ -\xde\x08\xfd\xa8\xbc\x71\xe3\x0f\x13\x5a\xf8\x73\x45\xf0\x7d\xae\ -\xbd\xa8\x2c\x4b\x71\x7d\xa9\xcd\x73\x26\x9f\xa7\x58\xdb\x96\xd8\ -\x19\x9f\xcb\x93\x74\xcc\xc0\x95\x89\x39\x21\x58\x9d\x80\x02\x77\ -\xbf\x69\x8d\x1b\xc4\xfa\x9f\xc3\x8f\xb5\xb5\xc6\x9d\xe5\xd9\xcd\ -\x1b\xdc\xd8\xc3\xbd\x55\x91\x9b\x69\x71\x21\x04\xb9\x50\x72\x14\ -\xaa\x83\x82\x73\xd2\xbf\x3d\xfe\x25\x7f\xc1\x5e\xee\xff\x00\x65\ -\xff\x00\x19\xdd\x5a\xf8\x07\xc3\xcf\xae\x5d\xea\xb1\x47\x65\x3d\ -\xf6\xb7\x6f\x34\x3a\x42\x3c\x6f\x23\x2c\x91\x91\xb6\x49\x36\xf9\ -\xa7\x76\x18\x29\x04\x73\x95\xe4\xfd\xa9\xff\x00\xe0\xa8\x5f\x1b\ -\xf5\x8f\x84\xb7\x23\x4d\x5f\x0b\x5a\xed\x91\x7e\xd6\xba\x7e\x8d\ -\x29\x57\x83\xa9\x61\xe6\x49\x2e\x30\xc1\x4e\x49\x03\x6e\x73\x5f\ -\x4d\x95\xf0\x5e\x6f\x98\x65\x4a\x9e\x25\x38\xca\xa2\x69\x73\x3b\ -\x7a\x5d\x2d\x6d\xb6\xff\x00\x71\xf2\x99\x87\x1c\x65\x38\x4c\x4c\ -\xdd\x17\xcc\xa9\xeb\x25\x15\x7f\xcf\x4f\xb8\xfa\x2b\xc1\x87\x50\ -\xd5\xfe\x30\x78\x4f\x46\xd2\x3f\x73\xa9\x6a\x77\x52\xba\xde\x97\ -\xdb\xf6\x04\x86\x16\x95\xa4\xfb\xa7\x76\x70\x10\x2e\x30\xde\x61\ -\x07\x03\x35\xf4\xef\x88\x35\x8f\x89\x5e\x0a\xf0\xe7\x9d\x63\xa5\ -\xf8\x77\xc6\x97\x10\x60\xc9\x10\xbc\x7d\x2e\x79\x00\xc0\x3b\x32\ -\x92\x46\xcd\xd4\xe0\x94\x07\x1d\x72\x70\x3f\x14\x3e\x07\xff\x00\ -\xc1\x4a\x7e\x2b\x68\x7f\x19\xfc\x35\xaa\x6a\x3a\xb6\x84\xab\xa7\ -\xce\xfb\x65\xb8\xd3\xa3\x58\xd0\x49\x13\x44\x41\x65\x0b\x80\xc1\ -\xf6\xe7\x38\x19\x07\xb5\x7d\x91\xe1\xef\xf8\x2d\x37\x8b\xa7\xbf\ -\x86\xd6\xeb\x4b\xf0\x6e\xb5\x0d\xcb\x35\xbf\x9b\xa5\x2c\xcc\xf1\ -\xb6\xc2\x41\x76\x12\xba\xa7\x43\x8c\xae\x0e\xd3\xc8\xeb\x5b\x60\ -\x7c\x2f\xcd\x72\x9c\x3c\xa3\x53\x59\xbb\xbb\xc2\x5a\x79\x68\xec\ -\xaf\xea\xb6\x39\xf0\xfe\x25\x65\x39\xac\xb9\xa9\x37\x14\xac\xad\ -\x24\xaf\xe7\xb3\x7a\x1e\xc7\xf1\x7f\xe3\xce\xa7\xf1\xa2\xd6\x38\ -\x64\x89\x74\xfb\x38\xd5\x9a\x28\xe2\x62\xdc\xb0\x18\x67\xe9\xd3\ -\x8e\x0e\x3a\xd7\xd2\xbf\x01\x3e\x24\x69\x7f\x12\x7e\x1b\x69\x77\ -\x3a\x7f\x93\x6f\x24\x56\xb1\x25\xc6\x9e\x1c\x19\x34\xe7\xdb\x8f\ -\x29\xd7\xa8\xc1\x04\x02\x40\xc8\x00\x8e\xb5\xf0\x4f\x80\xbe\x22\ -\xf8\x57\xe3\x1f\xc4\x1f\x0d\x68\x37\x9a\xe4\xda\x06\x93\xab\xdd\ -\x48\x9a\x8d\xe3\x5c\xad\x8c\xd6\x69\x1c\x12\x48\xaa\x92\xbf\xca\ -\xa6\x49\x56\x28\xb2\x39\x2b\x23\x00\x43\x15\x61\xf4\xc6\xa5\xf0\ -\x03\xc4\x9f\xb2\x7d\x9c\x9e\x24\xf8\x7f\xac\x6b\xde\x2b\xb7\x56\ -\xff\x00\x89\xae\x8d\xaa\xaa\xdf\x5c\x5c\xc3\xc0\x43\x6e\x61\x48\ -\xdd\x9a\x32\x59\x88\x72\xcc\x54\x9d\xa7\x23\x63\xfe\x7d\x92\x61\ -\xf3\x9c\x25\x6a\x98\xcc\x7c\x1b\x4f\x49\x27\xa4\xac\xbe\xd2\x5a\ -\x5d\x79\x7d\xc7\xdd\x62\x2b\x60\xeb\xd3\x8d\x2c\x3c\x97\x74\xd3\ -\xba\xbb\xef\xd8\xfa\x49\x5b\x2b\x4e\x12\x64\x8e\x47\xe7\x5f\x3e\ -\xde\xfe\xdd\x36\x63\x46\x66\xb7\xd1\x6e\x17\x50\xe3\x6a\x49\x28\ -\x31\x83\xdf\x24\x73\x56\x7f\x62\xcf\x18\x78\xff\x00\xe2\xbb\x6b\ -\xde\x2f\xf1\x33\x2d\x8f\x85\xb5\x69\x42\x78\x7e\xc2\x4b\x76\x59\ -\xa7\x8d\x78\x6b\xc0\x58\xe5\x60\x93\x8f\x2d\x40\x3b\x94\x09\x33\ -\x87\x15\xf5\x38\x3e\x22\xc2\x62\xeb\xaa\x38\x46\xe6\xed\x76\xd2\ -\xd2\x2b\xce\xf6\xfb\x8e\x1a\x98\x1a\xb4\xa1\xcd\x57\xdd\xed\xe6\ -\x7b\xdd\x18\xc5\x14\x57\xbc\x71\x85\x14\x51\x40\x05\x14\x51\x40\ -\x05\x14\x51\x40\x05\x14\x51\x40\x05\x15\xcb\x7c\x63\xf8\xcd\xe1\ -\xdf\x80\x3f\x0d\xf5\x4f\x17\x78\xb2\xf9\xb4\xbf\x0f\x68\xa8\xb2\ -\x5e\x5d\x8b\x79\x6e\x3c\x95\x67\x54\x07\x64\x4a\xce\x72\xcc\x3e\ -\xea\x9a\xf9\xe8\x7f\xc1\x6f\x7f\x66\x16\x38\xff\x00\x85\x99\xcf\ -\xa7\xfc\x23\xba\xb7\xff\x00\x22\xfb\x8a\xee\xc2\xe5\x78\xcc\x4c\ -\x5c\xf0\xd4\xa5\x34\xb4\xbc\x62\xda\xbf\x6d\x13\x3c\xec\x66\x71\ -\x80\xc2\x4b\x93\x15\x5e\x14\xdb\xd6\xd2\x94\x62\xed\xdf\x56\x8f\ -\xab\xa8\xaf\x1a\xfd\x9a\xbf\x6f\xff\x00\x84\xdf\xb5\xf6\xb7\xa9\ -\x69\xdf\x0e\xfc\x55\xff\x00\x09\x0d\xe6\x8f\x02\xdc\xdd\xc7\xfd\ -\x9b\x79\x69\xe5\x46\xc7\x6a\x9c\xcf\x12\x03\x93\xd9\x49\x35\xea\ -\xfa\xef\x88\x6d\x7c\x33\xa2\xde\x6a\x17\xd2\x79\x16\x76\x30\x3d\ -\xcc\xf2\x60\xb6\xc8\xd1\x77\x31\xc0\x04\x9c\x01\xd0\x02\x6b\x1c\ -\x46\x16\xbd\x0a\x9e\xc6\xb4\x1c\x65\xd9\xa6\x9e\xbb\x68\xf5\xd4\ -\xdf\x0f\x8d\xc3\xe2\x29\x7b\x7a\x15\x23\x28\x6b\xef\x26\x9a\xd3\ -\x7d\x56\x9a\x75\x2f\x51\x5f\x27\xff\x00\xc3\xef\xff\x00\x66\x12\ -\xa0\x8f\x89\x47\xb7\xfc\xcb\xba\xb7\xa6\x7f\xe7\xd6\xbd\x47\xf6\ -\x68\xfd\xbc\x7e\x15\xfe\xd8\x5a\x86\xaf\x6b\xf0\xe7\xc5\x1f\xf0\ -\x91\x4d\xa0\xac\x4f\x7c\xbf\xd9\xd7\x76\x7e\x42\xca\x58\x21\xcc\ -\xf1\x46\x1b\x25\x1b\xee\xe7\x18\xe7\x15\xd5\x5f\x26\xcc\x28\x53\ -\x75\xab\x50\x9c\x62\xb7\x6e\x32\x4b\xef\x6a\xc7\x1e\x1f\x3e\xcb\ -\x31\x15\x15\x1a\x18\x8a\x72\x93\xd9\x29\xc5\xb7\xf2\x4e\xe7\xaf\ -\xd1\x4d\xdf\x91\x46\xfa\xf3\x4f\x58\x75\x14\xdf\x33\x9e\x94\x09\ -\x73\xf8\xd0\x03\xa8\xa6\xef\xa0\xc9\xcf\x4a\x00\x75\x14\xdd\xf8\ -\x14\x79\x9f\xe7\x34\x00\xea\x29\xbb\xf8\xfb\xad\x40\x7a\x00\x75\ -\x14\xdd\xfc\xd0\x64\xc0\xfa\x50\x03\xa8\xa6\xf9\x9c\x7f\xf5\xe9\ -\xc0\xe4\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\x45\x14\x50\x01\ -\x45\x14\x50\x01\x45\x14\x50\x01\x45\x04\xf3\x5e\x63\xf1\x6b\xf6\ -\x9a\xd3\x7e\x0f\x78\xfb\x4b\xd0\xf5\x3b\x1b\xe0\x75\x68\x1e\x5b\ -\x69\xd5\x31\x1d\xcb\x27\x2c\x91\x93\xf2\xb3\xa8\x19\x65\x24\x10\ -\xa4\x10\x08\xce\xde\x5c\x66\x36\x8e\x16\x9b\xab\x5d\xda\x2b\xa9\ -\xa5\x3a\x72\xa9\x2e\x58\xee\x7a\x53\x70\x99\xaf\x98\xfe\x3f\x6a\ -\x93\xf8\xef\xe3\x05\xf5\xaf\x87\x74\x9d\x53\x5c\x93\x43\xb3\x8f\ -\xfb\x56\x4b\x38\x06\xcb\x25\xdd\x2f\x24\xb9\x51\x23\x1d\x8c\x3c\ -\xb8\x8b\xc9\xd0\xec\xc1\x04\xe9\xfc\x6c\xfd\xb0\xae\x9b\xc1\x7a\ -\x8c\x7e\x0f\xb2\x91\xb5\x2f\xb2\x48\xf1\x1b\xa4\x00\xbc\x81\x72\ -\x8a\x14\x1e\x8c\x70\x0f\x39\xc1\xe3\x07\x06\xb9\x4f\x8a\x3f\x1c\ -\x34\x8f\xf8\x27\xbf\xec\x25\x3f\x8c\x34\xeb\xab\x7f\x13\x78\xa7\ -\xc4\xf7\x96\xa9\x04\xd7\xd7\x0c\xf1\x6b\x3a\xe5\xd2\xc7\x0e\x58\ -\x29\x1b\x23\x8d\x22\x24\xc6\x81\x71\x1d\xb1\x1f\x7b\x2c\x7e\x7a\ -\xa5\x4c\x36\x7d\x55\x60\x30\xd2\xba\xd1\xdd\x75\x6f\x45\x6b\xef\ -\xbe\xa7\x67\x34\xf0\x14\xde\x26\xa2\xb7\xf9\x7f\x5b\x1e\x53\xe2\ -\xaf\xdb\x0e\x3f\xd9\xdf\x47\x9f\x54\xf0\xed\xe5\xbd\xc6\xb9\xe2\ -\x1b\x11\x0c\x10\x3a\x17\x05\x57\xcc\x11\xca\xca\x71\xb7\xca\x79\ -\x1c\xe0\xe0\x93\xb9\x48\x3c\xed\xf9\x77\xe2\x57\xc5\xcd\x77\xe3\ -\x27\x88\xdb\xc4\x7e\x36\xd7\x0e\xa1\x7d\x1c\x6b\x11\xb9\xb9\xd9\ -\x0c\x70\xc7\xbb\x21\x15\x54\x2a\x22\xe5\x89\xc2\x81\x93\xef\xcd\ -\x73\xda\xdf\x8d\xf5\x7f\x8b\x7e\x2f\xba\xf1\x07\x88\x2e\x21\xba\ -\xd5\x35\x09\x0c\x93\x3c\x36\xe9\x04\x6a\x4b\x16\x21\x11\x00\x0a\ -\xbb\x99\x8f\xa9\xdc\x49\x24\x92\x4d\xfb\xaf\x03\x69\xfe\x34\xd1\ -\xa4\xd3\xf5\x28\x7c\xeb\x59\xca\xee\x51\x23\x21\xc8\x20\x83\x95\ -\x23\xa1\xc1\xf4\xf5\xaf\xd6\xb8\x37\x85\x29\xe5\x18\x48\xd2\xab\ -\x2e\x69\xf5\x7d\xaf\xd2\x3d\x91\xf9\xaf\x12\x67\x95\xb1\xd5\x1c\ -\xa9\xab\x2b\x68\x9f\x5f\x37\xe6\xce\x0b\xe2\x57\x8b\x74\x5f\x12\ -\xe8\x9a\xad\x8c\xf6\x66\xfb\x4b\xb6\xb3\x97\xc8\xbf\x58\x9e\x48\ -\x63\xd4\x36\xe2\x38\xd4\xa8\xc0\xc0\x6c\x96\x27\x19\xc0\x3e\xf8\ -\x97\x5f\x1d\x2e\x35\xff\x00\x03\x43\xa4\xde\x69\xeb\x34\xcb\x2c\ -\x49\x78\xea\xfe\x5a\xde\xdb\xaf\x2d\x19\x03\x95\x2d\xb5\x01\x2a\ -\x46\x06\x71\x83\x5e\xb1\xe2\xad\x2b\xc3\x3f\x0c\xfe\x19\xcb\xa5\ -\x4b\x61\x7d\x0e\x8d\x7a\xc6\x27\x16\x8b\xe6\x48\x92\x36\x0a\x9c\ -\xc8\xc7\xe7\x25\x72\x0f\x3e\xe3\x6d\x78\x1c\x1a\x62\xbb\x61\x72\ -\xcb\x9e\x32\x73\xc5\x7e\xbd\x93\xe1\x69\x57\x86\x91\x76\x4f\x4d\ -\x7f\x1f\xf3\x3f\x9d\xf8\xdb\x3e\xc4\xe5\xd5\xf9\x5d\x45\x79\x47\ -\x54\xb7\x49\xf4\x7e\x5d\x99\x57\x4d\x93\x4f\xd3\xbc\x57\x26\xa0\ -\xda\x4a\x9d\x39\xd6\x64\x16\x1e\x69\x93\x01\xe2\x74\x55\xdc\xf9\ -\x27\x05\x81\xc9\xe9\x8e\xa0\xd7\xb5\xfc\x0f\xd3\x7c\x2f\x22\x6a\ -\x52\x78\x7e\x1b\x7b\x49\xae\xa2\x81\xa7\xb4\xf3\xa5\x91\xa2\xdb\ -\xbc\x82\x4c\xa3\x9f\x99\x8f\xdd\x2c\xa3\x68\xaf\x28\x6d\x17\x62\ -\xfd\xd5\x1d\xba\x74\xaf\x6e\xfd\x9f\xbc\x2b\xe1\xbd\x5f\xc3\xeb\ -\xaa\x59\xd8\xc7\x6b\xae\xe9\xe0\xc5\x75\xb6\xe2\x56\xc6\xe0\x7e\ -\x7d\xac\xdb\x42\xb0\x0d\xc6\x06\x30\x7d\x2b\xa3\x3c\xc3\xa8\xd0\ -\xe6\x5c\xdd\xb4\xfd\x4f\x1b\x80\xf3\xef\xac\x63\x55\x25\xc9\xd5\ -\xfb\xdb\xeb\xa3\xe5\xf4\xde\xc4\xde\x22\x86\xd2\xde\x66\xb7\x69\ -\xe1\x69\xd6\x26\x93\xc8\x8d\xbc\xc9\x99\x46\xdd\xd8\x45\xcb\x1c\ -\x7b\x0f\x4e\xf5\xed\x1f\xb3\xb7\xfc\x14\x63\xc5\xbe\x02\xf0\xfc\ -\x9e\x1f\xd4\xbc\x40\xfa\x97\x86\xee\xe1\x09\x6b\x7d\x2a\x89\xa5\ -\xd2\xc2\xf5\x08\xe0\x16\x65\x20\xe0\x86\xdc\x53\x00\x8d\xb8\x35\ -\xf2\x3f\xfc\x2b\xcd\x63\xe2\x17\xc4\x6f\x12\x6a\x9a\x7c\xf6\x17\ -\x16\xb1\xde\x34\x4d\x70\xf2\xbc\x09\x3a\xe7\xe5\x11\x3c\x4a\x4e\ -\xe5\xda\xbc\x8e\x38\x19\xdc\x09\x07\x93\xf8\xa9\xe2\x1f\x1c\x7c\ -\x16\x96\xcd\xef\x2e\x34\xfd\x50\x5d\x2c\xbb\x9b\xe6\x91\x6e\x71\ -\xb4\x0f\x31\xb6\x24\x9b\x93\x27\x04\xb7\xcd\xb8\xe7\x23\x8a\xf8\ -\x8c\xe7\x86\x68\x63\xf0\xf2\xc2\xb9\xeb\x24\xd5\xd6\x92\x57\xec\ -\xfb\xfe\x07\xed\x79\x2f\x16\x57\xc3\xcd\x62\x55\x36\xa0\x9e\x9a\ -\x5d\x34\x9f\x5e\xeb\xfa\x56\x3f\x4a\x3c\x1b\xa4\xeb\x3f\x13\xaf\ -\x75\x2f\xf8\x45\xb4\x2d\x4b\xc4\x50\xe8\x73\x98\x75\x5b\x9b\x53\ -\x1a\xc5\x62\xfe\x58\x93\x6e\x64\x75\xf3\x9f\x69\x04\xa4\x3e\x63\ -\x0d\xcb\x90\x37\x2e\x7e\xbc\xfd\x8c\xbe\x24\x58\xfc\x44\xf8\x03\ -\xe1\xe5\xb4\x68\xc5\xce\x87\x67\x0e\x95\x7b\x1a\xf4\x8e\x58\xa2\ -\x41\xc7\xaa\xb2\xed\x70\x46\x78\x60\x33\x90\x40\xfc\xe8\xff\x00\ -\x82\x20\x7e\xdf\xff\x00\x10\x2e\xbe\x2b\xe9\x3f\x0b\xfc\x69\xa5\ -\xd9\xc9\xe0\xbf\x15\x5a\xdc\x4b\xa0\xdf\xda\x59\x2c\x6f\x69\x7d\ -\x1a\xf9\xa4\x4d\x26\xfc\x94\x95\x12\x5f\xbc\xac\xde\x67\x94\xab\ -\x85\x27\x1f\x64\x7c\x41\xba\xb5\xfd\x91\xbe\x2f\x7f\x69\x78\x32\ -\x4b\x5f\xec\xff\x00\x10\x66\x4d\x5f\x44\x67\xdd\x1a\x3a\xbe\x43\ -\xc7\x83\xfb\xb2\xc1\x9f\x8e\x40\x3f\xc3\x8c\x01\xfc\xd7\x8a\xe1\ -\xdf\xf5\x3e\xba\xa9\x56\x7c\xd1\x7a\x4f\x5e\x97\xf7\x65\x15\xe4\ -\xef\x74\x7e\xf7\x97\xe7\x51\xcf\xa8\x2a\x94\x55\xbb\x2e\xda\x6a\ -\x99\xf5\x3d\x15\xf3\x77\x8c\xff\x00\xe0\xa3\xba\x07\x86\x74\x05\ -\x92\x0d\x0f\x5a\xba\xd6\x2f\x31\x6f\xa7\xd8\xa2\x23\xbd\xfd\xdb\ -\x29\xf2\xe0\x88\x2b\x6e\x76\x66\x18\x00\x0c\x9e\x4f\x00\x12\x3e\ -\x84\xf0\xde\xab\x26\xbb\xe1\xdb\x0b\xe9\xac\xee\xb4\xd9\xaf\x2d\ -\xa3\x9e\x4b\x4b\x9d\xbe\x75\xab\x32\x86\x31\xbe\xd2\x57\x72\x93\ -\x83\x82\x46\x41\xc1\x3d\x6b\xe9\x32\xfc\xdf\x09\x8e\xbb\xc2\xcf\ -\x99\x2d\xda\x4e\xc6\x75\xb0\xd5\x28\xbb\x54\x56\x2e\xd1\x45\x15\ -\xe9\x18\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\x40\x11\xcb\ -\x6a\xb3\x06\x0c\x15\x95\xba\x82\x33\x9a\xfc\x27\xff\x00\x82\xfa\ -\x78\x1f\x48\xf0\x2f\xed\xee\xcb\xa3\xe9\xb6\x7a\x6a\xea\x9e\x1e\ -\xb3\xbe\xb9\x4b\x78\x56\x35\x9a\x62\xf3\xa3\x48\xc0\x0c\x16\x2a\ -\x8b\x92\x79\x38\xf7\xaf\xdd\xca\xfc\x38\xff\x00\x83\x88\x7f\xe4\ -\xfe\xac\xff\x00\xec\x54\xb2\xff\x00\xd1\xd7\x35\xfa\x1f\x86\x52\ -\x6b\x39\xe5\x4f\x47\x09\x7e\x87\xe6\x5e\x2c\x45\x7f\x62\x73\x75\ -\x53\x8f\xea\x7e\xd6\xf8\x2f\xe1\xf6\x8f\xf0\xe3\xc3\x56\x7a\x3e\ -\x83\xa6\xd9\x68\xfa\x5d\x84\x4b\x0d\xbd\xb5\xa4\x22\x28\xe2\x45\ -\x00\x00\x00\xe3\xa0\xea\x6b\x5b\xec\xfc\x75\x34\xa6\x6c\x3e\xdc\ -\x7f\xf5\xe9\x44\x99\x15\xf9\xec\xa4\xe4\xf9\xa4\xee\xd9\xfa\x5c\ -\x62\xa2\x94\x62\xac\x8f\xcb\x0f\xf8\x2f\xef\xec\xd1\xe1\xdb\xbf\ -\x88\xdf\x07\xbc\x41\x63\xa6\xd9\xe9\x97\xfe\x29\xd6\x64\xd0\xb5\ -\x7b\xbb\x58\x44\x52\x5e\x07\x68\x0c\x4c\xfb\x71\xb9\x94\x19\x46\ -\x4f\x24\x36\x33\xc0\xaf\x7d\xfd\xac\xff\x00\x6d\x69\xbf\xe0\x96\ -\x7e\x23\xf0\x76\x88\xbf\x0b\xfc\x3f\x6f\xf0\x77\x53\x9e\x3b\x0b\ -\x5d\x47\x47\xd4\x4c\x57\x5a\x72\x24\x69\xe6\xf9\x96\x9e\x50\x05\ -\x86\x5d\x97\x6b\xb6\xf0\x87\x2c\xac\x71\x5c\x5f\xfc\x17\x89\xb2\ -\xdf\x00\x8f\xfd\x4f\x51\x0f\xfd\x17\xff\x00\xd7\xaf\x7c\xfd\xaf\ -\xbe\x1f\xe8\xbf\x16\x3e\x3e\xfc\x19\xf0\xdf\x88\x6c\x6d\xf5\x4d\ -\x13\x5c\x9b\x5e\xb3\xbd\xb5\x97\x3b\x66\x89\xf4\xa9\x43\x0c\x83\ -\x90\x7b\x86\x18\x20\x8c\x82\x0f\x35\xfa\x0d\x3c\x54\x2a\x60\x30\ -\x10\xc6\xa7\x52\x92\x55\xdb\x57\x7f\x66\xed\x35\x66\xb5\x56\xb2\ -\xbd\xd2\xec\x7e\x67\x53\x0b\x56\x9e\x63\x98\xcf\x01\x2f\x67\x55\ -\xca\x82\x4e\xca\xde\xf5\x93\x4e\xe9\xe8\xef\x77\x6b\x3d\x37\x3d\ -\x7a\xff\x00\xc7\x17\x5e\x2d\xf8\x54\xba\xef\x80\x9b\x42\xd7\xa6\ -\xd4\xac\x92\xf3\x48\x7b\xab\xc7\x86\xc6\xf5\x5c\x06\x52\xd2\xc7\ -\x1c\x8c\xaa\x54\xe7\x21\x1b\xe9\x5f\x20\xf8\xe3\xfe\x0a\x6d\xf1\ -\x7b\xe1\xc7\xec\xa5\xaa\xfc\x5c\xd5\xbe\x15\xf8\x2a\xdb\x41\xd1\ -\xf5\x89\xb4\x59\x6c\x97\xc5\x17\x0d\x7c\xd2\xc3\x78\xf6\x4e\xca\ -\xa2\xd3\xcb\x28\x27\x46\x00\xef\xe4\x0c\xe3\xb5\x60\x7e\xc6\xbe\ -\x37\xd6\xbf\xe0\x99\xdf\xb4\xd3\x7e\xce\xbf\x10\x35\x09\x6e\xbc\ -\x05\xe2\xb9\xde\xef\xe1\xc7\x88\x2e\x4f\xee\xc1\x77\xe6\xc6\x46\ -\xe0\x06\x2c\x40\xda\x31\x89\x58\x60\x11\x3a\xe3\x98\xfd\xb5\x53\ -\x6f\xfc\x11\x13\xc5\xc7\x8c\x7f\xc2\x73\xab\x9c\x11\xff\x00\x53\ -\x75\xe7\xf5\xae\x7c\x0e\x4d\x87\xa5\x8b\xa7\x46\xa4\x15\x5a\x75\ -\x2a\x53\x51\x9b\xba\xbc\x27\xcd\x7b\x59\xad\x55\xac\xd6\xe9\xdd\ -\x1d\x19\x86\x79\x89\xab\x84\xa9\x5e\x94\xe5\x4a\xad\x2a\x75\x1c\ -\xe0\xb9\x5f\x2d\x48\x72\x5b\x74\xdd\x9f\x35\xd3\xbd\x9c\x5a\x67\ -\xad\x43\xff\x00\x05\x14\xf8\xb9\xa4\xfe\xd7\x9e\x03\xf8\x47\xaf\ -\xfc\x2f\xf0\x76\x97\x7f\xe3\xeb\x21\xa9\xd9\xea\x71\xf8\x9a\xe2\ -\x6b\x31\x6e\x21\x96\x69\x00\x6f\xb2\x02\x65\x51\x0c\x8b\xb3\x1c\ -\xb6\xde\x76\xb0\x6a\xf6\xbf\xdb\x77\xf6\x89\xf1\x6f\xec\xcd\xf0\ -\xae\xcf\xc4\x9e\x15\xf0\xbe\x8f\xe2\xe9\xa4\xd4\xed\x74\xb9\x34\ -\xeb\xbd\x51\xec\x6e\x6e\x25\xb9\x9e\x3b\x78\x16\xdf\x11\xb8\x91\ -\x8c\x92\x02\x54\x95\xc2\x82\xc3\x38\xc5\x7c\xed\xff\x00\x05\x69\ -\xf0\xf5\xd7\xc3\xcf\x83\xbf\x05\x7e\x39\x69\x71\xc8\xda\x8f\xc1\ -\xdd\x72\xc2\xe6\xe8\x46\x48\x33\x58\x5c\x79\x29\x2c\x64\x8e\x48\ -\x69\x12\x14\xc7\xa4\xad\xea\x73\xec\xdf\x10\x75\x7b\x4f\xda\x47\ -\xf6\xc2\xf8\x69\xa0\x69\xf3\x43\x7f\xe1\x7f\x02\x69\x87\xe2\x1e\ -\xa3\x2a\x7c\xd0\xcd\x71\x3a\x49\x6b\xa5\x2e\x47\x7c\x35\xe4\xe0\ -\x1f\xf9\xe5\x19\xf4\xae\x7a\x98\x4c\x24\xe3\x87\xc6\xc6\x92\x54\ -\xd2\x9f\xb4\x4b\x9a\xce\x50\x7b\x5f\x99\xb5\xcc\x9c\x12\xb5\xb5\ -\x7d\x4e\xca\x38\xcc\x64\x25\x89\xc0\xd4\xad\x27\x51\xb8\x7b\x36\ -\xf9\x6e\xa3\x51\x6f\x65\x1b\x3e\x56\xa6\xdd\xd3\xd1\x1c\x57\x83\ -\xbf\x6e\x1f\x8d\x9e\x34\xfd\xaa\xbc\x53\xf0\x7e\xdf\xe1\xcf\xc3\ -\x5b\x7f\x13\x78\x47\x4c\x83\x56\xba\xba\xb8\xf1\x65\xe8\xd3\xe7\ -\x86\x51\x11\x51\x13\xad\x83\x48\x58\x79\xcb\x90\xd1\xa8\xe1\xb0\ -\x4f\x7a\x1f\x1d\x7f\xe0\xa2\xff\x00\x14\x7e\x01\x7e\xcf\x3e\x28\ -\xf1\xd6\xb3\xf0\xcf\xc2\xfe\x67\x81\xfc\x48\xfe\x1e\xd6\xb4\xf5\ -\xf1\x14\xe5\x9b\x70\xb6\x30\x5c\x5b\x37\xd9\xbf\x79\x1c\x82\xe0\ -\x1f\x98\x21\x00\x0e\x09\x24\x0e\x2f\x4c\xf1\x17\x8b\xbc\x2f\xff\ -\x00\x05\xa7\xf8\xd5\x71\xe0\xdf\x0b\xe9\xbe\x2b\xd5\x3f\xe1\x09\ -\xd3\x81\xb4\xbd\xd6\x3f\xb2\xd3\x68\x5b\x33\x91\x28\x86\x5d\xc7\ -\x70\x03\x69\x03\xaf\x51\x8a\xcd\xff\x00\x82\x82\x78\xb7\xc4\x5f\ -\x10\x7f\xe0\x87\xaf\xaf\x78\xb6\x35\x87\xc5\x7a\xa4\xda\x7c\xfa\ -\xaa\x94\x58\xca\xce\x35\x14\x42\xa7\x6f\x1f\x28\x55\x50\x7b\x85\ -\x1c\x9e\xb5\xe8\x52\xcb\xb0\x8f\x17\x85\x84\xa8\x43\x92\xa7\xb1\ -\xba\xe6\x7c\xd7\x9a\xbc\xb4\xe6\x6d\x2d\xed\x7b\x59\xda\xcd\xea\ -\x79\x75\x33\x4c\x62\xc1\xe2\xea\x46\xbc\xf9\xe9\x7b\x66\xaf\x18\ -\xf2\xda\x9b\xb4\x75\xe5\x49\xbd\xae\xb5\xd2\xf7\x4b\x46\x7b\x87\ -\x89\x3f\x6f\x7f\x17\x7e\xcf\x9e\x34\xf0\x0d\x9f\xc5\xcf\x02\xe8\ -\x3a\x3f\x87\x7e\x22\x5e\xc7\xa6\xd8\x78\x83\xc3\xbe\x21\x93\x50\ -\xb7\xb1\xba\x94\x03\x14\x57\x31\x4d\x6d\x03\x28\x60\x73\xbd\x4b\ -\x00\x01\xeb\x8a\xe8\xbe\x28\xfe\xd8\x3a\xdd\xe7\xed\x4c\xdf\x06\ -\x7e\x1a\xe8\x3a\x4e\xb3\xe2\xed\x3f\x46\xfe\xde\xd6\xaf\xf5\x9b\ -\xe9\x2d\x34\xdd\x1e\xdc\xb2\x2c\x69\x88\xe3\x79\x25\x95\xcc\x88\ -\x76\x80\xa1\x55\xc1\xdc\x79\x03\xe7\xff\x00\x8c\x3e\x27\x6f\xdb\ -\xe7\xf6\x8b\xf8\x43\xf0\x5e\x6d\x0f\x56\xf0\x4d\x9f\x81\x1a\xcf\ -\xe2\x06\xb4\x35\xff\x00\x26\x1b\x9d\x5e\x18\x10\xc5\x0c\x76\x51\ -\xc6\xf2\x2c\x81\x8c\x92\xab\x31\x65\x2a\x03\x71\x94\xc1\xe8\x3f\ -\xe0\xa0\x7f\xb2\x07\xc4\xaf\x07\x7c\x7f\xb5\xfd\xa3\xbe\x05\xdd\ -\xc7\x2f\x8d\xf4\x7d\x3c\x59\xeb\x9e\x1e\x9d\x0b\xc7\xaf\x5a\x46\ -\x3e\x60\x8a\x08\x2e\xc5\x42\x29\x8f\x2a\x5b\xcb\x8d\x91\x96\x45\ -\x01\xb9\x23\x97\xe0\x55\x4a\x54\xf1\x0a\x34\xea\x4e\x12\x69\x36\ -\xf9\x39\xaf\xfb\xb7\x27\x76\xd2\x6a\xfd\x6d\xf0\xb7\xa5\xce\xc9\ -\xe6\x79\x8b\xa5\x56\xa6\x1e\x52\xa9\x4e\x13\x82\x6d\x28\xfb\x4e\ -\x5b\x7e\xf1\x45\x59\x26\xe2\xed\xd2\xef\xde\x49\xdd\x23\xa3\xf8\ -\x8d\xfb\x7e\x7c\x50\xf8\x53\xfb\x37\x7c\x41\xf1\x96\xad\xf0\xe7\ -\xc2\x69\xac\x7c\x28\xf1\x0b\x68\x7e\x20\xd3\xc7\x88\x67\xf2\xee\ -\xe3\x30\x59\x4d\x0d\xd5\x9b\x7d\x94\x96\x12\x2d\xec\x67\x64\x9b\ -\x0a\xa8\xc9\x24\xfc\xa2\xdf\xc1\x3f\xdb\x17\xe3\xc7\xc7\xbd\x66\ -\x6b\x5d\x1b\xe1\x7f\xc3\xbb\x58\x6d\x74\x9d\x3f\x55\x9e\xf6\xff\ -\x00\xc5\x97\x71\xdb\x46\xd7\xb0\x2d\xcc\x56\xc0\xa5\x8b\xb3\x4c\ -\xb0\xba\x33\x85\x52\x8b\xb8\x0d\xe7\x20\x9f\x29\xfd\xa2\xbf\x6e\ -\x5d\x03\xf6\xed\xff\x00\x82\x3d\x7c\x56\xd7\xb4\xcb\x49\xf4\x5d\ -\x73\x4b\xb6\xb5\xb3\xd7\x74\x79\x9f\x74\x9a\x75\xc7\xda\xe0\x3c\ -\x36\x01\x68\xd8\x02\x55\x88\x04\xe3\x04\x64\x11\x5f\x64\xfe\xc9\ -\xd1\x67\xf6\x58\xf8\x66\x77\x75\xf0\xae\x97\xd3\xb7\xfa\x1c\x5d\ -\x2b\x1c\x66\x1e\x96\x13\x05\x29\xd7\xc2\xc6\x35\x7d\xa4\xa1\x66\ -\xe5\xa5\xa3\x07\xfc\xda\xee\xed\xe4\xd6\xae\xda\xf4\x60\x71\x15\ -\xf1\x98\xe8\xc2\x86\x2e\x52\xa5\xec\xe3\x3b\xa5\x1d\x6f\x29\xc6\ -\xdf\x0e\x96\xb2\xbf\x9a\x7a\x2b\xe9\xf3\x0f\xc2\x8f\xf8\x29\x17\ -\xc6\x6f\x8d\x9f\xb3\x77\x8a\x3e\x27\x78\x77\xe1\x4f\x81\xef\xb4\ -\x7f\x09\xdd\x5d\xda\xdd\xe9\xcb\xe2\xab\xaf\xed\x2b\x83\x6c\xa8\ -\xf2\x98\x53\xec\x5e\x5b\x0d\xae\x08\x06\x40\xc7\x04\x6d\xce\x33\ -\xd1\x7c\x20\xff\x00\x82\x85\xf8\xfb\xc6\xdf\xb6\xa6\x9b\xf0\x8f\ -\x5e\xf0\x2f\x84\xf4\x18\x75\x4d\x19\x7c\x47\x63\xab\x2e\xbf\x34\ -\xa9\xab\xd8\x32\x86\x56\xb4\x43\x6c\xa6\x49\x30\x5b\x28\xdb\x31\ -\xe4\xcb\xf3\x10\xa0\xb6\x27\xfc\x10\x7d\x3c\xdf\xd9\x07\xc4\xc7\ -\xa7\xfc\x57\x3a\xa7\x6f\xf6\x60\xab\x1f\xf0\x58\x0f\x87\x5a\x97\ -\x81\xfc\x3f\xe0\x8f\xda\x03\xc2\xd0\xaf\xfc\x25\x1f\x05\xb5\x88\ -\xae\xee\x44\x7f\x2b\xdf\xe9\x73\x3a\xc7\x3c\x0c\x47\x25\x7e\x60\ -\x08\x3c\x04\x92\x5f\x5c\xd7\x55\x6c\x3e\x5e\xf3\x5a\xb9\x5f\xb0\ -\x8c\x6e\xe5\x18\x4a\xf2\xd2\x4d\x7b\x97\xf7\xad\xf1\x69\xf3\xf2\ -\x38\xe8\xe2\x73\x25\x94\x51\xcd\xdd\x79\x4a\xca\x33\x9c\x6d\x0d\ -\x62\x9f\xbf\x6f\x75\x3f\x87\x55\xe9\xd2\xe7\xab\x78\xbf\xf6\x90\ -\xf8\x89\xa7\x7e\xdb\x7a\x5f\xc2\xfd\x17\xc1\xfe\x19\xd4\xf4\x0b\ -\xad\x36\x3d\x6e\xf7\x59\x93\x5a\x96\x3b\x8d\x32\xc7\xcc\x11\x39\ -\x92\x0f\x20\x8f\x35\xe5\x59\x04\x48\x1c\x87\x08\x49\x64\x01\xca\ -\x7b\xe0\x97\x68\xe9\x5f\x3f\x7e\xc1\xba\x6d\xd7\x8b\xfc\x03\xac\ -\x7c\x60\xd7\xe1\x5b\x5d\x6f\xe2\xf4\xc9\xae\xa2\xc8\xc3\x76\x9d\ -\xa3\xaa\x63\x4c\xb5\xc8\xe0\x05\xb6\x22\x56\xc7\xfc\xb4\xb8\x94\ -\xf7\xcd\x64\x7c\x01\xf1\xc7\x8d\xbf\x6e\x1f\x84\xb7\x9f\x10\xf4\ -\x7f\x1c\x6b\x1f\x0e\xf4\x3d\x72\xee\xee\x1f\x0b\x59\xe9\xda\x6d\ -\x85\xcb\x7d\x96\x09\xde\x14\xb9\xbc\xfb\x54\x12\x34\x8f\x2c\x91\ -\x3b\xf9\x71\x34\x4a\xb1\x95\x5c\x93\xfb\xca\xf9\xec\x66\x0a\x2d\ -\xb8\xc1\x46\x31\xa5\x68\xca\x5a\xb4\xe6\xef\x7e\xfd\xa5\x6b\x2b\ -\x5a\x37\xd2\xe7\xd2\xe0\x71\xf3\x51\x52\x9b\x94\xe5\x57\x9a\x71\ -\x8f\xbb\x75\x05\x6b\x6f\xcb\xde\x37\xbb\x6e\xf2\xb6\xb6\xb9\xf4\ -\xc7\xda\x3f\xd9\xa0\x4d\x9f\xff\x00\x5d\x7c\x1b\xf0\xef\xf6\xd3\ -\xf8\x81\xf1\xb3\xe2\xdf\xc2\x9f\x0a\xdd\x78\x8a\xe3\xc1\xfa\xa5\ -\xc7\x89\xbc\x4f\xe0\x8f\x1b\x43\xa5\x5a\xd9\xcd\x07\xdb\xb4\x7b\ -\x33\x70\x2e\x2d\x5e\xe6\x09\x4a\x2c\x85\xe3\xdc\x18\xb0\x00\xed\ -\x51\x91\xbc\xfd\x79\xfb\x3e\xcf\xa9\x5e\xfc\x2d\xb3\x9b\x54\xf1\ -\x15\xbf\x8b\xa5\xb8\xb8\xbb\x96\xd7\x57\x86\x38\xd1\x6f\xac\xda\ -\xe6\x53\x6a\xc4\x44\xa8\x9b\xc5\xbf\x94\x18\xaa\x85\x2c\x09\x1c\ -\x1a\xc7\x30\xca\x6b\x60\xd2\x75\x9a\xd7\xa2\xbe\xd7\x92\xbd\xed\ -\x6f\xb2\xfa\xed\x67\x63\xa7\x2c\xce\xa8\xe3\xa4\xd5\x04\xec\xba\ -\xbb\x2d\x6d\x19\x5a\xd7\xbe\xd2\x5d\x34\x69\xaf\x5e\xe8\x1c\x8a\ -\x29\x13\xee\x0f\xa5\x2d\x79\x67\xb0\x14\x51\x45\x00\x14\x51\x45\ -\x00\x14\x51\x45\x00\x23\x57\x3f\xf1\x1f\xe1\xc6\x93\xf1\x4f\xc2\ -\xf3\x68\xfa\xcd\xab\x5c\x58\xcc\xe9\x21\x0b\x23\x44\xe8\xe8\xc1\ -\x95\x95\xd4\x86\x56\x0c\x07\x20\x8e\xe3\xa1\x35\xd0\x37\x5a\xa5\ -\xaf\xeb\x76\xfe\x1c\xd2\x2e\x2f\xae\x9b\x6d\xbd\xac\x66\x59\x1b\ -\xd0\x01\x9a\xc3\x10\xa0\xe1\x25\x53\xe1\xb6\xb7\xda\xc5\x46\xf7\ -\xf7\x77\x3e\x2d\xb4\xf0\x5e\xb3\x71\xe3\x4d\x73\xc3\x7a\x7d\x9d\ -\xe7\x89\x35\x2f\x0c\x49\x8d\x4a\x4b\x57\x81\x7e\xcf\x13\x3c\xde\ -\x4b\xc8\x8c\xea\x59\x9d\x63\x27\x64\x61\x98\x7f\x74\x65\x73\xf2\ -\x3f\xed\x67\xa3\x78\xfb\xf6\x92\xfd\xa9\xbc\x1f\xf0\xbb\xc1\xfa\ -\x5d\xbd\xd5\xaf\x86\xed\xdf\xc4\xfa\xbe\x89\x73\x7b\x6d\xa6\xea\ -\x62\xe5\xa1\x9a\x08\xa5\x16\x57\x2f\x1d\xcb\x24\x71\xc9\x9d\xeb\ -\x19\x40\x2e\x54\x93\xf7\x48\xfd\x2c\xfd\x92\x27\xb5\xd6\x23\xf8\ -\x89\xe2\x0f\x26\x28\x6e\xb5\xbf\x12\xb5\xc5\xcb\x01\xfb\xc0\x8b\ -\x67\x6b\xb1\x09\xeb\x85\x05\x88\xec\x37\x92\x39\x26\xbf\x12\xff\ -\x00\x63\x3f\x8f\xd7\xff\x00\x1d\x7f\xe0\xbc\x16\xde\x3c\x7b\xeb\ -\xc6\x1a\xa7\x8c\xb5\x27\x84\x89\x88\x91\x6c\x96\x1b\x88\xa3\x84\ -\x73\xc2\x79\x0a\x10\xa8\xe0\x82\x47\x4a\xe0\xf0\xff\x00\x85\x68\ -\xc6\xbf\xf6\xad\x09\x5d\xc2\x33\x92\x4f\x55\xae\xdb\x59\xe8\xbc\ -\xf7\x39\xf8\xab\x35\x9f\xb2\x58\x4a\xab\x49\x49\x27\x6d\xfa\x5f\ -\xf1\x3d\xf7\xe2\x0f\xec\xcb\xe3\x8f\xd9\xe7\x4e\xd3\xee\xfc\x65\ -\xe1\xeb\x8d\x0a\xd7\x52\xb9\xfb\x1d\xb4\xd2\xcb\x1c\x91\xcb\x36\ -\xdd\xc2\x3d\xc8\xcc\x03\x15\x0c\x40\x38\x24\x23\x11\x90\xa7\x15\ -\x20\xd6\x6c\x7c\x3b\x66\xb7\x5a\x95\xf5\x8e\x97\x69\xb9\x55\xae\ -\x2f\x2e\x12\xde\x18\xf7\x10\x01\x67\x72\x15\x57\x27\x96\x62\x00\ -\x19\x24\x80\x09\xaf\xbd\xff\x00\x64\xcf\xda\xdf\xe1\xdf\xfc\x16\ -\x57\xf6\x56\xf1\x54\x3f\xd8\xb7\xda\x4f\x93\x75\x71\xa0\xea\x7a\ -\x75\xf4\x91\x49\x75\x61\x30\x4f\xdd\x5f\x5b\x38\x27\x03\xe6\x0f\ -\x0c\xfb\x51\x96\x48\xce\x00\x29\x5f\x98\x9f\xb4\x2f\xc0\x3d\x6b\ -\xf6\x1a\xf8\xdb\xaa\x78\x0f\xe2\x46\xb1\xa8\x78\x9a\xdf\x57\xd3\ -\x86\xa1\x61\x75\x61\x74\xdb\x75\x3b\x63\x39\x54\x96\x51\x27\xdc\ -\x95\x4c\x25\x59\x54\x1d\xa4\xf0\x48\x60\x4f\xec\x99\x0e\x3b\xeb\ -\xd5\x25\x87\xad\xee\xd4\x5d\x3b\xad\x3f\x23\xf3\x6e\x28\xa7\xfd\ -\x9f\x45\x62\x29\x2e\x6a\x6f\x47\x2e\x89\xf9\xdb\xbb\xd3\x62\xef\ -\xc7\xed\x2b\x5a\xd4\xfc\x1b\xff\x00\x09\x84\xba\xc7\x84\x5b\xe1\ -\xcc\x77\x72\x5a\xe9\xb7\xf6\xfe\x2c\xd2\x6e\x2d\xef\xee\xa3\x8c\ -\xbc\x91\xc2\x22\xb8\x67\x9a\xe3\x6e\xe3\xe4\xa0\x69\x40\xc0\x09\ -\x5c\xe7\xc3\x0f\x86\x9a\xb7\xc4\x97\xba\xfe\xc5\xb2\x7b\xc4\xb2\ -\xb4\x6d\x42\xf2\x77\x65\x86\xde\xc6\xd5\x00\x2f\x71\x3c\xd2\x15\ -\x8e\x18\x94\x10\x5a\x49\x19\x55\x47\x24\x8a\xd4\xd7\x2c\xfc\x33\ -\x75\xfb\x34\x78\x3f\xfb\x36\x3b\xeb\x3d\x3d\xbc\x61\xe2\x0b\xa8\ -\xa1\xba\x8d\x1d\x8d\xdf\xf6\x7e\x88\x3a\xaf\x00\x15\x24\x07\x3f\ -\x30\xcf\x3c\x12\x6b\xea\x1f\xf8\x27\x4f\xc1\x09\x3f\x68\x5f\xd9\ -\x07\xf6\x8a\xf0\xde\x96\xd6\xa7\x5e\xf1\x26\x97\x16\x89\x6f\xf6\ -\x8c\x2a\x10\xf6\xf3\x38\x47\x6c\x12\x23\x95\x9f\x6b\x75\x04\x2f\ -\x23\x8a\xfb\x4f\xed\xba\xd9\x7e\x59\x53\x11\x2e\x5f\x76\x7c\x8b\ -\x46\x92\xd5\x2b\xcb\x57\xeb\xa5\xbd\x4f\xe7\xfc\x7f\x09\xe1\xb3\ -\xfe\x23\xa1\x84\x84\xa6\xa3\x56\x93\xab\x37\xcc\xa4\xdd\xa2\xda\ -\x8c\x7d\xd5\x6d\x74\x57\xbe\xf7\xb1\xf2\x15\x9c\x5a\x7e\xaf\xae\ -\xff\x00\x67\x5b\xeb\xde\x17\xb8\x93\x05\xbe\xd4\xba\xdd\xa7\xf6\ -\x7e\x00\x27\x8b\xdf\x33\xec\xc7\x38\xc0\x02\x4c\x92\x40\x19\x24\ -\x0a\xef\xbc\x3f\xfb\x3e\xf8\xab\xe1\x9f\xc4\x2f\x0b\xcf\xe2\xcf\ -\x0e\xea\xda\x0e\x9b\xaf\x5e\x4b\x65\x6a\xd7\xb0\xbd\xb8\xbe\x91\ -\x6d\x27\x9f\x08\x0e\x0c\x89\xb2\x26\x25\x86\x57\x90\x3f\x88\x03\ -\xc9\xf8\xdf\xe1\x86\xa9\xf0\xc6\xfe\x6f\x0d\xf8\x8b\xc3\x77\x7e\ -\x1f\xbc\xb6\x50\x92\x69\xb7\xd6\xc2\x35\x55\xe8\x30\x3e\xe4\x89\ -\xf7\x79\x52\xca\x7d\x78\xad\x0f\x09\xfe\xd1\x7a\x86\x97\xa9\x7c\ -\x33\xf0\x2f\x88\x35\x4d\x4e\xf7\x44\xd1\x7c\x4b\x71\xa8\xe8\x8f\ -\x70\x5e\x74\xd2\xad\xdf\x4b\xba\xb7\x9a\xdf\xcc\x63\xfb\xb8\x56\ -\x46\xb7\x31\xa7\x45\xf3\x64\xc0\x55\x50\x2b\xb7\x32\xc5\x66\x0b\ -\x09\x1a\xb4\x1c\x2a\x42\x56\x4e\xc9\xdd\x27\xd5\x7b\xcd\x5a\xff\ -\x00\x71\xf3\x7c\x23\x96\xe4\x12\xcd\xa5\x85\xc7\x53\xab\x87\xad\ -\x4d\x39\x45\x4a\x6a\xcd\xc5\x5e\xd3\xbc\x22\xd5\xd2\xe8\xec\xf6\ -\x3e\x84\xf8\x5d\xf0\x83\x50\xf8\xcd\x63\x35\xa7\x81\x2d\xf4\xbd\ -\x6f\xfb\x36\x24\x96\xe2\xd2\xcb\x50\xb5\xf3\xec\xd6\x42\x76\x99\ -\x61\xf3\x04\x91\x64\xab\x0f\x9c\x03\x95\x61\xd5\x4e\x39\x5f\x8e\ -\x1f\x08\xf5\x0f\x83\x77\xf6\xfa\x6f\x8d\x2e\xbc\x27\xe1\x5b\xcd\ -\x42\x23\x2c\x16\xba\xe7\x89\x34\xdb\x19\x6e\x23\x04\x02\xca\x93\ -\x4e\xa4\xa8\xe9\x90\x31\x9a\xfa\x77\xfe\x09\xb3\x26\x7f\x69\xcd\ -\x40\x2f\xca\xaf\xe1\xbb\xc6\x60\x3f\x88\xfd\xa6\xcb\x04\xfa\xe3\ -\x27\xf3\x35\xe4\x1f\xf0\x56\x2b\x38\x6e\xbf\x6e\x9d\x4b\xce\x86\ -\x39\x9a\x3f\x08\x69\x22\x32\xe8\x1b\x66\x6e\x35\x0c\xe3\xeb\xc6\ -\x7e\x9e\xd5\xf9\xa7\xf6\x86\x25\xe6\x1f\x54\x56\xb5\xaf\x77\x7b\ -\xfe\x67\xf5\x6e\x07\x2d\xc3\x7f\x67\xac\x55\x9e\xff\x00\x0d\xd5\ -\xb7\xe9\xa1\xe1\xff\x00\x03\xfe\x01\xeb\xfe\x37\xd5\xa3\x87\xe1\ -\x1d\xef\x84\x7c\x41\xa9\x78\x75\x7e\xdc\xb1\x78\x73\xc5\xfa\x55\ -\xf4\x96\x00\x30\x3e\x63\x2c\x57\x2c\x55\x77\x30\x04\x9e\x0e\xec\ -\x77\xaf\xa8\xbe\x18\x4b\xab\xfe\xd0\x7f\x0f\xd3\xc5\xde\x15\xd1\ -\x7c\x41\xaf\xe8\x32\x40\xb7\x2d\xa8\x47\x6e\xd1\x44\xc9\xb7\x73\ -\x14\x33\x14\x69\xf6\x90\x41\x58\x04\x8c\x18\x6d\xc6\xee\x2b\xe4\ -\x3f\x02\x7c\x51\x87\xf6\x47\xfd\xa5\x34\x4f\x15\x5a\xe9\x8b\xfd\ -\xad\xe1\xfb\x0b\x1d\x62\xf3\xec\x90\x85\x9a\xe7\x4a\xbe\x46\x32\ -\xdb\x9c\x60\xb3\x34\x01\x98\x46\xd9\x50\xfe\x53\x75\x19\x1f\x65\ -\xff\x00\xc1\xba\x7f\x12\xe7\xd5\x7f\x65\x4d\x4b\xc1\xd7\xad\x70\ -\xb3\x78\x66\x4b\x6b\x98\x62\x90\x92\x21\x8e\xe2\x1f\x99\x00\xed\ -\x89\x23\x72\x46\x31\x97\xf7\xaf\x81\xf1\x03\x85\xe1\x9c\x42\x9d\ -\x6a\xf2\xd2\x17\xb3\x8e\x9f\x17\xf3\x5e\xfb\x35\x7b\x7a\x9f\x65\ -\xc3\x19\x87\xd4\x9c\xa9\x53\x56\xe6\xe8\xfc\xad\xb5\xad\xba\x3d\ -\x7f\xfe\x09\xcf\xf0\xbe\xd7\xc4\xd7\x9e\x21\xf8\x85\xa8\x7f\xa5\ -\x5c\xc3\xa8\x4b\xa4\x68\x71\x6f\xcc\x56\x16\xe8\x91\x79\xd2\x01\ -\xd1\xa5\x96\x4c\x8d\xed\x96\x54\x50\xaa\x54\x3b\x86\xfa\xd2\x20\ -\x55\x06\x7a\xd7\xcf\x3f\xb2\x37\x8a\xed\xfc\x33\xf1\x4f\xe2\x37\ -\x81\xd2\xdf\xec\xe9\x1e\xb9\x7b\xac\x69\xe1\x17\xf7\x7e\x43\x4e\ -\x22\x91\x3d\x8a\x38\x53\x8f\x49\x07\x61\xc7\xd1\x0b\xf7\x6b\xe5\ -\xf8\x56\x14\x61\x97\x42\x14\x6d\xa5\xd3\xb7\xf3\x27\x67\xf8\x9f\ -\x43\x98\x4a\x6e\xbb\x94\xfa\xeb\xf2\x0a\x28\xa2\xbe\x88\xe2\x0a\ -\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\xfc\x37\xff\x00\ -\x83\x88\x1b\xfe\x33\xee\xcf\xfe\xc5\x4b\x2c\x7b\x8f\x3a\xe6\xbf\ -\x72\x2b\xf1\x1f\xfe\x0e\x33\xf0\xec\xda\x6f\xed\xc5\xe1\xfb\xf6\ -\x52\xd6\xfa\x97\x84\xad\x4a\x1d\xbc\x6e\x4b\x9b\xb5\x65\xeb\xce\ -\x3e\x53\xff\x00\x02\x15\xfa\x07\x86\x72\x4b\x3a\x4b\xbc\x65\xfa\ -\x1f\x9a\xf8\xad\x16\xf2\x26\xd7\x49\xc7\xf5\x3e\xe2\xff\x00\x82\ -\x8b\x5c\x7e\xd4\x5f\x07\xed\xbc\x65\xf1\x0b\xe1\xbf\x8f\x3c\x27\ -\x1f\x81\x34\x1b\x3f\xed\x27\xd0\xee\x74\x88\xe4\xbe\xb4\x82\x18\ -\x10\xce\xeb\x23\xc4\xe2\x43\xb9\x65\x93\x05\x97\x0a\x71\xce\x2b\ -\xe4\xaf\xd8\x5b\xf6\xff\x00\xfd\xac\xbf\x6f\x4f\x8b\x5a\x97\x83\ -\xfc\x37\xf1\x13\xc2\x5a\x3d\xf6\x9b\xa4\x49\xac\x3c\xda\x8e\x83\ -\x6f\xe5\x3c\x69\x34\x30\x95\x1e\x5c\x2c\x77\x66\x75\x3d\x3a\x0a\ -\xfd\x15\xfd\xaa\x7c\x5b\x0f\x8f\xff\x00\xe0\x9b\xdf\x12\x35\xeb\ -\x77\x47\x83\x5a\xf8\x6b\xa9\xdf\xc6\xc8\x3e\x56\x59\x74\xb9\x64\ -\x04\x73\xd3\x0d\xeb\x5f\x98\x3f\xf0\x6d\xea\xe3\xf6\xe1\xf1\x56\ -\x3f\xe8\x46\xbb\xe7\xaf\xfc\xbf\xe9\xf5\xe8\x70\xff\x00\xb2\x9e\ -\x43\x8a\xaf\x56\x85\x37\x52\x8e\x91\x6e\x11\xbf\xcf\x4d\x5a\x3c\ -\xbe\x21\xf6\xd4\xf8\x87\x07\x87\xa1\x88\xaa\xa9\x57\xd6\x49\x54\ -\x92\x5b\xfd\x9d\x74\x5e\x47\x47\xff\x00\x05\x4d\xf8\x77\xfb\x49\ -\xf8\x52\xdf\xe1\x6b\x7c\x4c\xf1\xf7\x82\xfc\x54\xf7\x1e\x26\x44\ -\xd0\x63\xd3\x34\xef\xb3\x7d\x9a\xf7\xe5\xd8\xf2\x9f\x25\x32\x84\ -\x90\x3b\xd6\xa7\xc7\xbf\xdb\xc3\xf6\x9c\xfd\x91\xbe\x37\xf8\x13\ -\xc4\x1f\x1c\x3e\x1e\x68\xba\x9e\x9b\xe1\x3b\xab\xb7\xb0\xbb\xb0\ -\x43\x6b\x6d\xa9\x9b\x8b\x67\x85\x90\x5d\x46\x64\x88\x36\xd3\x90\ -\x8d\x18\x6f\x97\x91\xdc\x7b\xaf\xfc\x15\xea\xf3\xfe\x13\xff\x00\ -\xdb\x33\xf6\x55\xf0\x0d\x8b\x99\x2f\x27\xf1\x58\xd5\xae\xa3\x53\ -\x9f\x26\xdd\x6e\x6d\x17\xcc\x29\xdf\xe5\x4b\x83\xce\x07\xee\xcf\ -\xb9\x1f\x72\xfc\x4e\xf8\x53\xa0\xfc\x69\xf0\x0e\xa9\xe1\x9f\x14\ -\x69\xb6\xba\xc6\x85\xad\x40\x6d\xee\xec\xe7\x5c\xa4\x8a\x79\x1c\ -\xf0\x55\x94\x80\x55\x94\x82\xa4\x02\x08\x20\x1a\xca\xa6\x7f\x46\ -\x86\x0b\x07\xf5\xcc\x3c\x27\x19\xc6\xa5\xd2\x5c\xad\x45\xc9\xc6\ -\xf1\xb5\xad\x75\x7e\xd7\xdf\xcc\xda\x9f\x0d\xd7\xc4\x63\xb1\xab\ -\x03\x89\xa9\x09\x42\x54\xec\xdc\xb9\x93\x92\x8a\x95\xa5\x7b\xde\ -\xce\xde\x9d\x9e\xc7\xc7\x97\xbf\x13\x7e\x0f\x7f\xc1\x72\x7f\x66\ -\x5d\x4f\xc3\x3a\x3d\xf3\x68\x5e\x38\xd2\x23\xfe\xd0\xb2\xb5\xbe\ -\x51\x1e\xa5\xe1\xfb\xc5\xe1\x27\x5d\xa7\xf7\xb6\xec\xc4\x2b\x94\ -\x38\x2a\xc3\x3b\x1f\x6e\x3c\xef\xe2\xdf\xec\xd7\xf1\x83\x51\xff\ -\x00\x82\x3c\x68\xff\x00\x07\xee\x3c\x13\xe2\x0f\x11\x7c\x48\xd4\ -\x75\x4b\xcb\xbd\x4a\x68\x6e\xad\x5e\x18\x58\x6b\x93\xdd\x99\x65\ -\x95\xe5\x52\xde\x6a\x38\x75\xda\x18\x9d\xdf\x30\x5a\xf8\x07\xe3\ -\xd7\x80\xfc\x59\xff\x00\x04\xa4\xfd\xbe\xee\xa0\xf0\xde\xa7\x70\ -\x97\x9e\x11\xbe\x4d\x47\x45\xbc\x93\xee\xea\x16\x32\x0d\xc8\x92\ -\x85\xdb\xbf\x74\x65\xa2\x90\x0c\x29\x60\xe0\x63\xb7\xea\xb7\xed\ -\x7f\xfb\x6d\x78\xe7\x40\xfd\x82\xb4\x9f\xda\x07\xe1\x76\xad\xe1\ -\x78\x34\x27\xd3\xac\xae\xef\x34\x7d\x5f\x4a\x92\xee\x57\x7b\x9b\ -\x98\xad\xd8\x2c\xe9\x3a\x04\x68\xa4\x93\x61\x5f\x2c\xe4\xab\x1d\ -\xc3\x18\xaf\x43\x1d\x97\xd6\xc0\x4f\x08\xb2\xc9\x29\xe1\xea\x54\ -\x8c\xe9\xf3\xdf\xdd\x9d\x9d\xa3\x75\xad\xa5\x7b\xfa\xad\x5e\x8d\ -\xbf\x3b\x2f\xcc\xa8\xe6\x34\xf1\x92\xcd\x62\xe1\x89\xa5\x4e\x54\ -\xea\xf2\x5b\xde\x85\xd5\xe5\x67\xa5\xe3\x6f\xb9\xe9\x7d\x12\xf6\ -\x8f\x1a\x7c\x36\x93\xf6\xa4\xfd\x8a\x35\x8f\x08\xeb\x9a\x0e\xa5\ -\xe1\xbb\xaf\x12\x78\x7e\x5d\x31\xac\x75\x3f\x2b\xed\x16\x57\x01\ -\x36\x47\x21\x31\x3b\xa7\xcb\x2a\x24\x8a\xc1\xba\x00\x78\xaf\x3e\ -\xff\x00\x82\x4d\x7e\xcd\xde\x2e\xf8\x03\xfb\x36\x9b\x8f\x88\xb1\ -\xcd\x1f\x8e\xf5\xe9\x61\x4b\xd8\xa7\x74\x92\x4b\x2b\x3b\x38\x12\ -\xca\xca\xd7\x72\x7c\xa5\x52\x18\x43\x0c\x13\xcc\xcc\x49\xc9\x35\ -\x95\xe1\xff\x00\x12\xfe\xd2\x5e\x39\xfd\x92\x74\x6f\x89\x3a\x07\ -\x8e\xbe\x1a\xde\x6a\xda\xe7\x86\x2d\xbc\x47\x06\x83\x37\x82\xee\ -\x20\x19\x9a\xd9\x6e\x3e\xce\x2e\x05\xfb\x7c\xc3\x76\xd0\xc6\x3c\ -\x31\xc6\x42\xe7\x8e\x0f\xf6\xca\xfd\xb9\x7e\x31\xfc\x07\xfd\x86\ -\xfe\x19\x7c\x6a\xd0\x75\x5f\x05\xbc\x3e\x2c\xd1\xf4\x53\xa9\x68\ -\xd7\x7a\x0c\xce\xc9\x77\x77\x66\xd7\x12\xcf\x1c\xcb\x72\x30\x99\ -\xc2\x88\xcc\x64\x8e\xa5\xdb\xa5\x7c\xa5\x0c\x1e\x2e\xad\x39\x65\ -\x94\x2a\x41\xaa\x95\x2d\x6b\xcb\x49\x2b\xfb\xba\xc7\x44\xec\xb5\ -\xda\xf1\x5a\xe8\x7d\x75\x7c\x76\x0e\x8d\x58\x66\xb8\x8a\x75\x2f\ -\x4a\x9d\xef\x68\xeb\x17\x6f\x7a\xca\x5b\xab\xbd\x37\x4a\x4f\x4d\ -\x4b\x5f\x0f\xac\x7e\x23\x78\x33\xfe\x0a\x87\xf1\x17\xe2\xad\xc7\ -\xc1\xef\x1e\x4f\xe0\xff\x00\x15\xf8\x7e\xdb\x44\xb3\x92\x19\x74\ -\xf3\x74\xb2\x42\xb6\xd9\x91\xe2\x6b\xa0\x02\x16\x8a\x40\x08\x62\ -\x71\xb4\xe0\x64\x81\xcb\xff\x00\xc1\x45\x6c\xbe\x38\x7e\xd8\xbf\ -\x0f\xfc\x77\xe1\x5d\x0f\xe1\x2f\x8e\xb4\xff\x00\x0f\xde\x5a\x69\ -\x56\xfa\x1d\xb5\xdc\xfa\x6a\x79\xf7\x11\x5e\xb4\xf7\x77\x33\xed\ -\xb9\x6f\x2c\x79\x69\x0a\x46\xa0\x92\x7e\x62\x71\xbb\x03\xed\x0f\ -\xd9\x76\x7f\x1a\xeb\x1f\x06\xb4\x9d\x53\xc7\x9a\xd6\x83\xad\x6b\ -\x5a\xd4\x11\x6a\x00\xe9\x3a\x53\xd8\x5b\xda\xc5\x2c\x11\xb0\x83\ -\x6b\xcd\x29\x90\xab\x17\x3e\x66\x53\x70\x60\x36\x0c\x73\xf3\x04\ -\x5f\xf0\x52\xbd\x5a\xe3\xfe\x0a\xfa\x7e\x0f\xf9\xd0\x2f\x80\x25\ -\xb4\x93\x44\x8a\x47\xb7\x55\x0f\xac\x47\x08\xb9\x77\x59\xb1\xb8\ -\xed\x39\xb7\x29\x9d\xbb\x88\xe3\x35\xd1\x97\xe2\xf1\x35\x31\x72\ -\xad\x42\x8c\x25\x2c\x3c\x13\xbd\xe7\x6b\x53\xb5\x9a\x4d\xab\xbd\ -\x2d\xb2\xba\xbe\x88\xe6\xcc\x70\x58\x5a\x58\x28\xd1\xc4\x57\xa9\ -\x18\x62\x66\xd5\xad\x0b\xde\xaa\x77\x4e\xc9\xda\x3a\xdf\x77\x67\ -\x6d\x4b\xff\x00\xb6\x47\xc0\x8f\x88\x1f\x15\x3e\x1b\x7c\x2b\xf8\ -\xbb\xf0\xcf\xc2\xfa\xa6\x8b\xf1\x83\xe1\x7d\xcc\x6b\x1e\x8d\xa8\ -\x3d\xb4\x37\x3a\x85\x93\xe2\x2b\x9b\x59\x4a\x4a\xd1\x95\x38\xdc\ -\x3f\x79\xf7\x1e\x5c\x61\x9c\x63\xae\xf8\x7f\xfb\x53\x7c\x50\xf0\ -\x9f\xc4\xff\x00\x17\x49\xe3\x4f\x83\x9f\x12\xbf\xe1\x1b\xf1\x03\ -\x58\xea\x5e\x1d\xfe\xcd\x4b\x5d\x52\x4d\x31\xcd\x85\xb4\x37\x56\ -\x32\xac\x53\x62\x35\x17\x31\xca\xe8\xed\xf2\xb7\x9a\xcc\x76\xae\ -\x0d\x78\xdf\x8c\xff\x00\x6b\xaf\xda\x43\xc0\x1f\xf0\x51\x2f\x0d\ -\xfc\x08\xd5\x35\xef\x86\xd6\x96\x3e\x2c\x8c\xde\x69\x9e\x22\x3e\ -\x1a\x9f\x6c\xb6\xc2\x29\xa4\xe6\x0f\xb5\xff\x00\xac\xdf\x03\xc7\ -\xb3\xcc\xeb\xb4\xee\x1b\xab\xec\x5f\xda\x9b\xe3\x84\x3f\xb3\x2f\ -\xec\xd1\xe3\x0f\x1d\xde\x1b\x79\x9f\xc3\x3a\x54\x97\x31\x2c\x80\ -\xac\x77\x37\x38\xdb\x0c\x64\x67\x20\x3c\xcc\x8b\xd7\x8d\xfe\xd5\ -\x8e\x32\x35\xa9\xc2\x86\x12\xb4\x21\x53\xda\x2f\xdd\xd9\xca\xea\ -\x33\x92\x69\x5f\x4f\xb4\x9d\x93\xd5\x5d\xa7\x64\xd1\xd1\x83\xf6\ -\x15\x67\x88\xc6\x51\xa9\x52\x97\xb2\x7f\xbc\xe6\x51\xe5\x72\x84\ -\x1a\x6d\xad\x7e\xc3\x57\x6a\xc9\xda\x2d\x5d\xa3\xe0\xaf\x12\xfe\ -\xc6\x5f\x13\xa0\xfd\x9d\x3f\x69\x0d\x42\x3f\x87\x3a\xb4\x7e\x28\ -\xfd\xa2\xb5\xa8\x6f\x74\xef\x0e\x69\xf3\xda\x48\x34\x1b\x78\x2e\ -\xde\x74\x92\xf2\x46\x99\x51\x64\x90\x4e\xfb\x96\x2d\xe4\x14\xe8\ -\x33\x81\xf6\xd7\xec\xe3\xe2\xcd\x73\xc1\xbf\xb2\x1f\x85\x97\x56\ -\xf0\x2f\x8a\xac\xf5\xef\x0b\xe8\x96\x7a\x6d\xce\x89\xfe\x8a\xf7\ -\x97\x12\xc3\x04\x51\xbb\x42\x44\xde\x5b\x21\x6c\x90\x59\xd4\x90\ -\xa7\xe5\x07\x8a\x6f\xec\x19\xfb\x4e\xff\x00\xc3\x61\x7e\xca\x5e\ -\x13\xf1\xec\xb1\xd9\x5b\x6a\x7a\xb5\xbb\xc5\xa9\xdb\xdb\x2b\x08\ -\xa0\xbc\x89\xda\x29\x55\x55\x99\x98\x21\x65\x2c\xa1\x98\x9d\x8c\ -\xbc\x9e\xa7\xc9\xfc\x15\xf1\x57\xe3\xe6\xb3\xff\x00\x05\x02\xd4\ -\xfe\x19\x3f\x89\xbe\x1e\xea\x1e\x0d\xf0\xae\x9d\x69\xae\xea\xfa\ -\x94\x5e\x1d\x9a\x2b\xa1\x14\xf2\x37\x97\x63\xb3\xed\x4c\x12\x77\ -\x54\x7c\x48\x49\x01\x46\xfd\xa4\xfc\x95\x38\xec\x46\x27\x19\xed\ -\xb0\xb8\x95\x08\xba\x2d\xca\x57\x72\x5f\x0a\x8c\x2c\xb7\xbe\x8a\ -\x2b\xbb\x7a\xeb\x76\x56\x03\x0f\x84\xc0\xaa\x38\xbc\x2c\xa7\x25\ -\x5a\x2a\x11\xb2\x8b\xf8\x9c\xaa\x5d\xed\x6d\x65\x29\x3e\x89\x69\ -\x64\x92\x2a\xff\x00\xc1\x1c\x3e\x1b\x78\xe3\xe0\x27\xc1\x0f\x10\ -\x78\x47\xc7\x7e\x07\xd7\xbc\x2b\xa9\x4d\xaf\xde\x6b\x71\xcf\x73\ -\x2d\xb4\xd6\xb2\xc7\x30\x88\x08\xd5\xa2\x95\x98\xb8\xda\x73\x94\ -\x03\x1d\x09\xaf\x46\xff\x00\x82\x99\x68\x3e\x25\xf8\x83\xfb\x1f\ -\x78\xc7\xc2\x3e\x12\xf0\xae\xb3\xe2\xad\x6b\xc5\x96\x4d\x61\x6f\ -\x15\x8b\xdb\xc6\x96\xe4\xb2\x12\xd2\xb4\xd2\x20\x0b\x8c\xf4\xc9\ -\x3d\x31\x5e\x39\xf0\x1b\xfe\x0a\x51\xab\x7c\x4a\xff\x00\x82\xb0\ -\xf8\xcb\xe1\x2d\xcc\xd6\xeb\xe0\x75\xb5\xb9\xb3\xf0\xe8\x36\xea\ -\xb2\x4d\x7d\x65\x85\xb9\x65\x93\x19\x75\x67\x8a\xf4\x0c\x92\x07\ -\x93\x81\x57\x7f\xe0\xaa\x9f\xb5\x97\xc6\x1f\xd8\xad\xbc\x33\xe2\ -\x0f\x0a\xeb\x1e\x0c\xb8\xf0\xe7\x8a\x35\x68\xb4\x54\xb0\xbf\xd0\ -\xa5\x92\xea\xc2\x53\x11\x63\x21\x99\x6e\x02\xca\xa7\x63\x9c\x6c\ -\x4d\xbc\x0c\xb7\x5a\xda\xa6\x0b\x1d\x57\x3c\xa7\x52\xa4\x61\x1a\ -\xb5\x39\x6a\x45\x37\x2e\x57\xa5\xed\x7d\x5e\xe9\xdf\xa5\xd5\xae\ -\x65\x4f\x1d\x97\xd2\xc8\x2a\xd2\xa7\x29\xca\x95\x3e\x6a\x52\x69\ -\x47\x99\x2f\x85\xbb\x68\x9e\x8d\x59\xda\xfa\xa7\x63\xdd\xbf\x62\ -\x2d\x33\x56\xd2\xff\x00\x64\x6f\x02\xf8\x67\xc4\x9e\x19\xd5\xbc\ -\x39\xaa\x78\x5f\xc3\xd6\x1a\x05\xed\xa6\xa4\x20\x26\x69\x2d\xed\ -\x21\x89\xe4\x8f\xca\x91\xd5\xa2\x66\x04\x29\x24\x31\xc7\x2a\x2b\ -\xca\x7f\x63\x9d\x1f\xc6\x9f\xb0\xa7\xc3\x4d\x4b\xe1\x3e\xad\xe0\ -\x7f\x14\x78\xb3\x49\xf0\xcd\xe5\xdc\xfe\x11\xd5\xf4\x44\x86\x78\ -\xb5\x5b\x29\xe6\x79\x92\xde\x56\x79\x10\xc1\x70\x92\x48\xea\x7c\ -\xdd\xa9\x8c\x61\x88\x00\xb6\x3f\xed\x7b\xfb\x48\x7c\x77\xff\x00\ -\x82\x7f\xf8\x53\x4f\xf1\xd6\xbd\x7d\xe0\x1f\x89\xde\x05\x8a\xfa\ -\x2b\x3d\x6a\x0b\x2d\x0e\x7d\x0f\x51\xb2\x59\x5b\x6a\x49\x13\x1b\ -\xab\x84\x60\x5b\x0a\x4b\x77\x64\x18\xe4\x95\xe4\x7f\xe0\xa1\x7f\ -\xb7\xef\xc4\xdf\xd9\xf3\xc3\x3f\x0e\x7c\x79\xf0\xff\x00\x5c\xf0\ -\x7e\xa7\xe0\x9f\x8a\xcf\x6d\xfd\x97\x65\xa9\x78\x7a\x5f\xb5\xe9\ -\xf1\x4b\x6d\x0c\x82\x47\x95\x6e\x40\x97\x76\xf2\xdb\x76\x26\xdc\ -\x85\xf9\xb1\x93\x9e\x17\x2d\xc5\x62\xa4\xe3\x4f\x92\x54\xf1\x12\ -\x6d\x6b\x24\xb9\xe1\x77\x64\xed\xcc\x9a\x52\x7f\x16\x8d\x37\xad\ -\xec\x5e\x2b\x34\xc2\x61\x20\xa7\x57\x9e\x15\x30\xd1\x49\xe9\x16\ -\xf9\x27\x64\x9b\x57\xe5\x92\x72\x8c\x75\x8b\x6d\x34\xae\xad\x74\ -\xea\xe8\x7f\xb1\x0f\x89\x3c\x27\xf1\xbf\xe1\x3d\xf7\x89\xbc\x0c\ -\x7c\x5b\x0e\xa9\xe2\xef\x13\xf8\xeb\xc7\x49\x04\x76\xf7\x7a\x4e\ -\x9f\x75\xac\x5b\x18\x61\xb7\x55\x99\xc1\x94\x42\xd1\xc5\xb8\x84\ -\x20\x15\xde\x3a\xd7\xdd\xfe\x01\xf8\x7d\xa4\xfc\x31\xf0\x56\x99\ -\xe1\xed\x0e\xd2\x3d\x3f\x46\xd1\xe0\x4b\x6b\x3b\x58\xc9\xd9\x6f\ -\x12\xf0\xa8\x32\x73\x81\xd0\x7b\x0a\xf9\x73\xf6\xb0\xf1\x6f\xed\ -\x1d\xfb\x32\xfc\x20\xb9\xf1\xa5\x8f\x8d\xbe\x1c\xf8\xc2\xd7\x49\ -\xb9\xb7\xfe\xd2\xb2\xff\x00\x84\x3a\x7d\x3a\x61\x6b\x24\xa9\x1b\ -\x4b\x1b\xfd\xba\x60\xcc\xbb\xc1\x20\x85\x1b\x41\x39\xe3\x07\xeb\ -\xd5\x39\x51\xf4\xaf\x37\x3a\xc5\x57\xc4\x53\xa5\x52\xa4\xe3\x28\ -\xfb\xc9\x72\xb9\x6e\x9b\x96\xaa\x49\x5a\xdc\xf6\x5a\x6d\xe8\x7a\ -\xb9\x0e\x13\x0f\x87\xad\x56\x95\x38\x4a\x32\xf7\x64\xf9\xb9\x6f\ -\x67\x15\x15\x69\x45\xbb\xdf\x92\xef\x5d\xfd\x45\x03\x02\x8a\x28\ -\xaf\x9f\x3e\x9c\x28\xa2\x8a\x00\x28\xa2\x8a\x00\x28\xa2\x8a\x00\ -\xc1\xf8\x98\xfa\xfc\x7e\x07\xd4\x1b\xc2\xf1\xd9\x4d\xaf\x08\xbf\ -\xd0\xd2\xee\x53\x14\x0c\xf9\x1c\x33\x05\x6c\x0c\x67\x9d\xa7\xe9\ -\x5f\x0b\xfe\xd3\x5f\x16\xfe\x3f\xf8\x6a\x28\x34\xff\x00\x1f\x69\ -\xab\xa1\xe8\x57\xef\xe5\xc5\x77\xa2\xdc\x25\xdd\x94\xec\x00\x6d\ -\x92\x4a\xb1\xa3\xc6\xde\x82\x45\x50\xc4\x1c\x6e\xc5\x7e\x82\xb0\ -\xc8\xac\x8f\x19\x78\x32\xc7\xc7\xfe\x15\xd4\x34\x6d\x56\xde\x2b\ -\xad\x3f\x52\x85\xe0\x9e\x27\x19\x0e\x8c\x30\x7f\x11\xd4\x1e\xc4\ -\x03\xd4\x57\xcd\x71\x26\x47\x2c\xcb\x0d\x3a\x70\xab\x2a\x72\xb5\ -\x97\x2b\x69\x37\xba\xba\xeb\xd8\xee\xc0\xe3\x15\x0a\x8a\x52\x8a\ -\x6b\xcd\x6b\xf2\x3f\x34\xbc\x1d\xfb\x5c\x2f\x87\x61\xd4\xb4\x07\ -\xd7\x2f\xf4\xcd\x4a\x78\x1c\xce\xf6\x66\x44\x86\x47\x64\x21\x3c\ -\xef\x2d\x76\x46\xc4\x00\x17\x71\xf9\x80\x00\x7a\x57\xe5\xff\x00\ -\xfc\x11\xca\xe9\xe5\xff\x00\x82\x93\x7c\x35\xf3\xb2\xd2\x3e\xab\ -\x74\x5c\xb7\x52\x7e\xcd\x39\x39\xfe\x75\xfd\x03\xfe\xc3\x7a\x35\ -\xa7\x82\x7c\x1d\xe3\x0f\x03\x9b\x88\xae\x6f\x3c\x25\xaf\x4f\x6b\ -\x72\xcb\x1e\xd6\x9e\x39\x11\x1a\x39\x08\xe7\xef\x2e\x57\x04\x9c\ -\x79\x78\xe8\x05\x7e\x1c\xfe\xc4\x9f\x01\x35\x4f\xd9\xf7\xfe\x0b\ -\xd7\x63\xf0\xee\xe2\xdd\x85\xd6\x83\xe2\xed\x4e\x18\x17\x8c\xcd\ -\x01\xb6\xb9\x9a\x29\x38\x24\x00\xd0\xb2\x3f\x27\xb9\xaf\x67\xc2\ -\x3c\x0c\xb0\x18\x1a\x8a\xad\x57\x27\x28\x3b\xde\xde\xeb\x57\x4d\ -\x2f\x24\xcf\x1f\x8c\xa5\xf5\x9a\xd0\x94\x63\xa4\x65\xf8\x68\x79\ -\xbf\xec\x0f\xfb\x62\x78\xc3\xf6\x28\xf8\xbf\x0f\x8c\xbc\x27\x79\ -\x30\xd9\x7d\x24\x3a\xc6\x99\xb9\x16\x1d\x7a\xc5\x6e\xcc\x92\x5a\ -\x48\x59\x18\x26\xec\x30\x59\x40\x2d\x13\x36\xe1\x9c\xb2\xb7\xee\ -\xa6\xad\xe1\xcf\x85\x7f\xf0\x59\xff\x00\xd9\x0f\x47\xf1\x46\x9f\ -\x6f\x0b\x5e\x2e\xf9\x34\xeb\x99\x1c\xc7\x79\xe1\xed\x45\x14\x09\ -\x6d\x27\x31\x90\xfb\x32\xc0\x49\x16\x76\xba\xec\x71\x86\x11\xb8\ -\xfe\x73\xf4\xab\x7b\xbf\x0b\xeb\xba\xc6\x9b\x7f\x6f\x35\xad\xf6\ -\x9d\xaa\x5e\xdb\x5c\x43\x22\xe1\xe1\x91\x2e\x24\x56\x52\x3b\x10\ -\x45\x7d\x95\xff\x00\x04\x93\xff\x00\x82\x8c\xb7\xec\x1f\xf1\xf2\ -\x49\xb5\xd9\x2e\x6e\x3e\x1e\x78\xb4\x43\x63\xae\x40\x27\x29\x16\ -\x92\x7c\xd4\xc6\xa8\x10\x23\x19\x1a\x18\xf7\x86\x45\x1b\x9d\x1b\ -\x82\x4c\x6a\xad\xfb\x36\x6b\x92\xca\xb6\x12\x9e\x63\x83\xf7\x6b\ -\x41\x27\xa7\x5b\x7e\xbf\x99\xf9\xde\x03\x32\x85\x3c\x45\x4c\x0e\ -\x37\xde\xa5\x36\xf4\x6b\x6b\xfe\x9f\x91\xf4\x7e\xb7\xf0\x82\x3f\ -\x02\xf8\x7f\xc3\xfe\x15\xf1\x17\x85\xed\x74\x9b\xbb\x1d\x7b\xc4\ -\x51\x5f\x69\xae\xbb\xd2\x39\xbe\xc9\xa1\x0f\x31\x1f\x8d\xc1\x90\ -\x86\x59\x57\x04\xab\x02\x36\x92\x40\xea\x7f\x67\xcf\x89\x1a\xe7\ -\xec\x4f\xe3\x0d\x53\xc4\xde\x03\xd3\x5b\xc4\x5a\x3e\xaf\x6c\x90\ -\xeb\x7e\x17\xb8\xb9\x58\x4e\xa1\xe5\x16\x68\xe6\x82\xe5\x95\x99\ -\x26\x8c\x34\x81\x55\xb2\xb2\x09\x99\x58\xa9\x08\xc9\xec\x1f\xf0\ -\x55\xcf\x19\x69\xfe\x25\xf1\xb7\xc1\xdd\x6b\x49\xbc\x87\x50\xd2\ -\xf5\x5d\x27\x56\xb9\xb4\xba\x81\xc3\xc5\x71\x1b\x9b\x02\xac\xad\ -\xd0\x82\x31\x5e\x1f\x6f\xa2\xdf\x3f\xc1\x4b\x1f\x19\xc2\x9b\xb4\ -\xbd\x37\xc4\xb7\xba\x1d\xf9\x8e\x02\xf2\x2b\xdc\xdb\xe9\xd2\x5a\ -\x3b\x95\x07\x6c\x4a\xe9\x72\x9b\x8f\x1b\xee\x14\x64\x64\xd7\x9b\ -\x83\xc7\x4b\x13\x82\x71\xc4\xea\xaa\x36\x9a\xe9\x7b\xfe\x77\x4b\ -\xd0\xe5\xcc\xb2\x3a\x58\x7c\xc2\x38\xac\x14\x54\x67\x46\x2b\x96\ -\x49\x6b\x6b\x59\xaf\x4b\x3d\x9e\x8f\xb1\xf6\x77\xc2\x9f\xda\x27\ -\xe0\x4f\xfc\x14\xfb\x47\xba\xd0\x35\x2d\x22\xde\xe3\xc4\x9a\x4c\ -\x78\xbb\xd0\x7c\x43\x65\xf6\x3d\x67\x49\xf3\x07\xcc\x61\x6e\x1c\ -\x03\xb3\x1e\x64\x0f\x82\x00\xe6\xbe\x34\xff\x00\x82\xb3\xff\x00\ -\xc1\x3c\xac\xff\x00\x65\xcd\x07\x4d\xf1\xcf\x81\xcd\xeb\x78\x4e\ -\xfa\xec\x69\xfa\x8d\x8c\xf2\xf9\xbf\xd9\x0e\xe1\xbc\xa9\x11\xdb\ -\xe7\x78\xdc\x83\x19\x0e\x49\x0c\x53\x92\x1c\xed\xf2\x0f\xda\x9b\ -\xe2\x0c\x7a\x67\xc3\xfb\x57\xb5\x9a\x4b\x2d\x79\x2f\xa0\xb8\xd2\ -\x2f\xa1\x18\xba\xd3\x6e\x61\x91\x66\x5b\x88\x88\x1c\x32\xb4\x6b\ -\xc7\x72\xc0\x1f\x43\xf4\xd7\xfc\x15\x7b\xf6\xad\x93\xfe\x1d\x37\ -\xe0\x4f\x0e\x78\xe9\xa3\xd3\xfe\x28\x7c\x5a\x5d\x2a\x68\xb4\xf5\ -\x8c\xab\x4a\xd6\x77\x56\xb7\xb7\x73\x15\x03\x6a\x2e\xc8\xc6\x41\ -\x23\xe6\x98\x01\x9e\x95\x38\x0a\x78\xec\x9f\x15\x42\x58\x7a\x8d\ -\xd3\xa9\x2e\x57\x0b\xf4\xeb\xa7\x92\xeb\xe4\x71\xe7\x98\x6c\xa7\ -\x89\x30\x98\x9a\x38\xda\x09\x57\xa7\x0b\xaa\x96\x57\x4e\xd7\x49\ -\x4b\x7d\xd7\xc3\x7b\x59\x9c\xcf\xfc\x10\x8b\xe2\x06\xb1\xe3\x5f\ -\xda\x57\xc5\x10\xea\x57\xf7\x17\xcb\x65\xe1\x99\x3c\x8f\x38\x86\ -\x29\x9b\xab\x6c\xf3\x8c\x9c\xe0\x7d\xe2\x7a\x56\xe7\xfc\x15\x43\ -\xe3\xcf\x84\x7e\x15\x7e\xdf\x96\x36\xba\xc7\xc2\xad\x43\xe2\x05\ -\xc4\x9e\x12\xb3\xbb\xbd\xf2\x7c\x56\x74\xa1\x2c\x0b\x75\x72\xaa\ -\x8b\x08\x81\x8b\xba\x87\x66\xc7\x9d\x18\x6f\x94\x76\x39\xf3\xcf\ -\xf8\x37\x6e\xf1\xb5\x5f\xda\x77\xc7\x32\x22\xb3\x43\x1f\x86\x82\ -\x33\xaf\x2a\xa5\xae\xa1\x20\x13\xee\x11\xb1\xf4\x3e\x95\x4f\xfe\ -\x0b\x63\x2b\x68\xdf\xf0\x53\x9f\x0d\xc9\x71\x67\x37\x93\xa9\xf8\ -\x22\x38\x6d\xe7\x39\x54\x0c\x93\x5c\xb3\xe0\xe3\x9f\x94\x60\xfa\ -\x6e\x15\x59\xd5\x08\xd5\xe2\x49\xc1\x69\xee\xf4\x76\xfb\x27\xb1\ -\xc2\x3e\xd2\x8f\x0d\x52\xe7\xd5\xf3\x3d\xd5\xef\xef\x7f\x91\xe7\ -\x9f\xf0\x50\xfd\x73\x4d\xbf\xff\x00\x82\x86\xfc\x44\xb9\xd1\xa5\ -\xb7\x6d\x16\xeb\x44\xd0\x27\xd3\x8d\xb8\x0b\x03\x5b\xb5\x9e\xe8\ -\x8c\x61\x78\xd9\xb4\xae\xdc\x76\xc5\x58\xfd\x82\xfe\x33\x5d\xfc\ -\x21\xd6\x7c\x5d\x79\x6b\xa8\x6b\xd6\x3f\x68\x82\x05\xf2\xf4\xa8\ -\xe7\x79\x24\xc1\x90\xfc\xc2\x25\x24\x28\xf5\x6e\x05\x7c\xfd\xab\ -\xfd\xaf\x45\xd5\x75\x0d\x5b\x54\xd6\x22\xbc\xb7\x4b\x0b\x7b\x1b\ -\x65\x16\xfe\x5f\xd8\xad\x6d\x83\xec\x42\x41\x3b\xc8\x56\xc6\x70\ -\x0e\x14\x0c\x57\xe8\xbf\xfc\x1b\x57\xa5\xea\x5e\x30\xf8\x09\xe3\ -\xef\x88\xb7\xd6\x27\x4d\xb1\xf1\x2e\xb2\x9a\x66\x93\x1b\x10\xcd\ -\x2c\x56\x8a\xc2\x59\x8b\x63\x9d\xd2\x4a\x57\xa6\x07\x97\xc6\x73\ -\x5f\x3b\xc5\xd9\x6f\xb5\xc9\x65\x97\xb9\xb8\xb6\xd2\xba\xdf\x47\ -\x7b\xfe\x07\xd9\x65\x15\x5c\x71\xbf\x58\xb7\x9d\xba\x6d\x63\x93\ -\x87\xe3\xb7\x8b\x13\xc7\x1a\x5e\xa1\xe1\x99\xb5\x8b\xcf\x12\x6b\ -\xb7\xab\x6d\xa5\x41\x64\xe7\xcf\xbe\x9e\x5f\x98\x23\xb1\xea\xa4\ -\x02\xce\xd2\x61\x02\xab\x16\xe0\x57\xdd\xff\x00\xb2\xed\xaf\xc7\ -\x69\x35\xa4\xb9\xf8\xa3\x2f\x85\xad\xf4\xa6\xd3\x98\x2d\x9d\x85\ -\xd7\xda\x2e\xd6\xe4\xbc\x45\x0b\xb2\xc1\x1a\x00\xa8\x25\x07\x6b\ -\x30\x24\x8e\xa3\x9a\xe0\x3f\x62\x2f\x83\xff\x00\xdb\x3f\xb5\x1f\ -\xc6\x0f\x8a\x12\x5c\x37\x90\xda\xc5\xf7\x85\xf4\x9b\x7e\x36\xf9\ -\x6b\x72\xb3\x5c\xcc\x71\xfd\xf9\x56\x34\x0a\x47\x02\x12\x72\x77\ -\x60\x7d\x60\x16\xbf\x11\xe0\x7e\x17\x96\x0a\x8f\xd6\x6b\x55\x93\ -\x94\xa4\xdd\x94\x9a\x8d\xaf\x65\xa5\xec\xef\xbe\xa7\xdb\x66\xd9\ -\x8a\xad\x3e\x48\xc1\x2b\x25\xea\x20\x38\x93\xad\x3e\x9a\x06\x0d\ -\x3a\xbf\x48\x3c\x30\xa2\x8a\x28\x00\xa2\x8a\x28\x00\xa2\x8a\x28\ -\x00\xaf\x83\xff\x00\xe0\xba\x5f\xb0\xbe\xaf\xfb\x52\xfc\x10\xd2\ -\xfc\x59\xe1\x3b\x09\x35\x2f\x15\x78\x01\xa6\x94\xd9\x40\x37\x4d\ -\x7f\x63\x20\x06\x65\x45\xfe\x39\x11\xa3\x47\x09\x9c\x90\x1c\x0c\ -\xb1\x00\xfd\xe1\x51\xbd\xb0\x90\x93\xfc\xb8\xaf\x43\x2a\xcc\xab\ -\x65\xf8\xb8\x63\x28\x7c\x51\x7f\x7f\x46\xbe\x68\xf2\xf3\x9c\xa6\ -\x8e\x67\x82\xa9\x81\xc4\x7c\x33\x56\xd3\x75\xd5\x35\xe8\xd1\xf8\ -\xeb\xfb\x2b\x7f\xc1\x55\xfc\x33\x3f\xfc\x13\x67\xc7\xdf\x06\x7e\ -\x20\x5e\x4d\xa4\xf8\xa3\x4b\xf0\x5e\xaf\xa3\x78\x7a\xe9\xe1\x79\ -\x21\xd5\x63\x6b\x39\x92\x0b\x62\xca\x0f\x97\x32\x12\xb1\x28\x7c\ -\x29\x01\x40\x39\xe2\xbc\x3b\xfe\x08\xdb\xfb\x59\x78\x37\xf6\x31\ -\xfd\xa3\x7c\x55\xe3\x0f\x1b\x5f\x5c\x5a\xe9\xb2\x78\x3e\xea\xc2\ -\xda\x3b\x6b\x77\x9e\x6b\xbb\x96\xbc\xb2\x91\x21\x45\x51\x8d\xcc\ -\xb1\x39\xcb\x15\x50\x07\xde\xaf\xd4\xdf\xf8\x28\xff\x00\xec\x2b\ -\xf0\x8f\xc7\x7f\xb3\x97\xc5\x1f\x1b\x6a\x5e\x03\xf0\xfb\x78\xb7\ -\x47\xf0\xb6\xa9\xaa\xdb\x6a\xb6\xd0\x9b\x4b\xa3\x75\x05\x9c\xb2\ -\xc5\x2c\x8f\x11\x5f\x35\x83\xaa\x9f\xde\x6e\x07\x18\x39\x1c\x57\ -\xe6\xdf\xfc\x10\x27\xe1\x17\x85\xfe\x33\x7e\xda\x5a\xc5\xaf\x8b\ -\x3c\x3f\xa3\xf8\x8e\xd7\x4a\xf0\x9d\xce\xa5\x6b\x0e\xa5\x6a\x97\ -\x31\x45\x72\x97\xb6\x48\xb2\x84\x60\x57\x70\x59\x1c\x02\x41\xc6\ -\xee\x31\x5f\xaf\x65\xd8\xec\xb3\x17\x94\x63\xf1\x54\xa9\xca\x31\ -\x93\xbc\xe3\x75\xbf\xf7\x1d\xb4\x4f\xad\xd7\xa1\xf8\xa6\x67\x97\ -\xe6\xd8\x4c\xef\x2f\xc1\xd5\xab\x09\x4e\x2a\xd4\xe5\x67\xb2\xd1\ -\x73\xae\xad\x79\x3f\x53\xec\x9f\xf8\x27\x77\xc3\x1f\x17\x7e\xd9\ -\xbf\xb5\xbe\xab\xfb\x54\x7c\x44\xd1\xe4\xd0\xf4\xd6\xb4\x3a\x77\ -\x80\xf4\xa9\xf9\x68\x2d\xc8\x64\xf3\xc7\xfb\x21\x1a\x40\x1b\x00\ -\x3b\xdc\x48\xe0\x01\x8a\xfd\x0c\x43\xf2\x8f\xa5\x32\x2b\x61\x0a\ -\x05\x5c\x2a\x8c\x0c\x01\xd0\x54\x8a\x36\x8a\xfc\x8f\x36\xcc\xa5\ -\x8d\xaf\xed\x39\x79\x63\x14\xa3\x18\xad\xa3\x15\xb2\xff\x00\x37\ -\xd5\xea\x7e\xd3\x93\x65\x51\xc0\x50\xf6\x5c\xce\x52\x93\x72\x94\ -\x9e\xf2\x93\xdd\xbf\xc9\x2e\x8a\xc8\xfc\x85\xff\x00\x83\x97\xfc\ -\x05\x6f\x61\xf1\x2f\xe1\x6f\x8a\x12\x3f\xf4\x8d\x5b\x4d\xbf\xd2\ -\xe6\x75\x07\x25\x2d\xa5\x8a\x54\x07\xf1\xbb\x92\xb0\x7e\x12\x78\ -\xde\xe7\xc5\x5f\xf0\x6e\x1f\xc5\x0b\x09\xa4\x6f\x2f\xc3\x3e\x27\ -\x87\x4d\x84\x9f\xe1\x46\xd4\xb4\xbb\xae\x3d\xb7\x5c\xb1\xfc\x6b\ -\xd0\x7f\xe0\xe6\xbd\x65\x52\xc3\xe0\xe6\x9c\xa6\x3d\xd2\xcb\xac\ -\x5c\x37\x3f\x32\x05\x16\x4a\xbf\x81\x2c\xdf\xf7\xcd\x79\x5f\xc0\ -\x8d\x26\x7d\x2b\xfe\x0d\xd6\xf8\xd1\x2c\xb1\x32\x45\xa9\x78\xca\ -\x0b\x88\x0f\x4d\xe8\x2e\xb4\x68\xfb\xf5\xf9\xa3\x61\x91\x9c\x60\ -\xfa\x11\x5f\xae\x65\x7e\xff\x00\x0e\xe5\xce\x7b\xaa\xf0\xb7\xca\ -\xac\x91\xf8\xb6\x6e\xb9\x38\x9b\x33\x8d\x3d\x9d\x0a\x8d\xfc\xe9\ -\x45\xfe\x76\x67\xd4\x3f\x0d\xff\x00\xe0\xa1\x9a\x9f\xc2\xcf\xd8\ -\xd7\xe0\x4f\x87\xf4\x6f\x87\xbf\x11\x34\xdb\xed\x42\x0f\x0a\x78\ -\x70\x6b\xfa\xae\x85\xe5\xe8\x9e\x53\xfd\x92\x39\xa4\x49\xcb\x90\ -\xe2\x48\x84\x82\x33\x81\x92\xea\xdc\x10\x01\xd6\xff\x00\x83\x86\ -\x2d\xa3\xb4\xff\x00\x82\x7f\x58\x47\x1c\x69\x1c\x50\xf8\xaa\xc1\ -\x51\x14\x6d\x55\x02\x0b\x90\x00\x03\xb0\x1d\xab\xde\x3f\x64\x5f\ -\x05\x68\x7f\x17\x7f\xe0\x9f\x7f\x07\x34\xed\x5a\xde\x1d\x53\x4d\ -\x5f\x09\xf8\x76\xe4\xc6\xc4\x85\x17\x16\x90\xda\xcd\x13\x64\x10\ -\x72\x93\xc2\xa7\xea\xb8\x3c\x64\x57\xc8\xdf\xf0\x5a\x6f\xda\x12\ -\xcf\xe3\xef\xec\x35\xe2\xf8\xf4\xbb\x5d\xba\x6f\x82\xfe\x27\xdb\ -\xf8\x69\x2f\x04\xfb\xff\x00\xb4\x65\x82\xc5\x9e\x79\x02\xed\x01\ -\x42\x4b\x2c\x91\x00\x19\xb2\x61\x27\x23\x3b\x47\xc9\xe5\x3e\xce\ -\xb6\x79\x4b\xd8\xd3\xe5\xe4\xaa\xf9\xdd\xef\x7b\xc9\x25\xbf\x5d\ -\xf4\xf5\x7d\xcf\xb1\xce\x3d\xa5\x0e\x1f\xad\xf5\x9a\xdc\xde\xd2\ -\x8c\x54\x15\xad\x6b\x46\xef\x6e\x9b\x6b\xe8\xbb\x1f\x6e\xd9\x7c\ -\x53\xb1\xf8\x25\xfb\x19\x59\xf8\xbf\x54\x6d\xb6\x1e\x18\xf0\x7c\ -\x5a\x9c\xfc\xf2\xeb\x15\x98\x7d\xa3\xdd\x8a\x80\x3d\xc8\xaf\xce\ -\xcf\xdb\xd3\xf6\x7e\xd7\x3f\x67\x4f\xd8\xbb\xe0\x27\xc6\x2f\x2b\ -\x3f\x10\x3c\x1f\xe2\x51\xe2\x4f\x10\xb0\x4f\x29\xde\xf3\x53\x98\ -\x5f\xc8\x64\x27\x27\xf7\x77\x09\x1c\x38\x20\xfc\xac\x7b\x57\xd3\ -\x9f\xb4\xe5\xd4\x3f\x18\xfe\x0b\x7c\x03\xf8\x23\x0d\xc4\xaa\x7e\ -\x2b\x3e\x9e\xfa\xaf\xd9\xa7\xf2\x66\x5d\x1f\x4f\xb6\x8e\xf6\xf0\ -\xab\x8e\x54\xb9\x8e\x14\x52\x31\x9d\xc7\xaf\x4a\xe2\xaf\xff\x00\ -\x63\x4f\x0f\xfe\xdb\x3f\xb2\x3f\xc4\x0b\x9d\x0b\xc6\x7f\x18\xb5\ -\x88\x3c\xed\x5b\x4d\xd0\xa1\xd5\xfc\x7d\x7b\xaa\xe9\xfa\xd4\xf6\ -\x32\xbc\x70\x5c\x34\x0e\x76\x18\xde\xe2\x1c\x85\x20\xe3\x68\x23\ -\xb6\x23\x24\x9c\x30\x32\x8e\x26\xbc\xb9\x63\x2a\x97\x96\x97\x4e\ -\x0f\x9a\x16\x7a\xab\x5e\xf5\x3e\xeb\x97\x9f\x42\x78\xf8\xcb\x0b\ -\x46\x2a\x52\x8d\x34\xa3\xad\x9a\x9a\xe5\xa8\xda\x56\x77\xb2\x54\ -\xfa\xaf\x8a\xdd\x4e\x7f\xfe\x0b\x27\xe2\x7b\x6d\x12\xc3\xf6\x6f\ -\xfd\xa3\x3c\x3c\xcd\x3d\x97\x87\xb5\xdb\x69\xfc\xe8\xf9\x6b\x9b\ -\x4b\x94\x8e\xf2\x2c\xe3\xf8\x4a\x41\x2a\xe3\xa1\xf3\x88\xef\x5f\ -\x40\xfe\xda\xf0\x59\x7e\xd2\x3f\x15\xbe\x0f\xfc\x22\x1e\x5e\xa3\ -\xa0\xf8\x93\x50\x7f\x18\x78\x89\x11\xf3\x1c\xba\x4e\x9e\xaa\xf1\ -\xc7\x20\xcf\x31\x4f\x75\x2d\xba\xfb\xec\x3e\x95\xf2\x57\xc0\x5d\ -\x71\x7f\x6d\x2f\xf8\x20\x7f\x8c\x7c\x2d\x23\x7d\xab\xc4\x5f\x0c\ -\x6d\x67\x54\x0c\x73\x32\x2d\x93\x2d\xf5\xbe\xc1\xc9\xe6\x00\x61\ -\x1e\xbb\x58\x7a\xd7\xb0\xff\x00\xc1\x14\xf5\x2d\x6b\xe3\xd7\x84\ -\xaf\xfe\x2c\x78\x92\x16\x5b\x8d\x37\x42\xd2\xfe\x1e\x68\x7e\x60\ -\xf9\xcd\xa6\x9f\x00\x7b\x89\x81\xef\xe7\x5c\x4a\x09\xc7\x78\xb1\ -\xce\x2b\xaf\x1b\x85\xfa\xa6\x0d\xd4\x9b\xf7\xb0\x93\xa9\x4d\x77\ -\x7c\xda\xd3\x7f\x26\xe5\x25\xe8\x72\x65\xf8\xbf\xae\x63\x55\x38\ -\x2f\x73\x1b\x0a\x55\x1f\x65\xc9\xa5\x54\xfd\x52\x8c\x5f\xf8\x8e\ -\x53\xfe\x08\x95\xac\xdd\x7e\xce\xff\x00\x1e\xfe\x38\x7e\xce\xda\ -\xb4\xce\xd3\x78\x5b\x56\x7d\x5f\x4a\x12\x03\xba\x68\x43\x2c\x12\ -\x49\xf4\x78\xfe\xc4\xe0\x7a\x48\xc6\xbd\x13\xe0\x9f\xc6\x54\xf0\ -\x0f\xc0\x3f\xda\x37\xf6\x90\x74\xfb\x55\xc7\x8a\xb5\xeb\xd3\xa0\ -\x12\x37\x7d\xbe\xd3\x4f\x1f\xd9\xba\x64\x40\x0e\xf2\x5c\x2b\xaf\ -\x1f\xf3\xd4\x63\x27\x93\xe0\x3f\xf0\x58\x49\x7c\x45\xfb\x15\xfe\ -\xde\x3e\x13\xf8\xd5\xe0\xcb\x59\xde\xe7\xc7\x1a\x05\xe6\x85\x3a\ -\x26\x71\x2d\xfa\xdb\x3d\xb2\x16\xc0\xc9\x22\x39\xad\x9d\x54\xfd\ -\xe6\xb6\xe3\xd4\x7b\x9f\xc4\x6f\x82\x16\xb2\xf8\x5f\xf6\x77\xfd\ -\x96\x22\xba\xbe\xb1\x86\x3b\x15\xd7\xfc\x53\x36\x9b\x77\xf6\x7b\ -\x88\x6d\xf4\xe8\x32\x19\x5d\x3e\xeb\x4d\xa8\xc9\x1b\x06\x53\x90\ -\xd1\xb3\x73\x8a\xac\xc2\x8d\x2c\x47\xb3\xcc\x25\xf0\xe2\x54\x5c\ -\xed\xda\x92\xbd\x6d\x3c\xe5\x18\xb5\xdd\xb3\x3c\xbe\xad\x6c\x37\ -\x3e\x59\x1f\x8b\x0a\xe5\x18\x5f\xbd\x56\xa3\x45\xdf\xfc\x33\x9d\ -\xfb\x24\x78\x37\xed\xe3\xf0\x26\xe3\xfe\x09\xf7\xe1\xcf\xd9\x53\ -\xe2\x9d\xaa\xb4\xba\x97\xc3\xdb\xb8\xb4\xaf\x13\xdc\x2b\x7e\xf2\ -\xfe\x69\x58\xde\xcf\x96\xe7\x89\x24\x6d\x44\x12\x73\xfe\xbb\xbd\ -\x7a\x87\xfc\x1c\x0f\xac\xda\xdc\xfe\xce\xbf\x09\xef\xe3\xb8\x85\ -\xec\xe4\xf1\xa5\xb5\xc2\xcf\xbb\x11\xb4\x66\xda\x66\x0f\x9c\xe3\ -\x18\x20\xe4\xf1\x8a\xea\xbf\x6f\x6f\xf8\x26\x46\x9f\xe2\x7f\xd9\ -\x1f\xc7\x12\x58\xf8\xe3\xe2\xe7\x88\x35\x6d\x17\x4c\x97\x56\xd3\ -\xec\xb5\xcf\x18\x5e\xea\x96\x93\x4d\x6e\xa6\x5d\xa6\x09\x18\xab\ -\x33\x2a\xba\x03\x8e\x37\xd7\xc7\x9f\xb4\xc7\xed\x1d\x0f\xc6\xef\ -\xf8\x24\x2f\xec\xff\x00\xa9\x5f\x5e\x09\x2f\xbc\x1b\xe3\x18\xb4\ -\x3d\x51\x89\xde\xd1\x1b\x3b\x69\x84\x65\xb1\x92\x58\xdb\xf9\x2f\ -\xea\x4b\x1a\xee\xc9\xe7\x1c\x75\x4c\x26\x2e\x32\x73\x95\x3a\x93\ -\x8c\x9d\xac\xed\x35\x29\xae\xfa\x27\xcc\xbe\x7e\x87\x06\x75\x19\ -\xe5\xf4\xb1\xb8\x29\xc7\xd9\xc6\xad\x38\x4e\x2a\xf7\x57\x83\x8c\ -\x25\xae\x9a\xb5\xca\xde\x9e\x7d\xcf\xa9\xff\x00\xe0\xa5\xff\x00\ -\xb4\xef\x86\xff\x00\x6d\xff\x00\x82\x91\xfc\x11\xf8\x2b\xab\x58\ -\xfc\x45\xf1\x97\x8e\xaf\xad\x4c\xe9\xa4\x3f\xda\x2d\x74\xab\x3b\ -\x79\xd2\x79\x2e\x6e\x66\x50\x52\x34\x12\x24\x4a\x72\x73\x97\xe9\ -\xd8\xf9\xb7\xfc\x16\xbf\xe1\x95\xbf\xc0\x3f\xd9\x43\xf6\x71\xf0\ -\x9d\xb1\x7b\xe8\x7c\x23\x7f\x06\x98\xaf\x1c\x63\xcc\xba\xf2\x2d\ -\x23\x42\xca\xbd\xd9\xf6\x67\x1d\xc9\xaf\x54\xff\x00\x82\xc0\xfc\ -\x3f\xd7\x3e\x05\x78\xab\xc0\xbf\xb4\xe7\x81\xa1\xdd\xe2\x3f\x86\ -\xf7\x09\x61\xae\x44\xa7\x6a\xea\x1a\x64\xaf\xb4\x09\x31\xfc\x21\ -\xa4\x78\xc9\xc7\x02\xe0\x37\x1e\x58\xaf\x29\xff\x00\x82\xd2\xfc\ -\x73\xf0\xef\xed\x11\xfb\x31\xfc\x01\xf1\xc7\x87\x2f\x16\xe3\x43\ -\xd6\xbc\x40\x6e\x51\xd9\x94\x1b\x72\x23\x5f\x32\x29\x39\xc0\x78\ -\xd8\x32\xb0\xec\x51\xb9\xc0\xae\x7e\x1e\x49\x54\xc0\x3c\x2a\xfd\ -\xcf\x34\xf9\xaf\xab\x55\x39\x5a\x69\xbb\x2d\x39\x52\xe5\xd3\x55\ -\x7d\xd9\xd5\xc4\xcd\xba\x59\x8c\x71\x6d\x7b\x7e\x5a\x6a\x36\x56\ -\x4e\x97\x32\x69\xa4\xdb\x77\xe6\x6d\x4a\xef\x74\xb6\x4c\xfa\x96\ -\xc3\xf6\xf2\xbe\xf8\x97\xfb\x54\x7c\x3b\xf8\x77\x0f\xc3\xcf\x1d\ -\xf8\x57\x4d\xf1\x34\x5a\x95\xce\xa3\x3f\x8b\x34\x41\x66\x97\x69\ -\x05\xab\xbc\x71\x41\x97\x60\xe4\x48\x03\x37\x4c\x00\xbc\x10\xc4\ -\x8f\xaa\x57\xee\x8f\xa5\x73\x9e\x2c\xf0\xe6\x87\x3d\xee\x9f\xaf\ -\xea\xd0\xdb\x19\xbc\x2c\x66\xbc\xb5\xbc\x99\xca\x8b\x1d\xf0\xbc\ -\x72\xbe\x73\x8c\x18\x99\xc1\xc8\x22\xb9\x6f\xd9\xc7\xf6\x9a\xd2\ -\xff\x00\x68\x0f\x84\xbe\x17\xf1\x47\x97\x6f\xa2\xbf\x8b\x92\x7b\ -\x8d\x37\x4f\x9e\xf1\x5a\xe6\xe2\xdd\x66\x91\x62\x94\x29\x0a\x4e\ -\xf8\x91\x64\x2a\x14\xec\xdd\x8c\x9c\x6e\x3f\x9f\xe2\xb9\x2b\x53\ -\x55\x30\xf4\xf9\x63\x15\x69\x6b\x7b\xc9\xb9\x3b\xfd\xcb\xf0\xf4\ -\x3f\x49\xc1\xca\x74\x2a\x4a\x96\x2a\xaf\x3c\xa4\xf9\xa3\xa5\xad\ -\x14\xa2\xad\xdb\xe2\x7f\x3b\xfa\x9e\x9b\x45\x00\xe4\x51\x5e\x69\ -\xeb\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\x40\x08\xdd\x6a\ -\xb6\xa5\xa9\x43\xa4\xd8\xcd\x73\x71\x22\xc5\x0c\x2a\x5d\xdd\x8e\ -\x02\x81\x56\x5a\xbc\xbb\xf6\x8b\xfd\x9b\xbf\xe1\xa3\x2c\x61\xd3\ -\xee\xbc\x61\xe2\xcf\x0d\xe9\x68\x84\x4d\x6f\xa3\xfd\x91\x7e\xd4\ -\xdb\x94\x86\x63\x3c\x12\xf4\x00\x8c\x00\x3a\x82\x08\xc7\x3c\x78\ -\xd9\x56\x8d\x26\xf0\xf1\xe6\x9f\x44\xdd\x97\xab\x65\xd3\xe4\x72\ -\xf7\xdd\x91\xf1\xfd\xe7\xed\x6b\xaa\x7c\x35\xf8\xfd\xe3\x8d\x77\ -\xc3\x7e\x49\xb5\xf1\x14\xc1\x64\x49\x88\x2a\x76\x64\x46\xf9\xc7\ -\x55\x2c\xdf\x99\xaf\xcf\x6f\xf8\x29\xff\x00\xed\xaf\xf1\xb7\xe0\ -\x8f\xc6\xdb\x3f\x1c\x78\x23\xc7\x10\x78\x6d\xfc\x55\x68\x2c\xb5\ -\x29\xed\x74\xeb\x69\x35\x04\xb8\x84\xb0\x5c\xcd\x22\x99\x16\x37\ -\x8b\x6a\xec\x52\x14\xfd\x9c\xf5\xcd\x7e\x94\xfe\xd2\x7f\xf0\x4c\ -\x59\x3c\x05\xf0\x9b\x51\xd4\x3c\x1f\xe2\x0f\x17\x78\xa2\xee\x3f\ -\xf8\xf9\xb0\xbe\x8a\xde\x5b\xa9\xa2\x24\x29\xfb\x31\xb6\x86\x02\ -\xac\xbb\x8b\xb0\x21\x8b\x00\x42\xed\x60\x2b\x5f\xe3\x27\xec\x3d\ -\xf0\xe7\xfe\x0a\x47\xff\x00\x04\xc7\x5f\x87\x7a\x0e\x9b\xa6\xf8\ -\x31\xad\x56\x2b\xbd\x2c\x59\x45\xb3\xfb\x03\x5b\xb6\x8f\x60\x32\ -\xaf\x57\xdc\xae\xf1\xb9\x7c\xbb\x45\x3b\x36\x77\x95\x71\xf9\xb7\ -\x05\x60\x73\x6c\x06\x7a\xd6\x67\x56\xd0\xf7\xa5\xc8\xae\xe3\x25\ -\x36\xef\x67\xa5\xac\xf5\xb7\xf9\x9e\xee\x71\x5b\x0d\x5f\x07\xfe\ -\xcd\x1d\x74\x57\xea\x9a\xdb\xf0\x3f\x00\x3e\x24\xfe\xd7\x9f\x13\ -\x7f\x6a\x0d\x42\xca\xeb\xe2\x37\x8c\x5b\xc5\xb7\x16\x79\xf2\xae\ -\x27\xd3\xed\xe2\xba\x39\x00\x00\xd3\xc6\xa2\x47\x50\x33\x85\x62\ -\x54\x13\x90\x2a\x9d\x86\xa5\xb3\xdb\xa1\xce\x7f\x1a\xe3\x3e\x2c\ -\x7c\x1f\xf1\xa7\xec\xb5\xf1\x63\x54\xf0\x4f\x8f\x74\x1d\x43\xc3\ -\xbe\x23\xd1\xe4\x2b\x2d\xb5\xdc\x2c\x9e\x6a\x06\x2a\xb3\xc6\x48\ -\x1b\xe2\x7c\x65\x5d\x72\xa4\x74\x26\xa6\xd1\x7c\x49\xe6\x28\xcb\ -\x2d\x7f\x60\xe4\x98\xea\x11\xa4\x95\x0f\x84\xfc\x5b\x38\xca\xe7\ -\x39\xb9\x4f\x73\xeb\x5f\xd9\x03\xe2\x56\xaf\x7d\x6e\xbe\x1b\x93\ -\x56\x8d\x7c\x3f\xa0\xb5\xde\xa3\x65\xa6\xb4\x25\xa4\x8a\x6b\xcf\ -\xb3\xa4\xee\xb2\x6e\xe2\x3f\xf4\x68\xce\xc0\xb8\xdf\x23\x36\x72\ -\x4d\x7b\x66\xaf\xf1\x37\xc7\xfe\x0d\xb7\x6b\xfd\x03\xe2\x0e\xad\ -\xe1\xad\x2f\x42\x17\x5a\x9c\x36\x16\x10\xaf\x95\x73\x24\x91\x40\ -\xb3\x0b\xb4\x72\xd1\xdc\xc4\x52\xd5\x02\xc6\xe8\x36\x87\x97\x9f\ -\x9c\xd7\xc5\xbf\xb3\xcf\x8f\xd3\xc2\xdf\x13\xf4\xd6\x66\x5d\x9a\ -\x83\x0b\x17\xf6\xf3\x08\x00\xfe\x0d\x83\xf8\x57\x6d\xfb\x56\xf8\ -\xeb\x50\x9b\x5e\xb2\xd2\x9b\xf7\x7a\x6a\xc4\xb7\x0a\x73\xfe\xbd\ -\xfe\x60\x49\xff\x00\x77\xa6\x3d\xc9\x39\xca\xe3\x4a\xf9\x7e\x1e\ -\xb5\x5e\x44\xbd\xd6\xee\xd7\x99\x95\x1a\xb5\xe8\xe1\xfd\xa5\xfd\ -\xe8\xab\x7c\xba\x1d\x9a\x7e\xde\xff\x00\x11\x20\x9e\xdf\x54\xb4\ -\xd3\xfe\x13\xe9\xfe\x28\xb3\xf9\xac\xf5\xeb\x6f\x07\x94\xbc\xb1\ -\x93\xa8\x9a\x14\x37\x06\xdd\x24\x07\x04\x1f\x2f\x00\x80\x40\xe0\ -\x57\x8e\xeb\x9e\x27\xd6\x3c\x57\xe2\xdd\x4b\xc4\x9e\x28\xf1\x16\ -\xb5\xe2\xcf\x13\x6a\xe4\x1b\xbd\x4f\x54\x9c\xcb\x33\x81\x9f\x95\ -\x7a\x85\x5e\x4f\x0b\xc5\x72\x8d\xac\x37\x5d\xdf\x8d\x43\x36\xab\ -\x91\xcb\x8a\xf5\x28\x65\xd8\x2c\x3c\x95\x4a\x71\xd5\x2b\x27\x76\ -\xed\xe9\x77\xea\x78\x35\x25\x8e\xc4\x45\xc2\xac\xae\xa4\xee\xf4\ -\x4a\xfe\xb6\x47\xb5\x68\x9f\xf0\x51\x6f\xda\x0b\xe1\xee\x98\xb6\ -\x3e\x19\xf8\xb5\x7d\xe1\xab\x18\xd1\x53\xc8\xd2\xb4\x6b\x0b\x5d\ -\xe1\x46\x17\xcc\x64\x8c\x19\x08\x1d\xdc\x93\xd7\xd4\xd4\x37\xff\ -\x00\xb7\xf7\xc6\xef\x8b\xf7\xb1\x69\x5e\x3c\xf8\xc9\x75\xa9\x68\ -\xd2\x47\x32\x34\xda\xae\x93\x65\x72\x6d\x77\x46\x47\xee\x99\xe3\ -\x26\x36\x6c\x28\xca\xe0\x9c\x0e\xfc\xd7\x84\xdf\xeb\x8b\x0a\x7d\ -\xe1\x5c\x9f\x88\xbc\x53\x95\x2a\x19\x72\xc3\x00\x7a\xd7\x8b\x8d\ -\xc1\x65\xd1\x6e\xac\x69\xa5\x2e\xfe\xbf\x33\xe9\x32\xff\x00\xae\ -\xb4\xa3\x29\x5e\x2a\xda\x1e\xd9\xfb\x4c\xfc\x7a\xd3\xfc\x57\xe1\ -\x5b\x7f\x0f\x78\x6e\xe9\xb5\x4b\xcd\x5a\x48\xe0\x76\x8b\x77\x23\ -\x38\x11\x8e\x32\x59\x98\xae\x3f\x1e\xb9\xe3\xf5\x73\xf6\x44\xf8\ -\xd7\xac\x7e\xca\x3f\x06\xb4\xdf\x08\xf8\x4f\x52\x86\xf3\x41\xb3\ -\xd3\x45\x84\x4a\x30\xd1\x31\x00\x66\x75\x03\x21\x59\x89\x2d\xc6\ -\x7a\xf5\xaf\x9b\xff\x00\xe0\xd9\x5f\xf8\x27\x26\xb7\xf1\x27\xf6\ -\x80\xff\x00\x85\xf9\xe3\x2d\x16\xee\xcf\xc2\x7e\x0c\x85\xd7\xc2\ -\xe6\xe5\x0c\x43\x54\xd4\x65\x4d\x9f\x68\x40\xcb\x87\x86\x18\x64\ -\x90\x86\x1c\x19\x5e\x32\x0f\xee\xc8\xaf\xd2\x3f\xda\x97\xe1\x85\ -\xa7\xed\x49\xfb\x56\xe8\xbe\x14\xf0\x5d\xbe\x9b\x6b\x7b\xa5\x01\ -\x2f\x8b\xf5\xdb\x68\x77\x35\x95\xa6\x79\x8c\xb8\x06\x33\x74\xd9\ -\x02\x24\x90\x13\x9d\xee\x54\xa4\x6c\x0f\xf3\x9f\x8b\x5f\x5c\xcc\ -\x55\x15\x94\xd6\xe5\x94\x1b\x49\x2f\xb4\xe5\x6e\xba\xd9\x45\x5f\ -\xbe\xec\xfd\x53\x85\x95\x2c\x3f\x3f\xd6\x63\x75\x25\xab\xec\x96\ -\xdf\x7b\x35\x3f\xe0\x97\xdf\x17\xe1\x7d\x27\xc4\x1e\x0c\xba\x50\ -\xba\x83\x5f\xdc\x6b\xb6\xf2\xe7\xfe\x3e\x12\x79\x01\x94\x63\xfb\ -\xc9\x21\xcf\xb8\x7e\x9f\x29\xcf\xd7\x68\x72\xa3\xe9\x5f\x2c\x59\ -\xff\x00\xc1\x2a\xfc\x33\xa5\x45\x0c\x96\x7e\x3e\xf8\x95\x65\xa8\ -\x5a\xed\x68\xaf\x22\x9b\x4d\xf3\x95\xc0\xe1\xbf\xe3\xc8\x2e\x73\ -\x83\xc0\x5e\x99\xe2\xbe\x9c\xf0\xde\x92\xda\x07\x87\xac\x2c\x5a\ -\xee\xeb\x50\x6b\x2b\x78\xed\xda\xea\xe9\x83\x4f\x70\x55\x42\xef\ -\x90\x80\x01\x76\xc6\x49\x00\x0c\x93\xc0\xe9\x58\xf0\x9e\x17\x33\ -\xc2\xe0\xa3\x85\xcc\xb9\x5b\x86\x8a\x51\x77\xba\xec\xd5\x95\xac\ -\x5e\x61\x53\x0f\x52\xab\xa9\x87\xba\x4f\xa3\x45\xda\x28\xa2\xbe\ -\xa0\xe0\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\ -\xa2\x80\x3c\x9f\xf6\xf0\xff\x00\x93\x20\xf8\xcd\xff\x00\x62\x36\ -\xb7\xff\x00\xa6\xf9\xeb\xf2\x8f\xfe\x0d\xbd\xff\x00\x93\xe0\xf1\ -\x4f\xfd\x88\xb7\x9f\xfa\x70\xd3\xeb\xf5\x43\xfe\x0a\x0b\xac\xc1\ -\xa3\x7e\xc3\x1f\x18\xa5\xb9\x91\x21\x8e\x4f\x06\xea\xd6\xea\xcc\ -\x7a\xbc\x96\x72\xc6\x83\x81\xd4\xbb\xa8\x1e\xe6\xbf\x25\xff\x00\ -\xe0\xde\xaf\x1f\x69\x7e\x08\xfd\xbb\xee\xad\xf5\x2b\xb8\x6d\x64\ -\xf1\x27\x85\xaf\x34\xbb\x0f\x31\xc2\x89\xee\x3e\xd1\x6b\x38\x40\ -\x7b\x92\x96\xf2\x10\x07\xa5\x7e\x99\xc2\xd0\x94\xb8\x6f\x30\xe5\ -\x5f\xd5\x91\xf9\x2f\x16\xd4\x8c\x78\xaf\x2d\x72\x76\xff\x00\x87\ -\x67\xee\x65\x34\xc9\x83\xd3\xda\x9a\x27\xc8\xcf\xf3\xaf\x94\xbf\ -\x6f\xff\x00\xf8\x2a\xb7\x80\x7f\x63\xaf\x09\x6a\x16\x76\x3a\xa6\ -\x9f\xe2\x8f\x88\x0f\x1b\x43\x63\xa1\x59\x4e\x26\x36\xf3\x1e\x03\ -\x5d\x32\xe7\xca\x45\xc8\x25\x4f\xce\xdc\x00\x3b\x8f\xcf\xf0\x39\ -\x7e\x23\x1b\x59\x50\xc2\xc1\xca\x4f\xb7\xe6\xdf\x45\xe6\xcf\xd3\ -\x33\x0c\xcb\x0d\x81\xa0\xf1\x18\xa9\xa8\xc5\x77\xeb\xe4\xbb\xb7\ -\xd1\x23\xf3\xd3\xfe\x0e\x0e\xf8\xbf\x1f\xc5\x5f\xdb\x6b\x4b\xf0\ -\x7e\x96\xcd\x78\xde\x0d\xd2\x21\xb1\x96\x18\x97\x7b\x1b\xdb\x97\ -\xf3\xd9\x06\x3a\x9f\x2d\xed\xc6\x07\x73\x8e\xa3\x15\xf7\xf7\xc1\ -\x5f\xf8\x25\x27\x83\xb5\x2f\xd8\xab\xe1\xef\xc3\xaf\x88\x51\xf8\ -\x82\xe8\x68\xb6\x02\xe3\x53\xd3\xac\xf5\xdb\xbb\x3b\x39\xef\x66\ -\x90\xdc\x4a\x65\x8e\x19\x15\x26\x31\xca\xe5\x51\xd8\x12\x02\x2e\ -\x31\xd2\xbe\x6e\xff\x00\x82\x53\x7f\xc1\x32\x7c\x55\xe3\xbf\x8c\ -\x92\x7e\xd0\x3f\x1b\xad\x6e\xa3\xd5\xaf\x2f\x9f\x57\xd2\x34\xbb\ -\xe8\x7c\xbb\xab\x9b\xb9\x18\xc9\xf6\xdb\x84\xff\x00\x96\x6a\xac\ -\x49\x8e\x32\x33\xb8\x2b\x1d\xaa\xaa\x1b\xf5\x39\x3e\xe8\xfa\x57\ -\xdc\x71\x36\x78\xb0\xb4\x30\xf9\x46\x5d\x53\xf8\x0b\xde\x94\x5e\ -\xf3\xb3\x4e\xcf\xca\xef\x5f\x3f\x23\xf3\xfe\x13\xe1\xf7\x8c\xc4\ -\x62\x73\xac\xce\x9f\xfb\xc3\xb4\x61\x25\xb4\x2e\xb7\x4f\xbd\x92\ -\xf9\x79\x9f\x3b\x78\x5b\xfe\x09\x7f\xf0\xdb\xc0\xde\x11\x5f\x0f\ -\xe8\xba\xa7\xc4\xed\x23\x41\x50\x54\x69\xb6\x5e\x3c\xd5\xed\xed\ -\x00\x27\x2c\x3c\xa5\xb8\x09\xce\x79\xe3\x9a\xc3\xd4\x3f\xe0\x8e\ -\x7f\x04\x35\x3f\x00\x5a\x78\x52\x6d\x37\xc5\x4d\xe1\x9b\x19\xda\ -\xee\x2d\x2b\xfe\x12\x8d\x43\xec\x62\xe1\x8b\x13\x39\x8b\xcd\xd8\ -\x65\xf9\x88\xde\x46\xe0\x38\xce\x2b\xea\x6a\x2b\xe4\x56\x7b\x98\ -\xa7\xcc\xab\xca\xf7\xbf\xc4\xf7\xef\xea\x7d\xb3\xe1\xdc\xad\xc7\ -\x95\xe1\xe1\x6b\x5b\xe1\x5b\x76\xdb\x6d\x16\x87\xca\xe7\xfe\x08\ -\xdb\xf0\x3c\xcd\x63\x27\xf6\x7f\x8c\x3c\xcd\x32\xcd\xb4\xeb\x36\ -\xff\x00\x84\xb3\x52\xcd\xa5\xab\x06\x56\x82\x33\xe7\x7c\x91\x95\ -\x76\x1b\x17\x0b\x86\x3c\x62\xbd\x7b\xc1\x1f\xb2\x9f\x84\xbe\x1a\ -\x7e\xcf\x70\xfc\x30\xf0\xea\x6a\xda\x1f\x85\x2d\xa1\x96\x08\x12\ -\xc3\x53\x9e\x0b\xb8\x56\x59\x9a\x69\x0a\xdc\x2b\xf9\xa1\x99\xdd\ -\xc9\x21\xb3\xf3\x11\x5e\x95\x45\x63\x88\xcd\xb1\xb5\xd2\x8d\x7a\ -\xb2\x92\x4e\xe9\x36\xda\xbf\x7d\x7d\x5f\xde\xcd\x30\xd9\x2e\x5f\ -\x87\x93\x95\x0a\x31\x8b\x6a\xcd\xa8\xa5\x74\xed\x75\xf8\x2f\xb9\ -\x1e\x01\xfb\x3a\x7f\xc1\x33\x7e\x13\xfe\xca\xba\xd6\xa5\x7b\xe0\ -\x9d\x2f\x58\xd3\x7f\xb6\xad\x5a\xca\xfe\xda\x4d\x6a\xee\x7b\x4b\ -\xd8\x98\x11\x89\x21\x79\x0a\x31\x00\xb0\x04\x82\x46\xe3\x8e\xb5\ -\xe9\x9f\x01\xfe\x01\xf8\x67\xf6\x6b\xf8\x57\xa5\xf8\x2f\xc1\xf6\ -\x1f\xd9\x9e\x1d\xd1\x84\x82\xd6\xdc\xc8\xd2\xb2\x97\x91\xa4\x72\ -\x5d\xc9\x66\x25\xdd\x8e\x49\xef\x5d\x9d\x15\x9e\x2b\x30\xc5\x62\ -\x5b\x78\x8a\x92\x95\xec\xdd\xdb\x77\x69\x34\x9b\xbf\x64\xda\x46\ -\xd8\x5c\xaf\x09\x85\x49\x61\xe9\x46\x36\xba\x56\x49\x59\x36\x9b\ -\x4b\xd5\xa4\xdf\xa1\xc1\xfc\x6f\xfd\x9a\xfc\x1f\xfb\x45\xc3\xe1\ -\xd8\xfc\x5d\xa5\xae\xa9\x1f\x85\x75\x98\x35\xdd\x38\x6f\x68\xfc\ -\x9b\xa8\x73\xb0\x92\xa4\x6e\x43\xb8\xe5\x0f\xca\xdc\x64\x1c\x0a\ -\xe3\x61\xff\x00\x82\x7f\x7c\x3f\xb7\xfd\xa3\x4f\xc5\x75\x6f\x15\ -\x1f\x1c\x19\x59\xfe\xda\xfe\x22\xbd\x75\xd8\xcc\x58\xdb\xf9\x66\ -\x5d\x9f\x67\xe7\x02\x1c\x6c\x03\x00\x01\x5e\xdd\x45\x14\xb3\x0c\ -\x4d\x38\x7b\x3a\x73\x6a\x36\x6a\xd7\x76\xb3\xdd\x7a\x3e\xa1\x5b\ -\x2d\xc2\x55\x9f\xb4\xab\x4e\x2e\x57\x4e\xed\x2b\xdd\x6c\xfd\x57\ -\x47\xd0\xe5\xfe\x2d\x7c\x24\xd2\xfe\x34\xfc\x3e\xd4\x7c\x33\xac\ -\xcd\xaa\xc7\xa5\xea\xb1\xf9\x37\x3f\xd9\xf7\xf3\x58\xcf\x24\x67\ -\xef\x27\x9b\x0b\x2b\x85\x61\x95\x60\x0e\x08\x24\x57\xcd\x63\xfe\ -\x08\x6f\xfb\x3b\xff\x00\x65\xfd\x87\xfe\x11\xbd\x7b\xec\x3e\x6f\ -\xda\x0d\xb8\xf1\x1d\xf0\x84\xcb\x8d\xbe\x66\xdf\x37\x1b\xb6\xf1\ -\x9f\x4c\x57\xd7\x94\x56\x98\x4c\xdb\x1b\x85\x8b\x86\x1a\xac\xa0\ -\x9e\xbe\xec\x9a\xd7\xe4\x67\x8c\xc9\xb0\x18\xb9\xaa\x98\xaa\x31\ -\x9b\x4a\xc9\xca\x29\xe9\xdb\x53\x84\xf0\xff\x00\xec\xeb\xe1\xdd\ -\x1b\xe0\xe5\xdf\x80\xee\xff\x00\xb5\xbc\x45\xe1\xbb\xe8\x26\xb5\ -\xb9\x87\x5d\xd4\xae\x35\x49\x67\x86\x50\x43\x46\xd2\xce\xed\x26\ -\xdc\x1c\x01\xbb\x0b\xfc\x38\xc0\xc7\x82\x4f\xff\x00\x04\x48\xfd\ -\x9f\xae\x7c\x3b\x0e\x8e\xfa\x07\x88\xdb\x48\xb7\xb8\x7b\xb8\x6c\ -\x4f\x89\xaf\xda\xda\x19\x9d\x42\xb4\x8b\x19\x94\xa8\x76\x55\x50\ -\x5b\x19\x21\x54\x13\xc0\xaf\xad\xa8\xa7\x86\xcd\xf1\xd8\x76\xe5\ -\x42\xb4\xa2\xe4\xee\xed\x26\xae\xfb\xe8\xf7\xd4\x9c\x46\x4b\x97\ -\xe2\x14\x63\x5e\x8c\x64\xa2\xac\xaf\x14\xec\xbb\x6b\xd0\xf9\xd3\ -\x57\xff\x00\x82\x5f\x7c\x35\xd7\xfc\x18\x3c\x37\x7d\xa9\xfc\x4e\ -\xbc\xf0\xe8\x88\x40\x34\xa9\xfc\x7b\xac\x49\x62\x23\x03\x01\x3c\ -\x96\xb8\x29\xb4\x0e\x31\x8e\x95\xae\xff\x00\xf0\x4f\xff\x00\x06\ -\x5b\x78\xe3\xe1\xce\xad\xa7\x5c\x6a\xba\x5d\xa7\xc3\x4b\x0b\x6d\ -\x3b\x4e\xd3\x61\x74\x6b\x79\xa2\xb6\x2c\xd0\x79\x8c\xca\x64\x25\ -\x59\x98\x92\x1c\x6e\xcf\x3d\xf3\xee\x94\x53\xfe\xd8\xc6\xb5\x67\ -\x56\x5d\x7a\xbe\xaa\xcf\xe6\xd3\xb5\xc3\xfb\x0f\x00\xb5\x54\x62\ -\xb6\xd9\x5b\x67\x75\xb7\x44\xd5\xed\xb0\x28\xda\xa0\x7a\x51\x45\ -\x15\xe6\x9e\xa0\x51\x45\x14\x00\x51\x45\x14\x00\x51\x45\x14\x00\ -\x11\x9a\x69\x5a\x75\x06\x95\x93\x02\x17\x05\x57\xf8\x6b\xe3\x1f\ -\xda\x0b\xe2\x26\xa9\xfb\x17\x7e\xd0\xda\xb4\x9e\x13\xfb\x3b\xe9\ -\xfe\x30\xb2\x1a\x9d\xc5\x8d\xd6\x5a\x08\x6e\x5e\x47\x56\x91\x02\ -\xed\x20\xe6\x3c\xf5\x23\xe7\x23\xa0\x18\xfb\x1f\x5a\xbf\x6d\x33\ -\x4a\xb8\xb8\x8e\x09\xae\x9e\xde\x36\x91\x61\x84\x03\x24\xa4\x0c\ -\xed\x50\x48\x19\x38\xe3\x9a\xf8\x3f\xc4\xbf\x05\x7e\x26\x7f\xc1\ -\x41\xfe\x36\xea\x3a\x9c\x8b\x7d\xf0\xdf\xc2\x7a\x4a\x1b\x24\xd4\ -\x75\x5d\x21\xc5\xf4\xcc\xa4\xb0\x86\x0b\x69\xb6\x65\x06\xfc\xb4\ -\xcd\x95\xdd\xb9\x57\x2c\x1b\x6f\xc3\x71\xb5\x1c\x55\x7a\x14\xa8\ -\xe5\xc9\xfd\x63\x9a\xf1\x92\xd3\x95\x5b\x56\xdf\x4b\xad\x3c\xcf\ -\x5b\x29\x95\x28\x4e\x53\xc4\x7c\x16\xd5\x77\xed\x63\xe4\x0f\xda\ -\xa7\xfe\x09\xc7\xe2\x2f\xf8\x2b\xb7\x8d\x75\x0b\xad\x14\xd9\xda\ -\xfc\x40\xd0\xac\x45\xd0\xd6\xaf\xa6\x68\x2c\x23\x89\xde\x43\x15\ -\xac\xcc\xa8\xec\xc1\xe4\x59\x0a\x04\x52\x50\x86\x62\x42\x9c\x3f\ -\xe5\xdf\xed\x59\xfb\x20\x7c\x54\xfd\x80\x3e\x21\x5b\x78\x67\xe2\ -\xaf\x85\x6e\x3c\x37\xa8\xdf\x43\xf6\xab\x39\x16\x78\xae\xed\x6f\ -\x61\xdc\xcb\xbe\x39\xe1\x66\x8c\xf2\xa7\x2a\x58\x3a\xf1\xb9\x57\ -\x23\x3f\xd1\x5f\x81\x3f\x67\xff\x00\x89\x1f\xf0\x4f\x9f\x13\x49\ -\xaf\x69\xfa\xb0\xf8\x91\xe0\xcd\x4b\xca\x8b\x5d\x48\xf4\xf5\xb3\ -\xd4\x6c\xa3\x52\xc7\xce\x11\xa9\x64\x78\xe3\x0c\xc7\x2a\x55\x86\ -\xfe\x43\x2e\x59\x25\xff\x00\x82\x80\xf8\x8b\xe0\x8f\xed\xa9\xfb\ -\x21\x5e\x69\x7a\xf4\x3e\x1f\xf1\x94\x32\xcc\x92\xe9\xf6\xb3\x39\ -\x5b\xab\x1b\x9d\xac\xbe\x6c\x65\x58\x49\x1b\x05\x2e\xbb\xd1\xb8\ -\xdc\x46\x7d\x3a\xf8\x3f\x89\x2b\x70\xe6\x5c\xf0\xf9\xac\xdf\x3c\ -\x2f\x26\xa4\xd6\xab\x7f\xdd\xbd\x2f\xe9\xdf\xb1\x9e\x69\x81\x86\ -\x3a\xbf\x3e\x1d\x2e\x57\xa2\xb7\xfe\xdc\xbf\x53\xf9\x9d\xd0\xbc\ -\x7f\xf6\x3b\x98\xe4\x8e\x4d\xb2\x46\x43\xa3\x63\xa1\x04\x10\x47\ -\xe2\x2b\xd1\x35\xff\x00\x8d\x3a\xc7\xc6\xf8\x77\x5d\x5b\xd8\xee\ -\xf0\xfd\xa4\xd7\x72\x49\x0a\x34\x6c\x53\x28\x18\xb6\x58\xee\x39\ -\xdb\x80\x00\xfb\xc7\xb6\x71\xf7\x1f\x85\xbf\xe0\x89\x96\x3f\x1a\ -\x7c\x61\xac\x69\x9f\x0a\xb4\x1b\x73\x26\x9b\xa5\x9d\x4a\xee\x3d\ -\x5e\x43\x2d\xb1\x66\x93\xcb\x8e\x04\xb8\x72\xc5\x25\x93\x0e\x54\ -\x1e\x00\x89\xc9\x23\x39\xae\x13\xc5\x9f\xf0\x4a\x5f\x8b\x1f\xb3\ -\x96\x9d\xaa\xad\xe7\xc1\xff\x00\x10\xda\x69\xf7\x70\x18\xef\xae\ -\x6c\x23\x37\xd0\x34\x38\x65\x39\x78\x9d\xf6\x2e\x18\xf7\x03\xa7\ -\xa5\x7e\xbd\x91\x71\xe6\x07\x32\xc1\xc3\x1b\x42\x76\x8c\x93\x7e\ -\xf7\xbb\xa2\xef\x7d\x3f\x1f\x99\xf3\x38\xce\x1f\x95\x2a\x8e\x8c\ -\xf7\xf2\x3e\x28\x7f\x19\x21\x51\xd7\x9e\xfb\x4f\x1f\x5a\xa5\x75\ -\xe3\x78\xb0\xca\x1d\x77\x2f\x6e\xe7\xf0\xaf\xa7\xbc\x11\xfb\x08\ -\x6a\x5e\x20\xf1\x86\x9f\xa6\xe9\x1f\x0c\x75\xeb\xfd\x62\xf8\xba\ -\x5a\x59\x35\xbc\xf3\x34\xe5\x51\x99\xc0\x59\x09\x0d\x84\x0c\xc7\ -\xd0\x02\x78\xc5\x7d\x21\xf0\xbf\xfe\x0d\xff\x00\xf8\xad\xf1\x73\ -\x46\xb9\x5d\x6b\xc0\xba\x2f\x83\x74\xbb\x78\x5e\x70\x35\x06\x8f\ -\xed\x53\xb0\x52\x42\x47\x1c\x27\x76\xe6\x2a\x06\x4b\x28\x19\xaf\ -\x56\x5c\x5d\x83\x74\x9d\x58\x55\x8c\xa2\xba\xc5\xa9\x6d\xbd\xad\ -\x73\x95\x64\x3c\xb2\xe5\x92\xb7\xa9\xf9\x67\xaa\x78\xe0\x4c\x98\ -\x19\xdc\xc4\x00\xb8\xe5\xb3\xc0\xc7\xaf\x5f\xc7\xb6\x6b\xef\xbf\ -\xd8\xf7\xfe\x0d\xcd\xf8\xef\xf1\xbe\xc8\x78\xb3\xe2\x17\x85\xdb\ -\xc2\xbe\x13\xb7\x85\x2e\xa1\xd1\xae\x35\x38\x6d\xf5\xad\x78\x38\ -\x24\x2c\x69\x96\x58\x02\xf1\xbc\x5c\x98\x9c\xa9\xc2\x8c\x9d\xcb\ -\xf4\xa7\xfc\x13\xcb\xfe\x09\xff\x00\xf0\x5f\xf6\x64\xfd\xa8\x3c\ -\x13\xe2\x6d\x4f\x49\x8f\x52\x7d\x36\xf2\x56\x96\xfb\x5a\x7f\xb5\ -\x45\x09\x78\x26\x48\xdc\x44\xc7\xcb\x5d\x92\x3c\x64\x39\x52\xc3\ -\x19\xc8\xc5\x7e\x99\xfc\x73\xfd\xa9\xef\xbc\x52\xb3\x78\x3f\xe0\ -\xcc\x76\x9e\x33\xf1\xcd\xd6\xd5\x96\xe2\xd6\xe0\x36\x9f\xe1\xf8\ -\xcf\x22\x5b\xcb\x85\x0c\xb1\x6f\x45\x7d\x80\x8d\xd2\x15\x21\x03\ -\x15\x38\xfc\xaa\xb7\x89\x78\x5c\xef\x0b\x55\x60\x27\x28\xda\xf1\ -\xd9\x2a\x8d\xb4\xac\xe2\xae\xf4\xd7\x46\xf6\xeb\x63\xe8\xa1\xc3\ -\xf3\xc1\x54\x8b\xa8\x97\x47\xe5\xf3\x3e\x44\xf8\x07\xfb\x47\xf8\ -\x83\xf6\x6d\x8f\x50\xb7\xd0\x63\xb3\x36\xb7\xd1\x04\x36\xd7\x08\ -\x7c\xa8\x9d\x46\x16\x45\x55\x20\x2b\x05\xe3\x1d\x31\xc6\x3b\xd7\ -\xda\x1f\xf0\x4f\xef\x85\x96\xbf\x0f\xbf\x66\xdd\x0f\x52\xfb\x44\ -\x97\xda\xd7\x8e\x23\x4f\x12\xeb\x37\x8e\x41\x6b\x8b\xbb\x98\xd5\ -\xd9\x41\xfe\xe4\x6b\xb6\x35\x07\x24\x2a\x0c\x9c\xe6\xbe\x7a\x3f\ -\xf0\x48\xef\x19\xc3\xe1\xa3\x76\x3e\x2c\x5a\xdf\x78\x80\x0d\xcd\ -\x69\x2e\x84\x91\x69\x8c\xdf\xc4\xbb\x95\x8c\xe0\x7a\x36\x49\xe3\ -\xee\xf3\xc7\xa1\x7f\xc1\x38\xbc\x73\xe3\xed\x13\x54\xd4\xbe\x1c\ -\x78\xa7\xc1\xbe\x28\xd2\x74\xef\x0e\xda\xb4\xf6\xf7\xf7\xd6\x2d\ -\x15\x9d\xab\xf9\x8a\xbf\x63\x8e\x62\x36\xcf\x9d\xcd\x22\xb2\x33\ -\x00\xaa\x41\x38\x2b\x9f\xcc\xb8\x33\x2f\xcd\xb2\xac\x64\x70\xd9\ -\xa4\x5c\xa1\x34\xd4\x1a\x7c\xca\x2e\xf7\x95\xfb\x5f\x4d\x4f\xa2\ -\xcd\x6b\x61\x71\x34\x5d\x4c\x35\x93\x56\xba\xda\xeb\xa5\xbd\x0f\ -\xac\x82\x1f\x5a\x13\x81\x4e\xa3\x18\xaf\xd7\xac\x7c\xc8\x51\x45\ -\x14\x00\x51\x45\x14\x00\x51\x45\x14\x00\x51\x45\x14\x00\x51\x45\ -\x14\x01\xf2\x8f\xed\x63\xff\x00\x04\x89\xf0\x57\xed\x93\xf1\x27\ -\x54\xf1\x17\x8b\x3c\x79\xf1\x5a\x18\xf5\x46\x89\xff\x00\xb1\xec\ -\x75\x9b\x75\xd2\xac\xda\x38\x52\x20\x61\x82\x5b\x79\x02\x16\x11\ -\x86\x63\x93\x97\x24\xf1\x9c\x57\x94\xa7\xfc\x1b\x7d\xf0\x42\x39\ -\x7c\xc5\xf1\x67\xc5\x61\x22\x9c\x86\xfe\xd2\xb0\xc8\x3d\xbf\xe5\ -\xcb\xb7\xb5\x7e\x82\x51\x5e\xf6\x1f\x8a\x33\x5c\x3d\x35\x46\x8d\ -\x79\x46\x29\x59\x25\x6b\x5b\xee\x3e\x6f\x13\xc2\x39\x3e\x22\xab\ -\xaf\x5f\x0f\x19\x49\xbb\xb6\xef\x7b\xbf\x99\xf1\x11\xff\x00\x82\ -\x11\xfc\x3b\xb9\x8d\x61\xbc\xf8\x9b\xf1\xcb\x52\xb3\x03\x0d\x69\ -\x75\xe2\x48\x1a\x09\x07\x60\x42\xdb\x03\x8f\x60\x45\x7a\xef\xec\ -\xe9\xff\x00\x04\xbe\xf8\x1f\xfb\x2e\x6a\xb0\xea\x7e\x17\xf0\x36\ -\x9e\xda\xe4\x18\x31\xea\x9a\x9c\x8f\xa8\x5d\xc4\xc3\xa3\xc6\xd3\ -\x16\x11\x37\x6c\xc4\x13\x8a\xfa\x02\x8a\xc7\x11\xc4\x19\x95\x78\ -\x3a\x55\x6b\xc9\xc5\xee\xaf\x64\xfd\x52\xb5\xce\x8c\x2f\x0c\xe5\ -\x58\x7a\x8a\xad\x1a\x11\x52\x5b\x3b\x5d\xaf\x46\xef\x62\x3f\xb3\ -\xf3\xd7\xeb\xc7\x5a\x91\x46\xd5\x03\xae\x3b\x9e\xf4\x51\x5e\x39\ -\xee\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\ -\x40\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\x40\x05\x14\x51\ -\x40\x05\x14\x51\x40\x05\x14\x66\x9a\xcf\xb4\xd0\x03\xa8\xa6\xf9\ -\x9c\xd1\xbf\x14\x00\xea\x42\x3e\x5a\x03\x66\x97\x3c\xd0\x01\xb7\ -\xda\x93\x68\x1d\x85\x26\xfa\x1a\x4c\x11\xef\x40\x01\x5e\x1b\x8a\ -\xfc\xf8\xff\x00\x82\x88\x7c\x38\xd1\x7e\x1b\x7c\x64\xd1\xd7\x40\ -\xd2\x6c\xf4\xd6\xf1\x05\xb5\xba\x2d\x8d\x8d\xb8\x5f\xb6\x5e\xcb\ -\x71\x24\x68\xa9\x1a\x0c\x19\x24\x3b\x14\x05\x03\x71\xe7\xa9\xcd\ -\x7e\x83\x09\x37\x2f\xe1\x5e\x51\xe3\x1f\xd9\x52\xc7\xe2\x07\xed\ -\x39\xa0\xfc\x44\xd6\x35\x29\x35\x0b\x7f\x0d\x69\xc6\x1d\x3b\x46\ -\x9a\xdd\x7c\x9b\x4b\xf0\xe4\xa5\xf2\xc8\x08\x25\x96\x37\x95\x42\ -\x38\x60\x0b\x86\x18\x28\xb8\xf9\x5e\x2d\xc8\x23\x9c\x60\xd6\x13\ -\xfb\xd1\x77\xea\x95\xf5\x6b\xf2\x3d\x0c\xb7\x1a\xf0\xd5\x7d\xaa\ -\xec\xfe\xff\x00\x33\xe5\x9f\xd9\xc7\xe1\x3f\xed\x39\xf0\x63\x52\ -\xbe\xbe\xd0\x7c\x15\xe1\xed\x3f\x4d\xbd\x91\x7e\xd3\xa7\xea\xfa\ -\xf5\xb9\xb8\xba\xd9\xf7\x59\x44\x3e\x6a\x27\x0c\xc0\x0f\x30\x1e\ -\x79\xe8\x31\xd9\x7e\xd2\xdf\xb5\x47\xc4\x8d\x03\xe1\x5c\xfa\x4f\ -\x8c\x7e\x1c\x3f\x84\xff\x00\xe1\x24\xdf\xa5\xc7\x74\x6e\xa1\xbe\ -\xb7\x91\x99\x5b\x2a\xad\x0c\x8e\x15\x88\x04\xa8\x93\x6b\x1c\x1c\ -\x02\x41\xc7\xd9\x51\x46\xc8\x9b\x4e\x2b\x9f\xf8\x9d\xf0\xe7\x4f\ -\xf8\xa3\xe0\x5d\x5b\x41\xd4\xa1\x8e\x6b\x5d\x52\xdd\xe1\x3b\x97\ -\x3e\x5b\x11\xf2\xba\xf7\x0c\xac\x15\x81\x1c\x82\xa0\x8e\x95\xc9\ -\x5b\x84\xd5\x1c\xb2\x78\x1c\xbe\xb4\xe2\xb9\x5a\x49\xbb\xaf\xba\ -\xdd\x7c\xac\x69\x1c\xc9\xcf\x12\xab\x56\x8a\x7a\xfa\x1f\x99\x3f\ -\x01\xfc\x76\xdf\x0c\x7e\x3c\x78\x4f\xc4\x16\xfa\x6c\xda\xc6\xa9\ -\x6b\x74\xf6\xb6\x16\x70\x21\x92\x5b\xa9\x6e\x63\x6b\x7d\x8a\x07\ -\x72\x1b\x25\x89\x01\x42\x96\x62\x14\x13\x5f\x5b\x78\xf3\xe2\x97\ -\xed\x35\xe2\xfb\x09\x2d\xfc\x2b\xf0\xab\x47\xf0\xd3\x64\xaf\xda\ -\x75\x9f\x11\xd9\x99\x48\xe3\x95\x58\x4c\xe3\xd4\x7c\xc4\x1e\x6b\ -\xcb\x3f\xe0\x9b\x1f\x08\xf4\xdf\x14\x7e\xd1\xde\x2a\xd5\xb5\x7d\ -\x2f\x51\x6d\x53\xe1\x9c\x30\xdb\xe9\x77\x37\x36\xb3\xda\xc0\x67\ -\xba\xfb\x4c\x33\xc9\x18\x75\x55\x90\xac\x70\xed\x04\x06\x0a\xb3\ -\x9e\x85\xab\xef\x25\x5f\x2c\x1e\xf5\xe0\xf8\x7f\xc3\xb8\x8a\x59\ -\x47\x2e\x26\xa4\xe3\xce\xdb\xe5\x4e\xd6\xe8\xfa\x5d\x37\x6b\xe8\ -\x76\x67\x78\xe8\x4b\x13\x7a\x71\x4e\xc9\x6b\xbd\xfa\x9f\x95\x1f\ -\x11\xbe\x0a\xfc\x44\xf8\x48\x2d\xee\x7c\x75\xe1\x89\x34\x73\x7b\ -\x2b\x24\x37\x56\xb7\x71\xde\xda\xdc\xba\x8d\xc4\x6f\x8c\x92\x8d\ -\x8e\x82\x55\x4c\xf3\x8c\xe0\x8a\xfd\x01\xfd\x8c\x7e\x0d\x78\x77\ -\xe0\xf7\xc0\x0f\x0d\xc3\xa1\xd8\x5a\xc5\x3e\xad\xa6\xda\xdf\xea\ -\x77\xa0\x6e\xb8\xd5\x2e\x5e\x15\x67\x9a\x69\x0e\x59\xc9\x24\xe3\ -\x27\x0a\xb8\x55\xc2\x80\x07\x53\xf1\xc3\xe1\x25\xaf\xc6\xff\x00\ -\x85\x9a\xc7\x86\x2f\x24\xfb\x3a\xea\x50\xe2\x1b\x95\x5d\xcd\x69\ -\x3a\x90\xd1\x4c\x06\x46\xe2\x92\x05\x6d\xa4\xe1\x80\xc1\xe0\x9c\ -\xcd\xf0\x63\xe1\x94\x7f\x06\xbe\x18\xe8\xbe\x17\x87\x54\xd4\xb5\ -\x8b\x7d\x16\xd5\x2d\x22\xba\xbf\xf2\xcd\xc4\x88\xbd\x37\x18\xd1\ -\x17\x00\x60\x0c\x28\xc0\x03\x93\xd6\xbd\x9e\x1d\xe0\xfa\x59\x3e\ -\x61\x5a\xbe\x1f\x5a\x73\x8a\xb5\xdd\xe4\x9d\xdd\xd6\xdb\x3d\x3e\ -\x67\x2e\x3b\x34\x96\x2a\x84\x21\x53\xe2\x4f\xa6\xcd\x1d\x54\x6b\ -\xc7\x4a\x15\x02\x85\xf9\x47\xcb\xd3\x8e\x94\xaa\x72\xb4\x6e\xfa\ -\xd7\xdd\x1e\x48\xb4\x53\x7c\xc0\x28\x12\xa9\xe9\xcf\xd2\x8b\x80\ -\xea\x29\xa1\xf2\x29\x77\xd0\x02\xd1\x48\x5b\x14\xa0\xe6\x80\x0a\ -\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\ -\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\ -\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\ -\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x1a\xe7\x0a\xdc\x81\ -\x5f\x19\xfe\xd1\x5f\xb7\x5f\x8a\x7f\x61\xbf\xdb\x0a\xd5\xbe\x26\ -\x6a\x56\x17\x5f\x02\x3c\x4f\x0d\xbe\x9f\x67\xa9\xda\xe9\xeb\x0d\ -\xd7\x87\x75\x6b\xa9\xa6\x68\x16\xe9\x8c\x9f\x35\xa0\x82\xd2\xe4\ -\x99\x55\x77\x06\x23\x2b\xc6\x4f\xd9\x92\x0c\xa1\xfa\x71\x5e\x5b\ -\xa7\xfc\x3d\xf1\x36\xbf\xf1\xab\xc6\xcd\xe2\x6d\x1f\xc2\x77\x5e\ -\x01\xf1\x0e\x8d\x6b\xa5\xdb\x46\xba\x84\xb7\x37\x77\x02\x36\xb8\ -\xf3\x05\xc5\xbb\xdb\xac\x7b\x24\x5b\x8c\x60\x4a\xd8\xd9\x82\x0e\ -\xec\xaf\x66\x06\x74\xa3\x29\x3a\xd1\xba\xb6\xdd\x7a\x6a\xbb\x34\ -\x79\xf9\x84\x2b\x4a\x31\x54\x5f\x2b\xbe\xfb\xaf\x9a\xec\x71\xde\ -\x05\xfd\xa5\x97\xc1\x1e\x25\xf8\xb5\xaa\xfc\x46\xf8\x81\xe1\x7b\ -\x0f\x05\xf8\x6f\xc4\xd6\xda\x3e\x87\x73\x71\x1c\x5a\x7c\x69\x14\ -\xda\x4d\x96\xa2\x0b\x4c\xcf\x89\x64\x3f\x6d\x64\x00\x01\x94\x80\ -\x36\x09\x2c\x6b\xa9\xba\xfd\xb8\x3e\x13\xda\xf8\x83\xc2\x3a\x7b\ -\x7c\x40\xf0\xa3\x49\xe3\xcb\x39\x6f\xb4\x19\x46\xa3\x11\x87\x51\ -\x8e\x39\x63\x84\xec\x93\x76\xdc\x99\x24\x54\x51\x9c\xb3\x07\x00\ -\x1d\x8d\x8f\x96\xb4\x0f\xf8\x25\x0f\x8d\xbe\x02\x78\x13\x50\xf0\ -\x4f\xc3\x1d\x6b\x41\x8f\xe1\xee\xa1\xf1\x0f\x50\xf1\x2c\xda\x3d\ -\xee\xb9\x7d\xa7\x4b\x75\xa5\xdc\xe9\x16\xd6\xd1\xda\xc9\x71\x6f\ -\x0b\xc9\xfb\x9b\xc8\xe5\x6f\x28\x1d\xb2\xc6\x90\x96\x90\x36\xe5\ -\xad\x3f\xd8\xa3\xf6\x07\xf8\xd5\xfb\x22\x78\x53\xe0\x7e\x9c\x5b\ -\xe1\x8e\xb0\xdf\x0d\x34\xdf\x14\x68\x5a\xa3\x2e\xb7\x7d\x10\xba\ -\xb5\xd5\xb5\x2b\x2b\xf8\xe6\x87\xfd\x08\xe6\x54\x36\xce\x8d\x1b\ -\xed\x1c\x82\x1c\xee\x3b\x7d\x2a\x98\x5c\x0b\x87\x3c\x6a\xa6\xf5\ -\xd3\x6d\x14\x74\x76\xb3\xd5\xb4\xbe\xf3\xcd\xa3\x8a\xc7\xa9\x7b\ -\x39\x52\x76\xd3\x5d\xf7\x96\xbd\x56\xc9\xbf\xb8\xfa\x3b\xc0\xbf\ -\xb4\xfe\x99\x65\xe0\xef\x1a\x78\x87\xc6\x9e\x2a\xf8\x7b\x63\xa2\ -\xf8\x6b\xc4\x93\xe8\xe9\x7f\xa5\xea\xcd\x3d\xac\x11\x0f\x2b\xc9\ -\x8e\xe5\xe4\x55\x09\x78\x4c\xaa\x1e\x24\x2c\x14\xb2\xa8\x62\xd9\ -\x03\x76\xe3\xf6\xae\xf8\x6b\x67\xe0\xfd\x17\xc4\x13\x7c\x40\xf0\ -\x74\x3a\x1f\x88\x8c\x83\x4b\xbf\x7d\x5e\x05\x83\x51\x31\xe7\xcd\ -\x11\x31\x6c\x36\xcd\xad\xbb\x1f\x73\x69\xdd\x8c\x57\xc9\xde\x09\ -\xff\x00\x82\x70\x7c\x50\xf0\xb7\xc6\xdd\x0f\xe2\x43\x5c\x78\x11\ -\x7c\x41\xe1\x4f\x89\x3e\x21\xf1\x75\x86\x9e\x9a\xb5\xdb\x5a\xdf\ -\x69\xda\xd5\xb2\x5a\xdc\x41\x2c\xa6\xd0\x34\x77\x11\x24\x68\xc8\ -\xc1\x24\x57\x39\x04\xaf\x5a\xb5\xe1\x5f\xf8\x26\xff\x00\xc4\x3f\ -\x0d\xfc\x5f\xf0\x5f\x8d\xda\xe3\xc1\xb2\x6a\x4b\xf1\x47\x5b\xf8\ -\x85\xe2\x5b\x4f\xed\x6b\x9f\x22\xde\x2b\xbb\x67\xb4\xb6\xb7\xb3\ -\x6f\xb2\xe6\x56\x58\x99\x1d\xda\x45\x8b\xe7\x0c\x06\x41\x0c\xb3\ -\x53\x07\x81\x72\xbf\xb5\xfb\xad\xbe\xba\x7c\xf4\xd7\xbb\xb5\x82\ -\x9e\x33\x1e\xa1\x67\x4b\xef\xf3\xeb\xbf\x4d\x74\xec\xaf\x73\xea\ -\x29\x7f\x6b\x3f\x86\xb0\xfc\x1e\x8f\xe2\x14\x9e\x3c\xf0\xa2\xf8\ -\x1e\x49\x1e\x24\xd7\x4e\xa1\x18\xb1\x77\x59\x1a\x26\x55\x97\x3b\ -\x49\x0e\x8e\xa4\x03\xc1\x53\xd8\x1c\x79\x4f\x8a\xff\x00\x68\xad\ -\x6b\x57\xff\x00\x82\x82\x7c\x1b\xd0\xfc\x3b\xe2\xab\x1d\x47\xe1\ -\xc7\x8d\xbc\x25\xab\xea\xef\x05\x94\x71\x4d\x1d\xec\xd6\xfe\x5f\ -\x95\x30\xb8\x5c\xb3\x46\xcb\x38\x21\x54\x85\xcc\x60\xe5\xbb\x78\ -\x77\x8a\xbf\xe0\x9c\xff\x00\xb4\x16\xb9\xe1\x8d\x6b\xc3\xf6\xba\ -\xf7\xc3\xdd\x3f\xc3\x3e\x27\xf1\x87\x8a\xfc\x43\xad\x69\x90\xeb\ -\xd7\xf1\x8d\x4e\x1d\x52\x1c\x58\x87\x95\x2c\xd6\x4c\xda\xcf\xfb\ -\xc7\x8d\x48\x49\xb0\x03\x1e\x39\xd8\xfd\x83\xff\x00\xe0\x9d\x7f\ -\x16\xff\x00\x66\xff\x00\x15\x7c\x0b\xff\x00\x84\xa1\xfe\x1c\x7f\ -\x64\xfc\x24\xd0\x35\xcd\x0a\xee\x6d\x23\x58\xbc\x9e\xe2\xf8\x5f\ -\x4a\x93\x47\x2c\x71\x49\x67\x1a\x82\x1d\x70\xc1\x9f\xa1\xc8\xe7\ -\x83\x6b\x0b\x82\xa7\x4e\x53\x8d\x44\xdd\xa4\x92\x7e\x8e\xdd\x37\ -\xbd\x89\xfa\xde\x3a\xa5\x48\xc2\x74\xdc\x55\xe2\xdb\xf9\xab\xf5\ -\xda\xd7\xd0\xee\xbf\x6d\xdf\xdb\x5f\x5a\xf8\x59\xfb\x56\xf8\x1b\ -\xe1\x0e\x9f\xe2\x4d\x37\xe1\xb4\x9e\x36\xd1\x2e\x35\x1d\x2b\xc5\ -\x1a\xb6\x9b\xf6\xdb\x3d\x4b\x55\x13\x2c\x16\xda\x59\x04\x85\x44\ -\x62\xdb\xe4\x7c\x86\xc1\x85\x14\xa9\x93\x23\xdc\xe0\xf8\xdf\x63\ -\xf0\x87\xc1\x1e\x0d\xb7\xf8\xab\xe2\xaf\x07\x68\x7e\x2e\xd6\x60\ -\xb7\xb3\xb8\x10\xdd\xf9\x36\xb7\xb7\xec\xa8\xb2\x7d\x9b\xcd\xc3\ -\x98\xcc\x84\x85\x2c\x3a\x32\xe7\x04\xe2\xb8\x2f\xda\xef\xe0\xa7\ -\xc5\x3f\x8e\x3a\x3f\xc4\x4f\x08\x68\xad\xe0\x7b\x9f\x01\x78\xeb\ -\xc0\x72\xe8\x36\xeb\xaa\xde\xdc\x5b\xde\x69\x1a\xb4\x86\xea\x36\ -\xba\x0b\x1d\xbc\x8b\x24\x3e\x54\xd0\x9c\x16\x56\x0f\x6e\xb8\xc6\ -\xe2\xc3\xc8\x7e\x09\xff\x00\xc1\x39\xfe\x26\x7e\xc8\x5f\x1b\xbc\ -\x0b\xac\xfc\x3b\xd6\xbc\x17\xad\x68\x3a\x67\xc3\x5b\x3f\x87\xfa\ -\xe7\xfc\x24\x37\x17\x56\xf7\x22\x68\x6f\xa5\xba\x3a\x8c\x11\xc3\ -\x13\xac\xd8\xf3\x9c\x2c\x0f\x24\x59\xe8\x64\x19\xdc\x32\x8c\x30\ -\x95\x28\x45\x4a\x4a\x32\x57\xd3\xf9\xbe\x7f\x67\xb5\x9a\x7b\x68\ -\x6c\xea\x63\x21\x88\x94\x94\x5c\xa2\xed\xaf\x6f\x45\xf6\xbb\xdf\ -\x4d\xf5\x3e\x8b\xf0\x47\xed\x08\xa9\x2f\xc4\x8b\xff\x00\x16\x78\ -\x8b\xe1\xe5\xb7\x87\xfc\x1f\xac\xfd\x96\xde\xeb\x4b\xd6\x0d\xc3\ -\x59\x5b\x79\x31\x1d\x97\xfb\x95\x44\x37\x5e\x63\x31\xf2\xd4\x9f\ -\x95\xe3\x03\x27\x96\xb9\xac\x7e\xd8\xdf\x0a\xf4\x0f\x06\xe9\x3e\ -\x22\xbe\xf8\x8d\xe0\xbb\x7d\x07\x5e\x8e\x79\xb4\xeb\xf9\x35\x78\ -\x16\xde\xf1\x20\x52\xd3\x32\x39\x6c\x11\x18\x18\x63\x9f\x94\x90\ -\x0e\x09\x02\xbe\x45\xf8\x97\xff\x00\x04\xca\xf8\xb1\xe3\xc9\x3c\ -\x59\xaa\x45\x37\xc3\x54\xd5\x66\xf8\xcd\x61\xf1\x5f\x46\xb1\xbc\ -\xd4\x6e\xae\x6c\x6f\x23\x82\xcc\x5a\x3d\x85\xdf\xfa\x20\x31\x6e\ -\x8f\x2d\xbe\x35\x93\x93\x8c\x0c\x06\xae\xd3\xe2\x87\xec\x61\xf1\ -\x83\xe2\x97\x8a\x7c\x17\xaf\x49\x63\xf0\x87\x44\x9b\x41\xd1\xfc\ -\x57\xa6\xdc\xe9\x3a\x45\xed\xe5\xbd\xa4\x07\x54\xb0\x82\xda\xdc\ -\xa4\xbf\x65\xcc\xc4\x49\x03\x3c\x8e\xd1\xc4\x55\x64\x01\x43\x6d\ -\xcb\x12\xc2\xe0\x9c\x93\x75\x17\xca\xcb\x68\xed\xf3\x7a\x5c\x98\ -\xe3\x31\xaa\x2d\x7b\x27\x7e\x97\xbb\xbd\xe5\xfa\x2d\x6c\x7d\x35\ -\xad\xfe\xd1\xbe\x03\xf0\xbf\xc3\x0b\x7f\x1b\x5f\xf8\xc3\xc3\x76\ -\x9e\x12\xbb\x44\x78\x75\x89\x75\x18\x96\xca\x55\x6f\xba\x56\x5d\ -\xdb\x48\x3d\x72\x0f\x40\x4f\x18\x38\xb1\x7b\xf1\xdf\xc1\xba\x66\ -\xb9\xe1\xdd\x2e\x7f\x15\x68\x50\xdf\x78\xc2\x3f\x3b\x43\x88\xde\ -\x46\x5b\x55\x4d\xa1\x83\x43\xcf\xce\xa4\x11\x82\x32\x0e\x46\x33\ -\x9a\xf8\x43\xf6\x7d\xff\x00\x82\x5f\xfc\x74\xfd\x9c\xfc\x05\xfb\ -\x39\x4d\xa5\xdf\x7c\x2d\xbf\xf1\x67\xc0\x7b\xaf\x11\xc3\x35\xa5\ -\xce\xaf\x7c\xba\x76\xb7\x69\xab\xed\xcb\x79\xc2\xcf\xcc\x8e\x48\ -\xb1\x90\xbe\x59\x56\x20\x12\xc3\x90\x7d\x47\xc3\x7f\xb0\xa7\xc5\ -\x0f\x87\x1f\xb6\x6f\x8b\x3e\x24\x69\x32\xfc\x27\xd7\xac\xfe\x28\ -\xda\xe8\xf2\x78\x92\x5d\x6a\xd6\xe8\xdd\x68\x37\xb6\x31\xb4\x6f\ -\x26\x9d\x16\xc7\x12\x47\x22\xbb\x61\x64\x9a\x36\x52\xa8\x49\x60\ -\xbb\x4a\x96\x0b\x05\x17\x2e\x5a\xb7\xb5\xed\xe7\x67\xa2\xf2\xd3\ -\x5f\x3d\xbc\xcd\x21\x8c\xc6\xb5\x17\x2a\x56\xda\xfe\x57\x57\xbf\ -\xdf\xee\xdb\xa5\xaf\xe4\x75\x9f\xf0\x52\x7f\xda\x07\xc7\xdf\xb3\ -\xf3\xfc\x23\x93\xc1\x3e\x20\xd0\x74\x2b\x7f\x19\xf8\xda\xd7\xc2\ -\x9a\xb4\x9a\xa6\x99\xf6\xc5\x8e\x2b\xa5\x25\x6e\x10\x99\x63\x0a\ -\xd1\x79\x4f\xc1\x38\x6d\xfd\xb6\xd6\x87\xc1\xbf\xda\x66\x6f\x86\ -\xfa\x4f\x8d\x35\x7f\x8a\xdf\x17\x3e\x19\xea\xde\x17\xb5\xd6\xc6\ -\x91\xa1\x6a\xf6\xb1\x7f\x64\x1f\x36\x24\x22\xea\x09\x92\x47\x74\ -\x69\x12\x40\x48\x31\xbb\x0d\x81\x98\xe0\x29\xc3\xbf\xe0\xa0\x5f\ -\xb3\x47\x8f\xbf\x68\xbb\xcf\x84\x8d\xe0\x8f\xf8\x44\x76\x78\x0f\ -\xc6\xf6\x5e\x2d\xd4\x3f\xb6\xf5\x09\xed\x3c\xf8\xed\x43\x6d\x82\ -\x1f\x2a\xde\x6f\x99\xf7\x9c\xb1\xda\x17\x68\xe1\xb2\x71\x0f\xed\ -\x3f\xfb\x25\x78\xb3\xc6\x7f\xb5\x6f\xc2\x5f\x8a\x5e\x05\x4f\x09\ -\x99\xfc\x05\x6f\xe2\x0b\x6d\x53\x4e\xd5\x6e\xa5\xb1\x1a\x80\xd4\ -\x6d\x23\x8a\x37\x49\x61\x82\x63\xb9\x24\x8c\x16\xdc\xbc\xab\x1c\ -\x1c\x8c\x17\x47\xea\x92\xc3\xd3\xa5\x51\xa8\xb6\xa5\x7d\xaf\x74\ -\xef\x14\xdd\xb4\xbe\xd7\x33\xad\xf5\xb8\xe2\x6a\x55\x82\x72\x4b\ -\x96\xdd\xac\xd5\xa4\xd2\xeb\x6d\xec\x7b\x2f\x8b\xfe\x3f\x78\x1f\ -\xe1\xe5\xed\x85\xae\xbb\xe3\x0f\x0c\xe8\xb3\x6a\x70\x49\x77\x67\ -\x1d\xee\xa5\x0c\x2d\x73\x04\x71\xbc\xb2\x4c\xa1\x98\x13\x1a\xa2\ -\x33\x17\xfb\xa0\x29\xc9\xac\x4f\x12\xfe\xd8\xdf\x0b\x7c\x1d\xe0\ -\x7d\x0f\xc4\xda\xaf\xc4\x1f\x09\xd8\x78\x7f\xc4\xe1\xdb\x49\xd4\ -\x26\xd4\x63\x5b\x7d\x41\x63\x8d\xa4\x76\x89\xc9\xc3\x2a\xa2\x33\ -\x16\x1c\x00\x39\x3c\x8a\xf9\x8f\xc2\x9f\xf0\x4c\x1f\x1b\x7c\x07\ -\xf8\x33\xf0\x0b\x41\xf0\x46\xb1\xe1\x7d\x73\x55\xf8\x48\x9a\xd2\ -\x6a\x4f\xae\x5c\xdc\x59\x5b\xdf\xb6\xa7\x61\x3c\x32\x49\x11\x8a\ -\x29\x58\x04\x9a\x60\x55\x18\x0c\xa0\x3f\x30\x35\x17\xc3\xdf\xd8\ -\x0b\xe3\x07\x83\xbe\x10\xfe\xcd\x1e\x1d\x99\x7e\x1b\xc9\x71\xf0\ -\x3a\xfe\x4b\x8d\x46\x58\xb5\xfb\xd0\x97\xf1\xfd\x92\x6b\x64\xf2\ -\x73\x63\x9d\xc7\xce\x2c\x43\x01\x8d\xb8\x07\x9c\x82\x38\x3c\x0b\ -\xd7\xdb\x5f\x57\xe5\xa7\xbd\xeb\x6d\xa3\xf7\x95\x2c\x76\x39\x69\ -\xec\x6d\xb7\x9d\xbe\x1f\x3d\x77\x7d\xb6\x3e\xaa\xf8\x89\xfb\x44\ -\x78\x2f\xc2\x9f\x04\xe3\xf1\x85\xd7\x8e\xbc\x37\xa0\xf8\x7f\x5a\ -\xb5\x46\xd2\xf5\xdb\xab\xb8\x7e\xcb\x33\x4f\x19\x68\x1e\x32\xcc\ -\x16\x62\xc3\xe6\x54\x53\x96\x0a\x71\x9e\x6b\xc7\x3f\x61\x3f\xdb\ -\x12\xdb\x50\xff\x00\x82\x7a\xf8\x0f\xe2\x47\xc5\x9f\x1c\x68\xb6\ -\xb7\x5e\x20\x7b\x95\xb9\xd6\x35\x29\xe1\xb1\x82\xe2\x63\x77\x71\ -\xe5\xa2\x8e\x11\x7f\x77\x1f\xca\x83\x90\xab\xec\x4d\x79\x77\xc3\ -\x2f\xf8\x27\x67\xc6\x2f\x85\x7f\x0f\xff\x00\x67\x9b\xcd\x3a\xf3\ -\xe1\xcc\xde\x35\xf8\x31\x73\xab\xd8\xdf\xd9\xcf\xab\x5e\x7f\x65\ -\x6a\xda\x5e\xa2\x1f\xcd\x68\xe5\x16\x62\x44\xb8\x42\x53\x6a\x98\ -\xb6\x9f\x98\x97\xfe\x13\xcf\xeb\x7f\xf0\x4d\x6f\xda\x03\x53\xfd\ -\x86\x7c\x29\xf0\x7a\x3d\x67\xe1\xd4\x16\xba\x5e\x97\xaf\xe9\x9a\ -\xb5\xbc\x1e\x21\xd4\xad\xad\xb5\x26\xbd\x8a\x51\x65\x70\x64\x8e\ -\xcc\x3b\x2c\x12\x4c\xec\xd6\xce\xa6\x39\x30\xa4\xb3\x60\x28\xda\ -\x38\x5c\x0f\x27\xb3\xf6\xab\x59\x6f\xd5\x25\xcd\xb6\x9d\x55\x9f\ -\xcf\x6d\x0e\x79\xe2\xb1\xfe\xd1\x54\xf6\x4f\x48\xbd\x3a\x36\xf9\ -\x7c\xfd\x52\xff\x00\x82\x7d\x3f\xf1\x33\xfe\x0a\x2b\xf0\xa7\xe1\ -\xdf\xc6\xbd\x2f\xe1\xbc\xbe\x32\xf0\xf7\xfc\x26\x5a\xe5\x94\xd7\ -\x76\xf1\x49\x7d\x1a\x59\xda\x05\x84\x4b\x17\xda\xa7\xce\x21\xf3\ -\x72\x36\x00\x19\x98\x72\x17\x18\x27\xa3\xf0\x47\xed\x23\xa6\x68\ -\xff\x00\xb3\x7f\x87\xfc\x6f\xe3\xef\x12\x78\x1b\x4d\x4b\xcb\x68\ -\xc5\xf6\xa5\xa5\x6a\x86\x6d\x16\x5b\x82\x4a\x9f\xb2\xcd\x22\xab\ -\x48\x85\x81\xda\x71\x92\x01\x3c\x81\x9a\xf9\x22\x1f\xf8\x26\x47\ -\xc6\x4d\x07\xf6\x81\xf8\x57\xe3\xcd\x3a\xf3\xe1\xad\xc3\xf8\x4b\ -\xe1\x58\xf0\x06\xb5\xa7\xcf\xab\x5e\xc6\xad\x3a\xda\xcb\x00\x9a\ -\xde\x45\xb4\x6d\xd1\x9c\xc6\x72\xca\x8c\x3e\x71\x86\xe0\xd6\xf7\ -\xc2\xdf\xf8\x26\x77\x8f\xbe\x1b\x6a\xdf\xb2\xf7\x8b\xbe\xd9\xe0\ -\xfb\x8f\x18\x7c\x04\xd1\xef\x74\x0d\x47\x4e\x1a\xa5\xca\xe9\xfa\ -\xb5\xad\xc5\x9c\xb6\xe2\x48\xa7\xfb\x29\x78\xe4\x46\x93\x76\xd3\ -\x0e\x18\x71\xb8\x60\x1a\x9a\xb8\x3c\x02\x82\x50\xab\xd3\x5f\x37\ -\x69\x69\xe5\x76\x92\xeb\xbd\xcd\x29\x63\x33\x07\x36\xe7\x4b\xad\ -\xbd\x15\xe3\xae\xfa\xe9\x77\xd3\x6b\x1f\x59\x78\xe7\xf6\x99\xf8\ -\x7b\xf0\xc6\xdb\x47\x9f\xc4\x3e\x38\xf0\x9e\x8f\x07\x88\x20\x6b\ -\x9d\x36\x5b\xcd\x52\x08\x63\xbe\x89\x62\x32\x99\x22\x2c\xc0\x34\ -\x7e\x5a\x96\xde\x09\x5c\x77\xe4\x57\x4f\xe0\x8f\x1b\x68\xff\x00\ -\x11\xbc\x33\x63\xad\xf8\x7f\x53\xb1\xd6\x74\x5d\x4a\x11\x3d\xa5\ -\xed\x94\xcb\x35\xbd\xc2\x1e\x8c\x8e\xa4\x86\x1c\x1e\x9e\x86\xbe\ -\x37\xf8\x6b\xff\x00\x04\xdf\xf1\xe7\xc2\x7f\x10\x7e\xc9\xcb\xa7\ -\xde\xf8\x4e\xff\x00\x4b\xf8\x07\xa7\x6a\x63\x5c\x96\x6d\x4a\xe2\ -\x0b\x8d\x4a\xee\xfe\xca\x48\x25\x16\xe8\xb6\xcc\xbe\x4a\xca\xe5\ -\x97\x7b\xa9\x2b\x80\x46\x46\x4f\xaf\x7f\xc1\x2f\xbf\x65\xdf\x12\ -\x7e\xc5\xdf\xb1\x27\x82\xfe\x19\xf8\xb2\xe7\x44\xbc\xd6\xfc\x32\ -\x2f\x56\x6b\x8d\x26\xe2\x59\xed\x66\x13\x5e\xdc\x5c\xa9\x56\x96\ -\x38\xdf\x21\x66\x00\xe5\x47\x20\xf5\x15\xc7\x8a\xc3\x61\x61\x47\ -\x9e\x8d\x4e\x69\x5f\xf0\xbc\x97\xe4\xa2\xff\x00\xed\xef\x23\xb3\ -\x07\x8a\xc5\xce\xb7\x25\x6a\x7c\xb1\xb6\xfe\x76\x8b\xfc\xdc\x97\ -\xc8\xfa\x06\x8a\x28\xaf\x34\xf5\x82\x8a\x28\xa0\x02\x8a\x28\xa0\ -\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\ -\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\ -\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\x02\x8a\x28\xa0\ -\x04\x65\xdc\x29\x15\x36\x8a\x75\x14\x58\x04\x2b\x4b\x8a\x28\xa0\ -\x06\xb2\x64\x75\xc5\x1b\x78\xa7\x51\x40\x08\x57\x34\xdf\x2b\x8e\ -\xb4\xfa\x29\x72\xa0\x00\x30\x29\xa5\x33\x4e\xa2\x98\x0d\xf2\xe8\ -\x11\xe0\x75\xa7\x51\x40\x0d\xf2\xbd\xe8\x31\xe6\x9d\x45\x00\x34\ -\xc5\x92\x7d\xfd\xa8\x11\xe2\x9d\x45\x00\x18\xa4\xdb\x4b\x45\x00\ -\x26\xda\x4d\x94\xea\x29\x58\x06\x94\xa0\x45\x83\xd6\x9d\x45\x3b\ -\x00\x9b\x73\x4a\x06\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x0a\x28\xa2\x80\ -\x0a\x28\xa2\x80\x0a\x28\xa2\x80\x3f\xff\xd9\ -\x00\x00\x7d\x46\ -\xff\ -\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x02\x01\x00\x48\x00\ -\x48\x00\x00\xff\xe1\x14\xc1\x45\x78\x69\x66\x00\x00\x4d\x4d\x00\ -\x2a\x00\x00\x00\x08\x00\x07\x01\x12\x00\x03\x00\x00\x00\x01\x00\ -\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x00\x62\x01\ -\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x00\x6a\x01\x28\x00\x03\x00\ -\x00\x00\x01\x00\x02\x00\x00\x01\x31\x00\x02\x00\x00\x00\x1e\x00\ -\x00\x00\x72\x01\x32\x00\x02\x00\x00\x00\x14\x00\x00\x00\x90\x87\ -\x69\x00\x04\x00\x00\x00\x01\x00\x00\x00\xa4\x00\x00\x00\xd0\x00\ -\x0a\xfc\x80\x00\x00\x27\x10\x00\x0a\xfc\x80\x00\x00\x27\x10\x41\ -\x64\x6f\x62\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\ -\x53\x33\x20\x4d\x61\x63\x69\x6e\x74\x6f\x73\x68\x00\x32\x30\x31\ -\x30\x3a\x30\x37\x3a\x32\x38\x20\x31\x33\x3a\x30\x34\x3a\x35\x30\ -\x00\x00\x03\xa0\x01\x00\x03\x00\x00\x00\x01\xff\xff\x00\x00\xa0\ -\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\xb4\xa0\x03\x00\x04\x00\ -\x00\x00\x01\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x06\x01\ -\x03\x00\x03\x00\x00\x00\x01\x00\x06\x00\x00\x01\x1a\x00\x05\x00\ -\x00\x00\x01\x00\x00\x01\x1e\x01\x1b\x00\x05\x00\x00\x00\x01\x00\ -\x00\x01\x26\x01\x28\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x02\ -\x01\x00\x04\x00\x00\x00\x01\x00\x00\x01\x2e\x02\x02\x00\x04\x00\ -\x00\x00\x01\x00\x00\x13\x8b\x00\x00\x00\x00\x00\x00\x00\x48\x00\ -\x00\x00\x01\x00\x00\x00\x48\x00\x00\x00\x01\xff\xd8\xff\xe0\x00\ -\x10\x4a\x46\x49\x46\x00\x01\x02\x00\x00\x48\x00\x48\x00\x00\xff\ -\xed\x00\x0c\x41\x64\x6f\x62\x65\x5f\x43\x4d\x00\x02\xff\xee\x00\ -\x0e\x41\x64\x6f\x62\x65\x00\x64\x80\x00\x00\x00\x01\xff\xdb\x00\ -\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\ -\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\ -\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\ -\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\ -\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x00\x41\x00\xa0\x03\x01\x22\x00\ -\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x0a\xff\xc4\x01\x3f\ -\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\ -\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\ -\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\ -\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\ -\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c\x33\x01\x00\x02\x11\x03\ -\x04\x21\x12\x31\x05\x41\x51\x61\x13\x22\x71\x81\x32\x06\x14\x91\ -\xa1\xb1\x42\x23\x24\x15\x52\xc1\x62\x33\x34\x72\x82\xd1\x43\x07\ -\x25\x92\x53\xf0\xe1\xf1\x63\x73\x35\x16\xa2\xb2\x83\x26\x44\x93\ -\x54\x64\x45\xc2\xa3\x74\x36\x17\xd2\x55\xe2\x65\xf2\xb3\x84\xc3\ -\xd3\x75\xe3\xf3\x46\x27\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\ -\xb5\xc5\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\ -\x37\x47\x57\x67\x77\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\ -\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x05\x35\x01\x00\ -\x02\x11\x03\x21\x31\x12\x04\x41\x51\x61\x71\x22\x13\x05\x32\x81\ -\x91\x14\xa1\xb1\x42\x23\xc1\x52\xd1\xf0\x33\x24\x62\xe1\x72\x82\ -\x92\x43\x53\x15\x63\x73\x34\xf1\x25\x06\x16\xa2\xb2\x83\x07\x26\ -\x35\xc2\xd2\x44\x93\x54\xa3\x17\x64\x45\x55\x36\x74\x65\xe2\xf2\ -\xb3\x84\xc3\xd3\x75\xe3\xf3\x46\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\ -\xf4\xa5\xb5\xc5\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\ -\xe6\xf6\x27\x37\x47\x57\x67\x77\x87\x97\xa7\xb7\xc7\xff\xda\x00\ -\x0c\x03\x01\x00\x02\x11\x03\x11\x00\x3f\x00\xf4\x8e\xa9\x87\x9f\ -\x97\x53\x1b\x83\x9e\xfe\x9d\x63\x4c\x9b\x19\x5d\x76\xee\x11\xf4\ -\x1c\xcc\x86\xbb\xfe\x82\xe1\xfa\x2f\x54\xfa\xdd\xd5\x3a\xd3\xfa\ -\x4b\xba\xb9\xa5\xd4\xfa\xa6\xdb\x45\x34\x3b\xf9\x97\x0a\x5d\xe9\ -\xb4\xd0\xdf\xa5\x63\xbf\x3b\xf3\x17\xa2\xaf\x3a\xfa\x9f\xff\x00\ -\x8b\x8c\xef\x86\x5f\xfe\x7f\xad\x5a\xe5\xc8\xf6\xf2\xdc\x62\x78\ -\x63\x71\xb8\xc6\x4d\x6c\xf7\xee\x62\xa3\x21\xc5\x2a\x95\x48\x8b\ -\x14\xfa\x06\x2d\x57\x53\x8f\x5d\x57\xdc\xec\x9b\x58\xd0\x1f\x7b\ -\x83\x5a\x5e\x7f\x7d\xcc\xa8\x32\xb6\xff\x00\x61\xab\x23\xeb\x35\ -\x1d\x75\xb8\xd6\xe7\xf4\xae\xa2\xec\x5f\xb3\x52\xe7\xbb\x17\xd2\ -\xad\xed\x7e\xc9\xb1\xee\xf5\x2d\xae\xcb\x19\x66\xcf\x6b\x3f\xc1\ -\xad\xc4\x0c\xed\x70\xb2\x01\xff\x00\x44\xff\x00\xfa\x92\xa0\x84\ -\xaa\x60\xd0\x3a\xec\x40\x23\xec\x67\x9c\x6e\x24\x59\x1a\x6e\x0e\ -\xaf\x21\xf5\x6b\xa9\xf5\x6b\xe8\xa7\xaa\xf5\xae\xb8\xcc\x6c\x37\ -\xd8\xe6\x55\x8f\x6b\x31\xeb\xf5\xb6\x0f\x7c\xdc\xea\xea\x77\xd2\ -\xff\x00\x44\xbb\x3f\x5a\x93\x4f\xae\x1e\xd3\x4e\xdd\xfe\xa0\x23\ -\x6e\xd8\xdd\xbf\x7f\xd1\xd9\xb5\x71\x7d\x25\xac\x7f\xf8\xb5\xb4\ -\x3d\xa1\xed\xf4\xed\x30\x75\xe2\xc7\x10\x75\xfc\xe6\xfe\x6a\xbb\ -\xd0\xb2\x6f\xe8\x3d\x50\xfd\x5a\xcf\x71\x38\xb6\xcb\xfa\x3e\x4b\ -\xff\x00\x39\x93\x2e\xc4\x7b\xc7\xb7\xd5\xaf\xfd\x7f\x9c\xc7\xad\ -\x4f\x9a\x02\x46\x66\x34\x0c\x25\x21\xc1\x10\x23\xe8\x87\x6e\x16\ -\x0c\x39\x0c\x44\x04\xac\x89\x46\x27\x8c\x9b\xf5\xcf\xbb\xb2\x3e\ -\xb1\x7d\x5f\x31\x1d\x4f\x10\xcf\x1f\xa7\xaf\xff\x00\x26\xa7\x4f\ -\x5c\xe8\xb7\xd8\xca\xa8\xcf\xc6\xb6\xcb\x0e\xd6\x31\x97\x31\xce\ -\x71\xfd\xd6\xb5\xae\xdc\xe5\xcb\xf5\xc6\xb5\xbf\x56\x3e\xb3\x6d\ -\x00\x4e\x7c\x98\x11\xa9\x38\x5a\xab\xbd\x46\xba\xfa\x6f\xd6\xce\ -\x93\xd4\xda\xd0\xca\xba\x85\x6e\xc0\xc8\x70\x11\xef\x21\xaf\xc5\ -\x3a\x7e\x73\xde\xc6\x53\xfd\x44\xdf\x66\x15\xa5\xd9\xe2\xaf\xf0\ -\x21\x1c\x9f\xf7\x4b\xbd\xe9\x5e\xc2\xbd\x37\xfe\x14\xa5\x0f\xfb\ -\x97\x7b\x2b\xab\x74\xbc\x2b\x05\x59\x99\x94\x63\x58\x5b\xb8\x32\ -\xdb\x18\xc3\xb4\x9d\xbb\xb6\xd8\xe6\xfb\x77\x04\x1f\xf9\xc5\xd0\ -\x37\x06\xfe\xd3\xc4\xdc\x78\x1e\xbd\x73\xff\x00\x56\x80\xe0\xdc\ -\xef\xac\xcc\xd0\x1a\xfa\x45\x25\xd3\xdf\xd7\xca\xf6\x01\xff\x00\ -\x5a\xc4\xad\xff\x00\xfb\x14\xb9\xcf\xab\x99\xbd\x34\xfd\x5b\xab\ -\xa3\xe5\xb1\xcf\x3d\x43\x2a\xcc\x66\xb1\xac\x21\xad\xde\xef\xa6\ -\xdb\x9c\xcf\xb3\xef\xa7\xf9\xe6\x7b\x90\x8e\x28\x98\xdf\xa8\x91\ -\xc3\xc4\x07\xf5\xf8\xbf\xee\x62\xa9\x66\x22\x55\xa5\x1e\x2e\x1b\ -\xfe\xa7\x0f\xfd\xd3\xd6\x59\xd7\xfa\x15\x4f\x75\x76\xf5\x1c\x5a\ -\xde\xc7\x16\x3d\xae\xba\xb0\x43\x9a\x76\xb9\x8e\x6b\x9f\xed\x73\ -\x5c\xad\x8b\xe8\x75\x3f\x68\x6d\x8d\x34\x16\xef\x16\x87\x0d\x9b\ -\x63\x76\xfd\xff\x00\x47\x66\xdf\xce\x5c\xd3\x72\xb0\xb1\x7e\xbb\ -\xf5\x17\xe6\x5d\x55\x15\x3f\x06\x80\x5d\x6b\x9a\xc6\x93\xb9\xfa\ -\x7e\x90\xb7\x77\xb5\x67\x55\xd1\xba\x86\x6f\xd4\xde\xa3\x4e\x13\ -\x1d\x5d\x59\x39\x76\x64\x60\x62\xb8\x6d\xdd\x8d\xbc\x3e\xaa\x9a\ -\xc7\xed\xf4\x9b\x63\x5b\xea\x57\x5f\xfe\x95\x4b\xd9\x8e\x96\x4c\ -\x41\xe0\xd6\x5b\x7e\xb3\xfe\xf5\x5e\xf4\xb5\xa0\x24\x47\x16\x83\ -\x7f\x43\xd5\xd3\xd7\xfa\x25\xfe\xa7\xa5\x9f\x8e\xff\x00\x45\xa6\ -\xcb\x48\xb1\xb0\xd6\x0d\x1d\x6f\x3f\xcd\x7b\xbf\x9d\xfe\x6d\x44\ -\xfd\x62\xfa\xbe\x39\xea\x78\x9f\xf6\xfd\x7f\xf9\x35\x47\xa1\x75\ -\x4e\x97\xd7\x6e\xab\x29\xac\x38\xdd\x4b\xa7\xd6\xfa\x6d\xc4\x77\ -\xb5\xcc\x16\x6c\x16\xb7\x61\x1e\xfa\xb7\xd0\xcd\x9f\xb9\xfe\x11\ -\x53\xfa\x87\x85\x8d\x6f\x4a\xc7\xcc\x7b\x01\xbb\x1a\xdc\x96\x52\ -\x60\x7b\x7d\x57\xb7\xd4\x7f\xfc\x66\xda\xfd\x3d\xff\x00\xe8\xfd\ -\x89\x1c\x51\x02\x46\x42\x40\xc6\x87\x0f\xf7\xb8\xbf\xef\x52\x32\ -\x48\x98\x88\xf0\x9e\x2b\x37\xfd\xde\x1f\xfb\xe7\x6b\xfe\x71\x7d\ -\x5f\xd3\xfc\xa7\x89\xaf\x1f\xa7\xaf\xff\x00\x26\x8b\x47\x57\xe9\ -\x39\x37\x0c\x7c\x7c\xda\x2e\xbc\xcc\x55\x5d\xac\x73\xbd\xbf\x4f\ -\xd8\xc7\x17\x7b\x56\x17\xd5\xcc\x4a\x33\x4f\xd6\x3c\x4c\x96\xef\ -\xa2\xfe\xa1\x7b\x2c\x69\xee\x1d\xa1\x4d\xd4\x03\x3e\xaf\xfd\x64\ -\xc4\xea\x8e\x76\xdc\x1e\xa3\x58\xc3\xcf\xb5\xfd\xad\x60\xdd\x8b\ -\x93\x6b\xff\x00\x79\xfb\x7d\x27\xb9\x23\x8a\x1c\x46\x02\xf8\x80\ -\xb8\xff\x00\x5b\xd3\xc4\x81\x96\x5c\x22\x66\xb8\x49\xd7\xfa\xba\ -\xf0\xbd\x0d\x3d\x4f\xa7\x5f\x92\xec\x4a\x72\xa9\xb7\x26\xbd\xdb\ -\xe8\x65\x8d\x75\x8d\xd8\x76\x59\xbe\xb6\x9d\xed\xd8\xff\x00\x6b\ -\x95\x95\x89\xd2\x5f\x55\x18\x59\x7f\x58\x73\xe3\x1c\xe7\x7e\xb3\ -\x61\x70\x83\x5e\x3b\x1b\xb7\x0e\xa7\xed\xdd\xef\x6e\x38\xf5\x6c\ -\x6f\xfd\xc8\xba\xd4\x47\x75\xdb\x68\x14\x5f\x9d\x85\x66\x2e\x16\ -\x43\x9a\xc1\x7b\xdc\x0b\xab\x75\x84\x36\x8f\xb6\xd2\x3f\xa3\x36\ -\xcd\xdb\x37\xef\xb3\xd1\xb3\xf9\xe4\xc3\x8c\xd9\x11\xd6\xb4\xff\ -\x00\x0b\xf4\x84\x7f\x79\x90\x64\x14\x38\xb4\xbd\x7f\xc1\xfd\x1e\ -\x2f\xdd\x75\xd2\x59\x18\x1d\x72\xec\xcb\x8b\x5b\x86\xf6\xd6\xcc\ -\x9b\x30\xee\xb0\x38\x3b\x65\x95\x35\xce\x7b\xcb\x5a\xdf\xe8\xfb\ -\x99\xe9\xfa\xbf\xcb\xfe\x6d\x6b\xa6\x4a\x26\x26\x8a\xe8\xc8\x48\ -\x58\x7f\xff\xd0\xf5\x55\xe6\xdf\x56\x1d\x73\x3e\xb8\x75\x37\xe3\ -\xb0\x5b\x73\x6b\xcd\x35\x54\x4e\xd0\xe7\x8b\x99\xb1\x85\xff\x00\ -\x99\xbd\xdf\x9e\xbd\x25\x79\xcf\xd5\x77\x7a\x1f\x5f\x72\xea\x7f\ -\xd2\xb1\xf9\x95\x0e\xda\xfa\x9e\xb6\x9f\xd8\xa5\x59\xe5\xbe\x4c\ -\xdf\xdc\x6b\x73\x1f\xce\x60\xfe\xff\x00\xec\x74\xba\x97\xd7\xae\ -\xaf\xd2\xef\x18\xfd\x43\xa3\x8a\x2d\x2d\xde\xd1\xeb\x87\x07\x37\ -\x8d\xcc\x7d\x75\xb9\xaa\xd1\xeb\xdf\x5a\x32\xb0\x0d\xec\xe8\x4d\ -\x38\xf7\xd3\xbd\xb6\x7d\xaa\xbf\xa0\xf6\xee\x6b\xf6\x40\x7f\xd0\ -\x77\xd0\x58\xff\x00\xe3\x3b\xfa\x7e\x07\xfc\x4d\xbf\xf5\x55\xae\ -\x9a\xab\xc6\x37\xd4\x9a\xef\x26\x3d\x3e\x9a\xd7\x0f\x8f\xa0\x36\ -\x8d\x7f\x94\x9f\x28\xe3\x18\xf1\x4c\x63\x8f\x14\xcd\x6f\x3f\xfb\ -\xe5\x91\x96\x43\x97\x2c\x0e\x49\x70\xc0\x58\xd2\x1f\xf7\xaf\x19\ -\x89\xd7\xf2\x30\xfe\xa8\x7e\xce\xb7\xa7\xda\x71\x6f\x6d\x8c\xab\ -\x3d\xa7\xf4\x65\xce\x73\x8c\x3a\x5b\xb5\xae\x6b\xbf\x37\x7a\xea\ -\xae\xc8\xe8\x7f\x5c\xfa\x73\xf1\xf1\x2f\x35\xe6\x53\xfa\x6a\x77\ -\x02\xcb\xa9\xb1\xa7\xf4\x76\xed\xfd\xcd\xdf\x4f\xd2\x77\xfe\x0a\ -\x8d\xf5\x2f\x15\xa3\xea\x9e\x1d\x37\xd6\x1c\xdb\x59\x61\x7b\x1c\ -\x24\x39\xb6\x3e\xc3\xef\x6b\xbe\x93\x5f\x5b\x97\x19\xf5\x9f\xa4\ -\x5b\xf5\x67\xad\x53\x95\xd3\x5e\xea\xaa\xb2\x6d\xc4\x78\xd4\xd6\ -\xf6\xe9\x6e\x3e\xbf\xce\x57\xef\xfc\xff\x00\xe7\x29\xb3\xd1\xb1\ -\x3c\x70\x64\xcb\x28\xc7\xf5\x79\x23\x29\x4a\x12\xbb\x8c\xcf\x5b\ -\x58\x78\xf1\x63\x8c\xe5\xfa\xcc\x72\x8c\x63\x38\xd5\x4a\x11\xe9\ -\xc3\xfe\x33\xa7\x96\x7a\x8b\xfe\xa7\x75\x4c\x7e\xa1\x45\x83\xaa\ -\x65\xe5\x96\x9a\x99\x53\xce\xf7\xd6\x71\xb7\xd8\xcf\x49\x8e\x66\ -\xc7\xd7\x4f\xab\xea\xff\x00\x32\xff\x00\xf0\x6b\x7f\xeb\x2e\x38\ -\xea\xdf\x56\x1f\x76\x16\xf7\x5b\x46\xdc\xac\x63\xb5\xcd\x7e\xfa\ -\x4c\xe9\x53\xda\xdb\x77\xec\x16\x6c\x66\xc4\x1c\xaf\xad\x19\xdf\ -\xf3\x6a\x9f\xac\x18\x35\x52\xe6\x35\xbf\xad\xd3\x69\x70\x70\x7e\ -\xe6\xd0\xe6\xd2\xe6\x6e\xfa\x36\xff\x00\xa4\xff\x00\x04\x96\x47\ -\x58\xfa\xcf\x4f\x43\xfd\xb4\xca\x70\xad\xa7\xd0\x6e\x51\xa4\x1b\ -\x5a\xf1\x59\x6f\xaa\xef\x79\xdc\xc7\x7a\x4c\x51\x9e\x32\x62\x68\ -\x44\xc7\x21\xfd\x2d\x38\xfd\x23\x82\xbf\xc1\x64\x1c\x1a\xc6\xe5\ -\x21\x28\x0e\x9a\xf0\x7a\xa5\x19\xdf\xf8\x4d\xfe\x8b\xbf\x17\xa4\ -\xbf\xa8\xf5\x00\x6b\xc8\xcd\x71\xcc\xc9\x6c\x39\xc5\xbe\xa6\xd1\ -\x55\x3b\x36\xfa\xbf\xab\xe3\x36\x8a\x36\xec\xff\x00\x06\xb0\xfe\ -\xaa\xe6\xe0\xe2\x74\x21\x47\x52\xa6\xf6\x5b\x4d\xef\xbd\xb5\x3b\ -\x1e\xe2\xe9\xdd\xea\x52\xf6\x06\x56\x77\x2b\xfd\x6b\xae\xf5\xbe\ -\x9f\xd5\xf1\x7a\x7d\x35\x62\xd8\xce\xa2\xf2\xcc\x67\xbc\xd8\x1c\ -\xcd\xbb\x37\x7a\xf1\xed\x77\xb9\xff\x00\xe0\xd6\xce\x56\x63\xb0\ -\x3a\x65\x99\x99\x9b\x4b\xf1\xe9\x36\x5c\x2b\xd1\xa5\xcd\x6e\xe7\ -\x36\xad\xff\x00\xbe\xff\x00\x6d\x7b\x93\x09\x20\x6a\x2f\xdd\x22\ -\x51\xe1\x97\xee\xfa\x40\x5f\x40\x9d\x0d\x7b\x40\xc6\x5c\x51\xfd\ -\xed\xde\x5b\xa7\xbe\xae\xad\xd7\xf2\x5d\xd4\x71\xec\x65\x7d\x4f\ -\xa7\xd5\x45\x8c\x35\x5a\x1a\x2d\xf7\xd9\x75\x02\xd7\xd6\x1a\xd7\ -\xd2\xcf\xf0\x9f\xe9\x7e\x82\x2f\x4d\xeb\x9d\x47\xa3\xe2\x8e\x9b\ -\xd4\x71\xee\xb5\xdd\x3b\x21\xb4\x5b\x92\x29\xb1\xe1\xf8\x64\x3c\ -\x55\x99\x5b\xaa\x0e\x6f\xe8\x7f\x43\xeb\xff\x00\xc1\x7f\xc3\xa2\ -\xe1\xfd\x66\xeb\x39\x9f\x56\x9d\xd5\xb1\xe8\xa2\xcc\xac\x47\x58\ -\x33\xa8\x76\xf6\x08\xaf\xdf\xfa\x0f\x73\xdc\xd7\x36\xa2\xd7\xed\ -\xb1\x69\xfd\x59\xea\x79\xdd\x5b\xa6\xb7\xa8\x65\x32\x9a\xd9\x79\ -\x3e\x8b\x2a\x2e\x24\x06\x97\x56\xff\x00\x55\xcf\xfc\xed\xec\xfc\ -\xc4\xec\x96\x04\xb8\xa2\x38\x62\x44\x38\x78\xbe\x59\xc7\xf7\x7f\ -\xc0\x5b\x0a\x24\x70\xc8\xf1\x48\x19\xf1\x70\xe8\x60\x7f\x7b\xfc\ -\x27\x1e\xfb\x30\xb2\xbe\xb5\xe1\x75\x9e\x9a\xd7\x3a\x8c\x6a\x6d\ -\x3d\x4f\x32\xb6\x3b\xd3\x73\x4b\x3d\x3c\x7a\xb7\x06\xfe\xb1\x91\ -\xbd\xdf\x42\xbd\xef\xd9\x5f\xe9\x3f\x9b\x56\x3e\xa2\xda\x28\xe8\ -\x96\x51\x73\x2c\xaa\xda\x2c\xb2\xcb\x1b\x65\x6f\x61\xda\xe2\x5c\ -\xc7\x37\x7b\x1b\xbf\x73\x7f\x71\x68\x74\xdf\xac\x14\xe7\xf5\x9e\ -\xa5\xd2\xd8\xd0\x3e\xc0\x58\x19\x60\x33\xbe\x46\xdb\xfd\xb1\xec\ -\xf4\x2f\xfd\x12\x0f\x55\xea\x5d\x7b\x1b\xab\x63\x60\x61\x55\x8b\ -\x6b\x33\xb7\xfa\x4e\xb0\xd8\x1d\x58\xa9\xad\x7d\xd6\x5e\xd6\x7d\ -\x26\x6e\x77\xe8\xf6\x20\x4c\xa4\x3d\xb3\x1a\xf4\xc4\x8e\x29\x7e\ -\x84\x78\xa7\xff\x00\x76\xb8\x00\x0f\xb8\x0d\xeb\x20\x78\x63\xfa\ -\x53\xf4\xff\x00\xdc\x35\x7e\xa7\xdc\xd3\x99\xd6\x01\x6d\x8c\x39\ -\x39\xb6\xe4\x53\xea\x55\x63\x37\x54\x48\x0d\xb5\xae\xb1\x8d\x6f\ -\xbb\xfc\xf5\x2f\xaf\xff\x00\xa4\xfa\xbf\x6e\x2d\x75\xbe\xec\x8b\ -\x9c\xd3\x4b\x2b\xad\xd6\x12\x5a\xe6\xb9\xe7\xf4\x6d\x7f\xa7\xec\ -\x46\x1f\x59\x5c\x7e\xb7\x1e\x85\xb5\xbf\x67\xf4\x4c\x59\x07\x71\ -\xc8\x0d\xfb\x43\xab\x0e\x9d\x9e\x9b\x71\x8f\xee\xfd\x35\x0e\xbd\ -\xd6\xfa\xcf\x4c\xea\x78\x78\xb4\xd5\x8d\x65\x1d\x46\xd1\x4e\x3b\ -\xde\x5e\x1e\xc7\x7b\x03\x8d\xcd\x6f\xb5\xcd\xdc\xff\x00\xcc\x48\ -\x09\x7b\xd1\x97\x0d\x12\x06\x48\xc4\x9d\xc4\x7c\x7f\xc1\x41\x31\ -\x18\x65\x1b\xb0\x09\xc6\x48\x1b\x5b\x67\xeb\x06\x33\xfa\xe7\xd5\ -\xac\x9a\x7a\x7f\xb9\xf9\x0c\x0e\xa4\x3c\x16\x6e\x2c\x7b\x6c\xf4\ -\xdc\xdb\x83\x36\xfa\x9e\x9f\xa7\xfa\x45\x4b\xad\x65\xd7\xf5\x83\ -\xa1\xfe\xcc\xc3\x65\x83\x33\x3c\xb1\x96\x52\xf6\x39\xae\xc7\xda\ -\xf6\x59\x90\xfc\xcd\xe1\x9e\x93\x68\x6b\x5d\xff\x00\x86\x2c\xfe\ -\x8f\xea\x23\x3f\xaf\x75\x2e\x9b\xd5\x31\x30\x3a\xcd\x14\xfa\x5d\ -\x41\xde\x9e\x36\x5e\x33\x9c\x5a\x2c\x90\xd1\x55\xd4\xda\x37\xb7\ -\x73\x9e\xcf\xd2\x35\xea\xbd\x3d\x73\xeb\x1d\xbd\x72\xee\x87\xe9\ -\xe1\x37\x22\x8a\x85\xee\xbb\xf4\xa5\x85\xa7\x67\xb5\xac\xfa\x6d\ -\x77\xe9\x7f\x79\x28\x46\x42\xa8\x0a\x81\xf7\x60\x78\xbf\xc1\xff\ -\x00\x0b\xe5\x8a\x67\x28\x9d\xc9\xb9\x0f\x6a\x63\x87\xfc\x2f\xf0\ -\x7e\x66\x7f\x56\x71\x5d\x6e\x4e\x66\x5f\xad\x7d\x6d\x66\x7e\x53\ -\xdb\x8e\x41\x65\x6f\x65\xc4\x7a\x77\x6d\x7b\x19\x63\xf8\xfd\x1b\ -\xf7\xec\x5d\x2a\xc9\xe9\x9d\x43\xaa\xbf\xa9\xe5\x74\xee\xa7\x55\ -\x0c\x75\x15\x57\x75\x56\x50\x5c\x43\xdb\x61\xb1\x93\xb6\xcf\x73\ -\x36\x3a\xa5\xac\xa2\xca\x49\x96\xbd\x85\x56\xba\x32\x62\x00\x47\ -\x4e\xe6\xef\xbb\xff\xd1\xf5\x55\xe7\xff\x00\x5c\x3a\x4f\x50\xe9\ -\x3d\x6d\x9f\x59\x7a\x73\x37\xd5\xb9\xb6\xdb\x00\x91\x5d\x8d\x1b\ -\x1f\xeb\x35\x9e\xef\xb3\x64\xd4\x3f\x49\x67\xfc\x6f\xfa\x4a\xd7\ -\xa0\x24\xa4\xc5\x94\xe3\x95\x81\x60\x8e\x19\x44\xfe\x94\x58\xf3\ -\x62\x19\x23\x44\xd1\x07\x8a\x32\x1f\xa3\x20\xf9\x57\xd6\xee\xbf\ -\x87\xd7\x9f\x83\x93\x8a\x1c\xc7\x57\x53\xdb\x7d\x4f\x1a\xb1\xce\ -\x2c\x20\x07\x8f\x6d\x8d\xf6\xbb\xde\xd5\xab\x5e\x5e\x67\xd6\x7e\ -\x9d\x81\xf5\x77\xa6\x31\xf5\xe1\x51\x55\x2d\xea\x99\xae\x10\xd0\ -\x6a\x6b\x37\x51\x54\xfd\x27\xef\x6f\xf6\xdf\xff\x00\x01\xfa\x44\ -\x0f\xf1\x91\x8d\x8f\x47\x50\xc3\x34\x54\xca\x8d\x95\x5a\xeb\x0b\ -\x1a\x1a\x5c\x43\xab\x87\x3f\x68\xf7\xae\xdf\xea\xf8\x03\xa0\xf4\ -\xd8\x11\xfa\xad\x27\xef\xad\x8a\xde\x4c\x91\x8e\x0c\x52\x8c\x7a\ -\x9e\x0e\x23\xf2\x1e\xff\x00\xd6\x69\xe3\xc7\x29\x67\xcb\x19\x4b\ -\xa4\x78\xf8\x45\x71\x86\xe5\x14\xd5\x8f\x4d\x74\x52\xdd\x95\x54\ -\xd0\xca\xd8\x38\x0d\x68\xda\xc6\xff\x00\x9a\xb9\x7f\xf1\x91\x43\ -\x5f\xd1\x29\xba\x25\xd4\xe4\x32\x0f\x80\x7b\x5e\xc7\x7f\xdf\x57\ -\x58\xb9\x6f\xf1\x8d\x66\xcf\xab\xed\x68\x3f\xce\x64\x56\xd8\xf1\ -\x00\x3d\xff\x00\xf7\xc5\x5b\x97\x27\xde\x87\xf7\x9b\x5c\xc8\x1e\ -\xc4\xc7\xf5\x5e\x67\xa5\xdc\xe7\x7d\x43\xeb\x74\x1f\xa3\x55\xd5\ -\xb8\x1f\xeb\xba\x8d\xdf\xf5\x0b\xa4\xc0\xea\xfd\x46\xbc\x3e\x81\ -\x86\x30\xdf\x46\x36\x47\xa3\x4b\xf2\x6c\x35\x3d\x96\x30\x50\xe7\ -\xec\x63\x2b\xb2\xcb\x19\xeb\x6c\xf6\x7a\x8c\x62\xe5\xba\x7b\xe9\ -\xa3\xea\x4f\x57\x37\x5a\xca\xdf\x99\x73\x19\x8f\x5b\x9c\x03\x9e\ -\x6a\x34\x1b\x7d\x26\x1f\x75\x9b\x37\xfb\xb6\xae\xc7\xa4\x75\xef\ -\xab\x8c\xe8\x38\x07\x27\x3b\x14\x3b\x17\x1e\xa2\x58\xf7\xb3\x7b\ -\x1f\x5d\x7b\x1f\xb6\xa2\x7d\x5f\x55\xbe\xf6\xfb\x18\xad\x67\x1f\ -\x35\x43\x8b\xf5\x92\xff\x00\xd2\x71\xff\x00\xba\x6a\xf2\xff\x00\ -\xa3\xea\xe1\xfd\x5c\x7f\xe9\xc9\xad\xf5\xa7\xff\x00\x15\x3f\x57\ -\x3f\xe3\x5f\xf9\x6b\x5a\xbd\x70\x1c\xac\x9e\x9d\xd2\x9a\x25\xb9\ -\x17\x8c\x8c\x8d\x37\x0f\x43\x17\x6e\x43\xb7\xff\x00\x26\xcc\xaf\ -\xb2\x53\xff\x00\x5c\x5c\x9f\x50\xeb\xf8\xd9\xbd\x4f\xea\xe7\x50\ -\xc9\xba\x9a\x88\xb6\xdb\x2e\x60\x78\x3e\x95\x6f\xb1\xbf\x65\xfb\ -\x47\xb9\xde\x9b\xfd\x0f\x4f\xd4\xdd\xfc\xb5\x63\xa9\x75\x4e\x8b\ -\xd5\x3a\x9e\x4d\x8e\x38\xb9\xd6\x8b\x71\xba\x6f\x4b\xa2\xdf\xd2\ -\x34\xba\xc7\x87\x65\xe5\x7a\x6d\x73\x7f\x45\xfa\x5d\x9e\xb7\xd0\ -\xfd\x57\xe9\xfe\x91\x47\xed\x4a\xb1\xd8\x3e\x88\xcb\x5a\xbf\x57\ -\x1c\xa2\x3f\xef\xd9\x7d\xc8\xde\x4a\x20\xf1\xca\x3e\x17\x1e\x0d\ -\x7f\xef\x5b\xfd\x09\xbf\xb3\xfe\xb6\xf5\x9e\x91\x60\x9a\x73\x40\ -\xcd\xa0\x3b\x82\x1e\x7f\x4e\xd6\xb7\xf7\x77\xdb\xe9\xff\x00\xd6\ -\x15\x7f\xaa\xdd\x41\xbd\x17\xa3\xf5\xac\x5b\xce\xf3\xd1\x6e\xb4\ -\xb4\x38\xc6\xe6\xeb\xe9\x35\xbf\xf1\xd6\x57\xed\xff\x00\x8c\x40\ -\xfa\xc5\x5f\x48\xfa\xb3\xd7\x7a\x46\x7e\x10\xab\x18\x35\xce\x6e\ -\x56\x3d\x70\x1d\xe9\x3f\xf4\x6e\xbc\xd4\x3d\xde\xd6\x3a\xef\xfa\ -\xe2\x26\x4e\x19\xc8\xfa\xec\xda\xb1\x9e\xdb\x30\x3a\xad\x54\x67\ -\x64\x39\x90\xe6\xbd\x98\x87\xd9\xb4\xea\xd7\x57\x66\x43\x31\x77\ -\xfe\xff\x00\xa8\x8d\x09\x46\xcf\xcb\x38\x46\x56\x7d\x3e\xac\x1e\ -\x99\x7f\x8d\x8d\x16\x63\x2a\x1f\x34\x27\x28\x80\x3d\x5e\x9c\xde\ -\xa8\xff\x00\x8b\x34\x5f\x63\xb3\xea\xdf\x5e\xe8\x59\x76\xf3\x9d\ -\x51\xc5\xea\x2e\x99\xdd\x91\x61\xf5\x2d\xb5\xef\xfe\x56\x4d\xcc\ -\x76\xef\xf4\x54\x2d\xef\xb4\x54\x7e\xb0\xf5\x2e\xa3\x79\x23\x1f\ -\xa3\xe2\x36\x92\x62\x61\xd6\x0f\xb7\xe5\xb9\xbf\xf5\x86\x62\x28\ -\xfd\x7a\xe9\xdf\x6e\xfa\xbb\x7b\x9a\x3f\x49\x89\x19\x2c\x3c\x68\ -\xcf\xe7\x7f\xf0\x17\x58\xb0\xd9\x9b\x8e\x3a\x26\x16\x16\x76\x45\ -\x75\xe5\xfd\x61\xca\x6e\x56\x68\x73\xf6\x46\x3d\x8f\xf5\x5e\xfe\ -\x7f\x45\x5d\xf8\xf4\x55\x8b\x4f\xfc\x62\x03\xf5\x90\x13\x3f\x36\ -\xb8\xe5\x5b\xd5\xfb\x9c\x5f\xf8\x5a\x4f\xea\xe7\x28\x0f\x97\x4c\ -\x91\xed\x7f\x27\x0f\xf8\xeb\x75\x9c\x4c\xbe\x9f\xd1\xba\x47\x5f\ -\xb1\x84\x66\x63\x65\x1c\xcc\xc6\x34\x16\x99\xcb\x77\xda\x2d\xa9\ -\xff\x00\xb9\xb3\xf4\x78\x8a\xff\x00\xd7\x2b\xeb\x1d\x47\xea\xe6\ -\x40\x25\xf5\x0c\xb1\x60\x2c\x69\x79\x2d\xfd\x13\xbd\x8c\xac\x3a\ -\xcb\x3f\xaa\xc6\xab\x5d\x6f\xea\xbf\xd5\xca\xba\x46\x65\x8d\xc5\ -\xc7\xc4\x78\xa9\xc5\x99\x06\x18\x1a\xff\x00\xf0\x5f\xa4\x3f\x47\ -\x75\xbb\x1a\xb9\x4a\xfa\xe6\x2e\x46\x27\xd5\x71\x6d\xcc\x16\xf4\ -\xfc\xb1\x5e\x40\x73\x9a\xdd\xb5\xb5\xd5\x36\xab\x5d\x27\xdb\x4b\ -\x69\xdb\xfa\x4f\xf8\x37\xa7\x63\xf5\xf0\xcc\x59\xe0\x33\x07\x4a\ -\xd3\x24\x65\x2f\xeb\x2c\xc9\x70\xe2\x81\xa1\xc6\x20\x46\xb7\xea\ -\x84\xa3\x17\xa3\xcc\x73\x3e\xb3\xf5\xec\x2a\x70\xc3\x86\x27\x46\ -\xb4\x64\x67\x59\x6b\x4d\x6e\xf5\x34\x7e\x3e\x33\x71\xef\x0c\xbf\ -\x73\xfd\x3f\xd2\x6f\xaf\xd3\xf4\xd0\x3d\x7b\xf1\xff\x00\xc6\x16\ -\x73\xf1\xf1\x9f\x98\xf3\x86\xc0\x6b\xad\xcc\x69\x03\xf4\x3e\xf9\ -\xbd\xf5\x33\x6f\xe6\xfd\x25\x3f\xac\x57\x0e\x8f\xd5\xb0\xfe\xb6\ -\x61\x11\x76\x16\x43\x46\x3f\x50\xf4\x88\x73\x5f\x59\xfe\x62\xf6\ -\xb8\x1d\xae\x76\xdf\xa0\xff\x00\xf8\x3a\x6b\xff\x00\x0a\xab\x61\ -\xf5\xbe\x8f\xff\x00\x3f\x72\x73\x4e\x65\x23\x16\xfc\x36\xb2\xbb\ -\xcb\xc0\x61\x74\x52\xfd\x9e\xa3\xbd\xac\x7e\xd6\xbb\xe9\xff\x00\ -\xd5\xa1\x10\x78\x6e\x22\xe1\xed\x48\x01\xfd\x7e\x2f\x5c\x64\xba\ -\x64\x71\x00\x4d\x4f\xdd\x89\x27\xfa\xbc\x3e\x89\x45\xe9\x7a\x06\ -\x7e\x57\x50\xc6\xbe\xfc\xba\xfd\x0b\x9b\x91\x6d\x5e\x89\x8d\xd5\ -\xb5\x87\x6b\x2a\x7b\x99\xb9\xaf\x77\xe7\x6f\x5a\x8b\x0a\xcf\xac\ -\x9d\x30\x75\x3c\x6c\x3e\x9f\x75\x17\xb6\xc1\x6e\x4e\x75\x94\x91\ -\x60\x65\x55\x56\x7d\xe7\xd1\x3f\xcf\x3e\xdf\x47\xf7\xff\x00\x46\ -\xb5\x70\x73\xb1\xb3\xe8\xf5\xf1\x9c\x5c\xc9\x2d\x32\x08\x20\xb7\ -\x90\x41\x55\xb2\x44\xdf\x17\x0f\x08\x3d\x3b\x36\x61\x21\xf2\xf1\ -\x71\x11\xf8\xbf\xff\xd2\xf5\x54\x92\x43\xc8\xb8\x63\xe3\xdb\x79\ -\x63\xec\x15\x31\xcf\x2c\xad\xa5\xcf\x76\xd1\xbb\x65\x75\xb7\xe9\ -\xd8\xef\xcc\x62\x4a\x78\x1f\xf1\x9d\xfd\x3f\x03\xfe\x26\xdf\xfa\ -\xaa\xd7\x67\xf5\x7f\xfe\x41\xe9\xbf\xf8\x52\x8f\xfc\xf6\xc5\xc1\ -\x7d\x6e\xc8\xea\x3d\x7b\x36\x8b\x71\xba\x56\x7d\x74\xe3\xd6\xe6\ -\x03\x66\x35\xa1\xce\x2f\x21\xce\x3b\x5a\xc7\x6d\x6f\xb1\x6e\xf4\ -\x4f\xad\x19\x58\x9d\x33\x1f\x0f\x37\xa3\x75\x1f\x57\x1a\xb6\xd4\ -\x1d\x56\x35\x8e\x6b\x9a\xc1\xb1\x8e\xf7\x06\x39\xae\xd8\xdf\x7a\ -\xbb\x93\x1c\x8f\x2f\x8e\x22\xb8\xa2\x4d\x8b\x1d\x5a\x58\xa6\x07\ -\x31\x96\x44\x1e\x19\x01\x47\x86\x5d\x1e\xbd\x79\xff\x00\xf8\xc5\ -\xcf\x39\x59\xf8\x7d\x1f\x18\x1b\x6d\xa8\xef\x7b\x1b\xa9\x36\xdb\ -\xec\xc7\xa7\x6f\xef\xec\xf7\xff\x00\xd7\x6b\x5b\x19\x1f\x58\x3e\ -\xb2\x67\xb0\xd3\xd1\xba\x35\xd8\xee\x76\x9f\x6a\xce\x02\xa6\xb2\ -\x7f\x3d\xb4\x3c\xee\x7f\xfa\xfe\x8e\xc4\x5f\xab\x7f\x54\x2b\xe9\ -\x57\x3b\xa8\x67\xdb\xf6\xce\xa9\x61\x25\xd7\x19\x2d\x61\x77\xf3\ -\x86\xad\xfe\xf7\x5b\x67\xf8\x4b\xdf\xfd\x4f\xd1\xfb\xf7\xc7\x88\ -\x0c\x27\xdc\x99\x1c\x43\xe4\x80\x36\x78\xbf\xad\xfb\xac\x99\xaf\ -\x30\xf6\xe0\x0f\x0c\xbe\x79\x9d\x07\x0f\x68\xba\x1d\x0b\xa3\x55\ -\xd2\xfa\x4e\x36\x0b\xc3\x6c\xb2\xa6\x93\x63\xe0\x10\x6c\x79\xdf\ -\x69\x69\x2d\x6f\xb7\x77\xb5\x9f\xf0\x6a\xff\x00\xd9\xe8\x99\xf4\ -\xd9\x3e\x3b\x42\x22\x4a\xbc\xa4\x64\x49\x27\x52\x6d\x9e\x31\x11\ -\x00\x01\xa0\x14\xc3\xd1\xa6\x67\xd3\x6c\x9e\x74\x09\x0a\x69\x04\ -\x10\xc6\x82\x38\x20\x05\x34\x90\xb2\xba\x83\x17\x57\x5b\x8e\xe7\ -\x31\xa4\xf1\x24\x02\x61\x20\xc6\x36\x36\xb4\x08\x10\x20\x70\x3c\ -\x14\x92\x49\x4b\x10\x08\x83\xc2\x89\xa6\x93\xcb\x1a\x74\x03\x50\ -\x38\x1c\x05\x34\x92\x52\xce\x6b\x5c\x36\xb8\x07\x03\xc8\x3a\x85\ -\x1f\x46\x9f\xf4\x6d\xfb\x82\x9a\x49\x29\x8e\xc6\x6d\xd9\xb4\x6d\ -\xe3\x6c\x69\x1f\x05\x1f\x42\x88\x8f\x4d\xb1\xfd\x50\x88\x92\x56\ -\xaa\x47\xe8\x51\xb4\xb7\xd3\x6e\xd7\x02\xd7\x0d\xa2\x08\x3f\x49\ -\xa5\x36\x3e\x36\x3e\x2d\x2d\xa3\x1a\xa6\xd3\x53\x3e\x8d\x6c\x01\ -\xad\x13\xaf\xd1\x6a\x2a\x48\xd9\xee\x8a\x1b\xd3\xff\xd3\xf5\x54\ -\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\ -\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\ -\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\ -\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\ -\xca\xa9\x24\xa7\xff\xd9\xff\xed\x36\x84\x50\x68\x6f\x74\x6f\x73\ -\x68\x6f\x70\x20\x33\x2e\x30\x00\x38\x42\x49\x4d\x04\x04\x00\x00\ -\x00\x00\x00\x07\x1c\x02\x00\x00\x02\x00\x00\x00\x38\x42\x49\x4d\ -\x04\x25\x00\x00\x00\x00\x00\x10\xe8\xf1\x5c\xf3\x2f\xc1\x18\xa1\ -\xa2\x7b\x67\xad\xc5\x64\xd5\xba\x38\x42\x49\x4d\x03\xea\x00\x00\ -\x00\x00\x1c\xe1\x3c\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\ -\x6e\x3d\x22\x31\x2e\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\ -\x3d\x22\x55\x54\x46\x2d\x38\x22\x3f\x3e\x0a\x3c\x21\x44\x4f\x43\ -\x54\x59\x50\x45\x20\x70\x6c\x69\x73\x74\x20\x50\x55\x42\x4c\x49\ -\x43\x20\x22\x2d\x2f\x2f\x41\x70\x70\x6c\x65\x2f\x2f\x44\x54\x44\ -\x20\x50\x4c\x49\x53\x54\x20\x31\x2e\x30\x2f\x2f\x45\x4e\x22\x20\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\ -\x65\x2e\x63\x6f\x6d\x2f\x44\x54\x44\x73\x2f\x50\x72\x6f\x70\x65\ -\x72\x74\x79\x4c\x69\x73\x74\x2d\x31\x2e\x30\x2e\x64\x74\x64\x22\ -\x3e\x0a\x3c\x70\x6c\x69\x73\x74\x20\x76\x65\x72\x73\x69\x6f\x6e\ -\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x3c\x64\x69\x63\x74\x3e\x0a\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\ -\x46\x6f\x72\x6d\x61\x74\x74\x69\x6e\x67\x50\x72\x69\x6e\x74\x65\ -\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\ -\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\ -\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\ -\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\ -\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\ -\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x46\x6f\x72\x6d\x61\x74\x74\ -\x69\x6e\x67\x50\x72\x69\x6e\x74\x65\x72\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4b\x4f\x4e\ -\x49\x43\x41\x5f\x4d\x49\x4e\x4f\x4c\x54\x41\x5f\x62\x69\x7a\x68\ -\x75\x62\x5f\x43\x35\x35\x30\x5f\x35\x39\x5f\x42\x44\x5f\x33\x38\ -\x5f\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\ -\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\ -\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\ -\x6d\x61\x74\x2e\x50\x4d\x48\x6f\x72\x69\x7a\x6f\x6e\x74\x61\x6c\ -\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x48\x6f\x72\ -\x69\x7a\x6f\x6e\x74\x61\x6c\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x32\x3c\x2f\x72\ -\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\ -\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\ -\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\ -\x61\x79\x3e\x0a\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\ -\x4f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\ -\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\ -\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x61\x72\ -\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\ -\x61\x74\x2e\x50\x4d\x4f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\ -\x67\x65\x72\x3e\x31\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\ -\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x53\x63\x61\x6c\x69\ -\x6e\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\ -\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x53\x63\x61\x6c\ -\x69\x6e\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x3c\x72\ -\x65\x61\x6c\x3e\x31\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\ -\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\ -\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x3c\x2f\x64\ -\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\ -\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\x74\x69\x63\x61\x6c\ -\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\ -\x74\x69\x63\x61\x6c\x52\x65\x73\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x32\x3c\x2f\x72\x65\x61\ -\x6c\x3e\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\ -\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\ -\x3e\x0a\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\ -\x72\x74\x69\x63\x61\x6c\x53\x63\x61\x6c\x69\x6e\x67\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\ -\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\ -\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\ -\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\ -\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\ -\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\ -\x72\x6d\x61\x74\x2e\x50\x4d\x56\x65\x72\x74\x69\x63\x61\x6c\x53\ -\x63\x61\x6c\x69\x6e\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x09\x3c\x72\x65\x61\x6c\x3e\x31\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x3c\x2f\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x73\x75\ -\x62\x54\x69\x63\x6b\x65\x74\x2e\x70\x61\x70\x65\x72\x5f\x69\x6e\ -\x66\x6f\x5f\x74\x69\x63\x6b\x65\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x50\ -\x4d\x50\x50\x44\x50\x61\x70\x65\x72\x43\x6f\x64\x65\x4e\x61\x6d\ -\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\ -\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x50\x4d\x50\x50\x44\x50\x61\x70\x65\x72\x43\ -\x6f\x64\x65\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\ -\x72\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\ -\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\ -\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x50\ -\x4d\x50\x50\x44\x54\x72\x61\x6e\x73\x6c\x61\x74\x69\x6f\x6e\x53\ -\x74\x72\x69\x6e\x67\x50\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\ -\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\ -\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\ -\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\ -\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\ -\x79\x3e\x50\x4d\x50\x50\x44\x54\x72\x61\x6e\x73\x6c\x61\x74\x69\ -\x6f\x6e\x53\x74\x72\x69\x6e\x67\x50\x61\x70\x65\x72\x4e\x61\x6d\ -\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x73\x74\ -\x72\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\x72\x20\x2d\x20\x38\x2e\ -\x35\x78\x31\x31\x69\x6e\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\ -\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\ -\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\ -\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\ -\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\ -\x6b\x65\x79\x3e\x50\x4d\x54\x69\x6f\x67\x61\x50\x61\x70\x65\x72\ -\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\ -\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\ -\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\ -\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\ -\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x50\x4d\x54\x69\x6f\x67\x61\x50\ -\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x6e\x61\x2d\x6c\ -\x65\x74\x74\x65\x72\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\ -\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\ -\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\ -\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x67\x65\x52\x65\x63\x74\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\ -\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\ -\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\ -\x4d\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x67\x65\x52\x65\x63\ -\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x61\x72\ -\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\ -\x3e\x30\x2e\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\ -\x09\x09\x3c\x72\x65\x61\x6c\x3e\x30\x2e\x30\x3c\x2f\x72\x65\x61\ -\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\ -\x36\x38\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\ -\x3c\x72\x65\x61\x6c\x3e\x35\x38\x38\x3c\x2f\x72\x65\x61\x6c\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\ -\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\ -\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\x50\x4d\ -\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x70\x65\x72\x52\x65\x63\ -\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\ -\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\ -\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\ -\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\x72\x6d\x61\x74\x2e\ -\x50\x4d\x41\x64\x6a\x75\x73\x74\x65\x64\x50\x61\x70\x65\x72\x52\ -\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\ -\x61\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\ -\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\ -\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\ -\x3e\x37\x38\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\ -\x09\x09\x3c\x72\x65\x61\x6c\x3e\x36\x30\x30\x3c\x2f\x72\x65\x61\ -\x6c\x3e\x0a\x09\x09\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\ -\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\ -\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\ -\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\ -\x4d\x43\x75\x73\x74\x6f\x6d\x50\x61\x70\x65\x72\x3c\x2f\x6b\x65\ -\x79\x3e\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\ -\x6f\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\ -\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\ -\x62\x74\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\ -\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x69\x74\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x43\x75\x73\x74\ -\x6f\x6d\x50\x61\x70\x65\x72\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x09\x09\x3c\x66\x61\x6c\x73\x65\x2f\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\ -\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\ -\x74\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\ -\x09\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\ -\x74\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\ -\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x50\x61\x70\x65\ -\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x64\ -\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\x65\x79\ -\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\x65\x74\ -\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\x72\x72\ -\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\x72\x72\ -\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\ -\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\ -\x66\x6f\x2e\x50\x4d\x50\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\ -\x67\x3e\x6e\x61\x2d\x6c\x65\x74\x74\x65\x72\x3c\x2f\x73\x74\x72\ -\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\ -\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\x67\x3c\ -\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\x74\x65\ -\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\x3e\x0a\ -\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\ -\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\x49\x6e\ -\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\x64\x50\ -\x61\x67\x65\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\ -\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\x6b\ -\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x3c\ -\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\ -\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\x41\ -\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x61\ -\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\x3e\ -\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\ -\x49\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\ -\x64\x50\x61\x67\x65\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\x0a\ -\x09\x09\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\ -\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x30\x2e\x30\x3c\x2f\x72\x65\ -\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\ -\x30\x2e\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\ -\x09\x3c\x72\x65\x61\x6c\x3e\x37\x36\x38\x3c\x2f\x72\x65\x61\x6c\ -\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x35\x38\ -\x38\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x3c\x2f\ -\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\x6c\x61\ -\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x69\x6e\ -\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\x65\x72\ -\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\ -\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\ -\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\x72\ -\x49\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\x73\x74\x65\ -\x64\x50\x61\x70\x65\x72\x52\x65\x63\x74\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\ -\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\ -\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\ -\x67\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\ -\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\ -\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\ -\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\ -\x65\x6d\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\ -\x09\x3c\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\ -\x63\x74\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\ -\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\ -\x70\x65\x72\x49\x6e\x66\x6f\x2e\x50\x4d\x55\x6e\x61\x64\x6a\x75\ -\x73\x74\x65\x64\x50\x61\x70\x65\x72\x52\x65\x63\x74\x3c\x2f\x6b\ -\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\x61\x72\x72\x61\x79\x3e\ -\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x2d\x31\x32\ -\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\ -\x65\x61\x6c\x3e\x2d\x31\x32\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\ -\x09\x09\x09\x09\x09\x3c\x72\x65\x61\x6c\x3e\x37\x38\x30\x3c\x2f\ -\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\x09\x09\x09\x3c\x72\x65\x61\ -\x6c\x3e\x36\x30\x30\x3c\x2f\x72\x65\x61\x6c\x3e\x0a\x09\x09\x09\ -\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\ -\x65\x46\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\ -\x65\x67\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\ -\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\ -\x61\x70\x65\x72\x49\x6e\x66\x6f\x2e\x70\x70\x64\x2e\x50\x4d\x50\ -\x61\x70\x65\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\ -\x09\x3c\x64\x69\x63\x74\x3e\x0a\x09\x09\x09\x3c\x6b\x65\x79\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\ -\x74\x69\x63\x6b\x65\x74\x2e\x63\x72\x65\x61\x74\x6f\x72\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\ -\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6a\x6f\x62\x74\x69\x63\ -\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x69\x74\x65\x6d\ -\x41\x72\x72\x61\x79\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x3c\ -\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x09\x09\x3c\x64\x69\x63\x74\ -\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\ -\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x70\x65\ -\x72\x49\x6e\x66\x6f\x2e\x70\x70\x64\x2e\x50\x4d\x50\x61\x70\x65\ -\x72\x4e\x61\x6d\x65\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\ -\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x4c\x65\x74\x74\x65\x72\x3c\ -\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\x09\x09\x09\x3c\x6b\ -\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\ -\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x73\x74\x61\x74\x65\x46\ -\x6c\x61\x67\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x09\x09\x09\x3c\ -\x69\x6e\x74\x65\x67\x65\x72\x3e\x30\x3c\x2f\x69\x6e\x74\x65\x67\ -\x65\x72\x3e\x0a\x09\x09\x09\x09\x3c\x2f\x64\x69\x63\x74\x3e\x0a\ -\x09\x09\x09\x3c\x2f\x61\x72\x72\x61\x79\x3e\x0a\x09\x09\x3c\x2f\ -\x64\x69\x63\x74\x3e\x0a\x09\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\ -\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\ -\x6b\x65\x74\x2e\x41\x50\x49\x56\x65\x72\x73\x69\x6f\x6e\x3c\x2f\ -\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x30\ -\x30\x2e\x32\x30\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x09\ -\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\ -\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\x74\x79\x70\x65\ -\x3c\x2f\x6b\x65\x79\x3e\x0a\x09\x09\x3c\x73\x74\x72\x69\x6e\x67\ -\x3e\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\ -\x2e\x50\x61\x70\x65\x72\x49\x6e\x66\x6f\x54\x69\x63\x6b\x65\x74\ -\x3c\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x3c\x2f\x64\x69\x63\ -\x74\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\x6f\x6d\x2e\x61\x70\x70\ -\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\x69\x63\x6b\x65\x74\x2e\ -\x41\x50\x49\x56\x65\x72\x73\x69\x6f\x6e\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x30\x30\x2e\x32\x30\x3c\ -\x2f\x73\x74\x72\x69\x6e\x67\x3e\x0a\x09\x3c\x6b\x65\x79\x3e\x63\ -\x6f\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x74\ -\x69\x63\x6b\x65\x74\x2e\x74\x79\x70\x65\x3c\x2f\x6b\x65\x79\x3e\ -\x0a\x09\x3c\x73\x74\x72\x69\x6e\x67\x3e\x63\x6f\x6d\x2e\x61\x70\ -\x70\x6c\x65\x2e\x70\x72\x69\x6e\x74\x2e\x50\x61\x67\x65\x46\x6f\ -\x72\x6d\x61\x74\x54\x69\x63\x6b\x65\x74\x3c\x2f\x73\x74\x72\x69\ -\x6e\x67\x3e\x0a\x3c\x2f\x64\x69\x63\x74\x3e\x0a\x3c\x2f\x70\x6c\ -\x69\x73\x74\x3e\x0a\x00\x38\x42\x49\x4d\x03\xed\x00\x00\x00\x00\ -\x00\x10\x00\x48\x00\x00\x00\x01\x00\x01\x00\x48\x00\x00\x00\x01\ -\x00\x01\x38\x42\x49\x4d\x04\x26\x00\x00\x00\x00\x00\x0e\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x80\x00\x00\x38\x42\x49\x4d\ -\x04\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x38\x42\x49\x4d\ -\x04\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x38\x42\x49\x4d\ -\x03\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\ -\x01\x00\x38\x42\x49\x4d\x04\x0a\x00\x00\x00\x00\x00\x01\x00\x00\ -\x38\x42\x49\x4d\x27\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x01\x38\x42\x49\x4d\x03\xf5\x00\x00\x00\x00\ -\x00\x48\x00\x2f\x66\x66\x00\x01\x00\x6c\x66\x66\x00\x06\x00\x00\ -\x00\x00\x00\x01\x00\x2f\x66\x66\x00\x01\x00\xa1\x99\x9a\x00\x06\ -\x00\x00\x00\x00\x00\x01\x00\x32\x00\x00\x00\x01\x00\x5a\x00\x00\ -\x00\x06\x00\x00\x00\x00\x00\x01\x00\x35\x00\x00\x00\x01\x00\x2d\ -\x00\x00\x00\x06\x00\x00\x00\x00\x00\x01\x38\x42\x49\x4d\x03\xf8\ -\x00\x00\x00\x00\x00\x70\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\ -\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\x03\xe8\x00\x00\x38\x42\x49\x4d\x04\x08\x00\x00\x00\x00\ -\x00\x10\x00\x00\x00\x01\x00\x00\x02\x40\x00\x00\x02\x40\x00\x00\ -\x00\x00\x38\x42\x49\x4d\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\ -\x00\x00\x38\x42\x49\x4d\x04\x1a\x00\x00\x00\x00\x03\x5d\x00\x00\ -\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x00\ -\x00\xb4\x00\x00\x00\x14\x00\x55\x00\x44\x00\x50\x00\x72\x00\x69\ -\x00\x6d\x00\x61\x00\x72\x00\x79\x00\x4c\x00\x6f\x00\x67\x00\x6f\ -\x00\x32\x00\x39\x00\x34\x00\x35\x00\x77\x00\x65\x00\x62\x00\x00\ -\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xb4\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x6e\x75\x6c\x6c\x00\x00\x00\x02\x00\x00\x00\ -\x06\x62\x6f\x75\x6e\x64\x73\x4f\x62\x6a\x63\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x52\x63\x74\x31\x00\x00\x00\x04\x00\x00\x00\ -\x00\x54\x6f\x70\x20\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\ -\x00\x4c\x65\x66\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\ -\x00\x42\x74\x6f\x6d\x6c\x6f\x6e\x67\x00\x00\x00\x49\x00\x00\x00\ -\x00\x52\x67\x68\x74\x6c\x6f\x6e\x67\x00\x00\x00\xb4\x00\x00\x00\ -\x06\x73\x6c\x69\x63\x65\x73\x56\x6c\x4c\x73\x00\x00\x00\x01\x4f\ -\x62\x6a\x63\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x73\x6c\x69\ -\x63\x65\x00\x00\x00\x12\x00\x00\x00\x07\x73\x6c\x69\x63\x65\x49\ -\x44\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x07\x67\x72\x6f\ -\x75\x70\x49\x44\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x06\ -\x6f\x72\x69\x67\x69\x6e\x65\x6e\x75\x6d\x00\x00\x00\x0c\x45\x53\ -\x6c\x69\x63\x65\x4f\x72\x69\x67\x69\x6e\x00\x00\x00\x0d\x61\x75\ -\x74\x6f\x47\x65\x6e\x65\x72\x61\x74\x65\x64\x00\x00\x00\x00\x54\ -\x79\x70\x65\x65\x6e\x75\x6d\x00\x00\x00\x0a\x45\x53\x6c\x69\x63\ -\x65\x54\x79\x70\x65\x00\x00\x00\x00\x49\x6d\x67\x20\x00\x00\x00\ -\x06\x62\x6f\x75\x6e\x64\x73\x4f\x62\x6a\x63\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x52\x63\x74\x31\x00\x00\x00\x04\x00\x00\x00\ -\x00\x54\x6f\x70\x20\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\ -\x00\x4c\x65\x66\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\ -\x00\x42\x74\x6f\x6d\x6c\x6f\x6e\x67\x00\x00\x00\x49\x00\x00\x00\ -\x00\x52\x67\x68\x74\x6c\x6f\x6e\x67\x00\x00\x00\xb4\x00\x00\x00\ -\x03\x75\x72\x6c\x54\x45\x58\x54\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x6e\x75\x6c\x6c\x54\x45\x58\x54\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00\x4d\x73\x67\x65\x54\x45\x58\x54\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x06\x61\x6c\x74\x54\x61\x67\x54\x45\x58\x54\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0e\x63\x65\x6c\x6c\x54\x65\ -\x78\x74\x49\x73\x48\x54\x4d\x4c\x62\x6f\x6f\x6c\x01\x00\x00\x00\ -\x08\x63\x65\x6c\x6c\x54\x65\x78\x74\x54\x45\x58\x54\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x09\x68\x6f\x72\x7a\x41\x6c\x69\x67\x6e\ -\x65\x6e\x75\x6d\x00\x00\x00\x0f\x45\x53\x6c\x69\x63\x65\x48\x6f\ -\x72\x7a\x41\x6c\x69\x67\x6e\x00\x00\x00\x07\x64\x65\x66\x61\x75\ -\x6c\x74\x00\x00\x00\x09\x76\x65\x72\x74\x41\x6c\x69\x67\x6e\x65\ -\x6e\x75\x6d\x00\x00\x00\x0f\x45\x53\x6c\x69\x63\x65\x56\x65\x72\ -\x74\x41\x6c\x69\x67\x6e\x00\x00\x00\x07\x64\x65\x66\x61\x75\x6c\ -\x74\x00\x00\x00\x0b\x62\x67\x43\x6f\x6c\x6f\x72\x54\x79\x70\x65\ -\x65\x6e\x75\x6d\x00\x00\x00\x11\x45\x53\x6c\x69\x63\x65\x42\x47\ -\x43\x6f\x6c\x6f\x72\x54\x79\x70\x65\x00\x00\x00\x00\x4e\x6f\x6e\ -\x65\x00\x00\x00\x09\x74\x6f\x70\x4f\x75\x74\x73\x65\x74\x6c\x6f\ -\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x0a\x6c\x65\x66\x74\x4f\x75\ -\x74\x73\x65\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x00\x00\x0c\ -\x62\x6f\x74\x74\x6f\x6d\x4f\x75\x74\x73\x65\x74\x6c\x6f\x6e\x67\ -\x00\x00\x00\x00\x00\x00\x00\x0b\x72\x69\x67\x68\x74\x4f\x75\x74\ -\x73\x65\x74\x6c\x6f\x6e\x67\x00\x00\x00\x00\x00\x38\x42\x49\x4d\ -\x04\x28\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x01\x3f\xf0\x00\x00\ -\x00\x00\x00\x00\x38\x42\x49\x4d\x04\x11\x00\x00\x00\x00\x00\x01\ -\x01\x00\x38\x42\x49\x4d\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\ -\x00\x04\x38\x42\x49\x4d\x04\x0c\x00\x00\x00\x00\x13\xa7\x00\x00\ -\x00\x01\x00\x00\x00\xa0\x00\x00\x00\x41\x00\x00\x01\xe0\x00\x00\ -\x79\xe0\x00\x00\x13\x8b\x00\x18\x00\x01\xff\xd8\xff\xe0\x00\x10\ -\x4a\x46\x49\x46\x00\x01\x02\x00\x00\x48\x00\x48\x00\x00\xff\xed\ -\x00\x0c\x41\x64\x6f\x62\x65\x5f\x43\x4d\x00\x02\xff\xee\x00\x0e\ -\x41\x64\x6f\x62\x65\x00\x64\x80\x00\x00\x00\x01\xff\xdb\x00\x84\ -\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\ -\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\ -\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\ -\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\ -\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\xff\xc0\x00\x11\x08\x00\x41\x00\xa0\x03\x01\x22\x00\x02\ -\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x0a\xff\xc4\x01\x3f\x00\ -\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\ -\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\ -\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\ -\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\ -\x04\x02\x05\x07\x06\x08\x05\x03\x0c\x33\x01\x00\x02\x11\x03\x04\ -\x21\x12\x31\x05\x41\x51\x61\x13\x22\x71\x81\x32\x06\x14\x91\xa1\ -\xb1\x42\x23\x24\x15\x52\xc1\x62\x33\x34\x72\x82\xd1\x43\x07\x25\ -\x92\x53\xf0\xe1\xf1\x63\x73\x35\x16\xa2\xb2\x83\x26\x44\x93\x54\ -\x64\x45\xc2\xa3\x74\x36\x17\xd2\x55\xe2\x65\xf2\xb3\x84\xc3\xd3\ -\x75\xe3\xf3\x46\x27\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\ -\xc5\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\x37\ -\x47\x57\x67\x77\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\ -\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x05\x35\x01\x00\x02\ -\x11\x03\x21\x31\x12\x04\x41\x51\x61\x71\x22\x13\x05\x32\x81\x91\ -\x14\xa1\xb1\x42\x23\xc1\x52\xd1\xf0\x33\x24\x62\xe1\x72\x82\x92\ -\x43\x53\x15\x63\x73\x34\xf1\x25\x06\x16\xa2\xb2\x83\x07\x26\x35\ -\xc2\xd2\x44\x93\x54\xa3\x17\x64\x45\x55\x36\x74\x65\xe2\xf2\xb3\ -\x84\xc3\xd3\x75\xe3\xf3\x46\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\ -\xa5\xb5\xc5\xd5\xe5\xf5\x56\x66\x76\x86\x96\xa6\xb6\xc6\xd6\xe6\ -\xf6\x27\x37\x47\x57\x67\x77\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\ -\x03\x01\x00\x02\x11\x03\x11\x00\x3f\x00\xf4\x8e\xa9\x87\x9f\x97\ -\x53\x1b\x83\x9e\xfe\x9d\x63\x4c\x9b\x19\x5d\x76\xee\x11\xf4\x1c\ -\xcc\x86\xbb\xfe\x82\xe1\xfa\x2f\x54\xfa\xdd\xd5\x3a\xd3\xfa\x4b\ -\xba\xb9\xa5\xd4\xfa\xa6\xdb\x45\x34\x3b\xf9\x97\x0a\x5d\xe9\xb4\ -\xd0\xdf\xa5\x63\xbf\x3b\xf3\x17\xa2\xaf\x3a\xfa\x9f\xff\x00\x8b\ -\x8c\xef\x86\x5f\xfe\x7f\xad\x5a\xe5\xc8\xf6\xf2\xdc\x62\x78\x63\ -\x71\xb8\xc6\x4d\x6c\xf7\xee\x62\xa3\x21\xc5\x2a\x95\x48\x8b\x14\ -\xfa\x06\x2d\x57\x53\x8f\x5d\x57\xdc\xec\x9b\x58\xd0\x1f\x7b\x83\ -\x5a\x5e\x7f\x7d\xcc\xa8\x32\xb6\xff\x00\x61\xab\x23\xeb\x35\x1d\ -\x75\xb8\xd6\xe7\xf4\xae\xa2\xec\x5f\xb3\x52\xe7\xbb\x17\xd2\xad\ -\xed\x7e\xc9\xb1\xee\xf5\x2d\xae\xcb\x19\x66\xcf\x6b\x3f\xc1\xad\ -\xc4\x0c\xed\x70\xb2\x01\xff\x00\x44\xff\x00\xfa\x92\xa0\x84\xaa\ -\x60\xd0\x3a\xec\x40\x23\xec\x67\x9c\x6e\x24\x59\x1a\x6e\x0e\xaf\ -\x21\xf5\x6b\xa9\xf5\x6b\xe8\xa7\xaa\xf5\xae\xb8\xcc\x6c\x37\xd8\ -\xe6\x55\x8f\x6b\x31\xeb\xf5\xb6\x0f\x7c\xdc\xea\xea\x77\xd2\xff\ -\x00\x44\xbb\x3f\x5a\x93\x4f\xae\x1e\xd3\x4e\xdd\xfe\xa0\x23\x6e\ -\xd8\xdd\xbf\x7f\xd1\xd9\xb5\x71\x7d\x25\xac\x7f\xf8\xb5\xb4\x3d\ -\xa1\xed\xf4\xed\x30\x75\xe2\xc7\x10\x75\xfc\xe6\xfe\x6a\xbb\xd0\ -\xb2\x6f\xe8\x3d\x50\xfd\x5a\xcf\x71\x38\xb6\xcb\xfa\x3e\x4b\xff\ -\x00\x39\x93\x2e\xc4\x7b\xc7\xb7\xd5\xaf\xfd\x7f\x9c\xc7\xad\x4f\ -\x9a\x02\x46\x66\x34\x0c\x25\x21\xc1\x10\x23\xe8\x87\x6e\x16\x0c\ -\x39\x0c\x44\x04\xac\x89\x46\x27\x8c\x9b\xf5\xcf\xbb\xb2\x3e\xb1\ -\x7d\x5f\x31\x1d\x4f\x10\xcf\x1f\xa7\xaf\xff\x00\x26\xa7\x4f\x5c\ -\xe8\xb7\xd8\xca\xa8\xcf\xc6\xb6\xcb\x0e\xd6\x31\x97\x31\xce\x71\ -\xfd\xd6\xb5\xae\xdc\xe5\xcb\xf5\xc6\xb5\xbf\x56\x3e\xb3\x6d\x00\ -\x4e\x7c\x98\x11\xa9\x38\x5a\xab\xbd\x46\xba\xfa\x6f\xd6\xce\x93\ -\xd4\xda\xd0\xca\xba\x85\x6e\xc0\xc8\x70\x11\xef\x21\xaf\xc5\x3a\ -\x7e\x73\xde\xc6\x53\xfd\x44\xdf\x66\x15\xa5\xd9\xe2\xaf\xf0\x21\ -\x1c\x9f\xf7\x4b\xbd\xe9\x5e\xc2\xbd\x37\xfe\x14\xa5\x0f\xfb\x97\ -\x7b\x2b\xab\x74\xbc\x2b\x05\x59\x99\x94\x63\x58\x5b\xb8\x32\xdb\ -\x18\xc3\xb4\x9d\xbb\xb6\xd8\xe6\xfb\x77\x04\x1f\xf9\xc5\xd0\x37\ -\x06\xfe\xd3\xc4\xdc\x78\x1e\xbd\x73\xff\x00\x56\x80\xe0\xdc\xef\ -\xac\xcc\xd0\x1a\xfa\x45\x25\xd3\xdf\xd7\xca\xf6\x01\xff\x00\x5a\ -\xc4\xad\xff\x00\xfb\x14\xb9\xcf\xab\x99\xbd\x34\xfd\x5b\xab\xa3\ -\xe5\xb1\xcf\x3d\x43\x2a\xcc\x66\xb1\xac\x21\xad\xde\xef\xa6\xdb\ -\x9c\xcf\xb3\xef\xa7\xf9\xe6\x7b\x90\x8e\x28\x98\xdf\xa8\x91\xc3\ -\xc4\x07\xf5\xf8\xbf\xee\x62\xa9\x66\x22\x55\xa5\x1e\x2e\x1b\xfe\ -\xa7\x0f\xfd\xd3\xd6\x59\xd7\xfa\x15\x4f\x75\x76\xf5\x1c\x5a\xde\ -\xc7\x16\x3d\xae\xba\xb0\x43\x9a\x76\xb9\x8e\x6b\x9f\xed\x73\x5c\ -\xad\x8b\xe8\x75\x3f\x68\x6d\x8d\x34\x16\xef\x16\x87\x0d\x9b\x63\ -\x76\xfd\xff\x00\x47\x66\xdf\xce\x5c\xd3\x72\xb0\xb1\x7e\xbb\xf5\ -\x17\xe6\x5d\x55\x15\x3f\x06\x80\x5d\x6b\x9a\xc6\x93\xb9\xfa\x7e\ -\x90\xb7\x77\xb5\x67\x55\xd1\xba\x86\x6f\xd4\xde\xa3\x4e\x13\x1d\ -\x5d\x59\x39\x76\x64\x60\x62\xb8\x6d\xdd\x8d\xbc\x3e\xaa\x9a\xc7\ -\xed\xf4\x9b\x63\x5b\xea\x57\x5f\xfe\x95\x4b\xd9\x8e\x96\x4c\x41\ -\xe0\xd6\x5b\x7e\xb3\xfe\xf5\x5e\xf4\xb5\xa0\x24\x47\x16\x83\x7f\ -\x43\xd5\xd3\xd7\xfa\x25\xfe\xa7\xa5\x9f\x8e\xff\x00\x45\xa6\xcb\ -\x48\xb1\xb0\xd6\x0d\x1d\x6f\x3f\xcd\x7b\xbf\x9d\xfe\x6d\x44\xfd\ -\x62\xfa\xbe\x39\xea\x78\x9f\xf6\xfd\x7f\xf9\x35\x47\xa1\x75\x4e\ -\x97\xd7\x6e\xab\x29\xac\x38\xdd\x4b\xa7\xd6\xfa\x6d\xc4\x77\xb5\ -\xcc\x16\x6c\x16\xb7\x61\x1e\xfa\xb7\xd0\xcd\x9f\xb9\xfe\x11\x53\ -\xfa\x87\x85\x8d\x6f\x4a\xc7\xcc\x7b\x01\xbb\x1a\xdc\x96\x52\x60\ -\x7b\x7d\x57\xb7\xd4\x7f\xfc\x66\xda\xfd\x3d\xff\x00\xe8\xfd\x89\ -\x1c\x51\x02\x46\x42\x40\xc6\x87\x0f\xf7\xb8\xbf\xef\x52\x32\x48\ -\x98\x88\xf0\x9e\x2b\x37\xfd\xde\x1f\xfb\xe7\x6b\xfe\x71\x7d\x5f\ -\xd3\xfc\xa7\x89\xaf\x1f\xa7\xaf\xff\x00\x26\x8b\x47\x57\xe9\x39\ -\x37\x0c\x7c\x7c\xda\x2e\xbc\xcc\x55\x5d\xac\x73\xbd\xbf\x4f\xd8\ -\xc7\x17\x7b\x56\x17\xd5\xcc\x4a\x33\x4f\xd6\x3c\x4c\x96\xef\xa2\ -\xfe\xa1\x7b\x2c\x69\xee\x1d\xa1\x4d\xd4\x03\x3e\xaf\xfd\x64\xc4\ -\xea\x8e\x76\xdc\x1e\xa3\x58\xc3\xcf\xb5\xfd\xad\x60\xdd\x8b\x93\ -\x6b\xff\x00\x79\xfb\x7d\x27\xb9\x23\x8a\x1c\x46\x02\xf8\x80\xb8\ -\xff\x00\x5b\xd3\xc4\x81\x96\x5c\x22\x66\xb8\x49\xd7\xfa\xba\xf0\ -\xbd\x0d\x3d\x4f\xa7\x5f\x92\xec\x4a\x72\xa9\xb7\x26\xbd\xdb\xe8\ -\x65\x8d\x75\x8d\xd8\x76\x59\xbe\xb6\x9d\xed\xd8\xff\x00\x6b\x95\ -\x95\x89\xd2\x5f\x55\x18\x59\x7f\x58\x73\xe3\x1c\xe7\x7e\xb3\x61\ -\x70\x83\x5e\x3b\x1b\xb7\x0e\xa7\xed\xdd\xef\x6e\x38\xf5\x6c\x6f\ -\xfd\xc8\xba\xd4\x47\x75\xdb\x68\x14\x5f\x9d\x85\x66\x2e\x16\x43\ -\x9a\xc1\x7b\xdc\x0b\xab\x75\x84\x36\x8f\xb6\xd2\x3f\xa3\x36\xcd\ -\xdb\x37\xef\xb3\xd1\xb3\xf9\xe4\xc3\x8c\xd9\x11\xd6\xb4\xff\x00\ -\x0b\xf4\x84\x7f\x79\x90\x64\x14\x38\xb4\xbd\x7f\xc1\xfd\x1e\x2f\ -\xdd\x75\xd2\x59\x18\x1d\x72\xec\xcb\x8b\x5b\x86\xf6\xd6\xcc\x9b\ -\x30\xee\xb0\x38\x3b\x65\x95\x35\xce\x7b\xcb\x5a\xdf\xe8\xfb\x99\ -\xe9\xfa\xbf\xcb\xfe\x6d\x6b\xa6\x4a\x26\x26\x8a\xe8\xc8\x48\x58\ -\x7f\xff\xd0\xf5\x55\xe6\xdf\x56\x1d\x73\x3e\xb8\x75\x37\xe3\xb0\ -\x5b\x73\x6b\xcd\x35\x54\x4e\xd0\xe7\x8b\x99\xb1\x85\xff\x00\x99\ -\xbd\xdf\x9e\xbd\x25\x79\xcf\xd5\x77\x7a\x1f\x5f\x72\xea\x7f\xd2\ -\xb1\xf9\x95\x0e\xda\xfa\x9e\xb6\x9f\xd8\xa5\x59\xe5\xbe\x4c\xdf\ -\xdc\x6b\x73\x1f\xce\x60\xfe\xff\x00\xec\x74\xba\x97\xd7\xae\xaf\ -\xd2\xef\x18\xfd\x43\xa3\x8a\x2d\x2d\xde\xd1\xeb\x87\x07\x37\x8d\ -\xcc\x7d\x75\xb9\xaa\xd1\xeb\xdf\x5a\x32\xb0\x0d\xec\xe8\x4d\x38\ -\xf7\xd3\xbd\xb6\x7d\xaa\xbf\xa0\xf6\xee\x6b\xf6\x40\x7f\xd0\x77\ -\xd0\x58\xff\x00\xe3\x3b\xfa\x7e\x07\xfc\x4d\xbf\xf5\x55\xae\x9a\ -\xab\xc6\x37\xd4\x9a\xef\x26\x3d\x3e\x9a\xd7\x0f\x8f\xa0\x36\x8d\ -\x7f\x94\x9f\x28\xe3\x18\xf1\x4c\x63\x8f\x14\xcd\x6f\x3f\xfb\xe5\ -\x91\x96\x43\x97\x2c\x0e\x49\x70\xc0\x58\xd2\x1f\xf7\xaf\x19\x89\ -\xd7\xf2\x30\xfe\xa8\x7e\xce\xb7\xa7\xda\x71\x6f\x6d\x8c\xab\x3d\ -\xa7\xf4\x65\xce\x73\x8c\x3a\x5b\xb5\xae\x6b\xbf\x37\x7a\xea\xae\ -\xc8\xe8\x7f\x5c\xfa\x73\xf1\xf1\x2f\x35\xe6\x53\xfa\x6a\x77\x02\ -\xcb\xa9\xb1\xa7\xf4\x76\xed\xfd\xcd\xdf\x4f\xd2\x77\xfe\x0a\x8d\ -\xf5\x2f\x15\xa3\xea\x9e\x1d\x37\xd6\x1c\xdb\x59\x61\x7b\x1c\x24\ -\x39\xb6\x3e\xc3\xef\x6b\xbe\x93\x5f\x5b\x97\x19\xf5\x9f\xa4\x5b\ -\xf5\x67\xad\x53\x95\xd3\x5e\xea\xaa\xb2\x6d\xc4\x78\xd4\xd6\xf6\ -\xe9\x6e\x3e\xbf\xce\x57\xef\xfc\xff\x00\xe7\x29\xb3\xd1\xb1\x3c\ -\x70\x64\xcb\x28\xc7\xf5\x79\x23\x29\x4a\x12\xbb\x8c\xcf\x5b\x58\ -\x78\xf1\x63\x8c\xe5\xfa\xcc\x72\x8c\x63\x38\xd5\x4a\x11\xe9\xc3\ -\xfe\x33\xa7\x96\x7a\x8b\xfe\xa7\x75\x4c\x7e\xa1\x45\x83\xaa\x65\ -\xe5\x96\x9a\x99\x53\xce\xf7\xd6\x71\xb7\xd8\xcf\x49\x8e\x66\xc7\ -\xd7\x4f\xab\xea\xff\x00\x32\xff\x00\xf0\x6b\x7f\xeb\x2e\x38\xea\ -\xdf\x56\x1f\x76\x16\xf7\x5b\x46\xdc\xac\x63\xb5\xcd\x7e\xfa\x4c\ -\xe9\x53\xda\xdb\x77\xec\x16\x6c\x66\xc4\x1c\xaf\xad\x19\xdf\xf3\ -\x6a\x9f\xac\x18\x35\x52\xe6\x35\xbf\xad\xd3\x69\x70\x70\x7e\xe6\ -\xd0\xe6\xd2\xe6\x6e\xfa\x36\xff\x00\xa4\xff\x00\x04\x96\x47\x58\ -\xfa\xcf\x4f\x43\xfd\xb4\xca\x70\xad\xa7\xd0\x6e\x51\xa4\x1b\x5a\ -\xf1\x59\x6f\xaa\xef\x79\xdc\xc7\x7a\x4c\x51\x9e\x32\x62\x68\x44\ -\xc7\x21\xfd\x2d\x38\xfd\x23\x82\xbf\xc1\x64\x1c\x1a\xc6\xe5\x21\ -\x28\x0e\x9a\xf0\x7a\xa5\x19\xdf\xf8\x4d\xfe\x8b\xbf\x17\xa4\xbf\ -\xa8\xf5\x00\x6b\xc8\xcd\x71\xcc\xc9\x6c\x39\xc5\xbe\xa6\xd1\x55\ -\x3b\x36\xfa\xbf\xab\xe3\x36\x8a\x36\xec\xff\x00\x06\xb0\xfe\xaa\ -\xe6\xe0\xe2\x74\x21\x47\x52\xa6\xf6\x5b\x4d\xef\xbd\xb5\x3b\x1e\ -\xe2\xe9\xdd\xea\x52\xf6\x06\x56\x77\x2b\xfd\x6b\xae\xf5\xbe\x9f\ -\xd5\xf1\x7a\x7d\x35\x62\xd8\xce\xa2\xf2\xcc\x67\xbc\xd8\x1c\xcd\ -\xbb\x37\x7a\xf1\xed\x77\xb9\xff\x00\xe0\xd6\xce\x56\x63\xb0\x3a\ -\x65\x99\x99\x9b\x4b\xf1\xe9\x36\x5c\x2b\xd1\xa5\xcd\x6e\xe7\x36\ -\xad\xff\x00\xbe\xff\x00\x6d\x7b\x93\x09\x20\x6a\x2f\xdd\x22\x51\ -\xe1\x97\xee\xfa\x40\x5f\x40\x9d\x0d\x7b\x40\xc6\x5c\x51\xfd\xed\ -\xde\x5b\xa7\xbe\xae\xad\xd7\xf2\x5d\xd4\x71\xec\x65\x7d\x4f\xa7\ -\xd5\x45\x8c\x35\x5a\x1a\x2d\xf7\xd9\x75\x02\xd7\xd6\x1a\xd7\xd2\ -\xcf\xf0\x9f\xe9\x7e\x82\x2f\x4d\xeb\x9d\x47\xa3\xe2\x8e\x9b\xd4\ -\x71\xee\xb5\xdd\x3b\x21\xb4\x5b\x92\x29\xb1\xe1\xf8\x64\x3c\x55\ -\x99\x5b\xaa\x0e\x6f\xe8\x7f\x43\xeb\xff\x00\xc1\x7f\xc3\xa2\xe1\ -\xfd\x66\xeb\x39\x9f\x56\x9d\xd5\xb1\xe8\xa2\xcc\xac\x47\x58\x33\ -\xa8\x76\xf6\x08\xaf\xdf\xfa\x0f\x73\xdc\xd7\x36\xa2\xd7\xed\xb1\ -\x69\xfd\x59\xea\x79\xdd\x5b\xa6\xb7\xa8\x65\x32\x9a\xd9\x79\x3e\ -\x8b\x2a\x2e\x24\x06\x97\x56\xff\x00\x55\xcf\xfc\xed\xec\xfc\xc4\ -\xec\x96\x04\xb8\xa2\x38\x62\x44\x38\x78\xbe\x59\xc7\xf7\x7f\xc0\ -\x5b\x0a\x24\x70\xc8\xf1\x48\x19\xf1\x70\xe8\x60\x7f\x7b\xfc\x27\ -\x1e\xfb\x30\xb2\xbe\xb5\xe1\x75\x9e\x9a\xd7\x3a\x8c\x6a\x6d\x3d\ -\x4f\x32\xb6\x3b\xd3\x73\x4b\x3d\x3c\x7a\xb7\x06\xfe\xb1\x91\xbd\ -\xdf\x42\xbd\xef\xd9\x5f\xe9\x3f\x9b\x56\x3e\xa2\xda\x28\xe8\x96\ -\x51\x73\x2c\xaa\xda\x2c\xb2\xcb\x1b\x65\x6f\x61\xda\xe2\x5c\xc7\ -\x37\x7b\x1b\xbf\x73\x7f\x71\x68\x74\xdf\xac\x14\xe7\xf5\x9e\xa5\ -\xd2\xd8\xd0\x3e\xc0\x58\x19\x60\x33\xbe\x46\xdb\xfd\xb1\xec\xf4\ -\x2f\xfd\x12\x0f\x55\xea\x5d\x7b\x1b\xab\x63\x60\x61\x55\x8b\x6b\ -\x33\xb7\xfa\x4e\xb0\xd8\x1d\x58\xa9\xad\x7d\xd6\x5e\xd6\x7d\x26\ -\x6e\x77\xe8\xf6\x20\x4c\xa4\x3d\xb3\x1a\xf4\xc4\x8e\x29\x7e\x84\ -\x78\xa7\xff\x00\x76\xb8\x00\x0f\xb8\x0d\xeb\x20\x78\x63\xfa\x53\ -\xf4\xff\x00\xdc\x35\x7e\xa7\xdc\xd3\x99\xd6\x01\x6d\x8c\x39\x39\ -\xb6\xe4\x53\xea\x55\x63\x37\x54\x48\x0d\xb5\xae\xb1\x8d\x6f\xbb\ -\xfc\xf5\x2f\xaf\xff\x00\xa4\xfa\xbf\x6e\x2d\x75\xbe\xec\x8b\x9c\ -\xd3\x4b\x2b\xad\xd6\x12\x5a\xe6\xb9\xe7\xf4\x6d\x7f\xa7\xec\x46\ -\x1f\x59\x5c\x7e\xb7\x1e\x85\xb5\xbf\x67\xf4\x4c\x59\x07\x71\xc8\ -\x0d\xfb\x43\xab\x0e\x9d\x9e\x9b\x71\x8f\xee\xfd\x35\x0e\xbd\xd6\ -\xfa\xcf\x4c\xea\x78\x78\xb4\xd5\x8d\x65\x1d\x46\xd1\x4e\x3b\xde\ -\x5e\x1e\xc7\x7b\x03\x8d\xcd\x6f\xb5\xcd\xdc\xff\x00\xcc\x48\x09\ -\x7b\xd1\x97\x0d\x12\x06\x48\xc4\x9d\xc4\x7c\x7f\xc1\x41\x31\x18\ -\x65\x1b\xb0\x09\xc6\x48\x1b\x5b\x67\xeb\x06\x33\xfa\xe7\xd5\xac\ -\x9a\x7a\x7f\xb9\xf9\x0c\x0e\xa4\x3c\x16\x6e\x2c\x7b\x6c\xf4\xdc\ -\xdb\x83\x36\xfa\x9e\x9f\xa7\xfa\x45\x4b\xad\x65\xd7\xf5\x83\xa1\ -\xfe\xcc\xc3\x65\x83\x33\x3c\xb1\x96\x52\xf6\x39\xae\xc7\xda\xf6\ -\x59\x90\xfc\xcd\xe1\x9e\x93\x68\x6b\x5d\xff\x00\x86\x2c\xfe\x8f\ -\xea\x23\x3f\xaf\x75\x2e\x9b\xd5\x31\x30\x3a\xcd\x14\xfa\x5d\x41\ -\xde\x9e\x36\x5e\x33\x9c\x5a\x2c\x90\xd1\x55\xd4\xda\x37\xb7\x73\ -\x9e\xcf\xd2\x35\xea\xbd\x3d\x73\xeb\x1d\xbd\x72\xee\x87\xe9\xe1\ -\x37\x22\x8a\x85\xee\xbb\xf4\xa5\x85\xa7\x67\xb5\xac\xfa\x6d\x77\ -\xe9\x7f\x79\x28\x46\x42\xa8\x0a\x81\xf7\x60\x78\xbf\xc1\xff\x00\ -\x0b\xe5\x8a\x67\x28\x9d\xc9\xb9\x0f\x6a\x63\x87\xfc\x2f\xf0\x7e\ -\x66\x7f\x56\x71\x5d\x6e\x4e\x66\x5f\xad\x7d\x6d\x66\x7e\x53\xdb\ -\x8e\x41\x65\x6f\x65\xc4\x7a\x77\x6d\x7b\x19\x63\xf8\xfd\x1b\xf7\ -\xec\x5d\x2a\xc9\xe9\x9d\x43\xaa\xbf\xa9\xe5\x74\xee\xa7\x55\x0c\ -\x75\x15\x57\x75\x56\x50\x5c\x43\xdb\x61\xb1\x93\xb6\xcf\x73\x36\ -\x3a\xa5\xac\xa2\xca\x49\x96\xbd\x85\x56\xba\x32\x62\x00\x47\x4e\ -\xe6\xef\xbb\xff\xd1\xf5\x55\xe7\xff\x00\x5c\x3a\x4f\x50\xe9\x3d\ -\x6d\x9f\x59\x7a\x73\x37\xd5\xb9\xb6\xdb\x00\x91\x5d\x8d\x1b\x1f\ -\xeb\x35\x9e\xef\xb3\x64\xd4\x3f\x49\x67\xfc\x6f\xfa\x4a\xd7\xa0\ -\x24\xa4\xc5\x94\xe3\x95\x81\x60\x8e\x19\x44\xfe\x94\x58\xf3\x62\ -\x19\x23\x44\xd1\x07\x8a\x32\x1f\xa3\x20\xf9\x57\xd6\xee\xbf\x87\ -\xd7\x9f\x83\x93\x8a\x1c\xc7\x57\x53\xdb\x7d\x4f\x1a\xb1\xce\x2c\ -\x20\x07\x8f\x6d\x8d\xf6\xbb\xde\xd5\xab\x5e\x5e\x67\xd6\x7e\x9d\ -\x81\xf5\x77\xa6\x31\xf5\xe1\x51\x55\x2d\xea\x99\xae\x10\xd0\x6a\ -\x6b\x37\x51\x54\xfd\x27\xef\x6f\xf6\xdf\xff\x00\x01\xfa\x44\x0f\ -\xf1\x91\x8d\x8f\x47\x50\xc3\x34\x54\xca\x8d\x95\x5a\xeb\x0b\x1a\ -\x1a\x5c\x43\xab\x87\x3f\x68\xf7\xae\xdf\xea\xf8\x03\xa0\xf4\xd8\ -\x11\xfa\xad\x27\xef\xad\x8a\xde\x4c\x91\x8e\x0c\x52\x8c\x7a\x9e\ -\x0e\x23\xf2\x1e\xff\x00\xd6\x69\xe3\xc7\x29\x67\xcb\x19\x4b\xa4\ -\x78\xf8\x45\x71\x86\xe5\x14\xd5\x8f\x4d\x74\x52\xdd\x95\x54\xd0\ -\xca\xd8\x38\x0d\x68\xda\xc6\xff\x00\x9a\xb9\x7f\xf1\x91\x43\x5f\ -\xd1\x29\xba\x25\xd4\xe4\x32\x0f\x80\x7b\x5e\xc7\x7f\xdf\x57\x58\ -\xb9\x6f\xf1\x8d\x66\xcf\xab\xed\x68\x3f\xce\x64\x56\xd8\xf1\x00\ -\x3d\xff\x00\xf7\xc5\x5b\x97\x27\xde\x87\xf7\x9b\x5c\xc8\x1e\xc4\ -\xc7\xf5\x5e\x67\xa5\xdc\xe7\x7d\x43\xeb\x74\x1f\xa3\x55\xd5\xb8\ -\x1f\xeb\xba\x8d\xdf\xf5\x0b\xa4\xc0\xea\xfd\x46\xbc\x3e\x81\x86\ -\x30\xdf\x46\x36\x47\xa3\x4b\xf2\x6c\x35\x3d\x96\x30\x50\xe7\xec\ -\x63\x2b\xb2\xcb\x19\xeb\x6c\xf6\x7a\x8c\x62\xe5\xba\x7b\xe9\xa3\ -\xea\x4f\x57\x37\x5a\xca\xdf\x99\x73\x19\x8f\x5b\x9c\x03\x9e\x6a\ -\x34\x1b\x7d\x26\x1f\x75\x9b\x37\xfb\xb6\xae\xc7\xa4\x75\xef\xab\ -\x8c\xe8\x38\x07\x27\x3b\x14\x3b\x17\x1e\xa2\x58\xf7\xb3\x7b\x1f\ -\x5d\x7b\x1f\xb6\xa2\x7d\x5f\x55\xbe\xf6\xfb\x18\xad\x67\x1f\x35\ -\x43\x8b\xf5\x92\xff\x00\xd2\x71\xff\x00\xba\x6a\xf2\xff\x00\xa3\ -\xea\xe1\xfd\x5c\x7f\xe9\xc9\xad\xf5\xa7\xff\x00\x15\x3f\x57\x3f\ -\xe3\x5f\xf9\x6b\x5a\xbd\x70\x1c\xac\x9e\x9d\xd2\x9a\x25\xb9\x17\ -\x8c\x8c\x8d\x37\x0f\x43\x17\x6e\x43\xb7\xff\x00\x26\xcc\xaf\xb2\ -\x53\xff\x00\x5c\x5c\x9f\x50\xeb\xf8\xd9\xbd\x4f\xea\xe7\x50\xc9\ -\xba\x9a\x88\xb6\xdb\x2e\x60\x78\x3e\x95\x6f\xb1\xbf\x65\xfb\x47\ -\xb9\xde\x9b\xfd\x0f\x4f\xd4\xdd\xfc\xb5\x63\xa9\x75\x4e\x8b\xd5\ -\x3a\x9e\x4d\x8e\x38\xb9\xd6\x8b\x71\xba\x6f\x4b\xa2\xdf\xd2\x34\ -\xba\xc7\x87\x65\xe5\x7a\x6d\x73\x7f\x45\xfa\x5d\x9e\xb7\xd0\xfd\ -\x57\xe9\xfe\x91\x47\xed\x4a\xb1\xd8\x3e\x88\xcb\x5a\xbf\x57\x1c\ -\xa2\x3f\xef\xd9\x7d\xc8\xde\x4a\x20\xf1\xca\x3e\x17\x1e\x0d\x7f\ -\xef\x5b\xfd\x09\xbf\xb3\xfe\xb6\xf5\x9e\x91\x60\x9a\x73\x40\xcd\ -\xa0\x3b\x82\x1e\x7f\x4e\xd6\xb7\xf7\x77\xdb\xe9\xff\x00\xd6\x15\ -\x7f\xaa\xdd\x41\xbd\x17\xa3\xf5\xac\x5b\xce\xf3\xd1\x6e\xb4\xb4\ -\x38\xc6\xe6\xeb\xe9\x35\xbf\xf1\xd6\x57\xed\xff\x00\x8c\x40\xfa\ -\xc5\x5f\x48\xfa\xb3\xd7\x7a\x46\x7e\x10\xab\x18\x35\xce\x6e\x56\ -\x3d\x70\x1d\xe9\x3f\xf4\x6e\xbc\xd4\x3d\xde\xd6\x3a\xef\xfa\xe2\ -\x26\x4e\x19\xc8\xfa\xec\xda\xb1\x9e\xdb\x30\x3a\xad\x54\x67\x64\ -\x39\x90\xe6\xbd\x98\x87\xd9\xb4\xea\xd7\x57\x66\x43\x31\x77\xfe\ -\xff\x00\xa8\x8d\x09\x46\xcf\xcb\x38\x46\x56\x7d\x3e\xac\x1e\x99\ -\x7f\x8d\x8d\x16\x63\x2a\x1f\x34\x27\x28\x80\x3d\x5e\x9c\xde\xa8\ -\xff\x00\x8b\x34\x5f\x63\xb3\xea\xdf\x5e\xe8\x59\x76\xf3\x9d\x51\ -\xc5\xea\x2e\x99\xdd\x91\x61\xf5\x2d\xb5\xef\xfe\x56\x4d\xcc\x76\ -\xef\xf4\x54\x2d\xef\xb4\x54\x7e\xb0\xf5\x2e\xa3\x79\x23\x1f\xa3\ -\xe2\x36\x92\x62\x61\xd6\x0f\xb7\xe5\xb9\xbf\xf5\x86\x62\x28\xfd\ -\x7a\xe9\xdf\x6e\xfa\xbb\x7b\x9a\x3f\x49\x89\x19\x2c\x3c\x68\xcf\ -\xe7\x7f\xf0\x17\x58\xb0\xd9\x9b\x8e\x3a\x26\x16\x16\x76\x45\x75\ -\xe5\xfd\x61\xca\x6e\x56\x68\x73\xf6\x46\x3d\x8f\xf5\x5e\xfe\x7f\ -\x45\x5d\xf8\xf4\x55\x8b\x4f\xfc\x62\x03\xf5\x90\x13\x3f\x36\xb8\ -\xe5\x5b\xd5\xfb\x9c\x5f\xf8\x5a\x4f\xea\xe7\x28\x0f\x97\x4c\x91\ -\xed\x7f\x27\x0f\xf8\xeb\x75\x9c\x4c\xbe\x9f\xd1\xba\x47\x5f\xb1\ -\x84\x66\x63\x65\x1c\xcc\xc6\x34\x16\x99\xcb\x77\xda\x2d\xa9\xff\ -\x00\xb9\xb3\xf4\x78\x8a\xff\x00\xd7\x2b\xeb\x1d\x47\xea\xe6\x40\ -\x25\xf5\x0c\xb1\x60\x2c\x69\x79\x2d\xfd\x13\xbd\x8c\xac\x3a\xcb\ -\x3f\xaa\xc6\xab\x5d\x6f\xea\xbf\xd5\xca\xba\x46\x65\x8d\xc5\xc7\ -\xc4\x78\xa9\xc5\x99\x06\x18\x1a\xff\x00\xf0\x5f\xa4\x3f\x47\x75\ -\xbb\x1a\xb9\x4a\xfa\xe6\x2e\x46\x27\xd5\x71\x6d\xcc\x16\xf4\xfc\ -\xb1\x5e\x40\x73\x9a\xdd\xb5\xb5\xd5\x36\xab\x5d\x27\xdb\x4b\x69\ -\xdb\xfa\x4f\xf8\x37\xa7\x63\xf5\xf0\xcc\x59\xe0\x33\x07\x4a\xd3\ -\x24\x65\x2f\xeb\x2c\xc9\x70\xe2\x81\xa1\xc6\x20\x46\xb7\xea\x84\ -\xa3\x17\xa3\xcc\x73\x3e\xb3\xf5\xec\x2a\x70\xc3\x86\x27\x46\xb4\ -\x64\x67\x59\x6b\x4d\x6e\xf5\x34\x7e\x3e\x33\x71\xef\x0c\xbf\x73\ -\xfd\x3f\xd2\x6f\xaf\xd3\xf4\xd0\x3d\x7b\xf1\xff\x00\xc6\x16\x73\ -\xf1\xf1\x9f\x98\xf3\x86\xc0\x6b\xad\xcc\x69\x03\xf4\x3e\xf9\xbd\ -\xf5\x33\x6f\xe6\xfd\x25\x3f\xac\x57\x0e\x8f\xd5\xb0\xfe\xb6\x61\ -\x11\x76\x16\x43\x46\x3f\x50\xf4\x88\x73\x5f\x59\xfe\x62\xf6\xb8\ -\x1d\xae\x76\xdf\xa0\xff\x00\xf8\x3a\x6b\xff\x00\x0a\xab\x61\xf5\ -\xbe\x8f\xff\x00\x3f\x72\x73\x4e\x65\x23\x16\xfc\x36\xb2\xbb\xcb\ -\xc0\x61\x74\x52\xfd\x9e\xa3\xbd\xac\x7e\xd6\xbb\xe9\xff\x00\xd5\ -\xa1\x10\x78\x6e\x22\xe1\xed\x48\x01\xfd\x7e\x2f\x5c\x64\xba\x64\ -\x71\x00\x4d\x4f\xdd\x89\x27\xfa\xbc\x3e\x89\x45\xe9\x7a\x06\x7e\ -\x57\x50\xc6\xbe\xfc\xba\xfd\x0b\x9b\x91\x6d\x5e\x89\x8d\xd5\xb5\ -\x87\x6b\x2a\x7b\x99\xb9\xaf\x77\xe7\x6f\x5a\x8b\x0a\xcf\xac\x9d\ -\x30\x75\x3c\x6c\x3e\x9f\x75\x17\xb6\xc1\x6e\x4e\x75\x94\x91\x60\ -\x65\x55\x56\x7d\xe7\xd1\x3f\xcf\x3e\xdf\x47\xf7\xff\x00\x46\xb5\ -\x70\x73\xb1\xb3\xe8\xf5\xf1\x9c\x5c\xc9\x2d\x32\x08\x20\xb7\x90\ -\x41\x55\xb2\x44\xdf\x17\x0f\x08\x3d\x3b\x36\x61\x21\xf2\xf1\x71\ -\x11\xf8\xbf\xff\xd2\xf5\x54\x92\x43\xc8\xb8\x63\xe3\xdb\x79\x63\ -\xec\x15\x31\xcf\x2c\xad\xa5\xcf\x76\xd1\xbb\x65\x75\xb7\xe9\xd8\ -\xef\xcc\x62\x4a\x78\x1f\xf1\x9d\xfd\x3f\x03\xfe\x26\xdf\xfa\xaa\ -\xd7\x67\xf5\x7f\xfe\x41\xe9\xbf\xf8\x52\x8f\xfc\xf6\xc5\xc1\x7d\ -\x6e\xc8\xea\x3d\x7b\x36\x8b\x71\xba\x56\x7d\x74\xe3\xd6\xe6\x03\ -\x66\x35\xa1\xce\x2f\x21\xce\x3b\x5a\xc7\x6d\x6f\xb1\x6e\xf4\x4f\ -\xad\x19\x58\x9d\x33\x1f\x0f\x37\xa3\x75\x1f\x57\x1a\xb6\xd4\x1d\ -\x56\x35\x8e\x6b\x9a\xc1\xb1\x8e\xf7\x06\x39\xae\xd8\xdf\x7a\xbb\ -\x93\x1c\x8f\x2f\x8e\x22\xb8\xa2\x4d\x8b\x1d\x5a\x58\xa6\x07\x31\ -\x96\x44\x1e\x19\x01\x47\x86\x5d\x1e\xbd\x79\xff\x00\xf8\xc5\xcf\ -\x39\x59\xf8\x7d\x1f\x18\x1b\x6d\xa8\xef\x7b\x1b\xa9\x36\xdb\xec\ -\xc7\xa7\x6f\xef\xec\xf7\xff\x00\xd7\x6b\x5b\x19\x1f\x58\x3e\xb2\ -\x67\xb0\xd3\xd1\xba\x35\xd8\xee\x76\x9f\x6a\xce\x02\xa6\xb2\x7f\ -\x3d\xb4\x3c\xee\x7f\xfa\xfe\x8e\xc4\x5f\xab\x7f\x54\x2b\xe9\x57\ -\x3b\xa8\x67\xdb\xf6\xce\xa9\x61\x25\xd7\x19\x2d\x61\x77\xf3\x86\ -\xad\xfe\xf7\x5b\x67\xf8\x4b\xdf\xfd\x4f\xd1\xfb\xf7\xc7\x88\x0c\ -\x27\xdc\x99\x1c\x43\xe4\x80\x36\x78\xbf\xad\xfb\xac\x99\xaf\x30\ -\xf6\xe0\x0f\x0c\xbe\x79\x9d\x07\x0f\x68\xba\x1d\x0b\xa3\x55\xd2\ -\xfa\x4e\x36\x0b\xc3\x6c\xb2\xa6\x93\x63\xe0\x10\x6c\x79\xdf\x69\ -\x69\x2d\x6f\xb7\x77\xb5\x9f\xf0\x6a\xff\x00\xd9\xe8\x99\xf4\xd9\ -\x3e\x3b\x42\x22\x4a\xbc\xa4\x64\x49\x27\x52\x6d\x9e\x31\x11\x00\ -\x01\xa0\x14\xc3\xd1\xa6\x67\xd3\x6c\x9e\x74\x09\x0a\x69\x04\x10\ -\xc6\x82\x38\x20\x05\x34\x90\xb2\xba\x83\x17\x57\x5b\x8e\xe7\x31\ -\xa4\xf1\x24\x02\x61\x20\xc6\x36\x36\xb4\x08\x10\x20\x70\x3c\x14\ -\x92\x49\x4b\x10\x08\x83\xc2\x89\xa6\x93\xcb\x1a\x74\x03\x50\x38\ -\x1c\x05\x34\x92\x52\xce\x6b\x5c\x36\xb8\x07\x03\xc8\x3a\x85\x1f\ -\x46\x9f\xf4\x6d\xfb\x82\x9a\x49\x29\x8e\xc6\x6d\xd9\xb4\x6d\xe3\ -\x6c\x69\x1f\x05\x1f\x42\x88\x8f\x4d\xb1\xfd\x50\x88\x92\x56\xaa\ -\x47\xe8\x51\xb4\xb7\xd3\x6e\xd7\x02\xd7\x0d\xa2\x08\x3f\x49\xa5\ -\x36\x3e\x36\x3e\x2d\x2d\xa3\x1a\xa6\xd3\x53\x3e\x8d\x6c\x01\xad\ -\x13\xaf\xd1\x6a\x2a\x48\xd9\xee\x8a\x1b\xd3\xff\xd3\xf5\x54\x97\ -\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\ -\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\ -\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\ -\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\xa9\x24\xa7\xea\xa4\x97\xca\ -\xa9\x24\xa7\xff\xd9\x00\x38\x42\x49\x4d\x04\x21\x00\x00\x00\x00\ -\x00\x55\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00\x41\x00\x64\x00\ -\x6f\x00\x62\x00\x65\x00\x20\x00\x50\x00\x68\x00\x6f\x00\x74\x00\ -\x6f\x00\x73\x00\x68\x00\x6f\x00\x70\x00\x00\x00\x13\x00\x41\x00\ -\x64\x00\x6f\x00\x62\x00\x65\x00\x20\x00\x50\x00\x68\x00\x6f\x00\ -\x74\x00\x6f\x00\x73\x00\x68\x00\x6f\x00\x70\x00\x20\x00\x43\x00\ -\x53\x00\x33\x00\x00\x00\x01\x00\x38\x42\x49\x4d\x04\x06\x00\x00\ -\x00\x00\x00\x07\x00\x05\x00\x01\x00\x01\x01\x00\xff\xe1\x0e\x98\ -\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\ -\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x00\x3c\x3f\x78\ -\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\xbb\ -\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\x68\ -\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\x22\ -\x3f\x3e\x20\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\x3a\ -\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\x22\ -\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x34\ -\x2e\x31\x2d\x63\x30\x33\x36\x20\x34\x36\x2e\x32\x37\x36\x37\x32\ -\x30\x2c\x20\x4d\x6f\x6e\x20\x46\x65\x62\x20\x31\x39\x20\x32\x30\ -\x30\x37\x20\x32\x32\x3a\x31\x33\x3a\x34\x33\x20\x20\x20\x20\x20\ -\x20\x20\x20\x22\x3e\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\ -\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\ -\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\ -\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\ -\x78\x2d\x6e\x73\x23\x22\x3e\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\ -\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\ -\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x61\x70\x3d\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\ -\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x20\x78\ -\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\ -\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\ -\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3a\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\ -\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\ -\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x78\x61\x70\x4d\x4d\x3d\x22\x68\x74\x74\ -\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\ -\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x74\x69\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\ -\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\ -\x66\x66\x2f\x31\x2e\x30\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x65\ -\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\ -\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\ -\x30\x2f\x22\x20\x78\x61\x70\x3a\x43\x72\x65\x61\x74\x65\x44\x61\ -\x74\x65\x3d\x22\x32\x30\x30\x39\x2d\x30\x31\x2d\x31\x34\x54\x31\ -\x35\x3a\x33\x31\x3a\x34\x33\x2d\x30\x35\x3a\x30\x30\x22\x20\x78\ -\x61\x70\x3a\x4d\x6f\x64\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\ -\x30\x31\x30\x2d\x30\x37\x2d\x32\x38\x54\x31\x33\x3a\x30\x34\x3a\ -\x35\x30\x2d\x30\x34\x3a\x30\x30\x22\x20\x78\x61\x70\x3a\x4d\x65\ -\x74\x61\x64\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x31\x30\ -\x2d\x30\x37\x2d\x32\x38\x54\x31\x33\x3a\x30\x34\x3a\x35\x30\x2d\ -\x30\x34\x3a\x30\x30\x22\x20\x78\x61\x70\x3a\x43\x72\x65\x61\x74\ -\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\x64\x6f\x62\x65\x20\x50\x68\ -\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x53\x33\x20\x4d\x61\x63\x69\ -\x6e\x74\x6f\x73\x68\x22\x20\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\ -\x3d\x22\x69\x6d\x61\x67\x65\x2f\x6a\x70\x65\x67\x22\x20\x70\x68\ -\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\x72\x4d\x6f\x64\ -\x65\x3d\x22\x33\x22\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\ -\x48\x69\x73\x74\x6f\x72\x79\x3d\x22\x22\x20\x78\x61\x70\x4d\x4d\ -\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\x75\x75\x69\ -\x64\x3a\x30\x32\x39\x34\x41\x43\x45\x37\x44\x41\x39\x42\x44\x46\ -\x31\x31\x41\x43\x41\x33\x39\x37\x37\x38\x46\x42\x30\x42\x39\x45\ -\x36\x37\x22\x20\x74\x69\x66\x66\x3a\x4f\x72\x69\x65\x6e\x74\x61\ -\x74\x69\x6f\x6e\x3d\x22\x31\x22\x20\x74\x69\x66\x66\x3a\x58\x52\ -\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x30\x30\x30\ -\x30\x2f\x31\x30\x30\x30\x30\x22\x20\x74\x69\x66\x66\x3a\x59\x52\ -\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x30\x30\x30\ -\x30\x2f\x31\x30\x30\x30\x30\x22\x20\x74\x69\x66\x66\x3a\x52\x65\ -\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x55\x6e\x69\x74\x3d\x22\x32\x22\ -\x20\x74\x69\x66\x66\x3a\x4e\x61\x74\x69\x76\x65\x44\x69\x67\x65\ -\x73\x74\x3d\x22\x32\x35\x36\x2c\x32\x35\x37\x2c\x32\x35\x38\x2c\ -\x32\x35\x39\x2c\x32\x36\x32\x2c\x32\x37\x34\x2c\x32\x37\x37\x2c\ -\x32\x38\x34\x2c\x35\x33\x30\x2c\x35\x33\x31\x2c\x32\x38\x32\x2c\ -\x32\x38\x33\x2c\x32\x39\x36\x2c\x33\x30\x31\x2c\x33\x31\x38\x2c\ -\x33\x31\x39\x2c\x35\x32\x39\x2c\x35\x33\x32\x2c\x33\x30\x36\x2c\ -\x32\x37\x30\x2c\x32\x37\x31\x2c\x32\x37\x32\x2c\x33\x30\x35\x2c\ -\x33\x31\x35\x2c\x33\x33\x34\x33\x32\x3b\x33\x45\x36\x34\x31\x41\ -\x42\x34\x41\x30\x33\x45\x36\x32\x34\x42\x43\x32\x35\x46\x30\x31\ -\x37\x32\x44\x39\x43\x39\x38\x36\x41\x35\x22\x20\x65\x78\x69\x66\ -\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\ -\x3d\x22\x31\x38\x30\x22\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\ -\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x37\x33\x22\ -\x20\x65\x78\x69\x66\x3a\x43\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\ -\x3d\x22\x2d\x31\x22\x20\x65\x78\x69\x66\x3a\x4e\x61\x74\x69\x76\ -\x65\x44\x69\x67\x65\x73\x74\x3d\x22\x33\x36\x38\x36\x34\x2c\x34\ -\x30\x39\x36\x30\x2c\x34\x30\x39\x36\x31\x2c\x33\x37\x31\x32\x31\ -\x2c\x33\x37\x31\x32\x32\x2c\x34\x30\x39\x36\x32\x2c\x34\x30\x39\ -\x36\x33\x2c\x33\x37\x35\x31\x30\x2c\x34\x30\x39\x36\x34\x2c\x33\ -\x36\x38\x36\x37\x2c\x33\x36\x38\x36\x38\x2c\x33\x33\x34\x33\x34\ -\x2c\x33\x33\x34\x33\x37\x2c\x33\x34\x38\x35\x30\x2c\x33\x34\x38\ -\x35\x32\x2c\x33\x34\x38\x35\x35\x2c\x33\x34\x38\x35\x36\x2c\x33\ -\x37\x33\x37\x37\x2c\x33\x37\x33\x37\x38\x2c\x33\x37\x33\x37\x39\ -\x2c\x33\x37\x33\x38\x30\x2c\x33\x37\x33\x38\x31\x2c\x33\x37\x33\ -\x38\x32\x2c\x33\x37\x33\x38\x33\x2c\x33\x37\x33\x38\x34\x2c\x33\ -\x37\x33\x38\x35\x2c\x33\x37\x33\x38\x36\x2c\x33\x37\x33\x39\x36\ -\x2c\x34\x31\x34\x38\x33\x2c\x34\x31\x34\x38\x34\x2c\x34\x31\x34\ -\x38\x36\x2c\x34\x31\x34\x38\x37\x2c\x34\x31\x34\x38\x38\x2c\x34\ -\x31\x34\x39\x32\x2c\x34\x31\x34\x39\x33\x2c\x34\x31\x34\x39\x35\ -\x2c\x34\x31\x37\x32\x38\x2c\x34\x31\x37\x32\x39\x2c\x34\x31\x37\ -\x33\x30\x2c\x34\x31\x39\x38\x35\x2c\x34\x31\x39\x38\x36\x2c\x34\ -\x31\x39\x38\x37\x2c\x34\x31\x39\x38\x38\x2c\x34\x31\x39\x38\x39\ -\x2c\x34\x31\x39\x39\x30\x2c\x34\x31\x39\x39\x31\x2c\x34\x31\x39\ -\x39\x32\x2c\x34\x31\x39\x39\x33\x2c\x34\x31\x39\x39\x34\x2c\x34\ -\x31\x39\x39\x35\x2c\x34\x31\x39\x39\x36\x2c\x34\x32\x30\x31\x36\ -\x2c\x30\x2c\x32\x2c\x34\x2c\x35\x2c\x36\x2c\x37\x2c\x38\x2c\x39\ -\x2c\x31\x30\x2c\x31\x31\x2c\x31\x32\x2c\x31\x33\x2c\x31\x34\x2c\ -\x31\x35\x2c\x31\x36\x2c\x31\x37\x2c\x31\x38\x2c\x32\x30\x2c\x32\ -\x32\x2c\x32\x33\x2c\x32\x34\x2c\x32\x35\x2c\x32\x36\x2c\x32\x37\ -\x2c\x32\x38\x2c\x33\x30\x3b\x32\x34\x44\x41\x30\x37\x46\x44\x41\ -\x35\x39\x32\x37\x43\x36\x37\x32\x32\x34\x31\x36\x31\x35\x45\x41\ -\x37\x36\x34\x44\x32\x41\x42\x22\x2f\x3e\x20\x3c\x2f\x72\x64\x66\ -\x3a\x52\x44\x46\x3e\x20\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\x65\x74\ -\x61\x3e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\x6e\x64\ -\x3d\x22\x77\x22\x3f\x3e\xff\xee\x00\x0e\x41\x64\x6f\x62\x65\x00\ -\x64\x40\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x04\x03\x03\x03\x03\ -\x03\x04\x03\x03\x04\x06\x04\x03\x04\x06\x07\x05\x04\x04\x05\x07\ -\x08\x06\x06\x07\x06\x06\x08\x0a\x08\x09\x09\x09\x09\x08\x0a\x0a\ -\x0c\x0c\x0c\x0c\x0c\x0a\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x04\x05\x05\x08\ -\x07\x08\x0f\x0a\x0a\x0f\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\ -\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\ -\x08\x00\x49\x00\xb4\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01\xff\ -\xdd\x00\x04\x00\x17\xff\xc4\x00\xc5\x00\x00\x02\x02\x03\x01\x01\ -\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x06\x08\x03\x04\ -\x05\x02\x01\x09\x01\x00\x02\x02\x03\x01\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x05\x04\x06\x02\x03\x07\x01\x10\x00\x01\ -\x03\x02\x05\x02\x03\x04\x03\x06\x11\x0d\x00\x00\x00\x00\x02\x01\ -\x03\x04\x05\x06\x00\x11\x21\x12\x07\x22\x13\x31\x41\x08\x51\x32\ -\x14\x15\x61\x42\x23\x71\xd1\x52\x62\x93\x37\x81\x72\xb2\x33\x53\ -\x73\x54\x84\xb4\xc4\x75\x85\xb5\x16\x46\x76\x17\x91\x82\xa2\x63\ -\xd3\x74\x94\x35\x55\x36\x56\x18\x38\x11\x00\x01\x03\x02\x02\x04\ -\x07\x0d\x06\x06\x02\x03\x01\x00\x00\x00\x02\x00\x01\x03\x11\x04\ -\x21\x12\x31\x22\x13\x05\x41\x51\x71\xc1\x32\x42\x72\xf0\x61\x81\ -\x91\xa1\xb1\x52\x62\x82\xb2\xc2\x14\x06\xd1\xa2\x23\x43\x34\x35\ -\xe1\x92\xd2\x33\x73\x15\xf1\x24\xf2\x53\xc3\x25\xff\xda\x00\x0c\ -\x03\x01\x00\x02\x11\x03\x11\x00\x3f\x00\xbb\xd7\x8d\x2a\xe8\xab\ -\xd1\xfe\x16\xd1\xaf\xa5\xb9\x57\x47\x45\xc4\x9e\x51\x1a\x9e\x84\ -\xd8\xa1\x22\xb6\xad\xbd\xd2\x9b\x95\x51\x77\x78\xa6\x58\x93\x6f\ -\x24\x60\x75\x90\x73\xb7\x15\x72\xf9\x94\x4b\xa8\xe5\x30\xa4\x47\ -\x90\xb8\xe8\xc5\xe7\x55\x1a\xaf\xca\xbe\xa0\xe9\x3c\x84\x5c\x70\ -\x77\x63\x2e\xd6\x56\xa0\xcd\x31\x97\x86\x0c\x01\x64\xdc\x94\x40\ -\x2d\x16\x6b\x17\x34\x45\x47\x05\x57\x4d\x31\x76\x8e\xc2\xc4\xe0\ -\xdb\x64\xd5\xa6\x6d\x25\xc1\xed\x2a\x14\xbb\xc7\x78\x05\xc6\xc3\ -\x68\xd9\xb3\x30\xf4\x47\xad\xa3\xaa\xad\x7d\x8d\x45\xbd\x68\xd0\ -\x1f\x6e\xf7\xb9\x82\xe5\x9e\xf1\x89\xb2\xeb\x70\x99\x82\x0c\x0a\ -\x26\x4a\x09\xd9\xcb\x7e\x6b\xae\xe2\x14\xc5\x32\xea\x48\x4c\x9b\ -\x64\x19\x1b\x95\xca\xbe\x35\x7a\xb4\x8a\x78\xc5\xf6\xc7\xb4\x7e\ -\xcb\x0d\x3c\x5a\x57\x66\xbb\x12\xab\x3e\x91\x32\x1d\x12\xa3\xf2\ -\x8a\xb3\xcd\xa8\xc4\xa9\x76\x02\x57\x61\xcc\xf4\x3e\xd3\x8a\x82\ -\x7f\x71\x71\xa2\x22\x11\x36\x72\x6c\xcd\xe8\xd6\x95\xf0\xa9\x13\ -\x09\x90\x3b\x01\x65\x2e\x02\xa6\x6a\x78\x15\x4e\xbc\x6f\x3f\x52\ -\x16\x8d\xff\x00\x03\x8f\x8e\xeb\x66\x6d\x42\xae\x4c\x7c\xaa\x53\ -\x70\x69\xe0\xd3\xa1\x29\xc5\x68\x08\xb7\x46\xcc\x32\x21\x24\x34\ -\xd7\x2c\xbc\xd3\x2c\x5c\xed\xad\xb7\x7c\xd0\x3c\xd9\x28\xc3\x5c\ -\xd8\x97\x07\xb4\xa8\xb7\x57\x5b\xca\x0b\x86\x87\x68\xce\xe5\x4c\ -\xaf\x94\x7a\xd8\x7a\x2a\xca\x58\x50\xee\x9a\x5d\x3d\xd8\x57\xad\ -\xd4\xc5\xcd\x5d\x37\x54\xf7\xb1\x19\x88\x68\xc0\x20\xa0\xab\x48\ -\x2c\xed\xdf\x91\x22\xae\xf2\x11\x2d\x72\xcb\x15\x4b\xb2\x8c\x8a\ -\xb1\x03\x80\xf2\xb9\x57\xc6\xae\x36\x63\x28\x0d\x25\x91\xa4\x2e\ -\x46\x1a\x77\xb0\x52\xa7\x9f\x62\x38\x77\x24\x38\x0d\x06\x79\x6e\ -\x32\x41\x4c\xd7\xcb\x35\xc4\x36\x67\x7d\x0a\x73\xbb\x36\x95\x83\ -\xe6\x94\xcf\xdd\xac\x7e\x54\x3e\xfe\x32\xd9\x97\x13\xac\x36\x83\ -\xc6\xcb\xd3\x75\x0a\x7b\xa6\x8d\xb5\x29\x93\x70\xb4\x10\x17\x05\ -\x55\x57\xe8\x44\x5c\x0e\x04\xdc\x0b\xd6\x31\x7e\x16\x5e\xde\x99\ -\x12\x31\x20\xc8\x90\xdb\x24\xa9\x9a\x0b\x86\x22\xaa\x9e\xdd\x55\ -\x31\xe3\x0b\xbe\x86\x5e\xb9\x33\x69\x75\x8b\xe6\x94\xcf\xdd\xac\ -\x7e\x54\x3e\xfe\x3d\xd9\x97\x13\xac\x76\x83\xc6\xcb\xe9\x54\xa9\ -\xc3\xb5\x4a\x5b\x28\x84\x9b\x87\x37\x01\x33\x4f\x0c\xd3\x5f\xa3\ -\x06\x42\xe2\x75\xee\xd0\x78\xd9\x67\x69\xe6\x9f\x04\x71\x87\x05\ -\xc6\xd7\xc0\xc1\x50\x85\x72\xfa\x53\x18\xbb\x3b\x69\x59\x33\xb3\ -\xe8\x58\x66\x54\x20\x53\x80\x5c\xa8\x4a\x66\x23\x64\xbb\x44\xdf\ -\x70\x5a\x15\x5f\x62\x29\x2a\x63\x21\x02\x2d\x0d\x55\x89\x18\x8f\ -\x49\xd9\x97\xd3\x9f\x05\xb4\x15\x72\x53\x40\x86\x9b\x81\x49\xc1\ -\x4d\xc2\xbe\x69\x9a\xea\x98\xf1\x80\x9f\x81\x0e\x62\xdc\x2b\xc7\ -\xcd\x29\x9f\xbb\x58\xfc\xa8\x7d\xfc\x7b\xb3\x2e\x27\x5e\x6d\x07\ -\x8d\x90\x95\x4a\x6a\xae\x49\x31\x85\x55\xf0\x4e\xe8\x7d\xfc\x19\ -\x0b\x89\xd7\xbb\x41\xe3\x65\xed\xa9\xd0\x9f\x3e\xdb\x12\x5a\x75\ -\xcf\x1d\x80\x62\x4b\x92\x7d\x08\xb8\xf1\xc5\xdb\x4b\x2f\x58\xc5\ -\xf4\x3a\xfa\x33\x61\x9b\xdf\x0e\x12\x1a\x29\x08\xaa\x3d\xa4\x31\ -\x53\xcc\x7c\x53\x6e\x79\xe9\x96\x0c\xaf\x4a\xd1\x19\x9a\xb4\xaa\ -\xcf\x8c\x56\x48\xc0\x84\x60\x42\x30\x21\x7f\xff\xd0\xbf\xd8\x10\ -\xa8\xdd\xe7\xff\x00\xd5\xf1\xbf\xbc\x94\x5f\xd5\x45\xc7\x42\xb6\ -\xfd\xb1\xfb\x07\xf1\x2e\x67\x75\xfb\xb3\x7f\x90\x3e\x15\x79\x31\ -\xcf\x57\x4c\x46\x04\x2a\xf5\xca\xed\x82\x7a\x85\xe2\xd7\x51\x3e\ -\xd0\x90\xc4\x8b\xcd\x50\x5c\x35\x44\xfd\x0c\xd7\x16\x6b\x07\xff\ -\x00\xa3\x32\xa9\xef\x16\xff\x00\xf4\x60\x5c\xee\x61\xb2\x6a\x90\ -\x39\x21\x8b\xcf\x8c\xe3\xb7\x0a\xea\xa5\x52\xdd\xaf\x4c\x62\x38\ -\x64\xb3\xfb\x52\x85\xb7\x90\x80\x55\x10\x8c\x81\xc2\x53\xd3\x73\ -\xa9\xd3\xa9\xed\xc6\xdd\xdd\x72\x25\x6e\xf1\xce\xf5\x02\x2c\x8d\ -\xea\x61\x87\x77\x55\x69\xde\x76\x86\x37\x2d\x2d\xbb\x50\xc4\x76\ -\x8f\x4e\xbe\xb6\x3e\x7f\x69\x34\x28\xb7\x15\xa3\xcd\x1c\x6a\xe5\ -\x51\xf8\x4c\x4d\x86\xf3\x2e\x0c\xea\x6c\x91\x17\x56\x34\xd6\x9b\ -\x5d\xc3\xaa\x68\x43\x9e\xe6\xcd\x32\x2d\xaa\x24\x99\x61\x44\xb0\ -\xcb\x65\x71\x95\x9d\xd9\xf8\x1d\xba\xc2\x9d\xc5\x3c\x37\xf6\xd9\ -\x9d\x99\xda\x98\x8b\xf5\x4b\xbb\x42\x48\x5e\x16\x65\xa9\x0f\x8d\ -\xf8\x61\xe8\xd4\x68\x6d\xc9\xab\x4e\xa2\xa5\x4e\x40\xb0\xd8\xbd\ -\x24\x66\x47\x17\x1e\x17\x5c\x41\x42\x34\x22\x5d\x50\x97\x16\x0b\ -\x7b\x99\x5e\xe2\xe1\x9c\x9e\x82\xc7\x97\x1d\x19\x5f\x0a\x2a\xd5\ -\xd5\xac\x43\x6d\x6c\xec\x2d\x52\x70\xcd\x87\x4b\x33\x63\x55\x25\ -\x89\x68\x5b\x7c\x7b\xea\x6a\x00\xb1\x4b\x8e\xcd\x1e\xe8\xa6\x3c\ -\x74\x76\xd1\xa0\x46\x22\x54\x1b\xc8\x9c\xec\xa6\x59\x02\xe4\xca\ -\xe5\xb7\xc3\xbf\xb4\x74\xd3\x11\x4a\xe2\x4b\x8d\xdc\xf5\x27\xcc\ -\x05\xad\xeb\x0f\x7f\xc7\xf7\x54\xc1\xb6\x8a\xdb\x79\xb5\x05\xb2\ -\xc8\x2f\x97\x88\x4f\xd5\xe2\xe8\xfd\xe5\x3b\xe4\x3b\x6a\x81\x7c\ -\xf2\x1d\x9f\x6e\x54\x29\xb1\xa6\x9d\x34\x5f\xaf\x55\x5e\x75\xb1\ -\x23\x48\x51\xfe\xc1\x88\xe4\xaa\x9d\x4d\xbc\xfb\x9b\x89\xb5\xcc\ -\x4b\xb2\x5d\x38\x5d\x67\x31\xc1\x04\x86\xce\xed\x9a\x80\x3d\xa7\ -\xc4\x8b\x94\x47\xde\x4d\x2f\x60\x8e\xe2\xe2\x30\x21\x67\xcb\x59\ -\x0b\xb2\xd8\x08\xf2\x11\x3e\x8f\x55\x2f\xf8\xba\xd2\xe3\xf0\xb9\ -\xf9\x75\xca\xfd\x06\x98\xf5\x1a\x87\x54\x22\x61\x25\xc4\x61\xe6\ -\xe2\x46\x0f\x88\x33\x46\x91\xc0\x5e\xd8\xa2\x0f\xba\x19\x26\x89\ -\xec\xc3\x2b\xeb\x89\xf6\x70\x64\x22\xcc\x43\xc0\xef\xac\xf8\x25\ -\x3b\xbe\xda\xdf\x6b\x71\x9c\x07\x28\x17\x0b\x36\xa8\xeb\x68\xe2\ -\x5a\x9c\xa5\x63\xda\xf4\x4b\x73\x8b\xe3\x43\x87\x1e\x54\x77\x2e\ -\x28\xf1\xd8\x94\xe3\x03\xdc\x72\x97\x31\xf7\x64\xb7\x1d\xc5\x34\ -\x52\x20\x41\x71\x05\x44\xb4\xf1\xd3\x5c\x67\x63\x75\x21\xc9\x33\ -\xbb\xbb\x6a\x3f\x0f\x5c\x59\x87\x32\xc3\x78\x5a\x45\x1c\x70\x33\ -\x33\x3b\x67\x66\xd1\xd4\x27\x72\xca\xa4\xb7\x05\x1a\x0d\x93\xce\ -\x76\x14\x7b\x06\x2b\x54\x94\xaf\x35\x31\xbb\x86\x95\x00\x11\x88\ -\x8e\x44\x8e\x08\xa0\xe9\xb2\xde\x40\x8a\x99\x9e\x45\xb5\x3a\x81\ -\x3c\x71\x16\x19\x0a\x7b\x39\x5e\x57\xcd\x96\x99\x08\xba\x59\x9f\ -\xbe\xa6\x4d\x10\xdb\xdf\x44\xd0\xb6\x5c\xf5\xce\x23\x80\xe5\x6e\ -\x1c\xbd\xda\x17\x22\x93\x56\xb7\x0b\x9e\x2f\x2a\x07\x2c\xc5\x62\ -\x44\xda\x82\xb0\xc5\xa4\x75\x66\xc1\xd8\x63\x0b\xab\x26\x59\x47\ -\x51\x40\x55\xd4\x20\x5c\xd3\xdf\x70\x4c\x33\xdf\xd2\x5b\xa4\x8e\ -\x4f\x92\x8c\xed\xdd\xd9\x9a\xbb\x4c\xbd\x2c\xdc\x6f\xd9\xf3\x28\ -\xf1\x49\x1f\xcf\xc8\x17\x2c\xce\xe5\x4d\x9e\x7e\x8e\x5e\x26\xaf\ -\xa5\xe7\xef\xad\x7e\x73\xe3\xcb\x7e\xd1\xe2\x7a\x1d\x2a\x3c\x66\ -\x64\x14\x2a\xf7\x66\x14\xc2\x64\x46\x43\x50\x67\xca\x95\x29\x23\ -\x23\x8a\xa4\x7b\x01\x1c\x40\x5e\xae\xbd\x9b\xf6\x8f\x82\x65\xba\ -\xef\x0e\x6b\x92\x27\x7a\x54\x31\x6e\x0c\xc2\xc2\x39\x96\x3b\xde\ -\xca\x38\x2d\x04\x59\x99\xe8\x78\x3d\x31\xca\x64\x45\x97\xca\xa7\ -\x55\x9e\x1a\xb0\xad\xfb\x52\xf5\xaa\x2d\x0e\x9f\x2e\xa1\x2e\x3d\ -\x42\x6c\x77\x9c\x84\xce\x50\xc0\x63\x9f\x61\xa8\xe2\xa8\x48\xda\ -\x34\x88\x9d\x41\xb5\x48\xba\xbd\x88\x2b\xe3\xde\x33\xc9\x2c\x63\ -\x99\xd9\x99\xc5\xb4\xbe\xb6\x38\xb9\x71\xd5\x33\x97\x75\xdb\xc5\ -\x14\xa5\x94\x5d\xdd\x88\xb4\x36\xae\x1a\xac\x3c\x54\x51\xae\x2f\ -\xe2\x8b\x3e\xf1\xe1\x9b\x5e\x53\xd4\xb8\x51\x2e\x0d\xc3\x30\x2b\ -\x41\x11\xa2\x92\xae\xc6\x9a\x64\x88\xe9\x64\x24\xe8\x10\x8f\x6c\ -\x84\xcb\x2d\xbf\x71\x31\x2a\xfa\xfe\x58\x6e\xcd\x98\x9d\xc7\x46\ -\x5a\xe1\x88\xf9\x14\x3d\xdf\xbb\xa1\x9e\xca\x37\x71\x66\x2d\x39\ -\xa8\xd9\xb5\x4b\x87\xd2\xe2\x58\xed\x8a\x0d\x17\x89\xbd\x40\xcb\ -\xa4\x04\x08\xf1\xe8\x57\xac\x32\x91\x6f\xc9\xd8\x39\xc5\x94\xce\ -\x64\xf4\x66\xcd\x53\xec\xc0\xba\xfa\x07\x4d\x58\x0f\x2c\x65\x3c\ -\xa7\x77\x62\xc5\x57\x72\x8d\xf5\xfd\x66\xe0\x2e\xef\x59\x63\x6f\ -\x08\x59\x6f\x07\x1a\x33\x0c\xad\xa9\xea\x97\x08\xf7\xbf\xf1\x53\ -\x2e\x37\xb6\x2d\xea\xd5\xd5\x5f\xe5\xb6\x29\x91\x9a\x2a\xac\x93\ -\x8d\x40\x7c\x1a\x14\x25\x89\x1f\x36\x5d\x98\x99\x22\x64\x72\x9c\ -\xee\x12\x9e\x5b\x89\xad\xba\xf5\x9e\x70\x2f\x27\x90\x22\x1b\x77\ -\x77\xd5\x6a\x9f\x69\xf1\x60\xf6\x1b\xef\x26\x36\x36\xf1\xc9\x29\ -\xdc\xb0\xb6\xb3\xd0\x3b\x2d\x83\x9f\x29\xbd\x7d\x95\x2d\x9d\xc8\ -\xf6\x7d\x3b\xbe\x72\xa7\x38\x90\xe2\xbc\xb1\xa5\x54\x5b\x89\x2d\ -\xea\x7b\x2f\x21\x6d\x21\x76\x5b\x6c\x93\x01\xb4\xba\x4f\x73\x89\ -\xb0\xb4\x3d\xab\x88\x43\x67\x29\x52\x8d\x8b\xf0\x55\xb3\x7f\x2d\ -\x73\x79\x14\xf3\xbe\x84\x6b\x57\xc1\x9e\x8e\x54\x2c\x8d\xca\x74\ -\xcb\xe5\xc1\x66\x9b\x7e\x5b\x30\x6a\xbf\x23\x76\x44\x87\x6a\xbf\ -\x0c\x93\x86\x3c\x58\x53\x25\xa9\x44\x55\x44\xef\x0a\xc7\x65\xc1\ -\x26\xf3\x24\x15\x31\x55\x14\x2e\x95\xea\xc6\x23\x6b\x21\x0e\x6a\ -\x35\x2b\x4c\x5c\x47\x5b\x8b\x17\xd2\xb2\x3b\xc8\x84\xf2\x3b\xbd\ -\x69\x9b\x01\x22\xd5\xf4\xb5\x5b\x42\xed\xd3\xaa\x10\xea\xd4\xf8\ -\x95\x5a\x7b\xa8\xfc\x09\xcc\xb7\x26\x2b\xc8\x8a\x28\x6c\xbc\x28\ -\x60\x48\x84\x88\xa9\x98\xaa\x2e\xa9\x8d\x06\x0e\x04\xe2\xfa\x5b\ -\x05\x24\x0d\x8c\x58\x87\x43\xb5\x59\x6c\xe3\x05\x9a\xff\xd1\xbf\ -\xd8\x10\xa8\xdd\xe7\xff\x00\xd5\xf1\xbf\xbc\x94\x5f\xd5\x45\xc7\ -\x42\xb6\xfd\xb1\xfb\x07\xf1\x2e\x67\x75\xfb\xb3\x7f\x90\x3e\x15\ -\x68\x6a\x5c\xe7\xc5\x14\x8a\x8c\xba\x55\x46\xe5\x65\x8a\x84\x17\ -\x9c\x8b\x2d\x82\x6a\x42\xab\x6f\x32\x6a\x06\x2a\xa2\xd2\xa2\xe4\ -\x48\xa9\xa2\xe2\xa0\x1b\xae\xe4\xc5\x89\x81\xe8\xf8\xf0\x7d\xaa\ -\xed\x26\xf7\xb4\x02\x71\x23\x66\x76\x7a\x3e\x9f\xb1\x6b\x7f\xec\ -\x1f\x0e\x7f\xe5\x4c\x7e\x46\x4f\xfb\x2c\x67\xfe\xa2\xef\xd0\x7f\ -\x27\xda\xb0\xff\x00\x75\x67\xff\x00\xb1\xbc\x4f\xf6\x24\xd7\x21\ -\x72\x85\x85\x5c\xe6\x7e\x3c\xb8\xa9\x75\xb6\x9f\xa2\xd2\x54\xd2\ -\xa3\x33\x63\xa0\x0c\xee\x35\x54\xdd\xbc\x05\x7c\xfc\x93\x0f\x6d\ -\x2c\x67\x0b\x49\x40\x87\x58\xb4\x32\xae\xde\xef\x0b\x79\x2f\x61\ -\x31\x2a\x88\xf4\x9f\x1c\x13\x82\x87\x78\x5a\xd7\x5f\x2b\xc7\x93\ -\x6e\x56\x22\x54\xd9\x4b\x75\xf6\xc9\x63\x3a\x26\xa8\x7f\x1a\xc9\ -\xed\x51\xcf\x34\x5d\xba\xe4\xa9\x84\x72\xdb\xc9\x15\xb3\xb1\x8b\ -\x8e\xbb\x7b\xae\xac\x10\xdd\x45\x35\xdb\x38\x13\x16\xa3\xe8\xed\ -\x32\x81\x5f\xd4\xc9\xdc\x1b\x76\x4a\xe4\x1b\x72\x39\x39\xc7\x97\ -\x36\x71\x6e\xba\x53\x09\xd3\x16\x4b\xb9\xa0\x48\x6c\x74\x44\x45\ -\x22\xcc\x7c\xb7\x29\xb7\xd3\xdc\x6f\x6b\x2b\x43\x1b\xe8\x9a\x13\ -\x7f\xc4\x0c\x63\x2f\x49\xbd\x1e\xee\x5e\x04\xae\xf2\x32\xdd\xf3\ -\x3c\xc0\xdf\x85\x26\x12\x0f\xa2\x5e\x97\x77\x27\x0b\x2d\x5b\xeb\ -\xf3\x67\xc1\x1f\xef\xd6\xe7\xf0\x30\xc6\x76\xbf\xa8\xb9\xe4\x3f\ -\x79\x6b\xbb\xfd\x35\xa7\x2c\x7e\xea\x98\x7a\x90\x81\x2a\x2d\xb7\ -\x44\xe4\x0a\x60\x6e\xa9\xd9\x55\x58\xf5\x11\x54\x4c\xd5\x63\x38\ -\xe0\x83\x83\xf7\x14\xd1\xa5\x2f\xc5\x45\xc4\x1d\xcc\x6c\xf2\x14\ -\x25\xa2\x41\x71\xf0\xf7\x55\x30\xdf\xa0\xe3\x18\xcc\x3a\x62\x26\ -\x2f\x07\x76\x55\x24\xe2\xf7\xc2\xe7\x7e\xbf\xc9\x28\x84\xac\x5c\ -\x52\x52\x35\x19\x5c\x15\x12\x4a\x45\x33\x73\x0c\xaa\x09\x6a\x3d\ -\xd7\x3b\xcf\x65\xfe\xb0\x71\x16\xf9\xb6\x4c\x30\xfa\x0d\xad\xdb\ -\x3c\x5f\xc4\xd9\x45\x4c\xdd\xef\xb6\x73\x9f\xd3\x7a\x0f\xf8\xc3\ -\x54\x7f\x99\xf3\x17\x85\x2c\x6c\x5b\x0e\xd9\xbe\xee\xfe\x64\xa7\ -\xdc\x30\x1a\x94\x45\x57\x26\x63\x49\x70\x77\x38\xc1\x3b\xf1\x09\ -\xbd\xb5\x45\x45\x45\x45\x44\x5d\x17\xcb\x0d\xae\xae\xa4\x82\x2b\ -\x77\x07\xa6\xaf\x8f\x42\x4b\x67\x67\x15\xc4\xd7\x22\x6d\x5d\x6f\ -\x17\x49\x67\xe7\x27\xe9\xaf\x47\xb1\xad\x28\xb2\x5c\x71\xfa\x15\ -\xcb\x48\xa7\xce\x79\xbd\xcd\x10\x1b\x91\xb7\x0e\xd3\x15\xcc\x4f\ -\x62\x89\xe8\xb9\x8e\xe1\xc6\x3b\xad\x89\x9e\x49\x1d\xba\x40\x44\ -\xde\x35\x9e\xf7\x71\x76\x8a\x36\x7e\x84\x80\x2f\xe2\x5d\x2a\x28\ -\xc7\xe3\x7e\x75\x93\x4b\xb8\x1c\x72\x74\x5b\xce\x23\x69\x6c\x57\ -\xaa\x2e\x1c\xa9\x4c\xb8\xc2\xe4\xe4\x0e\xfb\xaa\xab\xb4\x89\x77\ -\x22\x7d\x2c\x8e\xa4\x58\xd5\x25\x6e\x6c\x98\x83\x07\x8d\xf5\xc4\ -\x70\x6e\xdd\x3b\xba\xcb\x74\x54\xb5\xbf\x71\x3c\x5a\x56\xfc\x33\ -\x2d\x62\x6a\x7e\x5e\x67\xee\xe8\xa9\x95\xe9\x64\xd9\x9c\xd7\x6e\ -\x4a\x8d\x20\x51\x26\xc1\x91\x32\x04\x3a\xa2\x02\x24\x98\x93\x21\ -\x3e\x71\xdc\x4f\x1c\xd4\x14\xdb\xd4\x17\x43\x0c\x8b\x45\xda\x49\ -\x02\xda\xe6\x5b\x29\x19\xdb\x43\xb3\x13\x8f\x01\x09\x36\x64\xc2\ -\xea\xd2\x1b\xf8\xdd\x9f\x4b\x3b\x8b\x17\x08\x90\xbe\x5e\x65\x5e\ -\xa7\xdc\x95\xeb\x8b\xd3\xd5\x3c\x2e\x19\x0b\x2e\x5d\x1a\xed\x62\ -\x92\xcc\xc2\x2e\xe2\xbc\xc4\x76\xb7\x81\x29\xfd\x7c\xbb\x8a\x08\ -\x5e\x68\x3e\xdc\x59\xc2\x10\x8e\xf9\xf2\x35\x18\xa3\x72\xa7\x2a\ -\xa9\x9c\xf2\x4b\xbb\x9b\x3b\xd5\xc6\x56\x0a\xf1\xb3\x32\xb5\x77\ -\xe7\xfd\x8d\x73\x7f\x24\xcf\xfe\x0c\xe6\x29\xb6\xbf\xde\x0e\xd3\ -\x79\xd5\xe6\xf3\xfb\x07\xd9\x2f\x32\x8a\x7a\x7c\xfc\xce\x5a\xbf\ -\xb4\x3d\xfc\x25\xdc\x4d\xde\xff\x00\xab\x3e\x5e\x66\x50\x77\x2f\ -\xe8\xe3\xe4\x7f\x3b\xa8\xa7\xaa\xf8\x11\xcf\x8e\x23\x56\xc7\x73\ -\x75\x5a\x4d\x45\x83\x83\x29\xb2\x50\x71\xbe\xf2\x10\x1a\x21\x26\ -\xa8\x8b\xa2\xe9\xe6\x23\x89\x9b\x84\xdf\xe6\x1c\x78\x09\x9e\xaa\ -\x0f\xd4\x60\xdf\x2c\xc7\xc2\x24\xd4\x74\xc9\xbb\xa2\x3d\x6f\x71\ -\x9d\x6e\x15\xaa\xd7\xc3\xbd\x4c\xa2\xc9\x66\x92\xd3\x59\xa1\x37\ -\xd8\x8c\x42\xd2\x06\x5a\xee\x1c\x93\x6f\xe3\x61\x55\xb9\x34\x97\ -\x02\xf2\x63\x98\x9b\x37\x8d\x38\xb9\x17\x8a\xd8\x9a\x3c\x32\x83\ -\xe5\xf0\x36\x0b\x43\x8d\x82\xdf\x97\xc3\xf6\xeb\x48\x8d\x95\x05\ -\xda\x1b\x2d\xcd\x13\xcb\x62\xa2\xb1\xb6\x52\x38\xba\x26\x7b\xbb\ -\x9d\xc5\xfc\x2d\xd8\xdb\x7a\xe6\xd7\x47\xe9\x66\xc3\xc7\xab\xfc\ -\x16\xab\x16\x8c\xac\xc1\xba\xb9\x1a\xbe\x2d\x6e\x7a\xa4\x77\x13\ -\x3f\x79\xb3\x2a\xd5\x72\x95\x15\x99\x97\x12\x58\x35\x0f\x84\x6a\ -\xa2\xf1\x30\x1d\x84\xad\x2f\xc2\xaa\x28\xb6\xe6\xee\x84\x69\x00\ -\x57\x60\xec\xfa\xe3\x96\x2c\x17\xed\x0b\xb1\xe6\x7a\x0e\xd4\x7a\ -\x3f\xe3\xd6\xe7\x55\x9d\xda\xf3\x33\xc7\x95\x99\xcb\x62\x54\xcc\ -\xf4\xc3\x69\xab\xc0\xfc\x19\x7e\xd5\x69\x29\xac\x24\x6a\x74\x48\ -\xc8\xd0\xb0\x8c\xb2\xdb\x68\xc3\x68\x82\x0d\xec\x04\x4d\xa2\x89\ -\xa2\x22\x65\x92\x22\x62\xa0\x6f\x52\x77\xef\xab\xb8\x35\x05\x9b\ -\x46\x0b\x6b\x18\x2c\xd7\xff\xd2\xbf\xd8\x10\xa8\xcd\xec\x62\xdf\ -\xaa\xd6\x0c\xc9\x04\x06\xe3\xa3\x11\x11\x2e\x48\x88\x85\x15\x55\ -\x55\x57\x1d\x0a\xdb\xf6\xc7\xec\x1f\xc4\xb9\x9d\xdf\xee\xcd\xfe\ -\x40\xf8\x53\xd7\xd4\xd5\xa5\x6d\xbb\xc5\xb5\xbb\x87\xe5\x71\x42\ -\xb9\x05\xc8\x8e\xb1\x50\x06\x5b\x09\x19\xbf\x31\xa6\x8d\x15\xc4\ -\x44\x25\x42\x47\x0b\x34\x55\xf1\xd7\x15\xed\xc9\x71\x23\x5c\x88\ -\x66\x7c\xaf\x5c\x38\x3a\x2e\xac\xfb\xfe\xda\x27\xb5\x23\xca\xd9\ -\x9a\x9a\xd4\xc7\x12\x66\xe7\x4b\x2f\x48\x14\x1a\x1d\x6f\xfa\xe5\ -\xf3\xaa\x64\x4a\x8f\x63\xe5\x9d\x8f\x8c\x61\xb9\x1b\x37\xfc\x5e\ -\xed\xbd\xc1\x2c\xb3\xda\x99\xe5\xec\xc3\x6f\xa8\x65\x30\xd9\xe5\ -\x77\x6e\x96\x87\xa7\xa2\x92\xfd\x33\x0c\x72\x6d\x33\x8b\x15\x32\ -\xe9\x6a\xfa\x4a\x47\xca\x16\x85\xa9\x2b\x9d\xf8\xf2\xd9\x6a\x8f\ -\x0d\x8a\x6c\xc6\x1e\x72\x7c\x46\x63\xb6\xcb\x2f\x02\x2b\xaa\x88\ -\x48\xda\x0e\x6b\xf6\x6b\xaf\x96\x22\xd8\xdc\x4a\xd6\x52\x9e\x67\ -\xab\x3e\x18\xf2\x29\x7b\xc2\xda\x27\xbf\x86\x36\x16\x66\x76\x7a\ -\xb5\x34\xe9\xfb\x17\x3f\x97\x7d\x31\xc5\xa5\xc1\x7e\xed\xe2\xe5\ -\x7d\x89\x50\x73\x92\xfd\x11\x0c\x9c\x2d\x8d\xf5\x29\xc4\x71\x57\ -\x7a\x18\xe5\x9f\x6d\x54\x94\xbe\xa2\xa1\x64\x05\xb3\x77\xef\xb7\ -\x27\x68\xe7\xa5\x1f\xad\xfd\x4b\x56\xf3\xdc\x0c\x02\xf2\x5b\xd5\ -\x9d\xb1\xc9\xfd\x1c\x3e\x0f\x12\xd2\xe1\x0e\x70\x3b\xad\x7f\xc2\ -\xce\x51\x31\xaa\x40\xab\xb6\xb0\xa0\x54\x65\x6a\x6e\x11\xa6\xd4\ -\x8e\xf9\x2f\xbe\xa7\xe0\xdb\x9e\xfe\xfc\x91\x54\x94\x91\x47\x66\ -\xf3\xdd\x9b\x2f\xc7\x83\x55\xc7\x17\x66\xf7\x87\x9d\x96\xbd\xd3\ -\xbd\xb6\xdf\xf5\xee\x35\x98\xb5\x58\x9f\xdd\x2e\x67\xd3\x54\xd7\ -\xbd\x28\x7c\x24\xc9\xd1\xed\xcb\xc2\xbc\x34\xf2\xb7\x63\xc5\x6e\ -\x95\x4d\x76\xac\xf4\x5e\xc0\x47\x0d\x8c\xba\x80\x8e\x8f\x5e\xd4\ -\xfd\x71\x7a\xfe\x9c\x26\xb6\x96\xf1\xf3\x1c\x63\x5c\xee\xf9\x8b\ -\x2b\x3d\x6b\xa7\xfe\x13\xdb\xa8\x6c\x5b\x2c\x72\x9e\x5c\x8c\xd9\ -\x47\x3b\x8d\x29\xd1\x7d\x3a\x7b\xeb\xab\x50\xbf\xf8\x62\xad\x6e\ -\xbf\x6b\xd5\x2e\xea\x6c\xca\x54\xa8\xcb\x0a\x42\x3f\x3c\x5c\x79\ -\xc6\x88\x76\xaa\x93\xaa\x5b\xd4\xbc\xf7\xe7\xbb\x76\xb8\xd2\x16\ -\x97\x61\x23\x18\xc6\x4c\xec\xf5\xe8\xad\xe7\x79\x64\x71\xbc\x65\ -\x20\xb8\xbb\x53\xa5\xce\xba\x2e\xde\x1c\x5d\x66\xc3\x4b\x21\xeb\ -\x8a\x05\x19\x29\x91\xc2\x0a\x42\x29\x62\xc4\x86\x1b\x46\x91\x03\ -\x5d\xc8\x68\x5b\x55\x0b\x77\xbd\xf5\xb1\xa9\xad\xee\x66\x7d\xab\ -\x03\x96\x67\xad\x69\x83\xad\xaf\x75\x6b\x00\xec\x9c\xd8\x72\xb6\ -\x5a\x56\x8e\xcb\x97\x6a\x71\x97\x1d\x3a\x32\x2e\xab\x3a\xa7\x51\ -\x36\xeb\x86\x6e\xca\xa9\xc0\xac\x4c\x51\x96\xe0\xba\x68\x66\x66\ -\x0e\xe4\x64\x87\xbf\x55\xd7\x76\xef\xa7\x1b\xa7\xbd\x9d\xa9\x1c\ -\x8c\xda\xbd\x52\x11\xd5\xf2\x2d\x36\xf6\x16\xcf\x59\x22\x22\xd7\ -\xd2\x42\x65\xad\xe5\xe3\x5c\x45\xe3\x8e\x16\x9d\x3a\xb5\x4e\x72\ -\xa5\x31\xe9\xf6\xdc\x81\xac\x56\xd1\xda\xac\xed\xd1\xa5\x1b\x5b\ -\x92\x51\x99\xb9\xa9\xa0\x37\xab\x88\x44\xa1\x96\xbb\x71\x23\xe7\ -\x2e\xc4\x45\xe8\xd4\x36\xc8\x3a\xa3\xac\xde\x8a\x8d\xf2\x36\x44\ -\x44\x39\x9e\xa0\xf9\xcf\x58\xb5\x4b\xd2\xd3\xe5\x5b\xb5\xda\x87\ -\x05\x72\x0c\x3a\x45\xb7\x57\xb8\xe1\x55\x5e\x86\xfb\x7f\x2a\x21\ -\xa9\x17\xc7\x7c\x42\xa7\x6c\x72\x78\x1c\x47\x08\x8b\x34\xcf\x35\ -\xea\x2c\x97\xde\x44\xc6\xb8\x82\xf6\xdd\xc8\xc4\x1c\x6a\xda\xda\ -\xba\xb4\xe4\xd0\xb6\x4c\x76\x17\x2c\x31\x91\xb1\x51\xf5\x75\xb5\ -\xab\xcb\xa5\x74\xa6\xf1\x65\x97\x42\x66\xad\x53\x2a\xdd\x52\x83\ -\x48\xa8\x19\xca\xaf\x20\xd5\xdd\x8f\x11\xe7\x1e\xd1\xd7\x5e\x37\ -\x49\x54\x48\xd5\x7a\xcc\x4c\x33\xf0\xf7\x74\xc6\xa1\xbe\x9a\x47\ -\x11\xca\x24\xed\x80\xea\xd4\xb9\x19\x6e\x3d\xdd\x0c\x6c\x45\x98\ -\x80\x4b\x13\xd7\x76\x17\xe3\x77\xaf\x1a\xcf\x5e\xe2\x2e\x38\xa8\ -\x5b\x71\x68\xd3\xe3\x39\x12\xd3\xa3\xb6\xaf\x33\x02\x34\xc7\xe3\ -\xc3\x04\x0d\xc6\xaf\x18\x81\xa2\x19\xf5\x12\xab\x87\xb8\xbf\x1b\ -\x18\xc5\xbc\x2e\x06\x47\x26\x7a\x99\x70\xd1\x9c\xb9\x3f\x82\xce\ -\x6d\xd9\x6c\x51\xb0\x13\x50\x07\x81\x9d\xd8\x7b\x5f\xc5\x63\x6a\ -\xb3\xc5\xd7\xbd\x35\xab\x02\x1d\xd8\x35\x54\x96\x0e\x37\xf0\xd1\ -\xea\xae\x9c\xe9\x2d\x6c\x32\x70\x0d\xd1\x73\xb8\xe0\xa8\x29\x6e\ -\x42\x5c\xb6\xa7\xd1\x8f\x5e\x3b\x98\x0b\x6a\xe1\x96\x9e\xae\xab\ -\x73\x2c\x5a\x5b\x5b\x81\xd8\xb4\x99\xab\xc4\x5a\xc5\xe1\xad\x5d\ -\x74\x38\xe2\x25\x8d\x45\x66\xa9\x6b\x59\x15\x07\x64\x33\x42\x7f\ -\xe1\x67\xc0\x76\x4b\xf2\x52\x1b\xd9\x9a\xab\x60\x8f\xaa\xa0\xa2\ -\xae\xec\xf6\x74\xee\x45\xf3\xc6\xab\xc2\x98\xdc\x64\x95\xa9\x99\ -\xaa\xcf\x46\x6c\xde\x25\xb6\xc4\x60\x8d\x8a\x38\x9e\xb9\x1e\x8e\ -\xd5\x72\xcb\xe3\x51\xee\x45\x9d\xc2\x77\x6b\xa5\x41\xbe\x6e\x68\ -\xc2\xb4\xf7\x54\x5f\xa5\xfc\xcc\xe2\x80\xbe\xda\xaa\x7d\xa3\x4d\ -\xb8\x28\xa6\x39\xaa\x75\x26\x98\x95\x66\x37\x90\xb6\x78\x81\xf1\ -\xeb\x65\xaa\x89\x7c\x76\x53\x3e\x49\x8d\xb5\x7a\xb9\xb2\xe3\xc8\ -\xa5\x96\x85\xd9\x62\xd4\xd9\x6e\x87\x6d\x5c\xd1\xab\x6f\xc7\x12\ -\x5e\xd9\x4f\x49\xd3\x08\x15\x54\x95\x48\x9c\x32\x70\xd1\x33\xcb\ -\x35\xcf\x24\xd3\x10\xae\x2d\xe6\x17\xcc\x60\xe3\xec\xe5\x1f\xb1\ -\x4f\xb6\xb9\x80\xdb\x24\x66\xc7\x4f\x5b\x31\x7d\xaa\x0f\x25\x78\ -\x32\x8e\xfd\x52\x80\xed\xd4\xc5\x36\x9c\xec\x97\x3e\x69\x6c\x8d\ -\x51\x58\x84\x8f\xa1\xaa\x3c\xda\xb0\x84\x8a\x02\x44\x8b\xdc\x68\ -\x14\x5b\x2d\x44\x83\x6e\x98\x60\x3f\x38\x6c\x27\x91\xdd\xe9\xaa\ -\x79\x75\xbb\xd8\xf9\x9f\x4a\x5a\x5f\x23\x1b\x90\x3c\x8c\x2d\x5d\ -\x68\xf3\x50\x6b\xc3\xab\xc1\xdf\x1d\x0b\xa9\x4d\xad\x70\xd5\x42\ -\xf5\x85\x5d\xa3\xdc\xf1\x1d\xb9\x8d\x80\xa4\x40\x8b\x16\xa1\xf6\ -\x4b\x19\x54\x76\xc7\x6e\x38\x16\xcd\xaa\x42\x85\xb5\x07\xde\xc6\ -\x93\x8a\xec\x61\x70\x20\x7c\xb5\xcc\xf5\x1e\x1f\x4b\x32\xdd\x1c\ -\xb6\x45\x3b\x18\x9b\x67\xa6\x46\x66\x2e\x0f\x47\x2a\x68\xe1\x42\ -\x76\x8c\x08\x5f\xff\xd3\xbf\xd8\x10\xa8\xff\x00\xa9\x9a\x6c\xeb\ -\x57\x99\x23\xdd\xac\xb6\xa8\xdd\x41\xb8\x75\x18\xae\xea\x80\xaf\ -\xc1\x40\x64\x87\x3f\x6a\x76\x81\x57\x2f\xc3\x4c\x74\x1d\xc8\x6d\ -\x2d\xa3\xc6\xfc\x15\x1f\xe6\xc7\x9d\x73\x5d\xff\x00\x19\x43\x78\ -\xd2\x37\x5a\x84\xdc\xa3\x87\x32\x7c\x73\xb5\x6e\x05\xc9\xe9\xea\ -\xb1\x5e\xa5\xb8\x8e\xd3\xea\x2c\x53\x64\xb0\x68\xa8\xbd\x2e\x4f\ -\x8c\xb9\x2e\x5e\x69\xe0\x49\xe4\xb8\xae\x6e\xb8\x8a\x3b\xe1\x02\ -\xd2\xce\x5e\xe9\x2b\x3e\xf8\x94\x65\xdd\xc4\x63\xa0\x98\x5f\xef\ -\x0a\x5c\xfa\x2d\x54\x44\xbe\x15\x74\x44\xf9\x56\x6b\xff\x00\x1b\ -\x86\x9f\x52\x7e\x5f\xb5\xf0\xa5\x1f\x4a\xfe\x6f\xb3\xf1\x29\x15\ -\xa1\x28\x79\x37\xd4\x85\x56\xf3\xa7\xaa\x3d\x6d\xd9\xb0\x96\x99\ -\x0e\x68\xae\xe0\x71\xf7\x05\xc6\xba\x57\xc1\x50\x95\xd9\x04\x8a\ -\x9a\x6d\x41\x5f\xad\x88\xb7\x03\xf2\xdb\xbc\x63\x7e\x94\x8f\x99\ -\xdb\xbb\x90\x54\xcb\x62\xf9\xbd\xe4\x52\x8f\x42\x26\xca\xcf\xdf\ -\xd1\xce\x6a\xc6\x62\xae\xad\xcb\xf3\xc3\x9d\x6d\x91\xb1\xf9\x5e\ -\xb1\x1a\x98\x9f\x0d\x11\xe7\x5b\xaa\x53\x95\xae\x8e\xda\x49\x44\ -\x75\x50\x32\xf7\x50\x1c\xde\x23\x97\x90\xe3\xa7\x6e\xb9\xf6\xf6\ -\xc2\xe5\x8b\xf4\x5f\xc1\xfc\x17\x25\xde\xf6\xff\x00\x2f\x76\x4c\ -\x38\x37\x48\x7d\xaf\xe2\x9c\xbe\xa0\xab\xcd\xde\x1c\x03\x64\xdd\ -\x6e\x00\xac\xd9\xd3\xa1\x93\xa6\x88\x8a\xa2\xe9\xc2\x94\x8f\x88\ -\xaf\x92\x2b\x81\xfe\x8a\x61\x16\xe8\x8b\x63\x7d\x24\x7c\x0c\xcf\ -\xef\x0e\x5f\x22\xb1\x6f\xa9\xb6\xfb\xbe\x29\x38\x5d\xdb\xdd\x2c\ -\xde\x54\xf8\xe4\xeb\x76\x87\x78\x5a\xcf\xda\x55\x97\x99\x8d\x22\ -\xb6\x4b\x0e\x91\x21\xe0\xee\x28\x4f\x46\xcd\xe6\xc8\x13\x45\xdc\ -\x88\xd1\x12\xe4\xa3\x98\x89\x26\x2b\x96\x33\x1c\x32\x34\x83\x8e\ -\x5c\x4b\xb3\xa3\x9d\x59\xf7\x84\x11\xcf\x13\xc6\x4e\xcd\x9f\x01\ -\xed\xe9\xe6\x4a\x1f\x55\x2c\xb4\xe5\x4b\x8e\x51\xc6\xc4\xd0\xea\ -\x8e\x81\xee\x44\x5c\xc1\x4e\x36\x62\xb9\xf8\xa2\xfb\x30\xf3\x71\ -\x3b\xb0\xcb\xd9\xfb\x52\x0f\xa8\x99\x9c\xa1\xed\x7f\x4a\xb0\x75\ -\x5a\x94\x3a\x1d\x26\x6d\x5a\x69\x23\x50\x29\xd1\xdd\x95\x20\xb4\ -\x44\x16\x98\x05\x32\xff\x00\x22\x26\x2b\x31\x83\x99\x30\xb6\x97\ -\x7a\x2b\x64\x92\x34\x60\xe4\xfa\x05\xab\xe2\x55\x53\x8e\x9d\xad\ -\xd9\x1c\xdf\x43\xa9\xdc\x2e\x16\xee\x4d\xa6\x1c\xf9\x48\x5e\xeb\ -\x52\x2a\x0e\x1c\x86\xda\x4f\x0d\x40\x9b\x6d\xbf\xc5\xee\x62\xe3\ -\x78\xc1\x3d\x99\x08\x7e\x49\x65\xf0\x0e\xad\x55\x1a\xc5\xce\xde\ -\xf8\x48\xff\x00\x3c\x73\x3f\x29\xeb\x53\xcc\xde\x15\x23\x81\x4a\ -\xa7\xf1\xff\x00\xaa\xce\xcb\x11\xdb\x62\x9f\x77\xd3\x5d\x76\x22\ -\x20\xa2\x03\x4f\xbc\x8a\x6e\x6c\xf6\x29\x39\x18\xfc\x3f\x65\xcb\ -\xc1\x71\x14\xe4\x2b\x8d\xd9\x8b\xe3\x19\x77\x79\x0b\xc8\xa6\x04\ -\x63\x6d\xbd\x68\xcd\x46\x90\x70\xe5\xff\x00\x90\xfb\xca\x4d\xea\ -\x66\x5d\x56\x7d\xa0\xc5\x93\x41\x05\x76\xa3\x58\x49\x35\x09\x60\ -\x9f\xf4\xea\x2b\x2b\x2d\xec\xf2\xd7\x35\x34\x68\x47\xf0\x8b\xa7\ -\x11\x37\x20\x88\xca\xf2\x9e\x81\xa0\xfb\x52\x3e\x56\xe7\x53\x37\ -\xf9\x19\x42\xd1\x06\x92\xa9\x3f\x62\x36\xcc\xfe\x5c\xaa\x51\xc1\ -\x37\x67\xf5\xc7\x8b\xe8\x55\x07\x5c\xee\x4e\x86\xd7\xcb\x67\x2a\ -\xae\x65\xde\x87\xf6\x68\xa4\xbe\xd3\x04\x07\x17\xf4\xf8\x87\xbd\ -\x2d\xf6\x37\x24\xdc\x0f\xac\xde\xd2\x9d\xb9\xee\x76\xf6\xa0\x5c\ -\x2d\xaa\xfe\xcf\x75\x54\x5e\xc7\x9d\x47\xa2\x53\x79\x33\x99\x9e\ -\x8c\xd0\x84\xda\x84\xf3\x84\xf0\x8a\x0a\xbd\x06\x94\x9d\x96\xd0\ -\x57\xc9\x5e\x78\x0f\x76\x5e\xf1\xed\xcf\x5c\x4c\xba\x13\x32\x86\ -\xda\xba\x18\x6b\xda\x3c\x7e\xe8\xa8\x36\x86\x11\x8c\xf7\x4e\xda\ -\x48\xa9\xd9\x0c\x3e\xf1\x28\x17\x0e\xb1\x59\xe3\x6e\x6d\x7a\xd6\ -\xb8\xde\x27\x24\xde\xb4\x86\x6a\x4e\x99\xe8\xa5\x50\x26\xd6\x53\ -\x99\xfe\x95\xc4\x94\xda\x7b\x7a\x70\xcb\x78\xb8\x5c\xd9\xed\x03\ -\xf2\xcb\x2f\xb3\xd1\xfe\x87\x4a\xf7\x5b\x1d\xad\xf6\xcc\xdf\x19\ -\x45\x8b\xdb\xe9\x79\xf3\xb2\x93\xf3\x5b\x4d\x0f\x35\xf1\x13\xc2\ -\x02\x8f\x1c\xd5\x13\x71\x11\x37\x10\x84\x86\x14\x51\x57\xc5\x51\ -\x37\x2e\x5f\x77\x10\xf7\x63\xbf\xc9\xce\xdd\xee\x67\x53\x77\xab\ -\x37\xce\xdb\xbf\x7f\x9d\x96\xb7\xaa\xc8\x4c\xd2\x61\xda\xb7\x8d\ -\x10\x52\x2d\xe7\x1a\xaa\x11\xe1\xcb\x8e\x3b\x64\x18\x2b\x46\xe2\ -\x22\x90\xea\x5b\x4c\x03\x6a\x2e\x7e\xf9\x65\xef\x16\x33\xdc\x24\ -\xe6\xe7\x19\x62\x0e\x38\xb7\x02\xc3\xea\x20\x60\x18\xe5\x0c\x24\ -\x62\xc1\xdb\x4a\xf1\xcc\x82\xbf\xe3\xc7\x14\x38\xe0\x08\xbe\x4e\ -\xb3\xdc\xdb\xae\xa9\x28\x74\xcf\x24\xcd\x13\x3d\x31\xee\xee\xfd\ -\x14\xfd\xdc\x0b\xcd\xe9\xfa\xfb\x7f\x07\xbc\x9b\xf7\x8d\xb3\x45\ -\xba\x6b\x76\xdb\x6e\xbc\xcb\x37\x0d\x0a\x73\x35\xc8\x8a\x41\xb9\ -\xf5\x8b\x19\xc4\x07\x81\x15\x15\x15\x04\xd4\xc5\x17\x5c\xb7\x6d\ -\x5c\xb4\xc2\x3b\x79\xce\x20\x3f\x44\x9b\x27\x85\xf4\x27\xf7\x56\ -\xe1\x31\x86\x2d\x98\x1d\x8d\xb8\xf2\x8e\x95\x32\xc4\x14\xc5\x18\ -\x10\xbf\xff\xd4\xbf\xd8\x10\xa1\x1c\xa1\xc6\x34\x2e\x52\xb7\x96\ -\x8d\x56\x55\x8f\x31\x82\x57\x69\xb5\x26\xd1\x09\xc8\xcf\x2a\x64\ -\xab\x92\xaa\x6e\x02\x4d\x0c\x33\xea\xfa\x08\x44\x91\x85\x8d\xe9\ -\xda\xc9\x98\x71\x6e\xb3\x71\xa5\xbb\xc3\x77\xc7\x79\x1e\x42\xc1\ -\xdb\xa2\x5e\x8a\xaa\xb7\xb7\x1b\xf3\x47\x17\xd8\x15\xca\x1c\xa9\ -\xf1\xea\x1c\x68\xe9\xb0\x73\x3b\x2e\x81\x8b\x6a\xb2\x9a\x26\xcc\ -\x1b\x79\x05\xd0\x52\x75\x01\x0c\x5b\xdc\x3a\xae\x79\xfb\xd8\xb8\ -\xdb\x5e\x5a\x5d\x4e\x24\xcc\xed\x2e\x34\xf1\x3f\x16\x1a\x38\xd5\ -\x1a\xee\xc6\xf6\xd2\xdc\x81\xdd\x8a\x2c\x2b\xfc\xcd\x4d\x3a\xcd\ -\xad\xc4\xb8\xdc\x17\x68\x72\x0d\xee\xcd\xc7\x40\xb4\x2b\x6d\xd0\ -\xa8\x12\x52\x18\x5c\xd2\x17\xf5\xe3\x64\xbe\x21\x1a\x06\xd0\x47\ -\x72\xe6\x9d\xdd\xc2\x86\xd8\x97\xd6\x2c\x6f\xde\x97\x10\x40\xe0\ -\x72\x0e\x62\x6a\xe4\xf2\x57\x9b\x8d\x47\xdd\x16\xd7\x17\x0c\x61\ -\x11\x64\x17\xa6\xd3\xef\x53\xe2\xe2\x57\x4e\xc2\xb0\xe8\x3c\x75\ -\x6e\xb1\x6e\x5b\xed\xaa\x47\x6d\x55\xc9\x12\x1c\xd5\xe9\x0f\x92\ -\x22\x13\xae\x2a\x79\xae\x49\xa2\x68\x29\xd2\x98\xa1\x5d\xdd\x1d\ -\xcc\x8e\x67\xff\x00\x0b\xa3\x59\xd9\xc7\x6b\x1b\x46\x1a\x3c\xef\ -\xc6\xa4\xf8\x88\xa6\xaa\x55\xeb\x0d\x86\xc3\x90\xe8\xf2\x05\x53\ -\xb8\xed\x19\xa1\x31\x4c\xbe\xa4\xa9\x19\x2a\xfd\xdc\xf2\xfd\x0c\ -\x5f\x7e\x9d\x7f\xc0\x26\xf5\xb9\x99\x73\x8f\xa9\xd9\xbe\x60\x5f\ -\xd5\xf8\x89\x78\xbb\xc8\x8b\xd2\x4d\x84\xa4\xaa\xab\xf3\xc7\x93\ -\x35\xd7\x44\x72\xa8\x88\x9f\xa0\x98\xf6\xdf\xf7\x49\x7b\x3f\xd0\ -\xbc\xb9\xfd\xa2\x2e\xdb\xff\x00\xf4\x4f\xf9\x9c\x4f\x51\x87\x77\ -\xd9\xf7\x1c\x1b\x82\xb1\x5a\x62\x91\x3d\xd3\x9f\x16\xb1\x35\x24\ -\xb4\xdb\x0f\x44\x78\x3b\xcd\xa2\x88\x75\xa1\xed\x0c\x93\x72\xaa\ -\x1f\xe2\xe2\xb6\x37\xe2\xf1\x48\x0e\x22\x39\x9b\x0c\xad\x4e\x16\ -\xc1\x5a\x8b\x76\x90\xcd\x19\xb1\x91\x65\x7c\x58\xca\xb8\x65\x7c\ -\x54\x2f\xd5\x37\xfc\xcf\x8d\xff\x00\x95\x9c\xfd\x5c\x6c\x4f\xdc\ -\x5d\x19\xbb\x3f\x6a\x5d\xf5\x0f\x4a\x1e\xd7\xf4\xa9\xef\x38\xd4\ -\x9c\xfe\xae\xd3\xad\x38\xb1\x25\x54\x24\xdc\xf3\xd9\x88\xfc\x1a\ -\x78\x89\xcb\x3a\x74\x65\xf8\xa9\xbd\xb1\x32\x01\x55\xed\x37\xb3\ -\x52\x4f\xd7\x30\xb7\x75\x87\xe2\x3c\x8e\xec\xcc\x0d\x5a\x97\x47\ -\x33\xea\x87\x95\x34\xde\xe6\xfb\x36\x8d\x99\xc9\xe4\x26\x6a\x0f\ -\x4b\x23\x6b\x1d\x3d\x96\xf2\xa5\x1f\xa8\x6a\xf5\x4e\xab\x4d\xb7\ -\x2e\xd8\x16\x8d\x72\x85\x36\xd2\x9c\x12\x1b\x9f\x53\x8f\x19\xa8\ -\xc0\xdb\x84\x1b\x53\x73\x12\x5d\x5c\xfb\xad\xb5\xb5\x36\xe5\xe3\ -\xd4\x9e\x6e\xf7\x44\x42\x04\x71\xbc\x82\x4d\x23\x68\x17\x7a\xf9\ -\x59\xb8\x2a\x90\xef\xb9\x88\xc4\x24\x18\xcc\x1e\x37\xd2\x4c\xd9\ -\x7e\xe9\x3f\x59\x85\x76\x39\xfa\xa2\xd2\xc1\xe3\x3e\x68\xa4\x22\ -\xac\x78\x13\x23\xbc\x4a\x3a\x91\x47\x96\x21\x28\x04\xbe\x84\xed\ -\x18\x2f\xed\x99\x63\x46\xe9\x07\xcd\x35\xb1\x70\xb3\xf8\xc7\x57\ -\x9d\x48\xdf\x26\xd9\x60\xba\x1d\x0c\xed\xe2\x2d\x6e\x6f\x2a\x63\ -\xda\x44\xc5\xe1\xc9\x17\x65\xdb\xd3\x26\x93\x48\x61\x9b\x5a\x94\ -\x7e\xf0\x1a\xa2\x24\xa9\xcb\x92\xe8\xb9\x9b\x8d\xb7\x9f\xe2\x61\ -\x55\xc5\x61\xb7\x08\xf4\x39\x3e\xd0\xbd\xd0\xe7\x4d\xed\xa9\x3d\ -\xcc\x92\xe9\x11\x66\x88\x7d\xe9\x3c\xb4\x6f\x02\x48\xd8\xf7\x33\ -\x9c\x2f\x51\xe5\xab\x11\xe3\x26\xfe\x5e\xcb\xd5\x2b\x74\x4b\x45\ -\x57\x4b\x6b\x31\xf2\xf3\x52\x70\x5f\x8c\xba\x7e\x02\xe2\xc1\x75\ -\x07\xce\x8c\x12\xf1\xea\x9f\x9c\xbc\x59\x49\x56\xed\x2e\x1e\xc0\ -\xae\x21\x7e\xab\x66\x0f\x30\xf8\xf3\x02\x61\x5d\x30\x4a\xd4\xb2\ -\x38\xef\x8c\x18\xa6\xcb\xaa\xba\xf3\xb1\x65\x56\xe9\xd4\xd0\x07\ -\x64\x3d\x16\x94\xa1\x2a\x56\x42\xe1\xb6\x39\x39\x24\x9b\xcf\x32\ -\x4e\x95\x2f\x3c\x2c\x80\xb6\xb3\x4b\x3b\xbb\x0e\x96\x17\x2d\x15\ -\x3d\x51\xfb\xb5\x4d\xae\x03\x63\x04\x36\xec\x2e\x5a\x1c\xc4\x74\ -\xb8\x86\xb1\xf1\x69\x3a\x28\x3f\x3b\xdc\xf3\xd2\xbb\x66\x72\x43\ -\x16\xa5\x6e\x88\xf5\xb9\x34\x42\x4c\x9a\xa3\x11\xda\x6d\xe6\xd5\ -\xc1\x79\xb6\x90\x99\x90\xea\xe7\xd0\xea\x64\xa8\x89\xd7\xe3\x86\ -\x1b\xaa\x01\xc9\x24\x2e\x62\x59\xdb\xaa\xef\xce\xcd\xde\x4b\x37\ -\xc5\xc1\x6d\x23\x9d\xa3\x30\xc8\xfd\x66\x6c\x78\x69\x81\x3f\xac\ -\xa4\x1c\xe2\xf3\xb5\x4e\x4f\xe2\x09\x34\x39\x6d\xb2\xec\xc7\xc9\ -\xd8\x13\x5c\x69\x64\x34\x3d\xd7\x63\x93\x6e\x2b\x68\x6d\xa9\xa6\ -\xa8\xbb\x77\x8e\x7e\xdc\x46\xdd\x8c\xc1\x6d\x3b\x13\x68\x6c\x5b\ -\x47\x1a\x97\xbd\x9d\xce\xea\xdd\xc1\xf4\xbe\x0f\xa7\x84\x79\x17\ -\xa5\xf8\xd9\x7c\xff\x00\x4d\xb7\x39\x7a\x60\xd4\xfe\x0a\x30\xcd\ -\xb1\xdc\x8e\xca\x42\xa6\xb9\x28\xb2\x22\x23\x61\x49\xd2\x57\x73\ -\x6d\x50\x37\x3c\x48\x84\xd7\x9e\xf1\xc7\x98\x35\x8b\x9d\xbb\x65\ -\xab\xd2\x5e\xb1\xd3\x97\x0c\x3d\x9e\x15\xee\xb1\x6f\x01\x8e\xe5\ -\xf3\x51\xb3\x45\x86\x50\xcd\xd9\xc7\x5b\xda\xea\xad\x6e\x7b\x85\ -\xf3\x2e\x6a\xe3\x28\x1f\x10\xfc\x4f\x89\x31\x6b\xe2\xa2\x1f\x6a\ -\x43\x7b\xa5\x0a\x6e\x6c\xf2\x5d\xa4\x9e\x4b\x96\x33\xdd\x45\x96\ -\xd2\x67\xa3\x3d\x38\xf4\x68\x58\x6f\x90\xcf\x7b\x00\xd5\xda\xbc\ -\x5a\x7a\x49\x9f\x6c\x71\xb4\xeb\x5f\x91\x1f\xb9\x52\xb1\x51\xad\ -\x53\x66\x51\xd6\x09\xbb\x57\x92\x92\x9f\x65\xf0\x92\xdb\x82\x00\ -\xb9\x0a\xec\x21\xdc\x59\x6d\xd0\xb3\xd7\xab\x0a\x27\xbd\x69\x60\ -\x60\xca\xc2\xec\x55\xd5\x6a\x70\x27\x56\xf6\x25\x0d\xcb\xc9\x98\ -\x89\x9c\x72\xeb\xbe\x67\x67\xaa\x64\xe1\x52\x70\x8c\x08\x5f\xff\ -\xd5\xbf\xd8\x10\x8c\x08\x4a\x8f\x52\xbf\x99\x4b\x9f\xf7\x87\xf4\ -\x8c\x6c\x39\xdc\xbf\xac\x0f\x6b\xdd\x24\x8b\x7f\x7e\x88\xfd\x9f\ -\x7c\x52\xa3\xd1\x6f\xf6\xdf\xf9\xab\xf8\xee\x1c\xfd\x49\xf9\x7e\ -\xd7\xc2\x91\x7d\x2b\xf9\xbe\xcf\xc4\xad\x76\x29\xaa\xf4\x8c\x08\ -\x54\x5f\xd5\x9d\x49\xb9\xdc\xac\x91\x41\x51\x4a\x99\x4c\x8b\x11\ -\xc4\x4f\x14\x23\x27\x64\xeb\xf4\xe4\xf2\x63\xa1\xee\x00\xcb\x6d\ -\x5f\x48\x9d\xfc\xc3\xf0\xae\x65\xf5\x24\x8c\x57\x74\xf4\x45\x9b\ -\xce\x5f\x12\x9a\xde\x16\x2d\xeb\x56\xe1\x0b\x23\x8f\x2d\xcb\x62\ -\x6c\xc9\x50\xfe\x1e\xb5\x32\x76\xf8\xad\xc6\x12\x92\xd4\x87\x09\ -\x94\x43\x78\x4d\x4d\x0a\x4f\x56\x60\x89\xd3\xef\x16\x20\x5b\xdd\ -\x42\x17\x92\x4c\x66\xcc\xcf\x50\x66\xc6\xb8\x53\x1d\x1e\xaa\x65\ -\x75\x67\x39\xd8\xc5\x00\x03\xbb\xb5\x0d\xdf\x56\x98\xb1\x61\xa6\ -\xbd\x74\xeb\xff\x00\x10\xaf\x51\xa3\x09\xa7\x1c\x56\x9c\xaf\xa3\ -\x3d\x4c\x13\xd4\xe1\x88\xaf\xed\xfd\x95\x25\x29\xed\xcf\xcf\xb5\ -\x9f\xd1\x84\x1f\x27\x0e\x7f\xee\x8e\x5f\x6b\x37\x8b\x2f\xc4\xac\ -\x7f\x3b\x3e\x4f\xec\x9e\x6a\x71\x86\x5a\xf2\xe6\xf8\x52\x36\xee\ -\xb3\x39\x4e\xb5\x6e\xd9\x50\x9a\xb4\x27\x48\xaf\xd0\xe7\x4d\xac\ -\xd6\xe5\x3a\xec\x36\xd9\x7e\x5d\x46\x52\x4b\x21\x02\x17\xc8\x97\ -\x25\x55\x12\x52\x14\xcb\xcb\x76\x2c\x36\xf7\x36\xc1\x24\x8f\xb4\ -\x66\x12\x66\x01\xe9\x60\x22\xd9\x78\x95\x66\xe6\xd6\xea\x48\xe2\ -\x66\x8d\xdc\x81\xc8\xcf\xa3\x89\x19\x67\xe3\x53\x9a\xc5\x63\x95\ -\xa6\xdf\x27\x78\x46\xe3\xb9\xca\x34\xfa\x2b\xd4\xeb\x76\x33\xf2\ -\xa1\x7d\x8d\x42\x59\x81\x3b\x21\xcc\x9e\x54\xcb\x68\xec\xc8\x7d\ -\xe1\x1f\xab\xbb\xa5\x74\x71\xdb\x0c\x3b\x37\x95\xb1\x2c\xc7\x81\ -\x74\x47\x40\xe8\x4c\xe5\x96\xec\xa7\xda\xb4\x2f\xaa\x0e\x21\x88\ -\xe0\x65\xa4\xb4\xa9\x2d\x6e\xd5\xab\x07\x00\x85\x9a\xf5\x26\x4d\ -\x5e\xe0\x93\x48\x6a\x2b\xb0\xd8\x26\x94\xc2\xa4\xe3\x7d\xd5\x70\ -\xcd\xd7\x04\x76\xb6\xff\x00\x51\x2a\x2a\xaf\xe0\x8e\x22\xc5\x38\ -\xfc\xf6\xd1\x89\x84\x58\xab\x5f\x53\xf8\x8a\x99\x2d\xb9\xff\x00\ -\xaf\xd9\x38\xb9\x13\x8d\x29\x87\x4f\x4f\x0b\xf0\x12\x82\x51\xac\ -\xbb\xfe\xbb\xc0\x55\x7e\x33\xb9\xad\xd9\x11\x2b\xb4\xb6\xfb\xd4\ -\x27\xdc\x72\x39\x84\x84\x69\xf4\x90\xdb\x42\x42\xe9\x28\x9a\x64\ -\x4d\x75\x22\x0e\xc5\x1e\xac\x31\x92\xe6\x08\xef\x86\x70\x36\x71\ -\x2e\x96\x9c\x30\xcb\xc5\xe1\x4b\x22\xb5\xb8\x93\x77\x95\xbc\x80\ -\xec\x43\xd0\xd1\xad\x8e\x6a\x69\xd3\xd5\xe4\x4e\x2e\x25\xb4\x5c\ -\xb2\x38\xf6\x89\x6f\xca\x0d\xb5\x26\xd8\xf8\x8a\x96\x6a\x84\x5f\ -\x19\x24\x95\xe7\x51\x49\x33\x42\xda\x45\xb3\x3f\x60\xe1\x16\xf0\ -\xb8\xdb\xce\x46\xda\x2b\x87\x65\xb4\x2b\x0e\xed\xb6\x7b\x7b\x71\ -\x07\xd3\x4d\x6e\xd1\x62\xe9\x77\xc9\xfc\x39\x36\xeb\xe6\x2b\x36\ -\xec\x87\x17\xb9\x45\x42\x04\xb8\xdc\x42\x11\x11\x4a\x71\xf7\x9a\ -\x53\x45\x54\x55\xee\xa7\xd9\x74\xe7\xee\xfd\x5f\x1c\x34\xb1\xde\ -\x2d\x15\xa4\x91\xbb\xeb\x75\x3d\xac\x3e\xef\x49\x28\xde\x1b\xac\ -\xa6\xbc\x8e\x46\x6d\x5e\xbf\xb1\x8b\x7f\x37\x45\x77\x2d\x43\xbb\ -\xaa\xbc\xbd\x55\xb9\xee\x0b\x56\x75\x2e\x8e\x74\xc6\xe9\x54\x19\ -\x52\x1c\x8a\x48\xcb\x2d\xb8\xaf\xbd\xde\x16\x9e\x35\x42\x78\xd0\ -\x72\xdb\xbf\xdd\x11\x55\xc4\x7b\x86\x88\x2d\x44\x00\xd8\x9f\x36\ -\x62\xd3\xc8\xd4\xc3\xaa\xa4\xdb\x3c\xc7\x78\x52\x1c\x6e\x23\x97\ -\x20\x74\x70\xeb\x16\x6a\x3f\x59\x75\x79\xd6\x89\x50\xb9\xb8\xe2\ -\xa7\x6f\x52\xa8\xf2\x2b\x15\x29\xea\xd0\xc4\x6e\x32\xb2\x1d\x97\ -\x5a\x70\x5d\x47\x0c\x9e\x30\xc8\x53\x66\x4b\xb7\x71\x2e\x7b\x7c\ -\xf3\xc6\x9d\xd7\x28\xc5\x70\xc6\x44\xc2\xcd\xc7\x5e\x65\xbf\x7b\ -\xc4\x52\xdb\x10\x08\xb9\x3b\xe8\xa5\x30\xe1\xae\x29\x12\x16\xc7\ -\x32\x3e\xff\x00\x18\x3f\x50\xb3\x66\x93\xb6\x0b\xa2\x32\x9d\x07\ -\xe1\x92\xc8\x88\xdc\x86\x8c\x05\xb4\x27\xb4\x24\x65\xbe\xde\xab\ -\xe3\xae\x98\xb1\x6d\xed\x19\xa6\x66\x91\xbf\x17\xbc\x58\x15\x1f\ -\xbd\xe9\x62\xab\x1f\x2f\x78\xef\x03\x94\x6f\xf8\x3a\x71\x1d\x61\ -\xab\x77\xfd\x16\xa2\x6c\xf3\x65\x83\x58\xe4\x8b\x42\x95\x70\xdb\ -\x70\x9f\xa7\xdf\x34\x37\x42\x7d\x2e\x33\xe4\xd3\x32\xc5\x15\x51\ -\x5c\x65\x4c\x1c\x36\xd0\xd1\x44\x5c\x15\x47\x14\x77\x07\xbd\xd5\ -\x84\xbb\xb2\xec\x2d\xa5\x20\x37\x67\x8c\xb5\x4b\xd1\xe5\x4f\x77\ -\xad\x99\xdd\x42\x27\x1b\x38\xc8\x1a\xc3\xa3\x37\x27\x17\x7f\x4a\ -\x5d\xdd\x50\x39\x8a\xe8\xba\xec\x1b\xca\x55\x89\x2b\xe6\x96\xba\ -\x34\x55\x76\x52\x44\x40\x6a\x43\xad\xbe\x8e\x12\xb2\xa8\xf2\xed\ -\x43\x14\xcf\xa9\x3a\x49\x72\xea\x11\xcc\x9a\x40\x76\x91\x45\x2c\ -\x6d\x2b\x50\xfa\x38\x16\x18\x70\xe0\x94\xdc\x05\xe4\xd2\xc5\x2b\ -\xc4\xf5\x8f\xa5\x88\xeb\x63\xc1\x8a\x67\xde\xf7\x9f\x20\xd4\xad\ -\x6a\x85\x32\xd3\xb0\x2b\x2c\xd6\xe7\x47\x72\x33\x72\x66\xbb\x4e\ -\x69\xa8\xea\xf0\xec\x57\x05\x5b\x96\xea\x91\x0a\x2a\xa8\xf4\x8e\ -\xb9\x61\x45\xb5\xb4\x03\x23\x14\x92\x8e\x56\x7a\xe1\x9b\x1f\xba\ -\xc9\xd5\xdd\xd5\xc1\xc4\xe3\x1c\x25\x99\xda\x98\xe4\xc3\xef\x3a\ -\xec\x5b\xf5\x8a\xe5\x1e\xe6\xa7\xf1\xe8\xd1\x89\x28\x34\xda\x6b\ -\x0d\x0d\x55\x01\xd4\x0c\x98\x8c\x08\x8b\xdc\x51\xed\xaa\x6f\x45\ -\x6f\x6a\x2e\xef\xad\x9f\x88\xe3\x44\xd1\x81\xc6\xf3\x66\xd6\x72\ -\x7d\x5f\x0f\x8f\xbe\xa4\x43\x29\x84\xad\x06\x5d\x51\x16\xd6\xc7\ -\x81\xbc\x5d\xe4\xc2\xc2\xc4\xd9\x7f\xff\xd6\xbf\xd8\x10\x8c\x08\ -\x4a\x8f\x52\xbf\x99\x4b\x9f\xf7\x87\xf4\x8c\x6c\x39\xdc\xbf\xac\ -\x0f\x6b\xdd\x24\x8b\x7f\x7e\x88\xfd\x9f\x7c\x52\xa3\xd1\x6f\xf6\ -\xdf\xf9\xab\xf8\xee\x1c\xfd\x49\xf9\x7e\xd7\xc2\x91\x7d\x2b\xf9\ -\xbe\xcf\xc4\xad\x76\x29\xaa\xf4\xb9\xf5\xca\xd5\x32\xdc\xa4\x4c\ -\xae\xd6\x1f\x18\xd4\xc8\x0d\x13\xf2\x5e\x2f\x04\x01\xf6\x27\x9a\ -\xaa\xe8\x28\x9a\x91\x68\x98\xdb\x14\x45\x21\xb0\x8b\x55\xdd\x6a\ -\x9a\x51\x88\x1c\xc9\xe8\xcc\xa9\x0f\x1f\xdb\x15\x2e\x7c\xe5\xf9\ -\xf7\x2d\x51\x85\x4b\x79\x26\x7c\xc6\xae\xa5\xa8\x0c\x74\x2f\xb0\ -\x89\x9e\x99\xa9\x08\x8b\x7f\xa4\x13\x3f\x2c\x74\x0b\xb9\xc6\xc2\ -\xd5\x80\x5f\x5a\x99\x47\x97\xac\x5c\xeb\x9a\xd9\x5b\x96\xf2\xbc\ -\x79\x09\xb5\x6b\x98\xb9\x3a\xa1\xcd\xc8\xaf\x72\x22\x22\x64\x9a\ -\x22\x78\x26\x39\xd2\xe9\xe8\xc0\x84\x60\x42\x30\x21\x18\x10\x8c\ -\x08\x46\x04\x23\x02\x11\x81\x08\xc0\x84\x60\x42\x30\x21\x18\x10\ -\x8c\x08\x46\x04\x23\x02\x17\xff\xd7\xbf\xd8\x10\x8c\x08\x55\xa7\ -\x9e\x2f\x6b\xd2\xec\xa1\xd6\x78\xf2\xdf\xe3\xdb\x81\xc6\x0e\x5a\ -\x31\x22\xb0\xb0\x5f\x36\x1d\x6e\x14\x94\x34\x36\x11\xb6\x8f\x78\ -\x38\x4d\x89\x09\xee\x1e\x9c\x5a\xf7\x55\xb4\x31\x18\xcc\x72\x86\ -\x8e\x8d\x5b\xac\xdd\x6c\x78\x15\x37\x7c\x5d\xcd\x34\x65\x00\x42\ -\x7a\x7a\x59\x5e\x9a\xaf\xd5\xc3\x86\x89\x65\xc2\xf3\xf9\x57\x89\ -\x2b\x13\xa5\x2f\x1e\xd7\x6a\x54\xaa\xa3\x4d\xb5\x36\x2a\x40\x98\ -\xcb\x88\x4c\x92\xab\x6e\x01\x2b\x04\x99\x8e\xe3\x4d\xaa\x9a\xee\ -\xf1\x4c\x37\xde\x41\x6d\x76\x0c\xdb\x51\x17\x1d\x1a\xc3\xf6\xa4\ -\xbb\xa8\xee\xec\x8d\xdf\x62\x64\xc5\xa5\xb2\x97\xd8\x9e\xa5\xce\ -\x77\xb4\x84\xed\x53\x38\x8e\xe3\x39\x4b\xee\xa4\xc6\x9c\x88\xd6\ -\xba\x26\x6e\x13\x0a\x9e\x2b\x8a\xef\xfa\xb8\x5b\xa5\x38\x53\xbd\ -\xad\xce\xac\xff\x00\xed\xe7\x7e\x8d\xb9\xd7\xbf\xab\xcc\xa3\x35\ -\x5e\x3a\xe6\xbe\x6b\x94\xc2\x72\x34\x88\xf6\x85\x9a\xcb\x88\xe8\ -\xd1\x21\x98\xbe\xf9\xe5\xe0\x4a\x80\x46\x2a\x79\x69\xb9\xc3\xe8\ -\x5d\x45\x9f\x2c\x4b\x8e\xf2\xce\xc9\x9f\x62\xcf\x21\xfa\x4f\xdd\ -\xe6\xfe\x65\x0e\x4b\x1b\xdb\xf7\x6d\xbb\xb4\x71\xfa\x0d\x8b\xf7\ -\x72\xff\x00\x2a\x7b\x5a\x16\x75\xbf\x62\xd0\xd8\xb7\xad\xb8\xa9\ -\x16\x9e\xc6\x64\x5f\x59\xc7\x5c\x2f\x79\xc7\x0f\xc4\x8c\xb2\xf1\ -\xff\x00\x35\x32\x14\x44\xc5\x76\xe2\xe0\xe7\x37\x33\x7a\xba\xb3\ -\xdb\x5a\xc7\x6f\x1b\x04\x6d\x46\xee\xd2\xbb\xd8\x8c\xa5\x23\x02\ -\x11\x81\x08\xc0\x84\x60\x42\x30\x21\x18\x10\x8c\x08\x46\x04\x23\ -\x02\x11\x81\x08\xc0\x84\x60\x42\x30\x21\x18\x10\x8c\x08\x5f\xff\ -\xd0\xbf\xd8\x10\x8c\x08\x46\x04\x23\x02\x11\x81\x08\xc0\x84\x60\ -\x42\x30\x21\x18\x10\x8c\x08\x46\x04\x23\x02\x11\x81\x08\xc0\x84\ -\x60\x42\x30\x21\x18\x10\x8c\x08\x46\x04\x23\x02\x11\x81\x08\xc0\ -\x84\x60\x42\xff\xd9\ -\x00\x00\x02\x7e\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x41\x00\x00\x00\x14\x08\x02\x00\x00\x00\x5d\xd6\xc7\x56\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x13\x49\x44\x41\x54\x58\x47\xed\x96\xbd\x8d\ -\x02\x31\x10\x46\x97\xeb\x00\x42\x22\x24\xc8\x91\x10\x22\x22\xa7\ -\x04\x68\x01\x4a\xa0\x03\xa8\x00\x24\x72\x22\x42\x12\x12\x02\x1a\ -\x58\x0a\x80\x90\x08\x68\x61\xef\x69\x3f\x6b\xd6\xb7\x3f\x88\x5b\ -\xdd\x49\x20\xf1\x82\xbb\xf1\x8c\x3d\x33\x9f\xed\xb5\xa8\x44\x51\ -\x14\xbc\x39\x5f\xee\xff\x3b\xf3\xd1\xf0\x3f\x9c\xcf\xe7\xd1\x68\ -\x54\x89\x99\x4c\x26\x72\x2e\x97\xcb\x56\xab\x85\xa7\x56\xab\x1d\ -\x8f\x47\x39\xc5\xcb\x69\xb8\xdd\x6e\xdd\x6e\xb7\xd3\xe9\xf0\xa1\ -\x6e\xb7\xdb\x46\xa3\x81\x73\x3e\x9f\xaf\x56\xab\xcd\x66\x83\xb3\ -\xd9\x6c\xb6\xdb\x6d\x4d\x76\xe0\xf5\x09\xc3\x70\x38\x1c\x2a\xc4\ -\xec\xf5\x7a\xed\x02\xbf\x67\x36\x9b\x29\x8f\xa0\x33\x92\x2b\x74\ -\x38\x1c\x9c\x37\xc6\x2f\x34\x9d\x4e\x69\x40\xb6\xb8\x5e\xaf\xcc\ -\xb1\xb5\x59\x7e\x68\x40\x37\xb3\xa9\xcd\x32\xd6\x54\xab\x55\x8a\ -\xb9\x58\x29\xe8\x9b\x9e\x30\x48\x48\x67\xf4\x2a\x3f\xe0\x27\x2a\ -\x5b\x6a\x4f\xa7\x13\x36\x73\x68\x43\x7e\x81\x3c\x9b\x99\x4b\xa2\ -\x81\x32\x34\x4d\x3a\x37\x8e\xa2\xc1\x60\xa0\xbc\x3e\x38\x53\x5b\ -\x42\x0d\x35\x9a\x85\x84\xb6\xc1\x18\x34\x2a\x1b\x90\x34\x1e\x8f\ -\x65\x53\x85\x90\xf6\x0b\x83\x4e\xe4\x17\xb4\x54\x94\x5f\x24\x49\ -\x99\x4a\x49\x37\x28\x86\x56\x98\x66\x32\x52\x43\x1f\x9c\xb6\xbb\ -\x40\x1f\xfe\x39\xf8\xf2\x74\xfe\x76\x0e\xf2\xe3\x94\x48\x86\x9c\ -\x03\xc2\x20\x77\x5b\x13\x0d\x2c\x7e\x2c\xd7\xb0\xbe\x1f\x08\x80\ -\xc5\x62\xa1\xa6\xa9\x8d\x4d\x97\x76\x49\x7c\x79\x38\x49\x62\xa5\ -\xc9\xc9\x2a\xa2\x26\x92\xe5\xf6\x89\xe6\x5e\x2a\xa7\xc1\x3f\xcd\ -\x67\x50\xf7\x50\x24\x00\xac\x30\xb0\x7f\x7e\x72\x49\x12\xb6\xf1\ -\xa5\x71\x6f\xeb\xe5\x72\xe1\x6f\xbd\x5e\xd7\xf0\x4f\xd8\xed\x76\ -\xf4\x4a\x0d\x6e\x29\x2f\x66\xbf\xdf\x77\x81\x20\xd8\xef\xf7\x7a\ -\x7c\x10\x76\xbf\xdf\x7b\xbd\x9e\x0b\x94\x23\x56\xe2\x1e\xbb\xec\ -\x55\xcb\xc5\xae\x90\x19\x2e\xe0\xa1\xdb\xa2\x50\xf6\x90\x59\x25\ -\x79\xc0\x39\xf8\x0f\x49\x09\x9c\x06\xee\x1c\x79\x75\x29\x75\x7d\ -\x39\x7d\x85\x52\xa4\xfa\x2e\x92\x41\x2a\xdb\x20\xf0\x1b\xd5\x17\ -\x6c\x92\xf8\x70\x8b\x6a\x3d\x49\x52\x86\xd4\xfa\x98\xe0\xc1\x1d\ -\xa5\x24\x22\xdd\x20\x86\x99\xa9\xc7\x40\xa7\x0a\xd6\x1c\xab\x90\ -\xaa\xbe\x15\x02\x85\x58\x8e\x6d\xc7\x52\x82\xcf\x6f\xef\xd7\xe0\ -\xa3\xe1\x35\x78\x7f\x0d\x41\xf0\x0d\xf7\xde\xa9\x12\x11\xdc\x6c\ -\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x04\xc2\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x85\x00\x00\x00\x1b\x08\x02\x00\x00\x00\xdd\xd4\xdb\x58\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x04\x57\x49\x44\x41\x54\x68\x43\xed\x99\x3b\x2f\ -\x6d\x41\x14\xc7\x8f\xfb\x01\x08\x3a\xe5\xa5\x91\x10\x8d\x47\x41\ -\x24\x14\x88\x4a\xe1\x55\x4a\x54\xb4\x12\x05\x4a\x0d\x9f\x80\x44\ -\x4f\x21\x51\x79\x17\x0a\x0a\xaf\x08\x51\xd0\x10\x89\x44\xe5\x11\ -\x9f\xe0\xdc\xdf\xd9\xff\xb9\x73\x67\xcf\x39\x1b\xd7\x3d\x64\x92\ -\xbb\x7f\xc5\x58\x6b\xcd\x6b\xcd\x5a\x33\x6b\x0b\x25\xd9\x6c\x36\ -\x93\x12\x0c\x3f\xcc\xcf\x94\x30\x48\xf3\x11\x16\x69\x3e\xc2\x22\ -\xcd\x47\x58\xa4\xf9\x08\x8b\xa0\xf3\x31\x3d\x3d\x5d\xe2\x30\x3f\ -\x3f\x8f\xb1\xa9\xa9\xc9\xe8\x11\x07\x07\x07\x18\x6f\x6f\x6f\xc7\ -\xc7\xc7\x35\xe0\xfb\x79\x7a\x7a\x32\xde\xfc\x26\xc9\xb8\xb2\xb2\ -\x52\x53\x53\x83\xdc\xd3\xd3\x13\x4d\xf5\x09\x3a\x1f\xa3\xa3\xa3\ -\xe5\xe5\xe5\xfc\x46\x0e\x0b\x0b\x0b\x75\x75\x75\x18\x27\x26\x26\ -\x86\x86\x86\x64\x44\xa8\xad\xad\xbd\xb8\xb8\x58\x5d\x5d\x7d\x7e\ -\x7e\xd6\xac\xef\xa7\xb2\xb2\x72\x6c\x6c\x0c\x0f\xe5\x55\x77\x77\ -\x77\x92\x71\x66\x66\xe6\xe8\xe8\xe8\xe6\xe6\xe6\xf8\xf8\x58\x37\ -\xc9\x47\xa3\xc5\xdc\xdc\x9c\xb1\x3a\xec\xef\xef\x9b\xee\xbf\x47\ -\x2b\xe0\x8a\xd1\x23\xb4\x0b\xbe\xba\xaa\x85\xc1\xe7\xe7\xe7\xea\ -\x5a\x5e\x5e\xd6\x30\x9b\x00\xc0\x82\xfd\xf1\xf1\xd1\xae\x20\x58\ -\x07\x8c\xf2\x59\x3c\x67\x1a\x1b\x1b\xad\x33\xc4\xc1\x58\x23\xaa\ -\xab\xab\x71\x43\x5d\x80\x4a\x94\x19\xec\xfa\x50\xd0\x28\x58\x99\ -\x23\x18\xc5\x21\x96\x0f\x60\xdc\xd4\xd4\x94\x64\x26\xb0\x71\xc1\ -\x69\x1f\x64\x7d\x7d\x9d\xf8\xb2\xa6\xd1\xb3\x59\xfc\xc3\x4b\x6f\ -\x59\xbb\x29\x46\x64\x1b\x7d\x22\x1e\x9d\x3d\x17\x17\x59\x40\xd3\ -\xc1\xfa\x29\x72\xd9\xf8\xe7\x7c\x80\xeb\x0c\x9e\xb0\x9d\xec\x80\ -\xdd\x7a\xc2\x5e\xf8\xc0\x71\x90\x69\xe5\x12\x70\x64\x0d\x28\x68\ -\x14\x3c\x1a\xcf\x62\xf1\xeb\xd5\xcb\xcb\x4b\x6b\x6b\xab\x64\x5e\ -\x1c\xe5\x82\x56\xaa\xd8\xd8\xd8\xa0\x52\x1b\x25\x82\x42\x49\x35\ -\xa4\x82\x1b\xdd\xe1\xfe\xfe\xbe\xb3\xb3\xf3\xf4\xf4\xd4\xe8\x51\ -\x10\x39\x12\xb8\xcb\xe2\xba\x36\xc5\x38\x30\x30\xb0\xb3\xb3\x23\ -\x3b\xd5\x56\xd7\xd3\x0e\xa6\x34\x51\x97\xb0\x70\x5b\xcb\xca\xca\ -\x64\x7c\x17\xdc\x63\xa2\x51\x22\x58\x99\x8f\x93\x51\xe2\xe0\x4c\ -\x7d\x7d\x3d\x02\x9b\xf6\xf5\xf5\xb9\x61\x45\xe6\xeb\x25\xb9\xbf\ -\xbf\x9f\xf6\xe1\xe1\x81\x76\x77\x77\x57\x77\x88\x24\x95\x96\x96\ -\x46\xfd\x85\x8d\xc0\xd6\x78\xde\xdb\xdb\x6b\xf4\x38\xb1\x7c\x10\ -\x53\xb6\xd4\xd0\xe1\xe1\x61\x1d\x5e\x5d\x96\x96\x96\x96\x93\x93\ -\x13\x9b\x12\x25\xe3\x67\x84\x2c\x2e\x7b\x7b\x7b\x7c\x03\x10\x18\ -\x46\x4b\xc5\xac\xa8\xa8\x40\xb0\xa7\x02\x76\xe1\x12\xb0\xac\xd4\ -\xbb\xbb\xbb\xe6\xe6\x66\x04\x95\xd7\x86\x86\x06\xda\x91\x91\x91\ -\xc5\xc5\x45\x84\xed\xed\xed\xae\xae\x2e\x84\xb6\xb6\x36\x46\xba\ -\x51\x3e\x3b\x3b\x7b\x7d\x7d\x35\x4a\x1c\xa6\x77\x74\x74\xd8\xc1\ -\x44\x04\xff\x07\x07\x07\xa5\xba\xc8\x19\x39\x00\x97\x97\x97\xf6\ -\x39\x02\x17\xa5\xbd\xbd\x5d\xf2\xf5\xf5\x35\x6d\x55\x55\x15\xed\ -\xda\xda\x1a\xeb\x23\x70\xd8\xd9\xd9\xd9\x5c\x77\x82\x91\xad\x69\ -\x89\x2d\xd7\xfa\xfd\xef\x07\x05\xd1\x58\x33\x19\xfb\x21\xcd\x47\ -\x55\x85\x62\x62\x05\xd3\x91\x07\xbd\xb4\xac\xa6\x8f\x10\x2a\x53\ -\x58\xd9\xad\xbc\x3c\x5e\x0d\xa3\x0b\x99\xc1\x7a\xcb\x18\x23\x47\ -\x0c\x3c\x14\x06\x18\x25\xc2\x7a\xe8\x55\x76\x19\x3d\xd8\x91\xf1\ -\x2c\x62\x05\xd3\x11\x07\x07\x54\xa0\x3c\x67\x80\x29\xa8\xdc\x57\ -\x64\x8c\x2c\xa2\xb2\x86\x1c\x6d\x6b\xd0\x9b\x28\x68\x74\x9f\x1a\ -\x14\xfc\x30\xc7\xbc\x27\xb2\x0a\x2e\xde\x78\x1f\x61\x0f\x06\x10\ -\x2f\x7c\x7a\x23\x19\x1c\x40\xbd\x8c\x64\x6f\x8e\xc7\xcb\x75\x4f\ -\x25\xf0\x55\xfe\x01\x23\xed\xf9\x8b\x8e\x32\x01\x49\xc9\x00\xd7\ -\x19\x22\xe0\x86\x4c\xe9\x11\xe4\xcc\xbd\x52\x45\x24\x56\xaf\x28\ -\x44\x7a\x8f\x94\xce\xad\xad\x2d\x19\x3f\xcd\xe1\xe1\xa1\xaa\x0d\ -\xab\x6d\x6e\x6e\x2e\x2d\x2d\x4d\x4e\x4e\x5e\x5d\x5d\x71\x18\xb7\ -\xb8\x51\x04\x38\xaa\xbc\xc1\x81\xa4\xc2\xfa\x3d\x58\x67\xb8\x3a\ -\xd4\x58\xaa\xa2\xe9\x88\x6a\xaf\xae\x39\x49\xa2\x8c\xdb\x9a\x56\ -\x64\xa2\x38\xe4\x50\x35\xb0\x37\x17\x21\xe9\x89\xe8\x71\x70\xf7\ -\xad\x60\x3a\xe2\xd8\xdf\x5c\x79\xd7\xac\xac\xbb\xc6\x60\x9d\x4a\ -\xe4\x3f\x97\x2f\xe2\x23\xf5\x4a\xce\xa8\x4b\xb5\xc5\x7d\x1f\xcc\ -\xb2\xf7\x86\x2b\x45\xc2\x24\x17\x97\x3f\xf9\x50\x4d\x94\xac\x40\ -\x17\xdc\xd2\xcb\x41\x52\x4a\xb0\x73\x1e\x5a\x64\xd6\x51\x0e\x50\ -\xd9\x42\x65\x57\x28\x55\x46\xf9\x32\xbc\x1c\x24\xa5\xc4\x73\xc6\ -\x0d\xba\xbe\x07\x36\x3d\x9c\xf7\xed\x7a\xfe\x69\xcc\xf6\x0a\x2b\ -\x5b\xba\xb8\xb7\xc3\x82\x67\x5e\xe9\x64\x2e\xce\x79\x77\x1c\x0b\ -\x2b\x78\x4e\xcb\x68\x57\xa6\x95\xfa\x45\x67\xb3\x10\x3e\xdd\x0c\ -\x0b\x47\x70\xaf\x05\xe4\x3b\xc3\x2c\xd2\x26\x57\xd5\x05\xea\x62\ -\x3a\xb2\x7d\x2e\x45\x24\xfd\xff\x60\x58\x04\xfd\xf7\xab\xff\x90\ -\x34\x1f\x61\x91\xe6\x23\x2c\xd2\x7c\x84\x45\x9a\x8f\xb0\x48\xf3\ -\x11\x16\x69\x3e\xc2\x22\xcd\x47\x48\x64\x32\xbf\x00\x43\x56\xb8\ -\x32\x46\xab\x27\xb2\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ -\x82\ -\x00\x00\x5d\x38\ -\xff\ -\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\ -\x48\x00\x00\xff\xe1\x10\xee\x45\x78\x69\x66\x00\x00\x4d\x4d\x00\ -\x2a\x00\x00\x00\x08\x00\x04\x01\x3b\x00\x02\x00\x00\x00\x0c\x00\ -\x00\x08\x4a\x87\x69\x00\x04\x00\x00\x00\x01\x00\x00\x08\x56\x9c\ -\x9d\x00\x01\x00\x00\x00\x18\x00\x00\x10\xce\xea\x1c\x00\x07\x00\ -\x00\x08\x0c\x00\x00\x00\x3e\x00\x00\x00\x00\x1c\xea\x00\x00\x00\ -\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x52\x6f\x62\x20\x52\x61\x65\x73\x69\ -\x64\x65\x00\x00\x05\x90\x03\x00\x02\x00\x00\x00\x14\x00\x00\x10\ -\xa4\x90\x04\x00\x02\x00\x00\x00\x14\x00\x00\x10\xb8\x92\x91\x00\ -\x02\x00\x00\x00\x03\x31\x33\x00\x00\x92\x92\x00\x02\x00\x00\x00\ -\x03\x31\x33\x00\x00\xea\x1c\x00\x07\x00\x00\x08\x0c\x00\x00\x08\ -\x98\x00\x00\x00\x00\x1c\xea\x00\x00\x00\x08\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x32\x30\x32\x31\x3a\x30\x37\x3a\x33\x30\x20\x31\x37\x3a\x31\ -\x35\x3a\x35\x39\x00\x32\x30\x32\x31\x3a\x30\x37\x3a\x33\x30\x20\ -\x31\x37\x3a\x31\x35\x3a\x35\x39\x00\x00\x00\x52\x00\x6f\x00\x62\ -\x00\x20\x00\x52\x00\x61\x00\x65\x00\x73\x00\x69\x00\x64\x00\x65\ -\x00\x00\x00\xff\xe2\x0c\x58\x49\x43\x43\x5f\x50\x52\x4f\x46\x49\ -\x4c\x45\x00\x01\x01\x00\x00\x0c\x48\x4c\x69\x6e\x6f\x02\x10\x00\ -\x00\x6d\x6e\x74\x72\x52\x47\x42\x20\x58\x59\x5a\x20\x07\xce\x00\ -\x02\x00\x09\x00\x06\x00\x31\x00\x00\x61\x63\x73\x70\x4d\x53\x46\ -\x54\x00\x00\x00\x00\x49\x45\x43\x20\x73\x52\x47\x42\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\ -\x00\x00\x00\xd3\x2d\x48\x50\x20\x20\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x11\x63\x70\x72\x74\x00\x00\x01\ -\x50\x00\x00\x00\x33\x64\x65\x73\x63\x00\x00\x01\x84\x00\x00\x00\ -\x6c\x77\x74\x70\x74\x00\x00\x01\xf0\x00\x00\x00\x14\x62\x6b\x70\ -\x74\x00\x00\x02\x04\x00\x00\x00\x14\x72\x58\x59\x5a\x00\x00\x02\ -\x18\x00\x00\x00\x14\x67\x58\x59\x5a\x00\x00\x02\x2c\x00\x00\x00\ -\x14\x62\x58\x59\x5a\x00\x00\x02\x40\x00\x00\x00\x14\x64\x6d\x6e\ -\x64\x00\x00\x02\x54\x00\x00\x00\x70\x64\x6d\x64\x64\x00\x00\x02\ -\xc4\x00\x00\x00\x88\x76\x75\x65\x64\x00\x00\x03\x4c\x00\x00\x00\ -\x86\x76\x69\x65\x77\x00\x00\x03\xd4\x00\x00\x00\x24\x6c\x75\x6d\ -\x69\x00\x00\x03\xf8\x00\x00\x00\x14\x6d\x65\x61\x73\x00\x00\x04\ -\x0c\x00\x00\x00\x24\x74\x65\x63\x68\x00\x00\x04\x30\x00\x00\x00\ -\x0c\x72\x54\x52\x43\x00\x00\x04\x3c\x00\x00\x08\x0c\x67\x54\x52\ -\x43\x00\x00\x04\x3c\x00\x00\x08\x0c\x62\x54\x52\x43\x00\x00\x04\ -\x3c\x00\x00\x08\x0c\x74\x65\x78\x74\x00\x00\x00\x00\x43\x6f\x70\ -\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x31\x39\x39\x38\x20\ -\x48\x65\x77\x6c\x65\x74\x74\x2d\x50\x61\x63\x6b\x61\x72\x64\x20\ -\x43\x6f\x6d\x70\x61\x6e\x79\x00\x00\x64\x65\x73\x63\x00\x00\x00\ -\x00\x00\x00\x00\x12\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\ -\x36\x36\x2d\x32\x2e\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x12\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\x2d\ -\x32\x2e\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x58\x59\x5a\x20\x00\x00\x00\x00\x00\x00\xf3\ -\x51\x00\x01\x00\x00\x00\x01\x16\xcc\x58\x59\x5a\x20\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\x59\x5a\ -\x20\x00\x00\x00\x00\x00\x00\x6f\xa2\x00\x00\x38\xf5\x00\x00\x03\ -\x90\x58\x59\x5a\x20\x00\x00\x00\x00\x00\x00\x62\x99\x00\x00\xb7\ -\x85\x00\x00\x18\xda\x58\x59\x5a\x20\x00\x00\x00\x00\x00\x00\x24\ -\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcf\x64\x65\x73\x63\x00\x00\x00\ -\x00\x00\x00\x00\x16\x49\x45\x43\x20\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x69\x65\x63\x2e\x63\x68\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x16\x49\x45\x43\x20\x68\x74\x74\x70\x3a\x2f\ -\x2f\x77\x77\x77\x2e\x69\x65\x63\x2e\x63\x68\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x64\x65\x73\x63\x00\x00\x00\ -\x00\x00\x00\x00\x2e\x49\x45\x43\x20\x36\x31\x39\x36\x36\x2d\x32\ -\x2e\x31\x20\x44\x65\x66\x61\x75\x6c\x74\x20\x52\x47\x42\x20\x63\ -\x6f\x6c\x6f\x75\x72\x20\x73\x70\x61\x63\x65\x20\x2d\x20\x73\x52\ -\x47\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x49\x45\ -\x43\x20\x36\x31\x39\x36\x36\x2d\x32\x2e\x31\x20\x44\x65\x66\x61\ -\x75\x6c\x74\x20\x52\x47\x42\x20\x63\x6f\x6c\x6f\x75\x72\x20\x73\ -\x70\x61\x63\x65\x20\x2d\x20\x73\x52\x47\x42\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x64\x65\x73\x63\x00\x00\x00\x00\x00\x00\x00\x2c\x52\x65\x66\ -\x65\x72\x65\x6e\x63\x65\x20\x56\x69\x65\x77\x69\x6e\x67\x20\x43\ -\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x20\x69\x6e\x20\x49\x45\x43\x36\ -\x31\x39\x36\x36\x2d\x32\x2e\x31\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x2c\x52\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x56\x69\ -\x65\x77\x69\x6e\x67\x20\x43\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x20\ -\x69\x6e\x20\x49\x45\x43\x36\x31\x39\x36\x36\x2d\x32\x2e\x31\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x76\x69\x65\x77\x00\x00\x00\ -\x00\x00\x13\xa4\xfe\x00\x14\x5f\x2e\x00\x10\xcf\x14\x00\x03\xed\ -\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01\x58\x59\x5a\ -\x20\x00\x00\x00\x00\x00\x4c\x09\x56\x00\x50\x00\x00\x00\x57\x1f\ -\xe7\x6d\x65\x61\x73\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\ -\x8f\x00\x00\x00\x02\x73\x69\x67\x20\x00\x00\x00\x00\x43\x52\x54\ -\x20\x63\x75\x72\x76\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\ -\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00\x23\x00\x28\x00\ -\x2d\x00\x32\x00\x37\x00\x3b\x00\x40\x00\x45\x00\x4a\x00\x4f\x00\ -\x54\x00\x59\x00\x5e\x00\x63\x00\x68\x00\x6d\x00\x72\x00\x77\x00\ -\x7c\x00\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\ -\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\ -\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\ -\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01\ -\x25\x01\x2b\x01\x32\x01\x38\x01\x3e\x01\x45\x01\x4c\x01\x52\x01\ -\x59\x01\x60\x01\x67\x01\x6e\x01\x75\x01\x7c\x01\x83\x01\x8b\x01\ -\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\ -\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\ -\x14\x02\x1d\x02\x26\x02\x2f\x02\x38\x02\x41\x02\x4b\x02\x54\x02\ -\x5d\x02\x67\x02\x71\x02\x7a\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\ -\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\ -\x00\x03\x0b\x03\x16\x03\x21\x03\x2d\x03\x38\x03\x43\x03\x4f\x03\ -\x5a\x03\x66\x03\x72\x03\x7e\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\ -\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04\ -\x20\x04\x2d\x04\x3b\x04\x48\x04\x55\x04\x63\x04\x71\x04\x7e\x04\ -\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\ -\xfe\x05\x0d\x05\x1c\x05\x2b\x05\x3a\x05\x49\x05\x58\x05\x67\x05\ -\x77\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\ -\xf6\x06\x06\x06\x16\x06\x27\x06\x37\x06\x48\x06\x59\x06\x6a\x06\ -\x7b\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\ -\x07\x07\x19\x07\x2b\x07\x3d\x07\x4f\x07\x61\x07\x74\x07\x86\x07\ -\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x08\ -\x32\x08\x46\x08\x5a\x08\x6e\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\ -\xd2\x08\xe7\x08\xfb\x09\x10\x09\x25\x09\x3a\x09\x4f\x09\x64\x09\ -\x79\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a\ -\x27\x0a\x3d\x0a\x54\x0a\x6a\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\ -\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b\x39\x0b\x51\x0b\x69\x0b\x80\x0b\ -\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c\x2a\x0c\x43\x0c\ -\x5c\x0c\x75\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d\ -\x26\x0d\x40\x0d\x5a\x0d\x74\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\ -\xf8\x0e\x13\x0e\x2e\x0e\x49\x0e\x64\x0e\x7f\x0e\x9b\x0e\xb6\x0e\ -\xd2\x0e\xee\x0f\x09\x0f\x25\x0f\x41\x0f\x5e\x0f\x7a\x0f\x96\x0f\ -\xb3\x0f\xcf\x0f\xec\x10\x09\x10\x26\x10\x43\x10\x61\x10\x7e\x10\ -\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\x31\x11\x4f\x11\x6d\x11\ -\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\x26\x12\x45\x12\x64\x12\ -\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\x23\x13\x43\x13\x63\x13\ -\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\x27\x14\x49\x14\x6a\x14\ -\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\x34\x15\x56\x15\x78\x15\ -\x9b\x15\xbd\x15\xe0\x16\x03\x16\x26\x16\x49\x16\x6c\x16\x8f\x16\ -\xb2\x16\xd6\x16\xfa\x17\x1d\x17\x41\x17\x65\x17\x89\x17\xae\x17\ -\xd2\x17\xf7\x18\x1b\x18\x40\x18\x65\x18\x8a\x18\xaf\x18\xd5\x18\ -\xfa\x19\x20\x19\x45\x19\x6b\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a\ -\x2a\x1a\x51\x1a\x77\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b\x3b\x1b\ -\x63\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\x2a\x1c\x52\x1c\x7b\x1c\ -\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1d\x47\x1d\x70\x1d\x99\x1d\xc3\x1d\ -\xec\x1e\x16\x1e\x40\x1e\x6a\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f\ -\x3e\x1f\x69\x1f\x94\x1f\xbf\x1f\xea\x20\x15\x20\x41\x20\x6c\x20\ -\x98\x20\xc4\x20\xf0\x21\x1c\x21\x48\x21\x75\x21\xa1\x21\xce\x21\ -\xfb\x22\x27\x22\x55\x22\x82\x22\xaf\x22\xdd\x23\x0a\x23\x38\x23\ -\x66\x23\x94\x23\xc2\x23\xf0\x24\x1f\x24\x4d\x24\x7c\x24\xab\x24\ -\xda\x25\x09\x25\x38\x25\x68\x25\x97\x25\xc7\x25\xf7\x26\x27\x26\ -\x57\x26\x87\x26\xb7\x26\xe8\x27\x18\x27\x49\x27\x7a\x27\xab\x27\ -\xdc\x28\x0d\x28\x3f\x28\x71\x28\xa2\x28\xd4\x29\x06\x29\x38\x29\ -\x6b\x29\x9d\x29\xd0\x2a\x02\x2a\x35\x2a\x68\x2a\x9b\x2a\xcf\x2b\ -\x02\x2b\x36\x2b\x69\x2b\x9d\x2b\xd1\x2c\x05\x2c\x39\x2c\x6e\x2c\ -\xa2\x2c\xd7\x2d\x0c\x2d\x41\x2d\x76\x2d\xab\x2d\xe1\x2e\x16\x2e\ -\x4c\x2e\x82\x2e\xb7\x2e\xee\x2f\x24\x2f\x5a\x2f\x91\x2f\xc7\x2f\ -\xfe\x30\x35\x30\x6c\x30\xa4\x30\xdb\x31\x12\x31\x4a\x31\x82\x31\ -\xba\x31\xf2\x32\x2a\x32\x63\x32\x9b\x32\xd4\x33\x0d\x33\x46\x33\ -\x7f\x33\xb8\x33\xf1\x34\x2b\x34\x65\x34\x9e\x34\xd8\x35\x13\x35\ -\x4d\x35\x87\x35\xc2\x35\xfd\x36\x37\x36\x72\x36\xae\x36\xe9\x37\ -\x24\x37\x60\x37\x9c\x37\xd7\x38\x14\x38\x50\x38\x8c\x38\xc8\x39\ -\x05\x39\x42\x39\x7f\x39\xbc\x39\xf9\x3a\x36\x3a\x74\x3a\xb2\x3a\ -\xef\x3b\x2d\x3b\x6b\x3b\xaa\x3b\xe8\x3c\x27\x3c\x65\x3c\xa4\x3c\ -\xe3\x3d\x22\x3d\x61\x3d\xa1\x3d\xe0\x3e\x20\x3e\x60\x3e\xa0\x3e\ -\xe0\x3f\x21\x3f\x61\x3f\xa2\x3f\xe2\x40\x23\x40\x64\x40\xa6\x40\ -\xe7\x41\x29\x41\x6a\x41\xac\x41\xee\x42\x30\x42\x72\x42\xb5\x42\ -\xf7\x43\x3a\x43\x7d\x43\xc0\x44\x03\x44\x47\x44\x8a\x44\xce\x45\ -\x12\x45\x55\x45\x9a\x45\xde\x46\x22\x46\x67\x46\xab\x46\xf0\x47\ -\x35\x47\x7b\x47\xc0\x48\x05\x48\x4b\x48\x91\x48\xd7\x49\x1d\x49\ -\x63\x49\xa9\x49\xf0\x4a\x37\x4a\x7d\x4a\xc4\x4b\x0c\x4b\x53\x4b\ -\x9a\x4b\xe2\x4c\x2a\x4c\x72\x4c\xba\x4d\x02\x4d\x4a\x4d\x93\x4d\ -\xdc\x4e\x25\x4e\x6e\x4e\xb7\x4f\x00\x4f\x49\x4f\x93\x4f\xdd\x50\ -\x27\x50\x71\x50\xbb\x51\x06\x51\x50\x51\x9b\x51\xe6\x52\x31\x52\ -\x7c\x52\xc7\x53\x13\x53\x5f\x53\xaa\x53\xf6\x54\x42\x54\x8f\x54\ -\xdb\x55\x28\x55\x75\x55\xc2\x56\x0f\x56\x5c\x56\xa9\x56\xf7\x57\ -\x44\x57\x92\x57\xe0\x58\x2f\x58\x7d\x58\xcb\x59\x1a\x59\x69\x59\ -\xb8\x5a\x07\x5a\x56\x5a\xa6\x5a\xf5\x5b\x45\x5b\x95\x5b\xe5\x5c\ -\x35\x5c\x86\x5c\xd6\x5d\x27\x5d\x78\x5d\xc9\x5e\x1a\x5e\x6c\x5e\ -\xbd\x5f\x0f\x5f\x61\x5f\xb3\x60\x05\x60\x57\x60\xaa\x60\xfc\x61\ -\x4f\x61\xa2\x61\xf5\x62\x49\x62\x9c\x62\xf0\x63\x43\x63\x97\x63\ -\xeb\x64\x40\x64\x94\x64\xe9\x65\x3d\x65\x92\x65\xe7\x66\x3d\x66\ -\x92\x66\xe8\x67\x3d\x67\x93\x67\xe9\x68\x3f\x68\x96\x68\xec\x69\ -\x43\x69\x9a\x69\xf1\x6a\x48\x6a\x9f\x6a\xf7\x6b\x4f\x6b\xa7\x6b\ -\xff\x6c\x57\x6c\xaf\x6d\x08\x6d\x60\x6d\xb9\x6e\x12\x6e\x6b\x6e\ -\xc4\x6f\x1e\x6f\x78\x6f\xd1\x70\x2b\x70\x86\x70\xe0\x71\x3a\x71\ -\x95\x71\xf0\x72\x4b\x72\xa6\x73\x01\x73\x5d\x73\xb8\x74\x14\x74\ -\x70\x74\xcc\x75\x28\x75\x85\x75\xe1\x76\x3e\x76\x9b\x76\xf8\x77\ -\x56\x77\xb3\x78\x11\x78\x6e\x78\xcc\x79\x2a\x79\x89\x79\xe7\x7a\ -\x46\x7a\xa5\x7b\x04\x7b\x63\x7b\xc2\x7c\x21\x7c\x81\x7c\xe1\x7d\ -\x41\x7d\xa1\x7e\x01\x7e\x62\x7e\xc2\x7f\x23\x7f\x84\x7f\xe5\x80\ -\x47\x80\xa8\x81\x0a\x81\x6b\x81\xcd\x82\x30\x82\x92\x82\xf4\x83\ -\x57\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\x47\x85\xab\x86\x0e\x86\ -\x72\x86\xd7\x87\x3b\x87\x9f\x88\x04\x88\x69\x88\xce\x89\x33\x89\ -\x99\x89\xfe\x8a\x64\x8a\xca\x8b\x30\x8b\x96\x8b\xfc\x8c\x63\x8c\ -\xca\x8d\x31\x8d\x98\x8d\xff\x8e\x66\x8e\xce\x8f\x36\x8f\x9e\x90\ -\x06\x90\x6e\x90\xd6\x91\x3f\x91\xa8\x92\x11\x92\x7a\x92\xe3\x93\ -\x4d\x93\xb6\x94\x20\x94\x8a\x94\xf4\x95\x5f\x95\xc9\x96\x34\x96\ -\x9f\x97\x0a\x97\x75\x97\xe0\x98\x4c\x98\xb8\x99\x24\x99\x90\x99\ -\xfc\x9a\x68\x9a\xd5\x9b\x42\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9d\ -\x64\x9d\xd2\x9e\x40\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0\x69\xa0\ -\xd8\xa1\x47\xa1\xb6\xa2\x26\xa2\x96\xa3\x06\xa3\x76\xa3\xe6\xa4\ -\x56\xa4\xc7\xa5\x38\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7\x6e\xa7\ -\xe0\xa8\x52\xa8\xc4\xa9\x37\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xab\ -\x75\xab\xe9\xac\x5c\xac\xd0\xad\x44\xad\xb8\xae\x2d\xae\xa1\xaf\ -\x16\xaf\x8b\xb0\x00\xb0\x75\xb0\xea\xb1\x60\xb1\xd6\xb2\x4b\xb2\ -\xc2\xb3\x38\xb3\xae\xb4\x25\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6\ -\x79\xb6\xf0\xb7\x68\xb7\xe0\xb8\x59\xb8\xd1\xb9\x4a\xb9\xc2\xba\ -\x3b\xba\xb5\xbb\x2e\xbb\xa7\xbc\x21\xbc\x9b\xbd\x15\xbd\x8f\xbe\ -\x0a\xbe\x84\xbe\xff\xbf\x7a\xbf\xf5\xc0\x70\xc0\xec\xc1\x67\xc1\ -\xe3\xc2\x5f\xc2\xdb\xc3\x58\xc3\xd4\xc4\x51\xc4\xce\xc5\x4b\xc5\ -\xc8\xc6\x46\xc6\xc3\xc7\x41\xc7\xbf\xc8\x3d\xc8\xbc\xc9\x3a\xc9\ -\xb9\xca\x38\xca\xb7\xcb\x36\xcb\xb6\xcc\x35\xcc\xb5\xcd\x35\xcd\ -\xb5\xce\x36\xce\xb6\xcf\x37\xcf\xb8\xd0\x39\xd0\xba\xd1\x3c\xd1\ -\xbe\xd2\x3f\xd2\xc1\xd3\x44\xd3\xc6\xd4\x49\xd4\xcb\xd5\x4e\xd5\ -\xd1\xd6\x55\xd6\xd8\xd7\x5c\xd7\xe0\xd8\x64\xd8\xe8\xd9\x6c\xd9\ -\xf1\xda\x76\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\ -\x1c\xde\xa2\xdf\x29\xdf\xaf\xe0\x36\xe0\xbd\xe1\x44\xe1\xcc\xe2\ -\x53\xe2\xdb\xe3\x63\xe3\xeb\xe4\x73\xe4\xfc\xe5\x84\xe6\x0d\xe6\ -\x96\xe7\x1f\xe7\xa9\xe8\x32\xe8\xbc\xe9\x46\xe9\xd0\xea\x5b\xea\ -\xe5\xeb\x70\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee\x28\xee\xb4\xef\ -\x40\xef\xcc\xf0\x58\xf0\xe5\xf1\x72\xf1\xff\xf2\x8c\xf3\x19\xf3\ -\xa7\xf4\x34\xf4\xc2\xf5\x50\xf5\xde\xf6\x6d\xf6\xfb\xf7\x8a\xf8\ -\x19\xf8\xa8\xf9\x38\xf9\xc7\xfa\x57\xfa\xe7\xfb\x77\xfc\x07\xfc\ -\x98\xfd\x29\xfd\xba\xfe\x4b\xfe\xdc\xff\x6d\xff\xff\xff\xe1\x0b\ -\x1e\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\ -\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x00\x3c\x3f\ -\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x27\xef\ -\xbb\xbf\x27\x20\x69\x64\x3d\x27\x57\x35\x4d\x30\x4d\x70\x43\x65\ -\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\ -\x27\x3f\x3e\x0d\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\ -\x73\x3a\x6d\x65\x74\x61\x2f\x22\x3e\x3c\x72\x64\x66\x3a\x52\x44\ -\x46\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\ -\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ -\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\ -\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x3e\x3c\x72\x64\x66\x3a\x44\ -\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\ -\x62\x6f\x75\x74\x3d\x22\x75\x75\x69\x64\x3a\x66\x61\x66\x35\x62\ -\x64\x64\x35\x2d\x62\x61\x33\x64\x2d\x31\x31\x64\x61\x2d\x61\x64\ -\x33\x31\x2d\x64\x33\x33\x64\x37\x35\x31\x38\x32\x66\x31\x62\x22\ -\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\ -\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x2f\x3e\x3c\x72\ -\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\ -\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x75\x75\x69\x64\x3a\x66\ -\x61\x66\x35\x62\x64\x64\x35\x2d\x62\x61\x33\x64\x2d\x31\x31\x64\ -\x61\x2d\x61\x64\x33\x31\x2d\x64\x33\x33\x64\x37\x35\x31\x38\x32\ -\x66\x31\x62\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\ -\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x3e\x3c\x78\ -\x6d\x70\x3a\x43\x72\x65\x61\x74\x65\x44\x61\x74\x65\x3e\x32\x30\ -\x32\x31\x2d\x30\x37\x2d\x33\x30\x54\x31\x37\x3a\x31\x35\x3a\x35\ -\x39\x2e\x31\x33\x33\x3c\x2f\x78\x6d\x70\x3a\x43\x72\x65\x61\x74\ -\x65\x44\x61\x74\x65\x3e\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\ -\x72\x69\x70\x74\x69\x6f\x6e\x3e\x3c\x72\x64\x66\x3a\x44\x65\x73\ -\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\ -\x75\x74\x3d\x22\x75\x75\x69\x64\x3a\x66\x61\x66\x35\x62\x64\x64\ -\x35\x2d\x62\x61\x33\x64\x2d\x31\x31\x64\x61\x2d\x61\x64\x33\x31\ -\x2d\x64\x33\x33\x64\x37\x35\x31\x38\x32\x66\x31\x62\x22\x20\x78\ -\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\ -\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\ -\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x3e\x3c\x64\x63\x3a\x63\ -\x72\x65\x61\x74\x6f\x72\x3e\x3c\x72\x64\x66\x3a\x53\x65\x71\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ -\x61\x78\x2d\x6e\x73\x23\x22\x3e\x3c\x72\x64\x66\x3a\x6c\x69\x3e\ -\x52\x6f\x62\x20\x52\x61\x65\x73\x69\x64\x65\x3c\x2f\x72\x64\x66\ -\x3a\x6c\x69\x3e\x3c\x2f\x72\x64\x66\x3a\x53\x65\x71\x3e\x0d\x0a\ -\x09\x09\x09\x3c\x2f\x64\x63\x3a\x63\x72\x65\x61\x74\x6f\x72\x3e\ -\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\ -\x6e\x3e\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x3c\x2f\x78\x3a\ -\x78\x6d\x70\x6d\x65\x74\x61\x3e\x0d\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x3f\x78\x70\x61\x63\ -\x6b\x65\x74\x20\x65\x6e\x64\x3d\x27\x77\x27\x3f\x3e\xff\xdb\x00\ -\x43\x00\x03\x02\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\ -\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\ -\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\ -\x10\x11\x13\x14\x15\x15\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\ -\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\ -\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\ -\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\ -\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\ -\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\xd8\x01\x68\ -\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1c\x00\x01\ -\x00\x03\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x05\x06\x07\x04\x03\x08\x02\x01\xff\xc4\x00\x1b\x01\x01\x00\x02\ -\x03\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x05\ -\x02\x03\x06\x01\x07\xff\xda\x00\x0c\x03\x01\x00\x02\x10\x03\x10\ -\x00\x00\x01\xfa\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x5e\x95\xd1\ -\x97\x61\xe3\xbb\x18\xa9\xbc\xcf\x40\x81\xbb\xb0\xe5\x9d\xa7\xa9\ -\x53\xb6\x61\x90\x6d\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x15\xcd\x59\x58\xdc\x31\x7e\x3f\x35\xc9\x08\x4a\x59\x73\x1f\ -\xb8\x18\xdb\xaa\xd9\x4e\xec\x73\x42\xd1\xe5\xc6\x12\x4a\xbb\x5f\ -\x61\x6a\xbb\x50\x25\x65\xe1\x6a\x46\x42\x4a\xd7\x6e\x12\x30\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x0c\xf5\x5a\x36\x70\x32\ -\x9c\x74\x28\x1b\xaf\xd9\x3f\x97\x17\x63\xcd\x43\x5b\xab\xdc\x56\ -\x94\x1c\x32\x1e\x7d\x12\x2b\xa5\xa5\x3f\x9c\xb5\x7d\x36\xb9\x25\ -\x84\xcf\xf3\xf7\xb6\x8b\xa4\x14\x9d\x05\xad\xcc\x5f\x42\x07\xa0\ -\x00\x00\x00\x00\x00\x00\x00\x00\x0a\xed\x8a\x1f\x46\x5c\xb1\x90\ -\x3f\x9a\x59\x9f\xbc\xbe\xbb\x67\xee\xb9\xae\xae\x8f\x2f\xdc\x88\ -\x9c\xb5\x7f\x6f\xd5\xbf\x0f\xe5\xd1\xfb\xf3\xdb\x5f\x79\xa1\xcc\ -\x4d\x55\x76\x74\xb8\x0d\x32\x13\xc9\xda\x35\xcf\x0a\xd1\x38\xde\ -\xa2\xe6\xa1\xea\x15\xf3\x26\x45\xdc\x40\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01\xcb\x8a\x9b\x49\xbe\xe2\xfa\xfc\xb9\x59\xb0\x0f\xa2\ -\x6d\xa1\x62\x7f\xdb\xbe\x6d\x69\x45\x21\x6f\xa8\x6c\x98\x43\xc4\ -\xa6\x2c\xb4\x29\x35\xb7\xdf\x7a\x0e\x8d\x5f\xd3\xd9\x31\xcd\x97\ -\x2c\x8b\x6b\x62\xf7\xcc\xee\x78\x65\xa0\xe8\x34\xdb\x0d\x15\x8c\ -\x88\xb0\xd2\x00\x00\x00\x00\x00\x00\x00\x00\x01\x56\xcd\xb7\x28\ -\xaa\xa9\x19\x36\x43\xbf\xe4\x59\xeb\xab\x73\x7a\xc1\x76\xfc\xe7\ -\xda\x99\x56\x63\xf5\x85\x54\xfc\x2b\xd7\x8f\xba\x5d\x6e\xab\xd9\ -\x8b\xc9\xc4\x9b\x48\x99\x9e\xac\xda\xd1\x6c\x75\x0b\x0e\x1f\x51\ -\xd3\xf2\xcd\x57\xef\xb9\x25\x3c\x6e\x56\xde\x1a\xee\x2e\xe0\x74\ -\xb0\x03\x67\x80\x00\x00\x00\x00\x00\x00\x00\x00\xe4\xc5\x4b\xa8\ -\x78\xc4\x73\x16\x15\xcc\xf6\x03\xd7\xe8\xdc\xdc\xbe\x9f\x93\xfb\ -\x4f\x81\xad\x5b\x33\x1e\xea\xe9\xd6\x4e\x1c\xbb\x9e\x55\x7d\x9a\ -\xe5\x96\x71\xe7\xef\xd4\x18\xad\x0e\x4a\x25\x8d\x83\x4f\xc0\x37\ -\x5e\x7e\xcb\x4e\xbd\xe0\x3b\x3d\x34\xc9\x71\x79\x10\x00\x00\x00\ -\x00\x00\x00\x00\x00\x01\x44\xbd\xb4\xe5\x98\xf5\x68\x94\xca\xfd\ -\xd9\xa7\xcc\xdf\x70\x7c\xaf\x65\x1e\xad\xd3\x07\xd9\xd3\xd5\x5e\ -\x39\xa0\x7b\x36\x61\xe5\xfc\xe5\xfe\x6e\x8f\xd3\xe7\xcd\xe1\xaf\ -\x77\xbf\x07\x9d\xda\xa6\x7e\xbf\xa4\xff\x00\x3d\x39\x9b\x28\xae\ -\xfb\xfb\x7e\x01\x33\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\ -\x69\x9a\x34\x6c\xf3\x8b\x7c\xef\x85\x24\xbc\xef\xe6\xef\xb5\xf3\ -\xcb\x2d\x1f\x37\x48\xfd\x1f\x11\xd0\xc3\xf9\xd3\xa3\x4d\xb7\xe3\ -\xef\xcf\xbc\xff\x00\x5a\x56\xaa\xf7\xfe\xb4\x5f\x6f\xc4\x4d\x99\ -\xd6\xa6\x8c\x81\xbb\x41\x1d\x0c\x20\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x0f\x00\x50\x73\x7d\x42\x67\x9f\x9b\x58\xf7\xbe\xc5\ -\xd9\x47\xc4\xef\x34\xad\x82\x8e\x65\x6a\x81\xf4\x04\x7d\x9c\x7c\ -\xf7\x52\xcf\x74\x29\x3a\xc2\x76\xa0\x03\xd0\x00\x00\x00\x00\x00\ -\x00\x03\x37\xcf\x5e\x90\xc5\x6e\xfb\x75\xdc\xd4\xae\x6c\x72\xbf\ -\x2a\xbe\xd8\xe5\x64\x57\x3c\x0b\x47\xeb\x2f\x82\xdb\xa7\x6d\x54\ -\xe0\xf0\xd9\xa4\x20\x78\x70\xcb\xc6\xe5\x5f\xf3\xd7\x95\x91\x5c\ -\xaf\xee\xd7\xa1\xb2\x1b\x9e\x58\xda\xd5\xde\x4c\x36\x5b\x7f\x95\ -\xaa\x3e\x58\x6b\xbf\xda\x6f\x8f\x9e\xde\x19\xf4\xd1\x67\x56\xfd\ -\xf1\xca\x74\x61\xb0\x00\x00\x00\x00\x14\xdb\x93\x2c\x32\x8e\x1d\ -\x95\xbf\x46\x0f\x63\xd5\x5e\xf9\x81\x4d\xec\x4f\x7c\xc3\x7d\x76\ -\xd1\x9d\xfe\xf4\x16\xbd\xb8\x1c\xfe\xba\xd9\xaf\x16\xf6\xd8\xde\ -\x31\x09\xcd\x4c\xf7\x1e\xb2\xdf\x18\xe5\x44\xcf\x77\xd7\xb8\xe4\ -\x75\x3f\xa2\x19\x63\x91\xd5\x7e\x86\x18\xcc\x17\xd0\x6f\x59\x34\ -\x2e\xe6\xc7\xdc\x4a\x7b\x4f\x79\xe8\x46\x94\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xff\ -\xc4\x00\x2d\x10\x00\x02\x02\x02\x01\x03\x03\x02\x05\x05\x01\x00\ -\x00\x00\x00\x00\x03\x04\x02\x05\x01\x06\x00\x07\x11\x12\x13\x14\ -\x40\x15\x50\x16\x26\x30\x36\x60\x20\x22\x23\x25\x31\x35\xff\xda\ -\x00\x08\x01\x01\x00\x01\x05\x02\xfe\x61\x3b\x2c\x45\xef\xb4\x5b\ -\x30\x60\x71\x56\x62\xd8\x78\x52\xc4\x30\x39\x25\x33\xac\xd4\x1a\ -\x1f\x18\x3c\x57\x15\x33\x67\x6d\x8f\xb2\x5c\x4b\x1c\x89\x72\x0c\ -\xae\x7b\x4b\x08\x9e\xa9\xdf\x4e\x52\xf1\x82\x95\x4f\x9c\x44\xc5\ -\xba\x91\x2b\x13\x63\x34\x05\xc0\xcb\xf6\x16\x2c\xe4\xbb\x90\x74\ -\x24\xc3\x97\x23\x07\x31\x52\xeb\x5c\x26\x71\x81\x0b\x78\x45\x60\ -\xd8\x6e\xec\xc0\x39\xdb\x98\x96\x2a\x77\x32\xfb\x2f\xc5\x8a\x9c\ -\x25\x27\x61\xce\x81\xb1\x45\x3b\xae\x4e\xc9\x78\x45\x3b\x62\xbb\ -\x67\xf3\xad\xc3\x89\xaf\xdf\x94\x70\x1c\x58\xb6\xda\x46\xae\x5c\ -\xcc\xac\xb9\x3a\xec\xa6\x63\x46\x38\x0c\xd7\x90\xf8\x30\x31\x00\ -\x09\x7f\x5b\x83\x24\xd7\x9d\x4e\xd3\x06\x33\x79\x90\xcb\x1c\xd6\ -\xc5\x88\x55\xfc\xeb\xb6\xf3\x18\x16\xa1\x95\x03\x65\x67\xe7\x98\ -\x47\x92\x77\xce\x4c\xc0\xe0\x0f\xa9\x3c\x8f\x3d\xe5\xc1\x1e\x62\ -\xca\xc7\x8b\x30\x2b\x63\x81\x70\x6c\x4f\x8a\x58\xe4\x7c\x5e\x81\ -\x83\xad\x40\x79\x0a\x5f\x33\xeb\x42\xf5\xcb\x6f\x1f\x1a\x58\x7a\ -\xef\x6e\x17\xbe\x86\x61\x8e\x47\x1c\x80\xe3\x89\x3b\x30\xc8\x7d\ -\xb9\xdb\x8b\xcb\xd2\x3e\x71\xc2\x2c\x42\xb6\x65\x0a\x29\xfb\xd3\ -\x42\x1a\x1e\xc7\x37\x21\x78\x1f\x4e\x60\xbe\x8f\x8f\xe2\x20\xe5\ -\xbf\x94\xfd\x60\x9e\x8e\x65\xe9\xe3\x2d\xc5\x51\x26\xe4\xec\xdd\ -\x87\x23\xc3\x1b\x0b\x84\x86\x93\x13\x8c\x79\xe3\xcc\xe3\x95\xfe\ -\x65\x96\x05\x11\x46\x5c\x3a\x61\x27\x06\x79\xa8\x79\xbb\xee\x21\ -\x3c\xca\x51\xad\xab\x0d\x60\xbe\x58\x14\x8b\xb7\xdd\x44\xf4\x2a\ -\x90\xd1\xac\x16\xbe\x5f\x60\xd7\x62\x40\x0e\xd0\x59\x22\xb6\x2c\ -\x2b\x65\x7c\xc9\x1b\xb7\xd6\xe9\xa0\xee\x33\x68\xf5\x8e\x50\xb1\ -\xc4\x0f\x64\x28\x07\x61\xa0\x84\xf1\x67\xb3\x8c\x15\x34\xbe\xe2\ -\xc6\x3c\xd7\xed\x44\xd3\x3a\x08\x57\x75\x77\x52\x8a\x76\xff\x00\ -\x2d\x93\xe1\x70\xd1\x93\x11\x6b\xaa\x6d\x7a\x96\xd4\x4e\x19\x0a\ -\x6d\x53\x64\x86\xc0\x96\xe5\xaf\x65\x62\x05\xf3\x4c\xb6\x13\xff\ -\x00\x69\xa5\x4e\x05\xa7\xb3\xd3\xce\x86\x65\x8e\x28\xf9\x70\xf5\ -\x2f\xfe\xd6\xf3\xfb\x6d\x60\x65\xa6\x86\x79\xf6\xe9\xf1\xb2\xbb\ -\xdb\x0c\xa3\x31\x22\xe4\x5d\x07\xc9\xb8\x69\xf5\xe6\xd5\x83\x0c\ -\x10\x76\x10\x1f\x37\x69\xf9\xdb\xd6\x67\xf2\xed\x5d\x89\xea\x9c\ -\xa7\xb6\x5e\xfa\xbe\xde\x8a\x34\xcc\xf8\xc6\x6f\xa9\x26\x29\x18\ -\xaa\xd9\x52\xb5\xe5\x95\x22\x96\x91\xba\xae\x25\x3b\xda\x69\x25\ -\x2d\x87\x73\x28\x81\xae\x6a\x97\x08\x18\xcb\xe7\xfc\x34\xe4\xc4\ -\x1d\xcb\x91\x2e\x16\x6c\xe3\x62\x98\x96\x84\x3f\xc9\xb1\xaf\x1d\ -\x8a\xfa\xd5\x78\x48\x5e\xa8\xa3\x05\x2d\x6a\xb3\xf9\x72\x12\xe6\ -\xb9\x7e\x5d\x7d\xe1\xcd\x7b\x64\xbc\xbb\x59\x4f\x32\x16\x58\x5c\ -\x4d\x63\x56\xd8\x8e\x2b\x5e\xa5\x4a\x31\x36\x95\x9e\xfb\x27\x50\ -\x3f\x6a\x28\x5c\x84\x00\x96\x7d\x1d\x14\x62\x72\xe7\x6b\x58\x6b\ -\xaf\x4f\x59\x0a\xa4\xbe\x5a\x6d\x61\x5b\xfe\xa7\xa7\x07\x6b\x69\ -\xab\xeb\x96\xa6\x60\x1e\xd0\x91\x97\x34\xcd\xa7\xe8\xac\xe4\xb8\ -\x95\x8c\xad\x2a\xbe\x89\x28\x97\x23\xa9\xc2\xd4\x0c\xdb\xdd\x16\ -\xfe\xcf\x54\x92\x75\x76\x5b\x1d\xed\x35\xdd\x30\x7c\x15\x13\xcc\ -\xe1\x70\xf4\xb2\x22\x59\x1b\x83\xc4\xd6\x9f\x2d\x96\x60\xa8\x9a\ -\x63\x2c\x32\xcf\x66\xa2\xd2\x52\xaf\x6c\x7e\x38\xe6\x33\xce\xfc\ -\xab\x90\xf0\xa7\x80\x03\x26\x60\x13\x31\x11\x08\x7c\xcc\xf9\x98\ -\xc3\x99\x84\x38\x07\x82\xa8\xa5\x93\x5d\x3c\x05\xf2\x88\xf1\x39\ -\x46\x75\xf6\x43\x7c\x5f\x29\xed\x74\xf6\x0d\x9f\x51\x20\xe3\xaa\ -\x78\x82\x7d\x4d\xd5\xb2\xd0\x60\x4e\x46\x7c\xc4\xb9\x50\x6c\x72\ -\xc9\x99\x4c\xde\x5c\xf2\xe7\x7e\x66\x5c\x94\xf9\x39\xf3\xa6\x3a\ -\xb6\x43\x0d\xac\xf1\x88\x14\xd4\x24\x41\x8f\x53\xc0\x1a\xf9\x97\ -\xc1\x90\x25\x3d\x90\x52\x53\x63\xa0\xf6\xd3\x89\x39\x12\x71\x56\ -\xbd\x02\xba\xd0\xd8\x27\x9f\x3c\xf9\x99\xf2\x44\xe4\x89\xcd\x7b\ -\x5f\xcb\xb2\xae\xd8\x07\x05\x28\xa3\x9b\x26\x7e\x75\xbc\xb1\x1a\ -\xee\x6b\x15\xa0\x39\x36\xae\x98\x0d\xc9\x36\x83\x75\xcc\xfb\x46\ -\x3b\x22\xa4\xa7\x39\x62\x70\x97\xb4\x63\x38\x2a\xc7\x16\x15\x55\ -\x8b\x13\xea\xbd\x2f\x82\xd9\xd8\xd0\x5a\x03\xe6\xaf\x38\xe6\xa7\ -\xe7\x5e\x25\x61\x60\xc8\x35\x1a\xe1\xc4\x9a\xee\x51\x90\x36\x68\ -\xf6\xb0\x2c\x5b\x9a\xba\x00\x5c\xaf\x63\xa7\x6e\x0b\x19\xa4\x62\ -\x3c\x43\x41\x69\xd5\xf1\xd3\xc5\xc2\xb0\x83\x15\xb8\x4d\xa4\x71\ -\x0f\xe1\xf2\xd9\xce\x7a\xa5\x64\xa3\x59\x50\xf5\x6d\xa7\xd8\x76\ -\x74\xe1\xe3\xe5\xea\x11\x2b\x4b\x25\x85\x3d\xac\x12\xc4\xff\x00\ -\xbf\x89\x6c\xcb\xaa\xb3\x77\x36\x05\x8c\xfc\xe0\x4d\x4d\x58\x91\ -\xdf\xb2\x6d\x38\x66\x6a\x53\xd5\x0e\xa5\x4e\x3d\x5a\xbd\x88\xdd\ -\x5c\xaa\x9a\xaa\xa0\x35\x2b\xf1\xe4\x85\x60\xbe\xb6\xb3\x4a\x37\ -\xf6\x2c\x4b\x12\xfe\xa6\xe9\x4a\xc5\xdf\xe8\x7f\xcc\x63\x3d\xf1\ -\xf0\xf7\x4a\xf2\x3a\x00\xdd\x66\xda\x82\x36\xc8\xd1\x21\x67\xb6\ -\x27\x5d\x09\x3e\x23\xec\xc6\xd9\xeb\x97\x23\xdb\x12\x15\xcc\xa7\ -\xb0\xd7\xbc\x9c\x2e\x52\xb6\x8f\x4e\x3f\x6d\x5d\xda\x41\x2d\xad\ -\x46\x54\xa5\xa8\xbe\xbb\x54\xf5\x2c\xdc\x2c\x86\x0f\xb4\xd6\x2f\ -\x1a\xeb\xe4\xad\x20\xb6\xc2\x93\x46\x5f\x61\x45\xa6\x37\xde\xf1\ -\xd6\xea\x33\x5c\xd6\x07\xb4\x56\x94\xb9\xbf\x46\x2e\x4b\x69\xad\ -\x8d\x62\x5b\x1a\x16\x0e\x6f\x17\x0a\x33\x44\xbd\xc2\xb5\x75\x16\ -\x5b\x72\x48\x57\x39\x64\x13\x5d\x35\xb2\x57\xa6\x57\xb6\x24\x2b\ -\xb3\x59\x76\x9d\xc7\xeb\xec\x19\x3f\xaf\xb9\xeb\x13\xb5\x0d\xda\ -\x76\xa7\x31\xeb\x6c\x25\x50\xc2\xcd\xb1\xb8\x8e\x8e\xc5\x4d\x7c\ -\xd5\x0e\x2f\x76\xaa\x16\x6b\x02\xb5\x5b\x15\xef\x74\x54\x99\xad\ -\xa4\xb1\x91\x9a\x86\x35\x7b\x4a\xca\xad\xa6\x0f\xdf\x50\xd8\xd5\ -\xb3\x8b\xcb\x0a\xc6\x32\xfc\x68\xde\x68\xf5\xf1\xb1\x72\x8f\x58\ -\xac\x2a\xdc\xdd\x17\x61\xea\x25\xab\x32\xee\xb9\x9a\x3b\x17\x35\ -\xf6\x92\x79\x3d\xb6\x34\xd6\x59\xd1\xbd\x93\x72\xda\xfe\x93\x68\ -\x9e\xb6\xd0\x2d\xa5\x12\x53\x59\x4f\x51\xb4\x0b\x8f\x6c\x51\xa7\ -\x7e\xb9\x66\x68\xdd\x57\x94\x09\xb4\xbe\xcd\xfc\x87\xff\xc4\x00\ -\x2d\x11\x00\x02\x02\x01\x03\x02\x05\x03\x03\x05\x00\x00\x00\x00\ -\x00\x00\x01\x02\x00\x03\x11\x04\x12\x21\x13\x31\x14\x30\x41\x51\ -\xf0\x05\x40\xa1\x22\x32\x42\x10\x23\x50\xb1\xc1\xff\xda\x00\x08\ -\x01\x03\x01\x01\x3f\x01\xff\x00\x01\xb4\xe3\x77\xf4\xb1\x36\xe0\ -\xce\xf1\x86\xd3\x8f\xb1\x0a\x5b\xb4\xda\x65\x65\x76\xe2\x36\xb6\ -\xa4\x24\xee\xed\xed\xcc\x1f\x54\xd3\xdc\x76\xd6\xdf\x89\x43\xab\ -\x8c\xc7\x01\xce\xe5\x9b\x0e\x33\xf6\x09\xfb\xa5\xd6\xa0\xaf\x26\ -\x5f\xa8\xc8\xc3\x76\xf6\x87\x50\xba\x72\xca\x16\x57\x72\x06\xef\ -\x2a\xb1\x55\x43\x03\x34\x9a\x95\x66\x1b\xcc\xb1\x83\xaf\x1e\x9e\ -\x7a\xe3\xf9\x43\x58\x0b\xc4\x77\xea\x1c\xcb\x08\x51\x93\x35\xba\ -\xae\xab\xe4\x45\xb5\x90\x86\x95\xb7\x8d\x45\x7c\x60\x4e\x81\xfe\ -\x06\x68\x72\xc3\x93\xda\x5a\xa8\x9e\x77\x79\xaa\x25\x14\xca\x99\ -\x6c\x4d\xad\xde\x6a\x1e\xdd\x3d\x9b\x58\xfa\xfe\x25\x55\xae\xaf\ -\xea\xcc\xb7\x72\x17\x38\x13\x57\xa9\xfa\x86\x8f\x50\x4d\xdf\xb7\ -\x3d\xbf\x89\x13\x4f\xaa\xaf\x51\x6e\xea\x4f\x1c\x4b\xb2\x18\x05\ -\x95\x39\xce\x23\x82\x54\x37\x9d\x5d\xbb\x0f\x22\x6b\x5b\x72\x95\ -\x12\xcc\xa8\x52\x22\x94\xd5\xa7\x3d\xc4\xb2\xaf\xef\x1b\x57\xb8\ -\x9e\x2a\xab\x31\x55\xe3\xf7\x45\xd1\xae\x97\xea\x00\x57\xdb\x89\ -\x63\xed\xb0\x4a\x78\xb0\x18\xd7\x8d\x83\x8e\xf0\x9c\x9c\xf9\xbd\ -\xe5\x9a\x70\xc3\x24\xcb\x94\x11\x8c\x45\x2d\x53\x6e\x10\x30\xc9\ -\x6f\x78\x4d\x5d\x40\xfb\x4f\x11\x1f\x36\xf5\x5c\x64\xce\xa0\xb4\ -\xe4\x89\xa5\xa8\x58\x4e\x65\xd5\x14\x03\x1e\x70\x62\xbd\xa2\xb9\ -\xb3\xf4\x34\xb3\x4e\xd8\xdd\x88\xd5\x42\xbf\xa3\x13\xa5\x16\xa9\ -\x4d\x05\xce\x04\x08\x69\x39\x3e\x90\xd8\xe7\xd7\xcf\x4c\x6e\xe6\ -\x3d\xcb\x60\xdb\xda\x0d\x31\x7e\xf0\xd7\xcc\x34\x15\xee\x25\x5a\ -\x6e\xa7\xac\x51\xd2\x6c\x99\x65\xab\x6a\xfd\x92\xdd\xb2\xbc\x40\ -\xcb\x9f\xd4\x26\xa1\x97\x02\x57\x76\xcf\x49\x69\xcb\x93\xe6\xbb\ -\x6c\x5c\x81\x16\xe5\x6e\x7d\x21\xb5\x7b\x09\xd4\x4f\x79\xd4\x5f\ -\x43\x3a\xe0\x56\xb6\x1f\x58\x6c\x0a\x32\x61\xb1\x47\x73\x0d\xa1\ -\xb1\xcc\x6b\x00\x42\xe3\x9c\x45\xb4\x11\x93\x3a\x89\xef\x1a\xd5\ -\x54\x2c\x0c\xea\xa0\x19\x26\x75\x57\x9c\xcd\xeb\x9d\xb9\xe7\xc8\ -\x65\xdc\x31\x1b\x4e\xac\x49\xf7\x9e\x1c\x7b\xfb\x7e\x27\x86\x51\ -\xeb\xf3\x39\x9e\x1c\x0c\x73\xdb\xe7\xfd\x82\xac\x20\x4c\xcf\x0e\ -\xa1\x4a\x83\xc1\x9e\x1c\x73\xcc\x14\x01\xeb\x05\x20\x56\x6b\x8d\ -\x42\xb7\xfa\x87\x4c\x0e\x79\xf7\xfc\xc3\xa6\x07\xd7\xe1\x87\x4c\ -\x0f\xaf\xcf\x82\x1d\x38\x27\x39\xf9\x8c\x41\x40\x07\x20\xfc\xc6\ -\x3e\xf3\xff\xc4\x00\x30\x11\x00\x01\x03\x02\x04\x04\x05\x04\x01\ -\x05\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x11\x12\x13\x21\ -\x31\x05\x14\x41\x51\x30\x32\x71\xa1\xf0\x22\x23\x40\x61\x33\x50\ -\x91\xb1\xc1\xf1\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\xfe\x80\ -\x25\x69\x79\x8f\xa8\x44\xdb\x52\xa9\xaa\x33\x4b\x9a\x4f\xfc\x44\ -\x86\x8b\x95\x1b\xf3\x1a\x1c\x3f\x06\x49\x1b\x18\xbb\x91\x95\x80\ -\x5e\xea\xa4\x3f\x33\x19\x1b\xa6\xd0\xba\x56\x0b\x83\xaf\x75\x17\ -\x08\x9e\x3d\x66\x6f\xba\xae\x8d\xd1\xb8\x34\x5d\x40\xf7\x40\xd1\ -\x1c\xda\x7e\xd1\x9d\x98\x83\x41\xb9\x3f\x81\x51\x6c\xb2\x15\x35\ -\x3c\xd9\xe1\xa0\x28\x69\xc3\x75\x1b\xac\xb3\x25\x8d\xd3\x9a\x6c\ -\x9e\xcc\x7f\x49\x0b\x88\xd2\xbc\x44\x72\x85\xd5\x24\x4e\xa7\x90\ -\x66\x0f\x37\x8f\x28\x92\xdf\x6c\xea\x9b\x54\xf3\x20\x2f\xd5\x47\ -\x16\x58\xb7\x54\x35\xd0\x28\xa3\xc0\x11\x00\xe8\xbf\x80\x90\xb3\ -\x01\xf3\x05\xc5\xed\x10\xb0\x6f\x9b\xd8\xaa\x49\x2a\x27\xdc\xe8\ -\x3c\x62\x43\x45\xca\xe1\xed\x64\xb8\x7d\x6e\xa6\x6b\xa2\x79\x73\ -\x36\x51\xe0\x9e\x3c\x41\x48\xe3\x0d\x18\x2c\xea\xa1\x8e\x9e\x68\ -\xfe\xde\xfe\xea\x48\x9d\x1c\x76\x7a\xa7\x01\xcd\x25\xca\xa2\x26\ -\xe1\xc4\xa0\x73\x19\x33\xe2\x1e\xbe\x35\x5d\x1b\xa7\x69\xc2\xf3\ -\xe9\xd1\x70\x68\x1c\xc7\xb6\x57\x1d\xd4\x60\x3d\xcf\x05\x3d\xae\ -\xa3\x7e\x9b\x14\xd3\xf6\xc3\x0e\xc5\x1a\x77\xb2\xef\x8b\xa2\x13\ -\x19\xe9\x0b\x9d\xba\x86\x3c\xc8\xce\xaa\xad\xb8\xe9\x9c\xce\xe1\ -\x45\xc3\x9c\x6a\x1c\x1c\xed\x1a\xa3\x66\x5b\x70\xdf\xc5\x24\x34\ -\x5c\xaa\x6e\x26\xe8\x9f\x81\xad\xbe\xbe\xd7\x50\x17\x5f\x15\xf7\ -\x52\x31\xb3\x33\x09\x4e\x88\xd8\x37\xb2\xca\x94\xb7\x0d\xf7\x4e\ -\x87\xed\x65\x30\xd8\x26\x40\x60\x16\x05\x71\x7a\xc7\x53\x31\xb8\ -\x45\xfb\xaa\x0a\xc6\xce\xe7\x87\x68\x4f\x8d\x24\x4c\x94\x59\xe2\ -\xea\x48\x19\x4c\x79\x88\x86\xdb\xfa\x2a\x6e\x27\x06\x31\x16\x2d\ -\xfe\x59\x36\x44\x1d\xf5\x5d\x66\x23\x22\xab\xac\x8e\x9a\x33\x24\ -\x85\x3e\x76\x57\x37\x03\x4f\x9b\x7f\xd0\x4d\xa4\x81\xb6\xb3\x3c\ -\x7a\x8c\x59\x64\x30\x5c\x95\x4f\xc3\xe4\xa5\x7e\x69\xb3\xbf\x49\ -\xfc\x61\x90\x5b\x0f\xd5\xfa\xea\x13\x6a\xda\x45\xce\x89\x9c\x42\ -\x09\x7f\x8d\xf7\x55\xdc\x5b\x95\xb0\x0d\xbd\xd4\xef\x15\xb1\x96\ -\xc7\xf5\x5f\xaf\x65\x4b\x47\x35\x14\xa0\xf9\x81\xfc\x29\xa8\x39\ -\x9a\xa7\x38\xe8\xd4\xe8\x65\x6b\x30\xc4\xff\x00\xee\xb8\x64\x33\ -\x63\x71\x06\xdd\x0a\xaa\xa0\xe6\x05\xf1\x1b\xaa\x26\x96\x53\xb5\ -\xa4\x5b\xc5\x63\x71\xba\xc4\xa7\x42\xe6\xe9\xd5\x08\x9d\xb9\x59\ -\x6f\xec\xb2\xdd\xd4\x2c\x8b\xc8\xe8\xc7\x44\x22\x2e\x36\x08\x46\ -\xe3\xb0\x4d\x83\x2e\xf6\x6f\xaa\x6c\x64\xbc\x30\xe9\x74\xe8\x88\ -\x36\x0b\x2d\xfd\x93\x62\x73\x9e\x1a\x42\xca\x79\x36\x01\x65\xbb\ -\x4b\x2c\x0e\xb6\x2b\x69\xe0\x35\xd8\x4d\xd3\x6a\x1c\xd0\x07\x65\ -\xcc\x1e\xdd\xfd\xd7\x32\xe3\xd3\xe6\xcb\x98\x3a\xe9\xbf\xcf\xf4\ -\x8c\xb7\x79\x7d\x97\x30\xe2\x43\x88\xd4\x2e\x60\xe9\xa2\x33\x93\ -\xd1\x19\x89\x90\x48\x9b\x3b\x9b\xfe\x50\xa9\x22\xda\x76\xf6\x42\ -\xa4\x8e\x9f\x02\x15\x24\x74\xf9\xf0\xa1\x50\x40\xb5\xbe\x5e\xe8\ -\xce\x48\xb1\x1f\x2f\x7f\xcc\xff\xc4\x00\x48\x10\x00\x02\x01\x03\ -\x01\x05\x03\x08\x03\x0c\x09\x05\x01\x00\x00\x00\x01\x02\x03\x00\ -\x04\x11\x12\x05\x13\x21\x31\x41\x22\x51\x61\x10\x14\x23\x32\x42\ -\x52\x71\x81\x40\x91\xd1\x06\x15\x20\x24\x33\x43\x50\x72\xa1\xb1\ -\xb2\xe1\x30\x34\x53\x60\x62\x73\x82\xc1\xf0\x44\x64\x74\x92\x93\ -\xf1\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\xfe\xf8\x25\xbe\x8f\ -\x58\xe9\xd5\xf2\xcf\xe8\x94\xdd\x1c\x6a\xfd\xf4\x1d\x7e\x63\xb8\ -\xf9\x0b\x31\xc0\xad\xf0\xf5\xc3\xeb\x14\x19\x0f\xc4\x75\x1e\x42\ -\xcd\x57\x3a\xdb\x31\x26\x00\x1e\x3c\xfe\xcf\xd0\xb1\xaf\x5e\x75\ -\xad\x5b\x47\x79\x14\x1e\x1d\x30\xc2\x79\x49\x37\x5f\x80\xa3\x23\ -\x5e\x2c\xac\x06\x74\xee\xf0\x0f\xed\xa2\xdd\x00\xcd\x24\xfb\xf8\ -\xad\xcb\x0c\x85\x08\x49\x1f\x3c\xd6\xa2\xf1\xdc\x20\xe7\xa3\x83\ -\x7d\x46\xb2\xec\x5a\xa7\x88\xf3\x73\xad\x7c\x7b\xff\x00\x41\x6e\ -\xcc\x7d\x91\xfb\x47\x78\xac\x89\x07\xce\x95\x22\x56\x9e\x67\xe0\ -\x88\xbd\x68\xcb\x3d\xca\xc3\x21\xe5\x1a\x2e\xa1\xf3\x34\xdb\xe2\ -\x10\x71\x56\xc9\xa8\xa0\xed\xdc\x4e\x3b\x1e\x88\x70\x3f\x3a\x63\ -\x1d\x92\x69\xe5\xc5\xf2\x68\x8f\x37\x8f\x1f\x3a\x8b\x79\x6a\x08\ -\x51\xa7\xb2\xdd\xd4\xca\x35\x47\x27\x2e\xd5\x66\x3c\x33\x31\x0a\ -\xbf\x13\x41\xe2\xba\x12\x4a\x38\xe1\x97\x4f\x1f\x03\x5b\xab\xa5\ -\x30\xce\xbc\xf2\x2b\x3b\xc0\x7e\x14\x62\x8e\x3c\xc2\xa3\xb6\x7d\ -\xde\xef\xa7\x89\x3d\xa8\xcf\x0f\x25\xc3\xb7\xf5\x86\x3c\x33\xee\ -\x78\x51\x8a\xdb\x13\x4b\xd5\xbd\x91\x4d\xe7\x07\x5e\x4e\x69\x64\ -\x07\xd1\xea\x1c\x7a\x8a\x72\xfc\x57\x15\xda\x52\xb9\xef\xad\x51\ -\x31\xd2\xdd\x16\xa2\x98\xe5\x5b\x14\xae\x87\x05\x4e\xa1\xf1\xa1\ -\x15\xd6\x22\x93\xa3\xfb\x26\x93\x91\x98\x75\xf0\xf2\x23\xfb\x72\ -\x33\x3b\x1f\x9f\xd3\xe3\xb7\x89\x77\x93\xca\xd8\x54\xad\xee\xff\ -\x00\xce\x08\xf5\xd3\x4e\x3f\xf5\xad\xd4\x27\x87\x57\xf2\x18\xa2\ -\x07\x79\x9c\x03\x42\x39\x08\x65\x27\x39\xad\x05\x8e\x8e\xea\xe2\ -\x49\xf8\xd2\xf1\x25\x07\xb3\x9a\xe0\x30\x47\x4a\x31\xf1\xd5\xf0\ -\xa3\xea\x91\xde\xa6\xb4\x4b\xda\x1d\x0d\x09\x9e\xe0\xc5\x33\x71\ -\x11\x60\x15\x1e\x06\xa6\xb3\x94\x68\x74\x3a\x82\xfe\xff\x00\xf9\ -\xe3\xf4\xd9\x23\xc6\x74\x1c\x1c\x57\xa3\x07\x3e\x35\x75\x73\x27\ -\x17\x5c\x46\xbe\x03\x99\xff\x00\x9e\x14\xbb\x3a\x06\xc4\xb2\x0d\ -\x52\x91\xec\xa7\xf3\xf2\xea\xd2\x35\x1e\xb4\x55\xcf\x68\x71\x5f\ -\x2a\x31\x00\x8c\xf5\xf2\x4b\xa3\xb5\x86\xe7\x4d\x2e\xe9\x48\xc7\ -\x10\xa6\x82\x29\xe5\xca\x8e\xce\xbb\xce\xfe\x21\x94\x63\xed\x2d\ -\x45\x72\x87\x44\xa0\xe2\xbd\x2a\x76\xbb\xd6\xa1\x80\x29\x26\x46\ -\xc7\x8f\xd2\xf3\xea\x4c\x3d\x59\x07\x31\x47\x79\x84\x2b\xc1\xb3\ -\x4f\x71\xaf\x4a\xaa\xe4\xb2\x9e\x95\x75\x77\x29\xcc\xb2\x37\xd4\ -\x3c\xa5\xfe\xa1\x5a\x9b\x9f\xe0\x34\x6c\xcd\xbb\x0b\xcb\x35\xa5\ -\x46\x07\x93\xd4\x03\xc5\x78\x52\x4d\x19\xc3\xa1\xc8\x34\xb2\xbc\ -\x9c\x0f\x56\x34\xa2\x2c\x34\x8e\x42\xa7\x76\x4d\x69\x41\xaa\x43\ -\xeb\xca\x7d\x66\x3f\x4c\x9c\xc8\xa1\xe2\x83\x8e\x93\xcb\x51\xff\ -\x00\xf2\xa2\x36\xcb\xb9\x9e\xe1\xf1\xd8\xe4\x40\xe3\xcb\xea\xa9\ -\x62\xb9\xb2\x80\x5d\x43\x8c\xba\xc6\x00\x71\xdf\x5b\xfb\x28\x82\ -\xcd\x1f\x38\xd7\xf3\x83\xed\xa0\xb8\x6c\x72\xc9\xa5\xd6\x23\xb8\ -\xb5\xde\x60\xc7\x24\x63\x97\x81\xab\xbb\x78\xc4\x56\xd6\xb0\x4b\ -\xa0\x2c\x71\x8c\x9c\x78\xd4\xb7\x33\x8c\xc1\x0f\xb3\xef\x1a\x32\ -\xad\xc3\x59\xc0\x4f\xa3\x86\xdf\xb3\x81\x4a\x9b\x51\x56\xf2\xd4\ -\xf0\xdf\x15\xc4\x91\xf8\xe4\x73\x15\x34\x51\x70\x89\x6d\xa3\x0a\ -\x07\xce\x92\xde\xe3\x77\x75\x0c\x80\xe3\x5c\x63\x52\x90\x3b\xea\ -\xe2\xe6\x0b\x58\x77\xcb\x80\xba\x93\x87\x13\x8a\xce\xfe\xdc\xf8\ -\x1b\x65\xa1\x69\xb4\x2c\x6d\x84\xaf\xf9\x39\xa3\x4e\x0c\x7b\x88\ -\xa9\x9a\x68\xc4\xb3\xc4\xe4\x2e\xbe\x38\x5c\xf4\x15\x68\xd1\xae\ -\x98\x9e\x50\x70\x39\x03\xf4\xc6\x73\xf2\xab\xad\x47\xb4\xfa\x48\ -\xcf\x5a\xb3\x88\x1c\x84\x88\x9f\xac\xff\x00\x2a\xdb\x33\xdb\xc8\ -\x62\x99\x52\x3d\x2e\x3a\x76\xeb\xb5\x84\xbb\x8f\x84\xa9\xfe\xe3\ -\xc2\x8e\xd4\xb3\x5e\x1c\xe6\x40\x39\x7f\x8a\x90\x17\xc8\x24\x70\ -\xad\xa4\xba\x3f\xea\x9b\x0f\x52\x27\x32\x25\x60\xc2\x99\xac\xc6\ -\xfe\xdf\x39\x08\x3d\x65\xfb\x68\x82\x3e\x20\xd6\x67\xc6\x81\x12\ -\xc2\x1b\xc0\x72\xab\x5f\xf5\x7f\x09\xab\x8f\xd6\x4f\xe2\x15\x14\ -\x40\x67\x53\x01\x5b\xd4\xf5\xd2\x42\x53\xe4\xdc\x2a\x68\xe5\x21\ -\x37\x88\x4f\x3e\x19\xcd\x45\xa5\xc6\xb0\x72\x31\x41\xc7\xad\xed\ -\x2f\x71\xfa\x52\x79\xa5\xb3\x4e\xb8\xe2\x57\x1c\x2b\x4d\xc6\xf2\ -\x37\x1e\xc3\x8c\x50\x13\x38\x5e\xe6\x26\xa3\x20\xe4\x6e\x87\x2f\ -\x89\xad\xb9\xfe\x5c\x7f\xc7\x51\xdd\x5b\xb6\x24\x4e\x9d\x18\x77\ -\x1a\x5b\x88\xb8\xab\x70\x74\x3e\xc9\xea\x0d\x66\x28\xff\x00\x15\ -\x95\xbb\x27\xdc\x3e\xef\xd9\x5b\x4d\x58\x6a\x1e\x74\xfc\xe8\xdc\ -\xd9\x1d\xe2\x9f\xca\x5b\xb7\xb6\x3e\xda\xd0\xaf\xb9\xb8\xeb\x04\ -\xbd\x96\x15\xe9\xa3\xed\xff\x00\x68\xbc\x1a\x9a\xda\x53\xab\x86\ -\xa4\x7f\x79\x6a\xdc\x12\x48\xc3\x7e\xea\xba\x79\xa3\x69\x50\x63\ -\xb2\xad\x83\xce\xb7\x5e\x68\xf6\xb7\x32\x2f\x61\xa4\x6d\x5a\xbe\ -\x06\x8f\xeb\xb7\xef\xa2\x58\x85\x1a\x4f\x13\x5e\x89\xc3\xf8\x83\ -\x5a\x2d\x44\x92\xcd\xee\xc5\xfe\xf4\xde\x7b\x16\xea\x1d\x1d\x9c\ -\x90\x4e\x7e\x94\x51\xc7\x6b\xd9\x6e\xaa\x6a\xf4\xdc\x42\x92\x4c\ -\x8e\x17\xb6\x33\x81\x8a\xb3\x78\xa3\x58\xd1\xe2\x3c\x14\x60\x64\ -\x1f\xe7\x5b\x77\xfc\xb8\xff\x00\x8f\xc9\xbe\x5c\xb4\x0f\xc2\x68\ -\xfb\xc7\x7f\xc6\x95\xc6\x99\xed\xe5\x19\x1d\xc6\xb6\x97\xfe\x53\ -\xd5\xb3\x1f\xc9\xce\x8d\x8f\xd6\x56\xfb\x2b\xd2\x26\x48\xe4\x7a\ -\x8a\x5d\x9f\x2c\x8d\x73\x6c\xe7\x4c\x6e\xfe\xb2\x9f\xf7\x15\xb3\ -\x7f\xb4\xed\xfd\x55\x6f\xfa\xaf\xfb\xaa\xf3\xfd\x3f\xbe\xad\xe5\ -\x4e\xd3\x47\x87\x1f\x2a\xc9\x5d\x19\x62\x74\x9e\x9c\x6a\xe1\x59\ -\x16\x51\x14\x5c\x75\x0c\x80\x73\x49\x2c\x31\x2a\xca\x7b\x3d\x91\ -\xeb\x77\x52\x44\xa3\xb7\xce\x46\xf7\x9b\xe9\x97\x48\xc7\x09\x37\ -\xef\xab\x67\x47\x5d\xf4\x32\xf5\x3e\xc9\xff\x00\x82\xb6\x95\xb5\ -\xe6\xd6\xb4\x49\xee\x94\x2a\xe8\x93\x50\x5c\x71\xe3\x41\x37\xd0\ -\xcd\x9e\xb0\xbe\xa1\xe4\xf3\x6b\x86\xfc\x46\x53\xff\x00\xcd\xbb\ -\xfe\x15\xb4\x4a\x90\xca\x6e\x5b\x04\x55\xb5\x95\xe5\xce\xe6\x72\ -\x59\xd1\x80\xce\x83\xa8\xf1\x34\x4c\x3a\x2e\xbb\x9a\x07\x0c\x0d\ -\x0b\xed\xa7\x3a\x44\x63\xe2\x90\x2b\x6a\x76\x3f\x0a\x6b\xd9\x57\ -\x76\x80\x69\x8a\x3f\x74\x52\xde\x5e\x6d\x1b\x58\xc2\xa9\xc2\x09\ -\x32\x78\xd5\xcd\x9a\x6d\x4b\x74\x79\x07\x64\x96\xe1\x9a\x8e\x2d\ -\xfc\x32\xb1\xcf\xe4\xa4\x0d\x4c\xc4\xf1\xe9\x57\x12\xc8\xfa\x65\ -\xb8\x7e\x19\xee\x15\xb3\xa1\x04\x30\x12\x82\x7e\x98\x5d\xce\x05\ -\x3c\xbd\xe6\x9a\xdd\x95\xe7\x69\x17\x1a\x10\x6a\x35\x2d\xb4\xd1\ -\xe9\x92\x33\x82\x08\xae\x00\x0f\x2a\x88\xc6\x9e\xf1\xe3\x4f\x26\ -\x15\x4b\x7a\xcc\x69\xdf\x40\xe2\x7a\x57\x65\x00\x3e\x4f\x54\x57\ -\xaa\x28\x01\x17\x6b\xbe\xa2\x82\x15\x25\xdc\xe9\x44\x14\x96\xe6\ -\x29\x20\x28\x30\x03\xae\x29\x5c\x1e\xd2\x9c\x83\x40\x83\x87\xea\ -\x9f\x4b\x91\xde\xf9\xa3\x83\x3d\x94\x45\xe3\xfb\x68\x9b\x7b\xb6\ -\x91\xbd\xc9\x80\xe3\xf3\x15\x77\x03\xa6\xee\xe3\x56\xa3\x9e\x75\ -\xf7\xda\xd9\x33\x2c\x43\x13\x28\xf6\x97\xbf\xe5\xf8\x0f\x1f\x5e\ -\x74\x63\xf6\x57\xf0\xfe\xfb\xdc\xa6\x1d\xc6\x20\x53\xd0\x7b\xd5\ -\x0c\x41\x77\x93\x33\x76\x10\x73\x34\x1a\xf2\xe5\xd5\xcf\xe6\xe0\ -\xe0\x17\xe7\xd6\xa1\x92\x3b\xc9\xb7\x68\xda\x9a\x37\xe3\x9f\x9f\ -\xd3\x62\xbe\x87\xb3\x24\x67\x0d\xe2\x28\xf6\x7d\x29\x18\xd3\xd2\ -\x9a\xea\xd5\x7d\x09\xe2\xd1\x8f\x67\xe1\xe5\x57\xfa\xe8\x32\x67\ -\x97\x1c\xfe\x10\xb9\xb9\x1e\x80\x7a\xa8\x7d\xaf\xe5\x41\x26\xe0\ -\xe8\x30\x31\xd6\xa6\xda\x72\x8e\x67\x77\x0f\x80\xea\x7e\x9f\x36\ -\xae\xa3\x1e\x49\x6e\x66\x02\x49\x51\xb4\xa2\x37\xb2\x3b\xe9\xee\ -\xb6\x4e\x98\x26\x3c\x4d\xb9\xf5\x1b\xe1\xdd\x46\xde\xe6\x07\x8a\ -\x61\xec\x91\x59\xdd\x1a\xcc\x8b\x85\x1e\xf5\x69\x2a\x73\xf0\xaf\ -\xc9\x9a\xc9\x43\x8f\x0e\x34\xb0\xdb\xc4\xd2\xc8\xc7\x00\x2d\x25\ -\xce\xd7\xc4\xd2\x73\x16\xc3\xd5\x1f\x1e\xfa\x59\x95\x44\x73\x72\ -\xec\xf5\x1e\x44\x8c\x7a\xd1\xb1\x07\xeb\xcf\xd3\xe2\x82\x1d\x29\ -\x6c\x78\x99\x7d\xdf\x95\x7a\x58\xda\xe5\xfa\xbc\x8e\x6b\x7d\xb3\ -\x65\x68\x9c\x7e\x69\x8e\x54\xd1\x59\xe2\x29\x2a\xf0\x23\xc6\xa5\ -\x92\x45\x0c\xbc\xf0\x6a\x29\x5a\x57\xb7\x9d\xc6\xad\x20\x64\x0e\ -\xe1\x4c\x63\xba\x8a\x40\x3b\xc1\x15\xc5\xd3\x85\x45\x31\xb9\x8a\ -\x34\x90\x6a\x1c\x09\x34\xe4\xcc\xf3\xcf\x8c\x8c\xf0\x5a\x02\x24\ -\x11\x60\xe7\x80\xeb\x48\x12\x26\x92\xe5\xf8\x2c\x4b\xd4\xd6\xfb\ -\x69\xcc\x4f\xfd\xbc\x47\x0a\x3e\x27\xad\x61\x6d\xf7\x47\xde\x8d\ -\x88\x35\xd9\x91\x5a\xd3\x1d\xa7\x3c\xdb\xc3\x1f\xa0\x92\xe0\x0c\ -\x3f\xaa\x7c\x6b\x73\x1c\x6d\x3c\xa7\xf3\x71\x8c\x9a\x54\x9b\x66\ -\x4c\xca\xa3\x19\x18\xcd\x32\x04\x61\x2f\xb8\xdc\x08\xa3\xe3\x50\ -\xdb\xb2\xb3\x4c\xab\xa4\x22\x0c\x93\xf2\xa2\xb0\x6c\xbb\x81\x9f\ -\x68\x81\x5a\x66\x89\xe1\x90\xf1\xd3\x20\xc5\x5d\x5c\x37\x16\x8c\ -\x08\xd3\xc3\x3c\x4f\xe8\x54\x4b\x7b\x77\x98\x93\xec\xf4\xa1\x1a\ -\xf1\x90\xf1\x92\x4e\xac\x7c\x9a\x66\x8c\x13\xd1\xfd\xa1\x46\xdc\ -\x76\xa6\xd7\xbb\x5f\x12\x79\x50\x48\xc6\x64\x3e\xbc\xa7\x9b\x1f\ -\x21\x8a\x51\x91\xd0\xf7\x1a\xbb\x49\x20\x65\x87\xfb\x43\xed\x11\ -\xdd\xfa\x0f\x81\xcf\xe1\x41\x76\x24\x41\x0c\x64\x31\x4c\x71\x3c\ -\x3f\xa2\xc8\xe2\x3e\x89\x68\xb6\xf3\x35\xbd\xcb\xcc\x23\x12\x2b\ -\x91\xd0\x9a\xda\x16\x57\xda\xa0\xda\xb6\x51\x31\x38\x6d\x24\x90\ -\x3d\x61\x50\xc7\x2c\x8d\x95\x88\x48\xc0\x66\x46\x03\xde\x35\x64\ -\xc3\x54\xfe\x76\x46\xef\x42\x9c\x63\xbf\xf9\x55\x90\x4d\xa1\x2a\ -\x96\x84\x9f\x32\xdd\x90\x1b\xfc\x46\x9d\x5e\x7e\xcc\x6d\xa1\xe4\ -\x0a\x4a\x23\x77\x16\xe5\x50\xdb\xcd\x36\x25\x94\x65\x55\x54\x9e\ -\x15\x35\xd4\x77\x00\x43\x09\xc4\x85\xfb\x3a\x7e\x39\xab\xbb\x58\ -\xdd\xb7\xa9\x1e\x59\x1d\x4a\x1c\x11\xce\x97\xfc\xd7\xa6\x4d\xae\ -\xb2\x7d\xed\x68\x80\x80\x8c\xe8\x07\xa9\xe1\x51\x33\xde\x6f\xad\ -\xc9\xf4\x52\x13\xa8\xb6\x4f\x00\x3b\xea\x6d\x37\xf3\x6c\xc6\x8e\ -\x45\x56\x6d\xd3\x6b\x07\x9e\x31\x51\xa4\x8e\xcf\x23\x26\xb0\x88\ -\x85\x9b\x1d\xf8\x15\x6a\x5a\xe7\x22\xeb\xf2\x5a\x54\x9c\xd4\xed\ -\x04\xdc\x20\x38\x93\x58\x2b\xa7\xe3\x9a\x8e\x38\xdd\xbd\x26\x4c\ -\x6e\x63\x21\x1f\x1c\xf0\x6a\x38\x63\x94\xe6\x5c\xee\x98\xa1\x0b\ -\x26\x39\xe9\x3d\x6a\xe2\x64\x66\x8e\x58\xca\x95\x64\x62\x08\xe2\ -\x2b\x64\x88\xae\xdf\xcf\x42\x89\xa4\xc4\xac\xd9\xc0\xed\x6a\xe3\ -\x51\xa0\x9f\x84\x8d\xa1\x24\x2a\x42\x3b\x77\x06\xe5\x53\xda\xef\ -\x4e\xfe\x04\xd7\x22\xe8\x3c\x05\x7d\xf0\xdf\xfe\x2b\xab\x40\x7d\ -\x27\x89\xaf\x35\x86\x63\xbf\xd3\xac\x2b\x21\x19\x1e\x15\x7f\x6f\ -\x13\xbc\xb2\x46\x54\x16\x8d\x4e\x94\x6c\xf2\x2d\xca\xac\x04\xce\ -\x75\x79\xb2\xb6\x84\x52\xcd\x80\xbc\x4e\x07\x4a\xb7\xbb\x4d\x57\ -\x0b\x70\x71\x16\x80\x78\xd6\xca\xd1\xb4\x26\x83\x5e\x71\x69\xba\ -\x23\x7b\xf1\xcf\x2a\x95\x24\x98\xfa\x1c\x6f\x59\x50\xb2\xc7\x9f\ -\x78\x8e\x55\x6e\x26\x9f\xfa\xc7\xe4\xf4\x8c\xea\xf1\xa9\x45\xb4\ -\x9a\x9a\x23\x87\x56\x52\xa4\x7d\x7f\xd3\xec\xfd\xcd\xac\xb7\x02\ -\x39\xc4\xae\x53\x1c\x06\x0f\xdb\x42\xfa\xc4\x14\xbf\x45\xc1\x03\ -\x81\x91\x7b\xaa\x5b\x78\x2d\x0f\x9b\xcb\x67\xa3\x79\x0e\x90\x59\ -\xf1\xc9\xc9\xe9\x5f\x73\xcc\xb6\x12\xef\x2c\x25\x1b\xc8\xb2\x35\ -\x1f\x1a\xb1\xbe\xf3\x29\x92\xdd\x20\x31\xbb\x70\xec\x93\x9f\x1f\ -\x1a\xda\x3b\x1b\xcc\xde\x69\x66\x9b\x54\x73\x82\x34\x11\xc3\x89\ -\x3d\x39\x56\xc0\x2b\x04\x93\xc3\x65\x16\xee\x49\x86\x31\xca\xbe\ -\xe8\x0a\x6c\xed\x52\xdc\x4d\xbe\x81\x67\x00\xa9\x19\xee\xef\xab\ -\x8b\xc9\xec\xae\xa5\x13\xda\x04\xd4\xda\x72\x1a\xbc\xda\xea\x06\ -\x82\x55\x91\x8e\x1b\xae\x6a\xfa\xce\xfb\x66\x49\x77\x11\x27\x70\ -\xf1\x00\x41\x1d\x3e\x04\x56\xc7\x92\x34\x17\x37\x16\x73\x34\xaf\ -\x6d\xab\xbf\xba\x8c\x71\x6c\xc9\x62\x91\xa4\x52\x11\x8a\xea\xe1\ -\xcf\x35\x16\xd1\x6d\x9a\xfb\x42\xd6\x5b\x71\x13\xc3\x9c\x3c\x66\ -\xb6\x03\x5b\xec\xc6\x82\x0b\x57\x2e\xe9\x19\x18\x40\x48\xfd\xb5\ -\xf7\x4b\x1e\xe1\xe0\x17\xdc\x61\x91\xb1\x83\x8e\xfa\xfb\xd7\x36\ -\xcf\x7b\x49\x16\x03\x0e\xfd\x98\x69\xe5\x81\x8a\xb5\x86\xe7\x62\ -\x6e\xee\x6d\xf8\x79\xdb\x38\xd3\xf1\x1e\x35\x35\xad\xb4\x0f\x3c\ -\xb2\xe3\x1a\x7a\x71\xa8\xed\xe4\x84\xdb\x5d\xad\xb1\x80\x17\xe6\ -\xa7\x4e\x2b\x67\xec\x73\x66\xd0\xcd\x04\xf9\x79\xce\x34\x05\xe3\ -\xc4\x1f\x9d\x5c\x5d\xc7\x67\x25\xd4\x13\x5a\xee\x83\xa1\x1c\x0f\ -\x8f\xd5\x5f\x7b\xbc\xc2\x6f\x39\x33\x6a\x03\x87\x2c\xe7\xbe\xb6\ -\x75\xe7\x9a\x4c\xb0\x25\xae\xe9\xdf\x87\x64\xe0\xf8\xd6\xd3\xd9\ -\x06\xc2\x49\x9d\xe5\xd6\x93\xc6\x46\x97\xe2\x3e\xca\xb2\x8a\x3b\ -\x17\x8e\x33\x67\xb9\x91\xd3\x46\xf3\x56\x39\x13\xd1\x6a\xc2\xd8\ -\x58\x48\x27\xb4\xb8\x0c\xc8\x48\xed\x0c\x9e\x55\xb1\xaf\x56\xc2\ -\x65\x8a\x0c\xef\x33\xa7\xb3\x9f\x9d\x6d\xdb\x1f\x34\x7b\x9f\x3d\ -\x62\xd0\xca\x98\xd2\x73\xef\x77\x57\xdc\xdc\x2b\x03\xdc\x79\x89\ -\xd5\x34\x89\x8c\x0a\xdb\x17\x12\xdb\x49\x1c\x17\x24\x18\xdc\xe3\ -\xa7\xf7\x8b\xff\xc4\x00\x2b\x10\x01\x00\x02\x01\x03\x03\x03\x04\ -\x02\x03\x01\x01\x00\x00\x00\x00\x01\x00\x11\x21\x31\x41\x51\x61\ -\x71\x81\x10\xa1\xb1\x40\x91\xc1\xf0\x50\xe1\x20\x30\xd1\x60\xf1\ -\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\xff\x00\xd8\x65\x6b\x74\ -\xd1\xfe\x24\x0a\x89\xb6\x53\x66\x7e\xd3\x18\xce\x8f\xae\xf0\xfa\ -\x56\x88\xf7\x83\x29\xad\x66\x96\x6d\xf6\xc4\xee\x64\x75\x38\x7d\ -\x15\x6d\x34\x39\x62\x0e\x55\xc6\xfc\xb3\xc5\x7f\x0a\x51\xb7\x5f\ -\x6d\x44\xa9\x41\x91\x58\xeb\x08\x9c\x8e\xb4\xf2\x39\xae\xe9\x33\ -\x55\xe3\x5d\x00\xda\xa0\xa1\x00\x40\x46\x71\x1d\x2e\x8c\xc5\x22\ -\x4b\x57\x03\xc9\x7f\x78\x13\x8a\x5c\x4b\xa8\x1e\x20\x0f\x63\xf8\ -\x25\xac\xa2\xe9\xd7\xf6\x31\x2a\xa3\xd3\x14\x8a\xaa\x14\x79\x7f\ -\xf3\xae\x93\x57\x20\x18\x3b\xda\xf8\xa8\x7e\x58\xc1\x01\xd1\xcc\ -\x12\xd2\x94\xd0\xb0\x36\x97\x5d\xcb\x5e\x07\x38\x23\x12\xf1\x55\ -\x71\xa2\x28\x14\xb4\xc2\xf4\x94\x51\x66\x1a\x0f\x24\x50\x11\x86\ -\xf0\xa5\x13\x61\xcc\xab\xb0\xd3\xcd\xc2\x57\x1e\x4f\xb9\xfd\x98\ -\x9e\x24\x39\x43\x95\x7a\xed\x79\xb7\x5e\x38\xfa\xfa\x84\x55\x57\ -\x47\x09\x3b\xa2\xea\x20\x1f\x00\x51\xe5\x77\x08\xd0\x63\xf5\x6e\ -\x3b\x6f\x3a\x68\x5f\x4a\x98\xc4\x75\x35\x92\x04\x05\xa5\x1d\xc8\ -\xd8\x3a\x2c\x06\xd0\x62\xb9\x1d\x63\xc7\xe4\x94\x97\xb1\x9b\xf7\ -\x77\x95\xd3\xdd\xc2\x9a\x35\x07\xf4\xe0\x35\x7f\x13\x0a\xa3\x83\ -\xa9\xc2\x6f\x28\x27\x74\x4d\x8f\x60\x0f\x1f\x5f\x52\x0c\xb1\x56\ -\xeb\x9e\x0d\xd7\x82\x65\x29\xae\x9e\x1b\xe1\xc7\x0e\xb1\x5f\x0b\ -\xa5\xbf\x42\x68\x40\xb0\x9b\x43\x07\x59\x59\xc7\x8b\x6d\xf1\x33\ -\x95\xca\xe2\x63\xe2\x70\x5a\xe0\x83\x65\x34\x0a\x65\x97\x4a\x2f\ -\x68\x94\xb8\xd6\xb0\x31\x35\xb7\x53\x0a\xeb\xb9\x04\xb9\x13\x99\ -\x3a\x43\x84\xd5\xc9\xed\xb8\xbc\xa3\x2c\x8e\xc8\x74\xbd\x07\x4b\ -\xcf\xd6\x93\xba\xd6\x4c\x8f\x52\x1d\x0a\x7b\xec\x8b\x8c\x4b\x3a\ -\xa1\x67\x96\xa1\xf3\x1a\x86\x78\x3b\xfc\x3d\x79\x49\x0c\x0d\x32\ -\xc4\xfc\x15\x14\x99\xe9\x0f\x4c\xc4\x56\x44\x0e\xd4\x9d\x20\x61\ -\xb3\x2a\xd0\xcc\x49\x38\xb6\x1c\x65\x8d\x9c\xdb\x2a\xb7\xb7\x69\ -\x5e\x8a\x8b\x4f\x07\x73\xe2\x0e\x4f\x2a\x6a\x9b\x3e\x3f\x31\x00\ -\x60\x6b\xa0\xc7\x09\x54\xea\x3a\xd1\xb7\x5f\xab\xb8\x40\x78\xde\ -\x07\x93\xa4\xcc\x29\x36\x28\x12\x19\x6e\xdb\x51\x99\x4b\xfc\x5b\ -\xf0\x1e\xc7\xda\x0f\x4b\x88\xb4\xc7\x23\x12\xbd\xe8\x2b\x40\xf4\ -\x0b\x68\x5f\xa2\x1a\x0c\xcf\x6a\x57\x9e\xb6\x21\x86\xe5\x23\x60\ -\x5a\x39\x1a\x81\x1e\xd3\x3b\x30\x27\x7e\x31\xa1\x43\xdb\x7f\x13\ -\x78\xa3\xe4\xa5\xfc\x6d\xf5\x83\x26\x2a\x36\x9e\x86\xba\x0b\xef\ -\x2a\x00\xd4\x61\x98\x2e\x97\x30\x51\x89\x3e\x0d\x28\x68\xc1\xc2\ -\x6c\x1a\x37\x4f\xc3\xed\x28\x45\x6b\x15\x53\xda\x5e\x1f\x2a\x59\ -\x35\xca\x4a\x31\x99\xc7\xdc\xea\x89\xf8\x8e\x1c\x17\x51\xba\x21\ -\x10\x36\xed\xd5\x7b\xc5\x10\x22\x07\x58\xa3\xa9\x70\x3c\x18\x06\ -\x2a\xe6\x81\x5d\xa1\xb4\x18\x6b\x83\x79\x90\x94\x20\x84\x2d\x5e\ -\x66\x1a\x5f\x43\xf8\x87\xb0\x1a\x20\x86\xa3\x46\x24\x99\xec\x0c\ -\xaa\xcc\x1b\xc3\xd9\x54\x55\xa0\x6b\xbd\x9f\x58\x90\x02\x18\x72\ -\xca\x27\x32\xa6\xc1\xbf\xde\xb0\x34\xbd\x97\x78\x1a\xd4\xfa\x98\ -\x69\xf1\x81\xfd\xad\x29\xb9\x6d\xf4\xe2\x7c\xfd\xe5\x10\xdc\xa0\ -\xad\x49\x4b\xce\xae\xe7\x69\x8c\x3d\xd8\x81\x3d\xa3\x51\xb5\xa2\ -\xfc\x56\xc9\x4a\xf0\x98\x15\x27\x72\x66\x9c\x8e\xe6\xd6\xcf\x86\ -\xbc\x45\x7d\xdf\x48\xc2\xcf\xca\x8e\x97\x9f\x69\x90\x29\xc9\xe5\ -\xbf\x08\xac\x24\xce\xa3\xf9\x60\xb6\x67\x95\xd7\x0f\xde\xa2\x5a\ -\x14\xad\xcd\xe3\xea\x8f\x18\x5b\x58\x79\x66\xf7\x9a\xfb\x20\x08\ -\x7a\x51\x5c\x11\x9c\x5a\xac\x85\xdf\xbb\x84\xdd\x75\x97\x75\xd2\ -\x65\x46\x83\x5b\x76\x14\x56\x2c\xaa\xef\x2e\xae\x9f\xd2\x51\xda\ -\xe0\x8a\x6b\x40\x56\x3a\x0f\x0d\xa2\x82\x3f\xa8\xad\xfc\x45\xd4\ -\x9b\x71\x9e\x77\xf3\x36\x3c\x00\xa3\x9b\xbe\xcc\x01\xa2\xb1\x70\ -\x67\x33\xdb\x6d\xe9\xad\x53\x4d\x43\xb6\x75\x18\xe3\x68\x1a\x3d\ -\x2a\x7e\xcb\xbe\x15\x53\x72\x51\xb4\x79\x41\xa3\x72\x60\x0e\xda\ -\x56\x87\xb0\xf3\x1f\xeb\x35\x19\x7e\x9d\x3e\xa8\xf3\xd3\x3f\x7c\ -\x10\xc2\x01\xa7\x84\x2f\xad\xc0\xe0\xf7\x2c\x3f\x09\x67\xa2\x81\ -\x38\x18\x3f\x69\xd1\x28\x94\xbb\xc1\xac\x20\x96\x6d\x90\x3b\x20\ -\x4f\x63\xf7\x81\x82\xd2\x38\xec\x3b\x45\xca\x65\xec\xc6\x8b\xb9\ -\x4f\x58\x36\x55\x90\xf3\x89\xf9\x95\x8f\xd2\xf3\xf6\xba\x62\xa8\ -\xe1\xdd\x6d\x5d\x7e\x22\x12\x96\xf6\x59\x32\xf4\x44\x20\x80\xaf\ -\x38\x62\xed\x0a\x95\xd9\xaa\x63\xac\x0a\x97\x39\xbb\x8a\xfd\x60\ -\x5e\x65\x5b\xc7\x4f\x96\x56\xd2\x36\x03\x0a\xae\xc5\xc1\x1f\xd9\ -\xb0\xaa\x28\xeb\x0a\xcb\x8b\x0f\xed\x69\xe7\xd0\x42\x46\xe5\xde\ -\xf9\x37\xfb\xc4\xba\x0a\x2c\x49\x44\x2e\x3f\x5a\x8a\x34\x35\x33\ -\xa9\x0e\x94\xaf\x34\x5a\xd9\xe6\x58\xbe\x46\x53\xf0\xd2\x36\x8b\ -\x4f\xf7\x5e\xac\x1d\x3d\x16\xe8\xac\x86\x93\x8b\xc9\x58\x6c\xbe\ -\x98\x96\x1a\x3a\x54\xfb\x4a\x60\x21\x0f\x2c\x1d\xc2\x75\xf1\x6b\ -\xdd\x66\xef\xc2\xa2\xf5\x3e\x0f\xac\x1d\x60\x60\xe6\x69\x29\xba\ -\x37\x60\x1b\x69\x71\xa1\x34\x71\x6f\x9e\x9e\xd2\xed\xa1\xd0\xf4\ -\xcb\x94\xe9\x0b\x18\x30\x50\x26\xf7\xa8\x85\x23\x30\x52\xb1\x18\ -\xbe\x49\x5e\x8b\x1b\xf6\xe7\xf5\x39\x7a\xd3\x6a\x68\x87\x45\x79\ -\x8c\xb0\xb4\x8e\xcd\x43\x7e\xb1\x08\x55\xe2\x24\x2e\xd5\xe6\x72\ -\x3f\xf3\xea\xd8\x82\xb0\x09\xe6\xdf\xf8\x83\xd4\x70\xdf\x61\x51\ -\x68\x09\xba\xc5\x55\x78\xfc\xc2\xd8\x4a\xb9\x1d\x3b\xfe\x1d\xbd\ -\x6e\xc8\x4c\xd9\x63\xf9\x8c\xcc\x3e\x0e\x5a\xd7\xd4\x66\x8f\x5f\ -\xd2\xd8\xb7\x2b\xaf\x96\xdd\x3b\xc5\x63\x87\x36\xda\x51\x09\x3d\ -\x5d\xc7\x4d\x82\xc3\x61\x16\x81\x57\x6a\x55\x6d\xf5\xba\xad\x24\ -\x1d\x8b\xf8\xf3\x1b\xb0\xb8\x79\x87\x2c\xb7\x96\xf3\xd1\xf1\x3a\ -\xfe\x8a\x19\x90\xc0\xe4\x94\x17\x70\xf4\x4f\xf8\x17\xa8\xca\x5e\ -\xa1\xf5\xfd\x5c\x1d\x5b\x20\x60\x9a\x76\x85\x2d\xb0\xdd\xbc\x07\ -\x77\x1e\x3e\xbf\x6f\x14\xbb\xfa\x6b\x3e\x62\x15\xec\xe5\xce\x7a\ -\x46\x83\x64\x54\xea\xdf\xed\xda\x32\x1c\xad\xf7\x6e\x7c\x40\x3e\ -\xc3\x8b\x89\xde\x66\x8c\x2d\x95\x55\xbd\x56\xe8\x04\x99\xb9\x42\ -\x38\x58\x6f\x22\x04\x80\xb7\xef\xb4\x46\x8b\xba\xbf\x5f\xc3\x4e\ -\xf0\x0b\x6a\xc5\x5d\xe3\xa4\xb8\xe1\x61\x7e\xe8\x7c\xfd\x7b\xb0\ -\x4d\xbc\xf5\xf5\x3c\x41\xa6\xe0\x22\xf8\x10\x26\xad\xd3\xe3\xd1\ -\x72\x7c\x41\xf6\x7f\xbe\x15\x1e\xb8\xba\xb7\x2c\x6a\xed\x26\xe6\ -\x87\xa4\x3a\xd1\x74\xcf\xe6\x10\xb4\xf2\xd5\xff\x00\x90\xb3\xb4\ -\x31\x0c\x2d\x93\x92\xb8\xa2\x0d\x41\x44\xaa\x83\x77\x28\x91\x84\ -\x5b\xc2\x40\xdb\x7e\x4e\xda\xea\x78\x54\xe8\x17\x90\xfb\xfc\xca\ -\x4e\x4b\xf0\xfe\x24\xe7\xf8\x2a\x0f\xb6\xf3\x66\xd7\x15\x40\x8b\ -\xd0\xdd\x78\x3b\xc3\xf5\x41\x70\x07\x66\x0d\xfc\x52\x3e\x40\xca\ -\xe7\x28\xbc\x11\xfa\x45\x57\x06\x10\x69\x63\x44\x7d\xd9\xd7\xb7\ -\x09\xed\xb3\x01\x2c\x94\xe0\xb3\xe3\xf8\x5d\x40\x49\xc8\x5a\x17\ -\xd3\xac\x11\x0f\x7f\x9b\xdb\x83\xd1\x86\xc1\x45\x2f\x23\x0f\xf1\ -\xc7\x0a\x29\x7b\xdc\x28\x24\xb2\x75\xca\xfe\x3d\x04\x4a\x67\x73\ -\x69\x23\xf2\x74\x0a\x02\xaa\xc6\xb4\x9b\xff\x00\x07\x75\x55\x1a\ -\x69\xba\x7f\xc9\x72\xc4\x1d\xc2\x35\xd3\xfd\x2a\x22\xb4\x1b\xb0\ -\x89\x04\x2c\x4d\xfe\x90\x11\x49\x8e\x9a\xcd\x3c\x92\xae\x3b\x11\ -\x4e\x98\x7e\xff\x00\xdc\xa6\x6a\x8f\x11\xba\x6d\x0b\x75\x66\xb0\ -\x11\x31\x37\x36\xad\x8e\xe8\x33\x37\x54\x14\xb9\x6a\xb4\xd3\x5c\ -\x47\x91\x45\xed\x34\x01\x46\x33\x2c\xb6\x1c\xb3\x83\xa4\x52\x34\ -\x1d\xb4\xe1\x17\x8a\x9d\x1b\x60\xb0\x6b\x3a\x91\x2b\xaa\xad\xcb\ -\xde\x35\x6b\x83\xa5\xda\x6a\x6e\xce\x4c\x4b\x64\x9d\xb9\xd9\xd7\ -\x2f\x35\xe2\x61\x46\xa7\x73\x10\x39\x25\xb2\xe8\x06\x4c\xb0\xc1\ -\xd6\x00\xc2\x5a\xa9\xe9\x78\x39\xf3\x2c\xed\x41\x57\xb4\x0a\xd1\ -\x89\x86\x12\x68\xc9\x29\x4d\x46\x50\xef\x0a\x04\xaa\x74\x81\x43\ -\x23\x11\x27\x47\x86\x60\xa6\xb3\x29\xd0\xb4\xcd\xc4\x07\x7c\xed\ -\x35\x41\x67\xcc\x70\x5c\x0a\xe9\xd6\x74\xce\xa6\x91\x6a\x79\xf4\ -\x9f\xb0\x55\xcb\xe4\x79\x49\xf6\x33\xe2\x33\x23\xb5\xa9\xc0\xd5\ -\x57\x8b\x85\x4c\xc7\x50\x4c\x05\xd3\x98\xf1\x04\x0a\x59\xd3\x6d\ -\x62\xb8\xd7\x12\xc7\x1d\x91\x32\x5d\x45\x0a\x75\x8e\x90\xa1\xb1\ -\x4a\x85\x41\x78\x1a\x67\xd4\xf4\x6d\x1c\x6e\xee\x87\xd4\x03\xfe\ -\xf4\xe8\xe7\xa8\x41\xd5\x2d\xe1\x2c\xab\x5b\xb1\x29\x7d\x69\x7e\ -\x21\x9d\x02\x91\x6a\x6b\x54\xce\x08\xf0\xf6\x0d\x21\x58\x67\x4c\ -\x4b\x3e\x00\x69\x7c\x36\x52\x30\xf2\x1f\x99\xcc\x3a\x3e\x50\xc8\ -\x2f\x55\x1a\x62\xdb\x49\xae\xda\x6b\xaf\x2d\x17\x60\xcb\xa3\x98\ -\x9d\x42\xc4\x10\x32\x60\x9a\x61\x41\x10\x2b\x29\x18\x85\x92\x76\ -\x46\x0e\x73\x37\x85\x31\x48\x34\x63\x4b\x4b\x2b\xde\x60\xd9\x7e\ -\x4c\x96\x54\x70\x67\xed\x0f\x40\x24\x85\xd2\xeb\xff\x00\xac\x4e\ -\x03\xfb\x4a\x1a\xe7\x05\x6b\xde\x3a\x2b\xf4\x2b\x0e\x28\xd9\x7f\ -\x98\x9d\xec\xb7\xbd\x2a\xab\x78\xf7\xcc\xa0\x74\xd9\x8a\x77\x56\ -\xdc\x54\x76\xee\x45\x6a\x85\x55\x53\x88\x3c\x64\x20\x45\xe8\x8e\ -\x8c\xb9\x36\xa6\x91\x55\x1c\xbc\x20\xb4\x90\x3d\x21\xb9\xfd\x31\ -\x85\x6b\xb5\xae\xe3\x84\x47\x09\xaa\xe6\xec\x70\xb2\x66\xbe\xdc\ -\x83\xaf\x9b\xb8\xa1\x7b\x9e\x90\x81\xab\x92\x9c\x73\x2c\x15\x65\ -\x37\x17\x97\x52\x0d\x8a\x77\x27\x40\xd3\x2e\xb1\xec\xf7\x12\xc8\ -\xd4\xba\x2e\xe5\x35\x7b\xa0\x13\x05\xb9\xaa\x98\xd8\xa4\x67\xaa\ -\x9c\x5f\xfe\x8b\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\ -\x00\x10\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\ -\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf0\x00\x00\x0c\x1b\xc7\x28\x00\x14\ -\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\x00\x42\xab\x6b\x6e\x69\x00\ -\x05\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x00\x5c\x8b\x64\x9e\x89\ -\x1e\x05\x4f\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xc0\x5e\xe9\x9b\x47\ -\x7e\x88\xa4\x53\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf0\x1c\x1c\x78\ -\x31\xd4\xd5\x41\x54\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\x04\x5a\ -\xbf\x29\xc6\x07\xd9\x55\x7c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x05\ -\x8c\x9a\x0f\xbc\x47\x1f\xa9\x4f\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\ -\xc4\xb7\x7f\xb2\x89\x23\x6e\xf1\x53\xcf\x3c\xf3\xcf\x3c\xf3\xcf\ -\x3c\xf0\x00\x45\x87\x10\x0d\xc2\x10\x14\xf3\xcf\x3c\xf3\xcf\x3c\ -\xf3\xcf\x3c\x00\x20\xaa\xcd\x18\xcb\x08\x25\x3c\xf3\xcf\x3c\xf3\ -\xcf\x3c\xaf\x0d\x00\x00\x62\x06\xa8\x11\x4c\x29\x7c\xf3\xf3\xcf\ -\x3c\xf3\xcf\x2f\x7e\xb3\xc3\x23\x8b\xec\xf0\xfe\xa7\x72\xff\x00\ -\xfc\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\xf3\xcf\x3c\ -\xf3\xcf\x3c\xf3\xcf\xff\xc4\x00\x28\x11\x01\x00\x02\x02\x01\x02\ -\x05\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x11\x21\x31\x41\ -\x51\x61\x71\xa1\xb1\xd1\xf0\x30\x40\x81\x91\xc1\xe1\x50\xf1\xff\ -\xda\x00\x08\x01\x03\x01\x01\x3f\x10\xff\x00\x80\x91\xe0\xc0\x56\ -\x88\xa0\x0c\x73\xe3\x01\x54\x45\x45\xc7\xd8\xb1\x50\x2b\x55\x2c\ -\x2d\xad\xc2\x40\xad\xa9\xfc\x0f\xac\x00\xab\xe6\xd1\x8f\xcd\xc7\ -\x05\x1a\xe9\x51\x46\x5e\xa7\x30\xb4\x8a\x0e\xbf\x61\x70\x27\x11\ -\x63\x78\x75\x59\x74\xb9\x7e\xdd\xbb\xfe\x63\xc0\x2c\xd3\xc3\x4f\ -\x96\xa2\x1b\x41\xc2\x39\x26\xdc\xfc\xea\xda\xff\x00\x3d\xe0\x87\ -\x80\xfb\xfb\xea\x32\xbe\xdf\x5d\x17\x0c\x44\x82\xae\xf1\x5b\x8f\ -\x1e\x1f\xee\xe2\xdd\x66\x61\x38\x50\x60\xe1\x4e\xf0\xea\x69\xb3\ -\x18\xf4\x96\x02\x25\xf1\xbe\xd8\xd7\x7f\x29\x5b\x75\xfc\xed\x1d\ -\x2b\x9d\xbb\x9f\x30\xcd\x11\x97\xeb\x02\xa8\x94\xcf\x40\xf4\x3d\ -\xe1\x2a\x6d\x7e\x4f\xac\x06\x81\xa5\x20\x22\x90\xcd\xff\x00\xe9\ -\x28\x00\xea\x80\x30\x94\x55\x17\x57\x7c\x8f\x94\x14\x55\xaa\x40\ -\xd8\xc0\x61\x0c\x78\x23\xc4\xa0\x85\x36\x3a\x58\x63\x5c\x6b\xf1\ -\x16\x10\xbe\xc7\xb4\x41\x5b\xc9\x8f\x9d\x48\x96\xf0\xfa\xc4\x14\ -\x57\x5e\x60\x9e\xd2\x7c\xf3\x8d\x76\x92\xfd\x60\x0a\x9e\x93\xec\ -\xcb\x82\xa7\x51\xe6\x96\xbf\x27\x51\xc4\x08\x07\x0a\x4b\x17\xc1\ -\xba\xf9\x99\x87\x66\xa0\xe9\x77\x8f\x01\xd4\x6a\x80\xe3\xfb\x17\ -\x6d\x6f\xd6\x01\x8c\xa3\x54\xaf\x0f\xaa\x0a\xa2\x60\x23\x15\xf9\ -\xa9\xa6\x49\x0d\xf0\xf9\x93\x10\xd8\x3d\x66\x59\x1d\x45\x2a\xfa\ -\xea\xd8\x09\xd3\x19\xd4\xa9\xa8\x84\x72\x55\x8c\x78\xc7\x0c\x80\ -\xfa\xcd\x5b\xa8\x15\xd7\x7a\x7b\xc5\xb5\xa6\xfd\xe5\xd2\xf8\x93\ -\xd9\x80\x4f\x32\x88\x76\x77\x7e\x66\x28\xaa\xcf\xd7\xc4\x55\x06\ -\x63\xa1\x7d\xde\xf2\xfb\x4e\xfc\x30\x70\x33\x38\xfa\x15\x9c\x2a\ -\x31\x61\xae\x39\x62\x71\xc2\x64\xef\xf6\x4e\x43\x2e\x7f\x04\x55\ -\xff\x00\x4e\x25\x39\x2d\xd9\x2f\xd5\x2b\x98\x46\x36\x7d\x56\x4b\ -\x89\xc4\xe8\x8a\x5d\xaf\x37\x54\x9d\x46\x0d\xb0\x5b\x0d\xf5\xd7\ -\xc2\x20\x2a\x71\xde\x5a\x14\x37\xac\xef\xe5\x44\x01\x58\x78\x17\ -\xd5\xe9\x2f\xa1\x75\x75\x67\xae\xa5\x95\x25\x77\x81\x24\xbc\x13\ -\x4e\xa5\xe1\xe9\x0f\x20\x5d\x56\x47\x83\xd2\xc1\x88\x5d\x9c\x5f\ -\x3d\x37\xfa\xe6\x1c\x46\xaf\x9d\xa7\x11\xa1\x45\x02\xf6\xd7\xbc\ -\x36\x80\x0d\x6c\xe9\x7f\x3f\x7a\x83\xd4\x3b\x2f\xf3\xe9\xf4\x2e\ -\xed\x5f\x2f\xf9\x00\x0a\x34\xba\xed\x7e\xb7\x98\x07\x3d\xae\x38\ -\x51\xfe\xc0\x80\x2c\x55\x6b\x45\x07\xef\x9d\xc2\xe0\x7c\xb8\xea\ -\xbf\xd4\x00\x70\x0a\xe1\xb3\xb9\xa9\x70\xc0\x02\x61\xd1\x57\x9e\ -\xd1\x7d\x99\x47\x46\xc4\x77\x57\x4a\x6a\xe3\xf6\x2c\xd8\xeb\x22\ -\xaf\xaa\xe4\x82\x07\x09\x57\x45\xd6\xb8\x3a\x72\xc1\x01\x5d\x5b\ -\x59\x31\xe7\x83\x24\x6d\x5f\x3d\x9d\x17\xe9\x2c\x9b\xdb\x7d\x38\ -\x03\xe8\x4b\x2b\x79\x2b\x8e\xdf\xd1\x12\x35\x6a\xf4\xe6\xcf\x2f\ -\x38\x7d\x98\x47\x8e\x3f\x87\x9f\xde\x7f\xff\xc4\x00\x29\x11\x01\ -\x00\x01\x03\x03\x02\x06\x03\x01\x01\x01\x00\x00\x00\x00\x00\x01\ -\x11\x00\x21\x31\x41\x51\x61\x71\x81\x30\x91\xa1\xb1\xc1\xf0\x40\ -\xd1\xe1\x10\xf1\x50\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x10\xff\ -\x00\xc0\xc6\xcf\x53\xa5\x00\x52\x02\x82\xe9\x4c\x9f\x5b\x53\x86\ -\x80\xa3\x35\x03\xbf\xe0\x8a\x7b\x4c\x50\x48\x59\xda\xf3\xd0\x2a\ -\x0a\x06\x8d\xed\xd3\x5a\x2a\x52\x2d\x24\xba\x6c\xa4\x5f\x8a\x91\ -\x9e\x5a\x20\x37\xec\x95\x6e\x6b\xa3\x31\x33\x68\x9f\xdb\x40\x0d\ -\x98\xd0\xf0\xba\x3d\x73\x41\xd8\x80\xbf\x76\x30\x7e\x00\x4e\xd4\ -\x83\xae\x9e\xb4\x5d\x03\x2a\xe0\x1d\x67\x7f\x59\xb7\x34\xb0\x12\ -\x35\x74\xe9\xb7\x6a\x88\x81\x8d\x77\x3f\x74\x9b\x01\x69\xd3\x2c\ -\x34\xcd\x58\xb1\xa9\xa8\x6e\x6f\x1b\x64\xd2\x69\x2a\x00\x40\xf3\ -\x98\xe1\x4f\x1d\x93\x20\x6e\x67\x8e\x28\xbe\xb2\xd0\x5a\xed\xad\ -\xcd\x45\xae\xae\xbf\xcc\x79\xd0\x56\xe5\x5a\x57\xef\x14\x2a\xa9\ -\xb2\xb2\xb4\x02\x24\xa7\x8e\x30\x8d\x08\x7a\xf2\x77\xda\xb1\xa9\ -\x14\xb0\x4b\xc7\xed\xf1\x9c\x34\x05\x2c\xe0\x65\x68\xc8\xaf\xa5\ -\xa9\x3a\x60\x9b\xb9\x27\xca\x8c\x66\x48\xb9\x2c\x8f\x6f\xad\x4b\ -\xd8\xc6\x59\x96\xfa\xe6\xd3\x8a\x15\x28\x86\x45\x03\xcd\xe7\x3d\ -\xa9\x68\x5c\x1b\xf4\x9b\xfc\xf7\xa4\x2a\x63\x97\x6e\xb4\x07\x98\ -\x43\x7d\x34\xd7\x86\x90\x52\x54\x1d\xcb\xc7\x47\xdf\xc6\x65\x03\ -\x92\x5e\x48\xa9\x56\xc1\x22\x31\xdf\xb5\x00\x72\x31\xed\x4f\x4b\ -\xbd\x6f\xe9\x46\xdc\x40\xb7\x69\xf3\xe6\xa5\x93\xab\x64\x2b\x46\ -\xd2\x3d\xb5\xa8\xdc\x8b\xf6\xc6\xb5\x76\x62\xc7\x9c\x52\x24\x20\ -\xb9\x65\x92\x7b\x73\x40\x01\x31\xaa\xcb\xe7\xe2\xb8\x78\x0a\xb2\ -\x56\x69\x13\x32\x4b\x6e\xec\x51\x23\x29\x0d\x38\xb4\x52\xad\x7f\ -\x47\x7a\x54\xf8\x56\x7a\x50\x8c\x61\x92\x0c\xc6\xd9\x82\x94\xd8\ -\x86\xd3\x34\x92\x68\xb3\x8a\x14\xbe\x67\x60\x1b\xba\x4a\xdb\xa5\ -\x5d\x61\x48\x71\x01\x07\x48\xf5\xf1\x81\x42\x1a\x7d\xcd\x1f\x8b\ -\xa0\x6a\xb3\x1c\x99\xe6\x12\xa2\xf2\xe6\x3a\x4e\xed\x97\x4f\x2d\ -\xbf\xc8\x0a\x21\xfe\x51\xa0\x0f\x35\xd8\xe7\xfe\xb5\x77\x24\x4f\ -\x61\x27\x5d\x0e\xed\x0e\x02\xd8\xb5\xed\xcf\x8e\xec\xe8\x83\xbd\ -\xa5\xe0\xa0\xc1\x06\x75\x75\x26\xca\x7a\xd0\x7a\xc6\x1c\x3c\xc3\ -\x7b\x43\xe7\x44\x64\xb2\x6e\x7e\xa6\xa6\x40\x8e\x62\x5f\x82\x85\ -\x3a\xb5\x36\x33\x7d\xd5\xe2\xd5\xd4\x48\x63\xfa\x36\x3b\xb4\x05\ -\x8b\x36\x2c\x9a\xcd\xf4\xfc\x20\x90\x00\x4f\x2c\x69\xf2\xd3\x94\ -\xcc\x5a\x03\xeb\x67\xde\x83\x0d\x8e\x09\x94\x7e\x37\xab\xf9\x8e\ -\x26\x23\xc8\x08\x9a\x9d\x50\x99\x1d\xe5\xf7\xf1\x48\x22\x0e\xb5\ -\xba\x25\x10\x1a\x44\xc8\xec\xd2\x48\x10\x85\xc6\xd9\xfa\xda\x84\ -\x40\x77\xe2\xa1\x59\x08\xcd\xb1\x8f\xdd\x09\x04\xdd\xd5\x88\xc1\ -\xbd\x45\x46\x26\x26\x1f\x6c\xd4\x14\x8c\xf1\x4e\xa7\x12\xcf\x53\ -\x57\x65\x28\xb9\xbd\xaa\x3c\x2c\x4c\xd9\x35\x7d\xe1\x68\x48\x87\ -\x78\xd3\x7c\x79\xe9\x4f\x10\x98\xd3\x03\xad\x12\x09\x96\x0e\x73\ -\xfa\xa7\x10\xaa\x4e\x1d\xe3\xec\x74\xcd\x27\x32\xe5\x1d\xbd\xfc\ -\x08\xb8\x4f\xfc\x8f\x9a\x40\x02\x4a\x27\x98\xf6\x8b\x7d\x85\x34\ -\xe0\x6b\xaa\x5f\xe5\x28\x54\x5e\x67\x39\x49\x3e\x46\x31\x4b\x01\ -\x3a\x35\xd8\x3e\x14\x88\xdc\xb3\xa9\x0f\x0e\x69\x25\x14\x51\xb9\ -\x96\x62\xdc\xd0\x38\x2c\x26\x5c\x42\x62\x62\x41\x6f\x46\xc2\x2d\ -\x09\x9b\x20\x1d\xec\x16\x69\x00\x5c\x66\x25\x89\xce\xae\xfa\x14\ -\xaa\x81\x98\x66\xcd\xfd\x2e\xd9\xa2\xc4\x2d\xcb\x74\x7b\xd4\x11\ -\x18\x23\x7d\x4a\x7b\xb5\x07\x06\xcc\xeb\xcf\xc2\x28\x21\x10\x06\ -\xfa\x41\xeb\xe6\x53\xf2\x5c\x4d\x75\xf9\x3d\x3f\x33\xff\xc4\x00\ -\x2a\x10\x01\x01\x00\x02\x02\x02\x01\x04\x01\x03\x05\x01\x00\x00\ -\x00\x00\x01\x11\x00\x21\x31\x41\x51\x61\x71\x10\x40\x81\x91\xa1\ -\x20\x50\xb1\x30\x60\xc1\xd1\xf1\xe1\xff\xda\x00\x08\x01\x01\x00\ -\x01\x3f\x10\xff\x00\x74\xdc\xb9\x72\xfd\x6e\x2e\x52\x5e\x8d\x3c\ -\x27\xa9\xce\x5f\xa5\xfa\x5f\xe8\xbf\xd8\x03\xc7\x09\x47\x10\x17\ -\xc8\xa3\x9b\xe8\xca\x5f\xf2\x10\xfe\xf4\xfd\x02\xa0\x28\x2e\xd7\ -\x83\xcb\x90\x4c\x06\xb9\x1c\xbd\x35\xf9\x61\x53\x54\xda\x9d\xa0\ -\xe9\x3f\x9f\xa1\x64\x21\xbb\xbe\xa0\xcb\xda\xbb\x06\x4c\x7c\x08\ -\x4f\x6f\xd3\xbf\xe8\x3e\xe9\xfe\x9a\xf0\x56\x1e\x0a\x1f\xba\xfe\ -\xb2\xcb\xb9\x14\x8d\xfa\x21\xef\x07\xa5\x6c\x8e\xb9\x65\x39\x1b\ -\x0e\xb1\x09\xa4\x55\x02\xb4\xca\x0c\x63\xbe\x4c\xa4\x74\x22\x6e\ -\x05\xfd\xe0\xab\xd2\x3f\x50\x77\x84\xa0\x43\xde\x39\x0b\xc0\x47\ -\x28\x03\x4e\x8b\xf9\xca\x80\x0b\x4d\x47\xd7\x58\x03\x9b\xcf\xa5\ -\x3d\x96\x9e\x1f\x5f\x4e\xff\x00\xb0\x18\x61\x5e\x87\x76\xf0\xc7\ -\x4a\xfe\x29\x86\xf5\x1d\xb7\xe7\x0e\xf1\x88\x12\x80\x9c\xa0\xcd\ -\x39\x54\x1d\xb9\xb3\xd0\xf1\x83\x36\xfc\x50\x83\xa5\xe7\x1e\x00\ -\x09\x0d\x46\xba\xb6\x64\xf9\x70\x05\x39\x00\x0a\x02\xcb\x37\x81\ -\x68\x8a\xba\x12\xc1\x35\xf2\xe2\xc6\xb9\xf4\xd2\x4b\x71\x64\x44\ -\x91\x70\x15\x5b\xd6\x0b\xf4\xc1\x0b\x3a\xaa\x33\xf2\x18\x34\x30\ -\xfa\xf0\xd4\xea\xa5\xf4\x39\x11\xda\x8e\x80\xef\xae\xfc\x47\xb6\ -\x47\xee\x4d\x0f\x84\x1d\x3d\x51\x74\xf4\x24\x7a\x94\xde\x73\x4e\ -\x51\x59\x63\x3a\x76\xfd\x45\xa6\xaf\xdf\x7b\x7d\x1d\x14\xf8\xc8\ -\xf1\xe8\xf1\x94\x76\xfd\xe2\xcc\x30\xf6\x7c\x52\xde\x0e\xd1\x7a\ -\xc4\xde\x6b\x1a\x9e\x29\xcc\xf0\x6b\xde\x24\x06\xf4\x49\xb6\x88\ -\x07\x1b\x1b\x09\x48\x78\x33\xd5\xd9\x87\x24\xf1\x24\x34\x7e\x75\ -\x9a\x2d\xc3\x55\x78\xf3\x85\x79\x95\x92\x6c\xb5\xce\x0c\x2f\x45\ -\x72\xf4\x44\x28\x7c\x3c\x5e\x71\x1d\xd4\x00\x09\x68\xd2\x8e\x3a\ -\x95\x35\x7e\xc7\x9b\xfa\xf8\xc2\x71\x6d\xe6\xa3\x69\xf0\xb1\x9e\ -\xae\x1b\xdb\x8c\x2f\x93\xb4\x8e\x4b\xf0\xaf\x5f\x7e\x04\xc0\x1e\ -\x83\x45\x74\xcf\x01\x3b\x4c\x29\xc4\xbf\xce\x49\x6d\xf2\x14\x1c\ -\x8e\x45\x2e\x8e\x4a\x4d\xaf\x46\xe2\xf7\xc6\x40\x01\x8b\x76\xe2\ -\xc3\x58\xf6\xd1\x1e\xb1\xcd\xc1\xb4\x1b\x52\xf5\xbb\x9c\xf9\xc2\ -\x50\x27\x1f\xf9\x9c\x86\x0a\x24\x1e\x0b\x83\xa6\x42\xdd\xc1\x4d\ -\x9b\xc5\x4e\x97\x6d\xe9\x1e\xcc\x34\xe8\xda\xb1\xaa\xee\xba\xf1\ -\x80\x29\x5b\x0f\xee\x0f\xf2\x93\xde\x1a\xd3\xab\xc2\x34\xbc\x8f\ -\x03\x84\x69\xe8\x0c\x54\xcd\x49\x00\x1b\x04\x37\xb0\x06\x91\x0a\ -\xa3\xb0\xa5\x39\x3d\x3e\xf4\x68\x87\x53\x9b\xcb\x10\xf0\xf7\x85\ -\xc4\x21\x30\xf6\x82\xdc\x73\xc6\xae\xe0\x0f\xf3\x0b\xe0\x18\x03\ -\x57\x94\xb2\x06\x70\x8c\xf4\x1f\x26\x10\x04\xd6\x71\xe0\xd8\x20\ -\x22\x07\x57\x1b\xe0\x28\x8e\xe0\xa9\x12\xe9\xeb\x35\x7b\xc1\xf8\ -\xc3\xce\x00\x14\x07\x57\xe4\xe7\xf1\x90\x0b\x56\xc7\x61\x3f\x19\ -\x72\xaa\x20\xe6\x15\x7f\xc7\xac\x25\x9b\x2d\x2e\x00\x23\xe7\x5b\ -\x37\x81\x24\x15\xe1\x38\xdf\xb5\xe1\xb8\xbe\x52\xe6\x96\xdd\xf2\ -\x93\xcf\xc3\x3a\x0d\x25\xcc\xbe\xca\xa7\xb1\x98\x55\xf2\x6d\xaf\ -\x98\xec\xfe\x70\x49\x8a\x1a\x08\xf7\x98\x65\x5a\x0f\xbb\x24\x97\ -\x69\x9b\xc9\xdf\xda\xd7\xc3\xbc\x4d\x7b\x29\x5d\x1d\xbd\x53\x5f\ -\x26\x6a\x46\x58\x88\x28\xa3\x1e\x38\xf3\x88\xa9\xe5\xba\x96\x3e\ -\x80\x31\xc5\x84\xd6\x02\x69\x10\xcb\xf0\x7f\xcf\xe3\x0a\x3b\x90\ -\x13\xc0\x0f\x19\xa2\xa6\x39\xda\x0f\x06\x1a\x3a\xca\xb1\x1d\x40\ -\x0b\xa1\xd8\x73\xc7\x8c\xdc\xd3\x51\xc9\x5e\xd7\xb7\x09\x1c\x12\ -\x1d\x08\x03\xf2\x61\xd9\x2a\x1b\xd7\x27\xe4\xa7\xe7\x20\xdb\x4d\ -\x82\xf5\x5d\x61\xa3\x54\x9a\x80\x84\xe4\x55\x7a\x59\x1e\x04\x08\ -\x3d\xae\x81\xe0\x68\x68\x30\xfb\xa7\x13\x31\x08\xb0\x25\x69\x63\ -\xf8\x6f\x35\x23\x56\x49\xc5\x5a\x05\x9b\xa8\xdc\x72\xb7\x69\xf4\ -\x81\x05\x22\x71\xd9\xce\x2a\x8d\x27\xf3\x02\x71\x3c\xae\xf6\xb9\ -\x20\x35\xbe\xe2\x51\x1e\x44\x74\xf6\x78\xc0\xbd\x5a\x7d\xe9\x62\ -\x80\xd0\xa9\xa7\xce\x5e\x2e\x43\xe8\xb3\xf2\x7a\x10\x98\xf6\xfa\ -\xb4\x85\x6b\xc0\x4b\xf2\x65\x10\xb8\x3e\x48\x8a\x82\xaa\x77\x97\ -\xf9\x17\x99\x80\x68\xba\x05\x0d\xdd\x4c\xb0\xbf\xd4\x2e\x11\xee\ -\xdb\x7d\xe3\x98\x15\xb8\x06\x80\x95\x07\x66\xc6\xf3\x88\x06\x06\ -\x4b\x05\xda\x6d\x3b\x98\xa7\x91\xeb\x9f\x1d\x07\xf9\xc2\x2d\x3b\ -\xae\x1d\xc5\xc1\x48\xa3\x13\x4e\x0b\xe1\x8b\x5c\x54\x25\x05\x0b\ -\x00\xb9\x2f\x18\xc0\x76\x23\x41\x44\xf2\xbe\x70\xfb\xb7\x46\x01\ -\x1d\xf5\x86\x21\x9e\x32\x10\x18\xbe\x16\xb8\x00\x8c\xa5\x82\x77\ -\xf3\x06\x29\x55\x86\x22\x0f\xd4\xd2\x76\x29\x82\xd6\xc0\xdd\xf4\ -\x1d\xf2\xfa\x69\xd6\x4d\xac\x42\x27\xf0\x4f\x1f\xfb\x62\x21\x6f\ -\x02\x1e\x22\x6b\xe7\x22\x14\x0e\x08\xb6\x54\xf0\x9f\xe3\x03\x16\ -\x4b\xca\x50\x1e\x14\x67\x20\xd2\x13\x9b\xea\x15\x89\xb9\x28\xf3\ -\x8c\xae\xeb\x2f\x20\x4d\x9f\x0e\x1f\x36\x16\xaf\x72\xfb\x05\x7a\ -\xac\xb5\xe4\x50\x7e\x94\x26\x04\xfa\x3a\x62\xfe\x0a\x7f\x19\x28\ -\x6a\x8a\x4d\x85\x3e\x23\xf9\xcd\x74\xac\xe0\x26\x0b\xe0\x2c\x03\ -\x45\x89\x4c\x07\x47\xa6\x07\x70\x15\x70\x36\x1e\x2f\x0f\x64\xfb\ -\xa4\x05\x75\x2e\x8e\xa1\x2e\xbc\x66\x97\x94\x91\xbc\x83\xc9\xec\ -\xa6\x20\x6c\xc0\x15\xee\xf7\xef\x1a\x37\x61\x13\xc0\x99\x63\xe3\ -\x1a\xa9\x84\x52\x27\x88\x72\x1f\xa6\x27\x19\x50\x8d\x22\x2c\xf4\ -\x17\xe1\x11\xe1\xc8\x91\xf1\xd9\x0a\xb7\x5c\x95\xe2\xf2\x0a\xd0\ -\xe8\xca\x9c\x9b\xf4\xfb\xc7\x15\x09\xb0\xba\xf1\xd1\xa4\xed\x1a\ -\x61\xed\x25\x3d\x5d\xc5\xc7\xda\x4c\x37\x4c\x49\x5f\xf1\xe1\xea\ -\x8f\x58\x75\x0c\x5f\x02\x84\x74\x11\x0e\x93\xc2\x65\x8c\xde\xef\ -\x82\x30\x86\x5b\x1b\x9e\xc8\x6d\x3a\x75\x72\x4b\xd0\x92\xb0\xe0\ -\x85\x74\x28\x3c\xe4\x36\x61\xc1\xaa\x46\x5b\xe4\xb8\x44\x11\x86\ -\x27\xa2\x62\xc8\xf9\xdb\x1c\x2a\x83\xed\x19\x21\x31\x11\x36\xd1\ -\xb3\xe4\xfd\xcb\x91\xb8\x53\x1c\x1d\x27\x8f\x27\x09\x9a\xe8\xa3\ -\x69\xb0\x04\x2d\x54\xe6\x1e\x32\x1d\x8c\xca\x05\x40\x0b\x30\xb1\ -\xf1\xfe\x36\x68\x3e\x30\x1d\xa8\x9b\x1e\x07\xf2\x9e\x4a\x62\xf2\ -\xea\x27\x00\x3e\x11\x0f\x62\x79\x32\x65\x7f\xf4\x33\x77\xcd\x16\ -\x84\xf6\x76\xa5\xeb\x0d\xf2\x2e\xf7\xf2\x7b\x5f\x0e\x52\xdc\x30\ -\xf1\x3c\x10\x0b\xa6\xb6\xe2\x8c\x23\x1e\x4b\xf5\x06\x08\x19\x4a\ -\x36\x77\xa0\x17\xe2\x2c\x9e\xb8\x7f\x2c\xea\x0b\x4d\x0c\x1f\x71\ -\x30\xb4\x08\x8a\x31\x88\x9a\x27\xa9\x8d\xb2\xa3\x9c\x44\x06\xda\ -\x03\xe7\x14\xc4\xe3\xdb\xcb\xce\x25\xa1\xe0\x03\xee\xf8\xcd\xcc\ -\x02\xa0\x2a\xdb\xec\x0f\x99\x81\xbe\x03\x30\x27\x1b\x00\x95\xe0\ -\xb8\x0e\x63\xbb\x18\x84\x6c\xd0\xba\xb8\xaf\x69\x77\x01\x9b\x76\ -\xf8\x01\xc8\xcc\x60\x2d\xf6\xa3\x24\xf8\x49\x1d\x3f\x2c\x1c\xc1\ -\xd9\x24\x88\x9a\x4c\x13\x43\xaa\x13\x40\x44\xd8\x45\x1f\x9c\x7f\ -\xd6\x15\xe4\xd5\x40\x77\x00\x98\x2d\x6d\x0b\x88\x1b\xb0\x57\x99\ -\xbc\xb7\xe4\xcd\x6b\x7e\x43\x6e\x76\x04\xa9\x36\x43\x51\x79\xdd\ -\xc1\x2b\x1d\x40\x31\xa9\xa4\x81\x7a\xb9\x6c\x88\xe0\xa6\xf7\xa1\ -\x3c\x86\x00\x3e\xf0\x23\xa9\xfe\x73\x71\xcf\x98\x1d\x08\xbb\x5b\ -\xbc\x8e\x05\x74\x00\x3f\xc9\xf7\x63\x8d\x1d\x4a\x3b\x5e\x0c\x46\ -\x2a\x65\x35\x37\x8d\xae\x1c\xe2\xda\x0c\x3c\x2c\x29\x89\x45\xb8\ -\x37\xb4\x8f\x15\x0f\xe7\x37\x44\x69\x40\xca\x82\x38\x69\xb1\x11\ -\x1e\xf1\xc0\xaf\xc2\x0a\xfe\x74\xe3\x2e\xf3\x40\xbf\x77\x1d\x5f\ -\xeb\x74\x68\xe3\xd1\x9f\x95\xd1\x3f\xbc\xb7\x78\xe9\x22\xed\x53\ -\xbc\x89\xbf\xa3\x96\xab\xf6\x19\x5e\x9e\x78\x98\x87\x6e\xea\x13\ -\x6f\xcf\x2a\xf8\x31\x9f\x3d\x41\x11\x0f\x14\xed\x45\xe7\x00\x69\ -\xde\xd5\x54\x7f\x66\x06\xba\x0e\x21\x6e\x79\xf0\x73\xbf\xba\x18\ -\xb2\x3a\x89\xa2\x90\x2d\x81\xc3\x01\xb2\xd3\xe2\x00\x92\x7d\x89\ -\x97\x9a\x93\xa1\x05\xde\xc6\x6a\x6a\x59\xce\x32\xe2\x2f\x38\x80\ -\x39\xe0\x7d\xb0\x50\xde\xb2\xc1\xbc\x3e\xd8\x2a\x42\x1e\xf0\x27\ -\xfc\x33\x57\x15\xaa\x28\x2a\xf3\xeb\xd6\x57\x9c\x57\x9c\xf2\x38\ -\x63\x9c\x20\x77\x9c\xfb\xc4\x4a\x57\xa0\x33\x1d\x3c\x7e\x47\x02\ -\x3d\xc5\xa7\x10\x3e\xeb\x7a\x02\xbc\x61\xcf\x92\x4c\x3d\x92\x07\ -\x6e\x8b\xc1\x82\x58\x11\x26\x90\x12\x0b\xb5\x1a\x09\xdf\xde\xeb\ -\x0d\x39\x71\xa5\xe4\x0e\xde\xbd\x30\x3a\xd2\x04\xa2\x45\xaf\x27\ -\xa4\xc3\x62\x5f\x22\xdb\x43\xb7\xe0\xdf\xc3\x8e\x2e\x99\xa0\xde\ -\x55\xa6\xc2\xf2\xf2\x61\x1c\x81\x10\x54\xe2\x6f\xc6\x4f\x9c\x1f\ -\x38\x67\x78\x51\xde\x73\x6f\x17\x11\x5a\xae\x50\x8e\x41\xce\xff\ -\x00\x86\x13\x42\x9a\x00\x9a\x1c\xa0\x1a\xc5\x2c\x8d\xed\xfe\x91\ -\x36\xbc\x7b\xbf\x53\xef\x02\xd1\xa4\x3d\xa4\x9f\xf7\x8b\xdf\x9c\ -\x87\x8a\x21\x1b\xab\xd2\xa8\xae\x08\x26\xf1\x14\x92\xe5\xad\xaf\ -\x71\xe3\x0d\xac\x13\x75\x7b\x94\x1e\xd3\x8d\xd4\x02\xa1\x5f\xa5\ -\xb8\x58\xfc\x13\xa7\xad\x72\x87\x2e\x21\xb5\x85\xaa\xf5\xe7\xf1\ -\x81\x52\x70\x18\xfc\x8b\x4c\xe7\xaa\x4c\x03\xf5\xbc\xb1\x6e\x29\ -\xb3\x01\x5a\xdb\xb5\x32\x15\x7d\x9e\xe8\x7b\xe7\x87\xcb\x0b\xf0\ -\xa0\x44\xc8\x01\xa7\x84\x79\x38\xe3\x00\xd8\x8f\xc3\x82\x13\xc8\ -\xd1\x51\xf0\x87\xf9\xfa\x9f\x78\x85\x14\x8f\x0c\x86\xeb\xde\x1a\ -\xe6\xc9\xb5\x23\x42\xb5\x76\x80\x1e\x83\x19\x00\xd0\xf0\x77\x6e\ -\xbe\xd7\xd0\xe7\x19\x96\x26\x22\x1c\xa5\xc7\xed\x3c\x63\x1c\x16\ -\x09\x0d\xac\xbc\x64\x17\x1e\x5b\x58\x6b\x44\x54\x4d\xdc\x40\xbe\ -\xb3\x40\xbd\x02\xfe\x70\xce\x41\x4f\x18\x73\x80\x86\x1d\x04\xa9\ -\x4d\x03\x1f\x38\xd0\x56\x24\x41\xba\xdc\xd8\x9b\x7b\xc7\xf8\x19\ -\x72\x01\x4e\x5a\x77\x8d\x4a\x6a\x06\x7e\x8e\x5a\xc0\x36\xe4\x84\ -\x91\x18\x79\x97\x71\xc3\xa3\xe7\x1e\x0c\x0d\xc6\x79\xb4\x3f\x83\ -\x95\x9c\xa2\xb4\x6c\x61\xa5\x6d\xe3\x3a\xdc\x3e\xed\xc7\xfa\x3a\ -\xc7\x6b\x82\xd3\x5a\xfb\x12\x20\xf8\x73\x93\x89\x87\x46\x83\x5e\ -\xc4\x19\x11\xb4\x1f\x50\xa2\xab\x0f\x17\x13\x4b\x51\x39\x26\x90\ -\xff\x00\x18\x93\xb8\x01\xe1\xc2\x24\x9c\xc8\xd0\x05\xe0\x3d\x63\ -\x7a\xa1\xa6\x9f\x00\xa7\xeb\x1e\xfa\x40\x90\xf6\xae\x0f\x85\xc0\ -\xaf\xd2\xa1\x41\x7b\x75\xbe\x07\xcf\xd4\xfe\xc1\x7e\x90\x10\xe8\ -\x89\xec\x36\x9b\x56\x10\x30\xbf\x30\x83\x6c\xd8\xf3\x0e\xb8\x02\ -\x7b\xfa\x09\x6a\x40\x3a\x2e\x59\x3c\x70\xf6\x38\x85\x05\x24\x11\ -\x0f\x88\x17\xe7\x0b\x39\x01\x3f\x3c\x25\xe3\x80\x40\xce\x70\x46\ -\x8c\x61\xe7\x3e\x93\xff\x00\x98\xfb\xd5\xd0\x36\xc6\x99\x74\x9a\ -\xfe\xc6\x6b\x1d\x98\xa0\xe4\x67\x09\xe3\xe9\x37\x93\x26\x4c\x54\ -\x9d\x2a\x78\x95\x1b\x47\x8e\xbf\xa3\x9c\x99\x3e\xa6\x98\xd5\x48\ -\x07\x97\x07\xf8\x93\xa0\x78\x47\xb3\xed\x35\xec\xf1\x42\x19\x08\ -\x8e\xd1\x4f\xe3\x35\x8c\x6f\x35\x22\x56\x84\x0a\x6c\x78\x19\x4d\ -\xb8\xad\x0d\x31\x9e\x6c\x2b\xac\x97\x3c\x7c\x98\x89\x55\x2c\x56\ -\xc2\x1c\xe3\x25\xf0\x3a\x1d\x0d\x43\x44\x6c\x78\xad\x3a\xae\x4a\ -\xe1\x31\xe9\x2e\xbb\x99\x7d\x60\x5f\x24\x5b\x08\xd0\x4a\xac\x86\ -\x28\xe5\x2b\xf5\x00\x25\xd4\xd6\xf8\x37\xac\x72\x4a\x2c\x92\x06\ -\x10\x27\x90\xe2\x98\xcb\x19\x45\x56\x76\xbd\xe1\x96\xb7\x26\x09\ -\xa1\xce\x9d\x8d\x04\x6e\x34\x53\x69\x61\x50\x88\x03\x2a\x9c\x39\ -\xc7\xd1\xb2\x71\x40\xea\x1a\x88\xcd\x6d\x94\xc6\x96\x70\x47\xae\ -\xc8\xf6\x80\xba\x3c\x61\x8c\xe5\xc5\xb5\xb1\x26\x88\xf2\xd4\xb8\ -\x15\x58\x82\x31\x6a\x41\x36\x3e\x1f\x18\x2a\x26\x16\xa8\x3c\x80\ -\xb6\xc4\x29\x70\xb8\xdb\xf0\x0f\x07\xce\x37\x92\xe6\xd6\x32\x7d\ -\x0a\x2a\x28\x46\xf3\x95\x3f\xf0\x89\x13\x70\x9e\xd3\x49\xe0\xc2\ -\x30\x65\xe4\x41\x81\x3a\xd4\x3d\x2e\x3e\xae\xc7\x52\x34\xf3\x46\ -\xd4\xe3\x15\xaa\x11\x6a\x3b\xe5\x8c\x50\x3d\xe2\x38\x99\x92\x80\ -\xd0\x82\x0f\x67\xb9\x41\xce\x1a\x0e\x37\x02\xc6\x85\x2e\x62\x59\ -\x8c\x18\xc7\xb6\x6b\x07\x63\x00\xf3\x96\x63\xea\xc2\x3b\x17\x6d\ -\xb6\x50\x0f\x56\xc6\xd8\x05\x00\xb8\x47\x12\xf0\x81\x6e\x29\xc8\ -\x3e\x0a\x15\x51\x7a\x5a\x77\x32\xe3\xed\x07\x14\x09\x4e\x46\xef\ -\x64\x1c\xa1\xfe\x66\x16\x69\x06\x3b\x9d\x3f\xeb\xc7\xe0\x1a\x5c\ -\x8e\xb2\x41\xd1\xce\x32\x2f\x14\x6b\x52\xc9\x01\x5d\x8a\xba\x93\ -\x31\xa1\x91\x09\x46\xa1\xcd\x48\xed\xc6\xa6\x19\x0d\x9c\x75\xa5\ -\x85\x47\x65\x26\xf0\xa4\xac\xa6\xc0\xe9\x29\xb0\x96\x37\x99\x82\ -\xbd\x4a\x29\xc9\x85\x0b\x89\x57\x4b\x80\x62\x46\x0a\x5a\x44\x0f\ -\x3a\xd1\xe7\x00\xb8\x20\x70\xd7\x69\x21\xa8\xa7\xa9\x85\xaa\x49\ -\x64\xa5\xe2\x80\x6e\x4f\x72\x88\xf8\x5b\x10\x48\x7c\x39\x66\xf6\ -\xc5\xba\x12\xb8\x97\x08\x0d\xf2\x01\x56\x18\x94\x63\x40\xac\xed\ -\xa5\x9b\x56\xa6\x0c\xae\x19\x2e\xcd\x85\xdd\x34\xa6\xc0\xd0\x72\ -\x77\x28\x5e\x76\x9e\x0d\x55\xac\x79\x1a\xa9\x10\x01\xa0\x5d\x3c\ -\xb0\x9e\x72\x64\x9e\xd9\xdb\x0d\x9c\x2b\x92\x68\x23\x18\x44\xcb\ -\x42\x00\x02\xba\x0b\x2d\x6a\x03\xe9\xa9\x00\x84\x03\x95\x4e\x32\ -\x61\xea\x29\xcb\x29\xa5\x39\xae\x0a\x97\x0e\x51\x45\x58\x37\x76\ -\x1c\x65\xc4\xd8\xba\x58\x0b\x1a\x02\xeb\x73\x21\x25\xec\x02\xe1\ -\xcd\xfb\x70\x97\x24\x30\x01\x53\xba\x5e\x00\x91\x06\xb8\xb2\x0e\ -\x80\x8c\xde\xc4\x64\xa0\xcd\xcb\x30\xba\xbc\x12\x42\xd1\xee\x49\ -\xde\xe4\xb9\x10\x53\xdb\x47\x7e\x08\x2a\xd7\x0e\xb2\x08\xba\xf2\ -\x2a\x6e\x84\x37\x1d\xa9\x43\x0e\x8e\xc6\xe2\x84\x5a\x34\xc5\x97\ -\x2c\xd7\x0e\xc4\x30\x57\x25\x4d\xc6\x5d\x60\x22\x4f\x52\x9f\xaf\ -\x76\xb8\x38\x0f\x33\x0d\x1f\x89\x1b\x46\x15\xd9\x4a\x6f\xd7\xdd\ -\xcf\xf4\xe7\xf7\xcf\xff\xd9\ -\x00\x00\x03\x31\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x48\x00\x00\x00\x18\x08\x02\x00\x00\x00\xd6\x01\x2c\xe7\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\xc6\x49\x44\x41\x54\x58\x47\xed\x97\x3f\x4e\ -\x6a\x41\x14\x87\x2f\x6f\x01\x88\xb8\x83\x27\x25\x09\x8d\x46\x13\ -\x12\x12\x4d\x00\x4b\x3a\x12\x76\xa0\x4b\xc0\x15\xb8\x01\x94\x84\ -\x5e\x3a\x68\x90\x00\x25\x14\x2a\x0d\x54\x90\x18\xad\x2c\x35\x06\ -\x36\x80\x1f\xf7\x37\x8e\xf7\x5e\x88\xef\xc5\x50\x88\xe1\x2b\x86\ -\x73\xce\xcc\x9d\xf3\x67\xce\x4c\x42\x68\x36\x9b\x39\xbf\x91\x3f\ -\xe6\xf7\xd7\xb1\x49\x6c\xdd\xd8\x24\xb6\x6e\xfc\xf4\xc4\x6e\x6e\ -\x6e\x42\x1f\xc4\x62\xb1\x6a\xb5\x8a\xf1\xf5\xf5\xd5\x98\x42\xa1\ -\x68\x34\x7a\x7e\x7e\xae\xc5\x3e\x78\xee\x7f\x38\xbb\xbb\xbb\x83\ -\xc1\x00\xe1\xea\xea\x2a\x9b\xcd\xca\x78\x7a\x7a\x8a\x8a\xc0\xd4\ -\xd2\x2c\x82\x27\x76\x72\x72\x62\x4a\xe1\x42\x91\xa8\x99\x99\xfb\ -\x16\x76\x43\xa3\xbb\xf4\x7a\x3d\x2c\xfb\xfb\xfb\xd4\xde\xaa\x16\ -\xaf\xd3\xa7\xa7\x27\xc6\x44\x22\xc1\xca\xe1\x70\x78\x7c\x7c\x2c\ -\x7b\xbb\xdd\x4e\xa7\xd3\x08\xb7\xb7\xb7\x64\x2b\xa3\x0f\x93\xe0\ -\x07\x2f\x2f\x2f\x18\x1b\x8d\x86\x64\x0a\xb3\xbd\xbd\xad\xa9\xef\ -\xc1\x26\x72\x8c\x60\x4c\xb3\x99\x2c\xf2\x22\x8a\xc5\xe2\xde\xde\ -\x9e\x64\xaf\xd3\xeb\xeb\xeb\x79\x94\x2e\xd8\x65\x7c\x7c\x7c\x34\ -\x26\xc7\xe1\x2b\xef\xce\x96\xe0\x89\x4d\x26\x13\xc6\x83\x83\x03\ -\xc6\x9d\x9d\x9d\x54\x2a\xe5\x9a\x7d\x50\x45\xce\x41\xc5\xb6\x9c\ -\x9d\x9d\x2d\x3d\xdb\xe7\xe7\x67\x95\x79\x34\x1a\xc9\x52\x2e\x97\ -\x23\x91\x08\x82\xbc\x08\x62\xcd\x64\x32\x92\x0b\x85\xc2\xdb\xdb\ -\x1b\xe7\x83\x5c\xaf\xd7\xd5\x72\x2c\xb8\xbc\xbc\xd4\x01\x76\x3a\ -\x9d\x7c\x3e\x8f\x51\xc7\x80\x3a\xff\xcc\x4f\x30\xb1\xfb\xfb\x7b\ -\xca\x49\x4a\xc8\x04\x4a\xb8\xa5\x52\x49\x53\x96\xbf\x2e\xde\xdc\ -\x58\xd6\xef\xf7\xbd\x81\x5a\x68\x95\x78\x3c\xce\x9e\xd3\xe9\x14\ -\x95\x4f\x2a\x95\xca\xd1\xd1\x11\x37\x47\x5e\x04\xad\x95\x4c\x26\ -\x25\x53\x0b\x46\xb5\x1f\xf6\xc3\xc3\x43\xd4\xf1\x78\xcc\xb8\xb5\ -\xb5\xc5\x58\xab\xd5\xd8\x41\x2b\x29\x41\x38\x1c\x46\x0e\xe2\x9e\ -\xdb\x27\x1c\xb7\x99\x70\x1c\xfa\xc1\xdb\x2d\x01\x58\xa9\x36\xb0\ -\x82\x99\xf0\x43\x69\x29\x36\x89\x5d\x5c\x5c\xa0\xb2\xb8\xdb\xed\ -\x62\xb4\x7d\x05\x7a\x00\xb4\x03\x1e\xf1\x4b\x67\x22\x33\x2a\x12\ -\xc0\x85\x82\x61\x34\x26\xc7\xa1\x3a\xda\x76\x91\x60\x62\x2c\xd5\ -\xf7\xb8\xc1\x3d\x01\xc9\xbe\x14\x82\x23\x88\x2f\xb2\x02\x66\x19\ -\x09\x91\x08\x48\x40\x1b\xf2\x15\x97\xc7\x9d\x9f\x43\xb3\x99\x48\ -\xbf\x8c\xf5\xff\x61\x07\x5f\x62\xc4\xc7\xd6\x14\x58\x2a\xa5\x45\ -\x95\xbc\x94\x7f\x26\x46\x26\xba\x0c\x78\x22\x25\x60\x73\xf0\x7a\ -\x01\xd6\x68\xd9\x0a\xf1\xdd\xb1\xbb\xbb\x3b\x0a\xc6\xfd\x91\xda\ -\x6c\x36\x89\x5b\xf2\x22\xba\x57\x0f\x0f\x0f\xbc\xda\x8b\x6f\x89\ -\x68\xb5\x5a\xba\x0c\x5c\x33\x64\x5e\x11\x36\xe7\x1a\xb3\xad\xf5\ -\x02\x5c\xa4\x5c\x2e\x67\x94\x55\x61\x12\x74\xa1\x61\x6c\xe5\xf4\ -\xce\xaa\xd7\x17\x09\xdc\xab\x80\x6a\xc1\xa8\xc6\xe6\xf0\x29\x99\ -\x16\x70\x6e\xea\x4f\xa1\x3b\xc3\x02\xa3\xaf\x88\xcf\xc4\x68\x1b\ -\xef\xf9\xe0\x5b\xef\xec\x22\x74\xd1\x62\xc2\xe4\xa6\x1c\x2c\xf3\ -\x46\x77\x31\xba\x8b\x35\xda\x8b\x24\x15\xa4\xae\x8a\xcd\x3f\xe8\ -\x75\x63\x93\xd8\xba\xb1\x49\x6c\xbd\x70\x9c\x77\x69\xcd\x78\xc7\ -\x7f\xf6\xa6\x43\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\ -' - -qt_resource_name = b'\ -\x00\x09\ -\x0a\x6c\x78\x43\ -\x00\x72\ -\x00\x65\x00\x73\x00\x6f\x00\x75\x00\x72\x00\x63\x00\x65\x00\x73\ -\x00\x0a\ -\x0b\x3e\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x41\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x39\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x44\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x11\ -\x0e\xfd\xfe\xa7\ -\x00\x73\ -\x00\x65\x00\x63\x00\x6f\x00\x6e\x00\x64\x00\x5f\x00\x64\x00\x61\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\ -\x00\x0a\ -\x0b\x37\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x46\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x10\ -\x02\x88\x45\x47\ -\x00\x66\ -\x00\x69\x00\x72\x00\x73\x00\x74\x00\x5f\x00\x64\x00\x61\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0e\ -\x03\x3a\x8d\x87\ -\x00\x62\ -\x00\x6f\x00\x74\x00\x68\x00\x5f\x00\x6c\x00\x6f\x00\x67\x00\x6f\x00\x73\x00\x2e\x00\x6a\x00\x70\x00\x67\ -\x00\x18\ -\x03\x13\x9b\xc7\ -\x00\x55\ -\x00\x44\x00\x50\x00\x72\x00\x69\x00\x6d\x00\x61\x00\x72\x00\x79\x00\x4c\x00\x6f\x00\x67\x00\x6f\x00\x32\x00\x39\x00\x34\x00\x35\ -\x00\x77\x00\x65\x00\x62\x00\x2e\x00\x6a\x00\x70\x00\x67\ -\x00\x0a\ -\x0b\x3c\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x43\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x3a\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x45\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x05\x96\xc3\xa7\ -\x00\x75\ -\x00\x73\x00\x5f\x00\x6e\x00\x73\x00\x66\x00\x2e\x00\x6a\x00\x70\x00\x67\ -\x00\x0a\ -\x0b\x3b\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x42\x00\x2e\x00\x70\x00\x6e\x00\x67\ -' - -qt_resource_struct_v1 = b'\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00\x03\ -\x00\x00\x00\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x11\x37\ -\x00\x00\x00\xd6\x00\x00\x00\x00\x00\x01\x00\x00\xc4\x3a\ -\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x3a\ -\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x01\x48\xcc\ -\x00\x00\x00\x74\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xdc\ -\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x02\xdb\ -\x00\x00\x01\x26\x00\x00\x00\x00\x00\x01\x00\x01\x44\x06\ -\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x01\xa6\x08\ -\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x01\x41\x84\ -\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x05\x96\ -' - -qt_resource_struct_v2 = b'\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00\x03\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x11\x37\ -\x00\x00\x01\x84\x35\xad\xa6\xc2\ -\x00\x00\x00\xd6\x00\x00\x00\x00\x00\x01\x00\x00\xc4\x3a\ -\x00\x00\x01\x84\x39\x1f\xb6\xa5\ -\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x3a\ -\x00\x00\x01\x84\x39\x42\x94\x8d\ -\x00\x00\x01\x40\x00\x00\x00\x00\x00\x01\x00\x01\x48\xcc\ -\x00\x00\x01\x84\x39\x2b\xcd\x2b\ -\x00\x00\x00\x74\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xdc\ -\x00\x00\x01\x84\x35\xa2\x0c\xbc\ -\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x02\xdb\ -\x00\x00\x01\x84\x35\xa1\x87\x1b\ -\x00\x00\x01\x26\x00\x00\x00\x00\x00\x01\x00\x01\x44\x06\ -\x00\x00\x01\x84\x35\xa1\xc0\x5d\ -\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x01\xa6\x08\ -\x00\x00\x01\x84\x35\xa0\xfc\x02\ -\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x01\x41\x84\ -\x00\x00\x01\x84\x35\xa1\x3f\xd3\ -\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x84\x35\xa0\xb2\x82\ -\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x05\x96\ -\x00\x00\x01\x84\x35\xae\x2b\x19\ -' - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - - -def qInitResources(): # noqa: N802, D103 - QtCore.qRegisterResourceData( - rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data - ) - - -def qCleanupResources(): # noqa: N802, D103 - QtCore.qUnregisterResourceData( - rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data - ) - - -qInitResources() diff --git a/modules/systemPerformance/REWET/REWET/GUI/Restoration_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Restoration_Tab_Designer.py deleted file mode 100644 index b4bae11b5..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Restoration_Tab_Designer.py +++ /dev/null @@ -1,217 +0,0 @@ -"""Created on Wed Nov 2 00:24:43 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os - -from PyQt5 import QtGui, QtWidgets - -from .Node_Damage_Discovery_Designer import Node_Damage_Discovery_Designer -from .Pipe_Damage_Discovery_Designer import Pipe_Damage_Discovery_Designer -from .Pump_Damage_Discovery_Designer import Pump_Damage_Discovery_Designer -from .Tank_Damage_Discovery_Designer import Tank_Damage_Discovery_Designer - - -class Restoration_Tab_Designer: # noqa: D101 - def __init__(self): - """These are variables that are shared between ui and settings.""" # noqa: D401 - self.setRestorationSettings(self.settings) - - """ - Reassignment of shared variables. - """ - self.current_policy_directory = os.getcwd() # noqa: PTH109 - - """ - ui value assignments. - """ - self.setRestorationUI() - - """ - Field Validators. - """ - self.minimum_job_time_line.setValidator(QtGui.QIntValidator(0.0, 2147483647)) - - """ - Signals connection. - """ - self.policy_browse_button.clicked.connect(self.browsePolicyDefinitionFile) - self.pipe_damage_discovery_button.clicked.connect( - self.pipeDamageDiscoveryByButton - ) - self.node_damage_discovery_button.clicked.connect( - self.nodeDamageDiscoveryByButton - ) - self.pump_damage_discovery_button.clicked.connect( - self.pumpDamageDiscoveryByButton - ) - self.tank_damage_discovery_button.clicked.connect( - self.tankDamageDiscoveryByButton - ) - - def getRestorationSettings(self): # noqa: N802, D102 - if self.restoration_on_radio.isChecked(): - self.restoration_on = True - elif self.restoration_off_radio.isChecked(): - self.restoration_on = False - else: - raise ValueError( # noqa: TRY003 - 'None of Restoration-on/off buttons are checked which is an error.' # noqa: EM101 - ) - - if self.script_txt_radio.isChecked(): - self.restoraion_policy_type = 'script' - elif self.script_rrp_radio.isChecked(): - self.restoraion_policy_type = 'binary' - else: - raise ValueError( # noqa: TRY003 - 'None of File-Type buttons are checked which is an error.' # noqa: EM101 - ) - - self.minimum_job_time = int(float(self.minimum_job_time_line.text())) - - if self.restoraion_policy_addr == '': - self.errorMSG('REWET', 'Policy Definition file is needed.') - return False - - self.settings.process['Restoration_on'] = self.restoration_on - self.settings.scenario['Restoraion_policy_type'] = ( - self.restoraion_policy_type - ) - self.settings.scenario['Restortion_config_file'] = ( - self.restoraion_policy_addr - ) - self.settings.process['minimum_job_time'] = self.minimum_job_time - self.settings.scenario['pipe_damage_discovery_model'] = ( - self.pipe_damage_discovery_model - ) - self.settings.scenario['node_damage_discovery_model'] = ( - self.node_damage_discovery_model - ) - self.settings.scenario['pump_damage_discovery_model'] = ( - self.pump_damage_discovery_model - ) - self.settings.scenario['tank_damage_discovery_model'] = ( - self.tank_damage_discovery_model - ) - self.settings.scenario['crew_out_of_zone_travel'] = self.out_of_zone_allowed - - return True - - def setRestorationUI(self): # noqa: N802, D102 - if self.restoration_on == True: # noqa: E712 - self.restoration_on_radio.setChecked(True) - elif self.restoration_on == False: # noqa: E712 - self.restoration_off_radio.setChecked(True) - else: - raise ValueError( - 'Unknown restoration-on status: ' + repr(self.restoration_on) - ) - - self.script_rrp_radio.setEnabled(False) - self.policy_designer.setEnabled(False) - self.policy_definition_addr_line.setText(self.restoraion_policy_addr) - - if self.restoraion_policy_type == 'script': - self.script_txt_radio.setChecked(True) - elif self.restoraion_policy_type == 'binary': - self.script_rrp_radio.setChecked(True) - else: - raise ValueError( - 'Uknown policy type: ' + repr(self.restoraion_policy_type) - ) - - self.minimum_job_time_line.setText(str(self.minimum_job_time)) - - if self.out_of_zone_allowed == True: # noqa: E712 - self.out_of_zone_travel_yes.setChecked(True) - elif self.out_of_zone_allowed == False: # noqa: E712 - self.out_of_zone_travel_no.setChecked(True) - else: - raise ValueError( - 'Unknown out-of-zone travel value: ' - + repr(self.out_of_zone_travel_no) - ) - - def setRestorationSettings(self, settings): # noqa: N802, D102 - self.restoration_on = settings.process['Restoration_on'] - self.restoraion_policy_type = settings.scenario['Restoraion_policy_type'] - self.restoraion_policy_addr = settings.scenario['Restortion_config_file'] - self.minimum_job_time = settings.process['minimum_job_time'] - self.pipe_damage_discovery_model = settings.scenario[ - 'pipe_damage_discovery_model' - ] - self.node_damage_discovery_model = settings.scenario[ - 'node_damage_discovery_model' - ] - self.pump_damage_discovery_model = settings.scenario[ - 'pump_damage_discovery_model' - ] - self.tank_damage_discovery_model = settings.scenario[ - 'tank_damage_discovery_model' - ] - self.out_of_zone_allowed = settings.scenario['crew_out_of_zone_travel'] - - def browsePolicyDefinitionFile(self): # noqa: N802, D102 - if self.script_txt_radio.isChecked(): - file_type = 'scenrario text file (*.txt)' - elif self.script_rrp_radio.isChecked(): - file_type = 'scenrario binary (*.rrp)' - - file = QtWidgets.QFileDialog.getOpenFileName( - self.asli_MainWindow, - 'Open file', - self.current_policy_directory, - file_type, - ) - if file[0] == '': - return - split_addr = os.path.split(file[0]) - self.current_policy_directory = split_addr[0] - self.restoraion_policy_addr = file[0] - self.policy_definition_addr_line.setText(file[0]) - - def pipeDamageDiscoveryByButton(self): # noqa: N802, D102 - pipe_damage_discovery_designer = Pipe_Damage_Discovery_Designer( - self.pipe_damage_discovery_model - ) - return_value = pipe_damage_discovery_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.pipe_damage_discovery_model = ( - pipe_damage_discovery_designer.damage_discovery_model - ) - - def nodeDamageDiscoveryByButton(self): # noqa: N802, D102 - node_damage_discovery_designer = Node_Damage_Discovery_Designer( - self.node_damage_discovery_model - ) - return_value = node_damage_discovery_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.node_damage_discovery_model = ( - node_damage_discovery_designer.damage_discovery_model - ) - - def pumpDamageDiscoveryByButton(self): # noqa: N802, D102 - pump_damage_discovery_designer = Pump_Damage_Discovery_Designer( - self.pump_damage_discovery_model - ) - return_value = pump_damage_discovery_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.pump_damage_discovery_model = ( - pump_damage_discovery_designer.damage_discovery_model - ) - - def tankDamageDiscoveryByButton(self): # noqa: N802, D102 - tank_damage_discovery_designer = Tank_Damage_Discovery_Designer( - self.tank_damage_discovery_model - ) - return_value = tank_damage_discovery_designer._window.exec_() # noqa: SLF001 - - if return_value == 1: - self.tank_damage_discovery_model = ( - tank_damage_discovery_designer.damage_discovery_model - ) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Result_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Result_Designer.py deleted file mode 100644 index ef734eb67..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Result_Designer.py +++ /dev/null @@ -1,502 +0,0 @@ -"""Created on Thu Nov 10 18:29:50 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import pandas as pd -from PyQt5 import QtGui, QtWidgets - -single_scenario_curve_options = ['', 'Quantity', 'Delivery', 'SSI'] -multi_scenario_curve_options = ['', 'Quantity Exceedance', 'Delivery Exceedance'] -curve_settings = { - 'Quantity Exceedance': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'Population', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - { - 'Label': 'Percentage', - 'Type': 'Custom_Combo', - 'Default': 'Yes', - 'Content': ['Yes', 'No'], - }, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '0.75'}, - { - 'Label': 'Group method', - 'Type': 'Custom_Combo', - 'Default': 'Mean', - 'Content': ['Mean', 'Min', 'Max'], - }, - {'Label': 'Daily bin', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'Min time', 'Type': 'Int Line', 'Default': '0'}, - {'Label': 'Max time', 'Type': 'Int Line', 'Default': '9999999999'}, - ], - 'Delivery Exceedance': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'Population', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - { - 'Label': 'Percentage', - 'Type': 'Custom_Combo', - 'Default': 'Yes', - 'Content': ['Yes', 'No'], - }, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '0.75'}, - { - 'Label': 'Group method', - 'Type': 'Custom_Combo', - 'Default': 'Mean', - 'Content': ['Mean', 'Min', 'Max'], - }, - {'Label': 'Daily bin', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'Min time', 'Type': 'Int Line', 'Default': '0'}, - {'Label': 'Max time', 'Type': 'Int Line', 'Default': '9999999999'}, - ], - 'Quantity': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'Population', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'Percentage', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '0.75'}, - ], - 'Delivery': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'Population', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'Percentage', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'LDN leak', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - {'Label': 'leak Criteria', 'Type': 'Float Line', 'Default': '1.25'}, - ], - 'SSI': [ - {'Label': 'Time', 'Type': 'Time', 'Default': 'seconds'}, - {'Label': 'Population', 'Type': 'Yes-No_Combo', 'Default': 'No'}, - ], -} - - -class Time_Unit_Combo(QtWidgets.QComboBox): # noqa: D101 - def __init__(self): - super().__init__() - time_units = ['second', 'hour', 'day'] - - self.addItems(time_units) - - def changeCurveTimeUnit(self, raw_time_curve): # noqa: N802, D102 - res = {} - if type(raw_time_curve) == pd.core.series.Series: # noqa: E721 - time_justified_curve = raw_time_curve.copy() - res = self.applyUnitToSeries(time_justified_curve) - else: - for k in raw_time_curve: - time_justified_curve = raw_time_curve[k].copy() - res[k] = self.applyUnitToSeries(time_justified_curve) - return res - - def applyUnitToSeries(self, data): # noqa: N802, D102 - time_unit = self.currentText() - if time_unit == 'second': - pass - elif time_unit == 'hour': - data.index = data.index / 3600 - elif time_unit == 'day': - data.index = data.index / 3600 / 24 - else: - raise ValueError('Unknown unit time: ' + repr(time_unit)) - - return data - - -class Yes_No_Combo(QtWidgets.QComboBox): # noqa: D101 - def __init__(self): - super().__init__() - self.addItems(['No', 'Yes']) - - -class Result_Designer: # noqa: D101 - def __init__(self): - self.current_raw_curve = None - self.current_curve = None - self.curve_settings_widgets = {} - self.main_tab.currentChanged.connect(self.tabChanged) - self.all_scenarios_checkbox.stateChanged.connect( - self.curveAllScenarioCheckboxChanged - ) - self.save_curve_button.clicked.connect(self.saveCurrentCurveByButton) - self.scenario_combo.currentTextChanged.connect(self.resultScenarioChanged) - self.curve_type_combo.currentTextChanged.connect(self.curveTypeChanegd) - - self.initalize_result() - - def initalize_result(self): # noqa: D102 - self.setCurveAllScenarios(True) - self.all_scenarios_checkbox.setChecked(True) - self.scenario_combo.clear() - self.scenario_combo.addItems(self.result_scenarios) - # self.current_curve_data = None - - def curveAllScenarioCheckboxChanged(self, state): # noqa: N802, D102 - if state == 0: - self.setCurveAllScenarios(False) - elif state == 2: # noqa: PLR2004 - self.setCurveAllScenarios(True) - - def clearCurvePlot(self): # noqa: N802, D102 - self.mpl_curve.canvas.ax.cla() - - def plot_data(self): # noqa: D102 - x = range(10) - y = range(0, 20, 2) - self.mpl_curve.canvas.ax.plot(x, y) - self.mpl_curve.canvas.draw() - # self.mpl_curve.canvas.ax.set_ylabel("y_label") - # self.mpl_curve.canvas.ax.set_xlabel("x_label") - # self.mpl_curve.canvas.fig.tight_layout() - - def plotCurve(self, y_label=None, x_label=None): # noqa: N802, D102 - if y_label == None: # noqa: E711 - y_label = self.mpl_curve.canvas.ax.get_ylabel() - if x_label == None: # noqa: E711 - x_label = self.mpl_curve.canvas.ax.get_xlabel() - - self.mpl_curve.canvas.ax.clear() - data = self.current_curve - - if type(data) == pd.core.series.Series: # noqa: E721 - self.mpl_curve.canvas.ax.plot( - self.current_curve.index, self.current_curve.to_list() - ) - else: - for k in data: - self.mpl_curve.canvas.ax.plot(data[k].index, data[k].to_list()) - - self.mpl_curve.canvas.ax.set_ylabel(y_label) - self.mpl_curve.canvas.ax.set_xlabel(x_label) - self.mpl_curve.canvas.draw() - self.mpl_curve.canvas.fig.tight_layout() - - def setCurveAllScenarios(self, flag): # noqa: N802, D102 - if flag == True: # noqa: E712 - self.all_scenarios_checkbox.setChecked(True) - self.scenario_combo.setEnabled(False) - self.curve_type_combo.clear() - self.curve_type_combo.addItems(multi_scenario_curve_options) - self.clearCurvePlot() - elif flag == False: # noqa: E712 - self.all_scenarios_checkbox.setChecked(False) - self.scenario_combo.setEnabled(True) - self.curve_type_combo.clear() - self.curve_type_combo.addItems(single_scenario_curve_options) - self.clearCurvePlot() - else: - raise ValueError('Unknown flag: ' + repr(flag)) - - def resultScenarioChanged(self, text): # noqa: N802, D102 - self.result_current_scenario = text # self.scenario_combo.getText() - # self.current_curve_data = None - - def curveTypeChanegd(self, text): # noqa: N802, D102 - if self.project_result == None: # noqa: E711 - return - self.current_curve_type = text - self.setCurveSettingBox(text) - self.calculateCurrentCurve() - - def calculateCurrentCurve(self): # noqa: C901, N802, D102 - curve_type = self.current_curve_type - if curve_type == 'Quantity Exceedance': - iPopulation = self.curve_settings_widgets['Population'].currentText() # noqa: N806 - iRatio = self.curve_settings_widgets['Percentage'].currentText() # noqa: N806 - iConsider_leak = self.curve_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.curve_settings_widgets['leak Criteria'].text() - group_method = self.curve_settings_widgets['Group method'].currentText() - daily_bin = self.curve_settings_widgets['Daily bin'].currentText() - min_time = self.curve_settings_widgets['Min time'].text() - max_time = self.curve_settings_widgets['Max time'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - if iRatio == 'Yes': - iRatio = True # noqa: N806 - else: - iRatio = False # noqa: N806 - - if daily_bin == 'Yes': - daily_bin = True - else: - daily_bin = False - - group_method = group_method.lower() - min_time = int(float(min_time)) - max_time = int(float(max_time)) - - self.current_raw_curve = self.project_result.getQuantityExceedanceCurve( - iPopulation=iPopulation, - ratio=iRatio, - consider_leak=iConsider_leak, - leak_ratio=leak_ratio, - result_type=group_method, - daily=daily_bin, - min_time=min_time, - max_time=max_time, - ) - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve('Exceedance Probability', 'Time') - - elif curve_type == 'Delivery Exceedance': - iPopulation = self.curve_settings_widgets['Population'].currentText() # noqa: N806 - iRatio = self.curve_settings_widgets['Percentage'].currentText() # noqa: N806 - iConsider_leak = self.curve_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.curve_settings_widgets['leak Criteria'].text() - group_method = self.curve_settings_widgets['Group method'].currentText() - daily_bin = self.curve_settings_widgets['Daily bin'].currentText() - min_time = self.curve_settings_widgets['Min time'].text() - max_time = self.curve_settings_widgets['Max time'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - if iRatio == 'Yes': - iRatio = True # noqa: N806 - else: - iRatio = False # noqa: N806 - - if daily_bin == 'Yes': - daily_bin = True - else: - daily_bin = False - - group_method = group_method.lower() - min_time = int(float(min_time)) - max_time = int(float(max_time)) - - self.current_raw_curve = self.project_result.getDeliveryExceedanceCurve( - iPopulation=iPopulation, - ratio=iRatio, - consider_leak=iConsider_leak, - leak_ratio=leak_ratio, - result_type=group_method, - daily=daily_bin, - min_time=min_time, - max_time=max_time, - ) - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve('Exceedance Probability', 'Time') - elif curve_type == 'Quantity': - iPopulation = self.curve_settings_widgets['Population'].currentText() # noqa: N806 - # iPopulation = self.curve_population_settings_combo.currentText() - iRatio = self.curve_settings_widgets['Percentage'].currentText() # noqa: N806 - iConsider_leak = self.curve_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.curve_settings_widgets['leak Criteria'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - if iRatio == 'Yes': - iRatio = True # noqa: N806 - else: - iRatio = False # noqa: N806 - - scn_name = self.scenario_combo.currentText() - self.current_raw_curve = self.project_result.getQNIndexPopulation_4( - scn_name, - iPopulation=iPopulation, - ratio=iRatio, - consider_leak=iConsider_leak, - leak_ratio=leak_ratio, - ) - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve('Quantity', 'Time') - - elif curve_type == 'Delivery': - # self.current_curve_data = (curve_type, pd.DataFrame()) - iPopulation = self.curve_settings_widgets['Population'].currentText() # noqa: N806 - # iPopulation = self.curve_population_settings_combo.currentText() - iRatio = self.curve_settings_widgets['Percentage'].currentText() # noqa: N806 - iConsider_leak = self.curve_settings_widgets['LDN leak'].currentText() # noqa: N806 - leak_ratio = self.curve_settings_widgets['leak Criteria'].text() - - if iConsider_leak == 'Yes': - iConsider_leak = True # noqa: N806 - else: - iConsider_leak = False # noqa: N806 - - if iRatio == 'Yes': - iRatio = True # noqa: N806 - else: - iRatio = False # noqa: N806 - - scn_name = self.scenario_combo.currentText() - self.current_raw_curve = self.project_result.getDLIndexPopulation_4( - scn_name, - iPopulation=iPopulation, - ratio=iRatio, - consider_leak=iConsider_leak, - leak_ratio=leak_ratio, - ) - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve('Delivery', 'Time') - - elif curve_type == 'SSI': - # self.current_curve_data = (curve_type, pd.DataFrame()) - iPopulation = self.curve_settings_widgets['Population'].currentText() # noqa: N806 - scn_name = self.scenario_combo.currentText() - self.current_raw_curve = ( - self.project_result.getSystemServiceabilityIndexCurve( - scn_name, iPopulation=iPopulation - ) - ) - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve('SSI', 'Time') - - def setCurveSettingBox(self, curve_type): # noqa: N802, D102 - for i in range(self.curve_settings_table.rowCount()): # noqa: B007 - self.curve_settings_table.removeRow(0) - - if curve_type in curve_settings: - self.populateCurveSettingsTable(curve_settings[curve_type]) - else: - pass - # raise ValueError("Unknown Curve type: "+repr(curve_type)) - - def populateCurveSettingsTable(self, settings_content): # noqa: C901, N802, D102 - self.curve_settings_widgets.clear() - vertical_header = [] - cell_type_list = [] - default_list = [] - content_list = [] - for row in settings_content: - for k in row: - if k == 'Label': - vertical_header.append(row[k]) - elif k == 'Type': - cell_type_list.append(row[k]) - elif k == 'Default': - default_list.append(row[k]) - - if 'Content' in row: - content_list.append(row['Content']) - else: - content_list.append(None) - - self.curve_settings_table.setColumnCount(1) - self.curve_settings_table.setRowCount(len(settings_content)) - self.curve_settings_table.setVerticalHeaderLabels(vertical_header) - - i = 0 - for cell_type in cell_type_list: - if cell_type == 'Time': - self.time_combo = Time_Unit_Combo() - self.curve_settings_table.setCellWidget(i, 0, self.time_combo) - self.time_combo.currentTextChanged.connect( - self.curveTimeSettingsChanged - ) - - elif cell_type == 'Yes-No_Combo': - current_widget = Yes_No_Combo() - self.curve_settings_table.setCellWidget(i, 0, current_widget) - current_widget.currentTextChanged.connect(self.curveSettingChanged) - - default_value = default_list[i] - current_widget.setCurrentText(default_value) - - self.curve_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Custom_Combo': - current_widget = QtWidgets.QComboBox() - contents = content_list[i] - current_widget.addItems(contents) - self.curve_settings_table.setCellWidget(i, 0, current_widget) - current_widget.currentTextChanged.connect(self.curveSettingChanged) - - default_value = default_list[i] - current_widget.setCurrentText(default_value) - - self.curve_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Float Line': - current_widget = QtWidgets.QLineEdit() - self.curve_settings_table.setCellWidget(i, 0, current_widget) - current_widget.editingFinished.connect(self.curveSettingChanged) - current_widget.setValidator( - QtGui.QDoubleValidator( - 0, - 1000000, - 20, - notation=QtGui.QDoubleValidator.StandardNotation, - ) - ) - - default_value = default_list[i] - current_widget.setText(default_value) - self.curve_settings_widgets[vertical_header[i]] = current_widget - - elif cell_type == 'Int Line': - current_widget = QtWidgets.QLineEdit() - self.curve_settings_table.setCellWidget(i, 0, current_widget) - current_widget.editingFinished.connect(self.curveSettingChanged) - current_widget.setValidator(QtGui.QIntValidator(0, 3600 * 24 * 1000)) - - default_value = default_list[i] - current_widget.setText(default_value) - self.curve_settings_widgets[vertical_header[i]] = current_widget - else: - raise ValueError(repr(cell_type)) - - i += 1 # noqa: SIM113 - # for label in settings_content: - - def curveTimeSettingsChanged(self, x): # noqa: ARG002, N802, D102 - self.current_curve = self.time_combo.changeCurveTimeUnit( - self.current_raw_curve - ) - self.plotCurve() - - def curveSettingChanged(self): # noqa: N802, D102 - if 'Population' in self.curve_settings_widgets: - new_population_setting = self.curve_settings_widgets[ - 'Population' - ].currentText() - if new_population_setting == 'Yes' and type( # noqa: E721 - self.project_result._population_data # noqa: SLF001 - ) == type(None): - self.errorMSG('Error', 'Population data is not loaded') - self.curve_settings_widgets['Population'].setCurrentText('No') - return - self.calculateCurrentCurve() - - def tabChanged(self, index): # noqa: N802, D102 - if index == 1: - self.initalize_result() - - def saveCurrentCurveByButton(self): # noqa: N802, D102 - # if self.current_curve_data == None: - if type(self.current_curve) == type(None): # noqa: E721 - self.errorMSG('REWET', 'No curve is ploted') - return - - file_addr = QtWidgets.QFileDialog.getSaveFileName( - self.asli_MainWindow, - 'Save File', - self.project_file_addr, - 'Excel Workbook (*.xlsx)', - ) - if file_addr[0] == '': - return - - # self.current_curve_data[1].to_excel(file_addr[0]) - self.current_curve.to_excel(file_addr[0]) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Run_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Run_Tab_Designer.py deleted file mode 100644 index f606975a9..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Run_Tab_Designer.py +++ /dev/null @@ -1,105 +0,0 @@ -"""Created on Wed Nov 2 14:40:45 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import subprocess -import threading - -from PyQt5.QtCore import QObject, pyqtSignal - - -class Custom_Object(QObject): # noqa: D101 - outSignal = pyqtSignal(bytes) # noqa: N815 - - -class Run_Tab_Designer: # noqa: D101 - def __init__(self): - self.run_button.clicked.connect(self.runREWET) - self.stop_button.clicked.connect(self.stopRun) - self.cobject = Custom_Object() - self.cobject.outSignal.connect(self.updateRunOuput) - self.rewet_sub_process = None - self.if_run_in_progress = False - - def runREWET(self): # noqa: N802, D102 - if self.if_run_in_progress == True: # noqa: E712 - return False - if_saved = self.saveProject() - - if if_saved == False: # noqa: E712 - return False - self.ouput_textedit.clear() - # start = Starter() - if self.project_file_addr == None: # noqa: E711 - self.errorMSG( - 'REWET', - 'File address is empty. Please report it as a bug to the developer.', - ) - self.if_run_in_progress = True - self.setAllTabsEnabled(False) - threading.Thread(target=self._RunREWETHelper, args=(), daemon=True).start() # noqa: RET503 - - def _RunREWETHelper(self): # noqa: N802 - self.rewet_sub_process = subprocess.Popen( # noqa: S603 - ['python', 'initial.py', self.project_file_addr], # noqa: S607 - stdout=subprocess.PIPE, - bufsize=0, - ) - - for line in iter(self.rewet_sub_process.stdout.readline, b''): - # sys.stdout.flush() - self.cobject.outSignal.emit(line) - self.rewet_sub_process.stdout.close() - - def setAllTabsEnabled(self, enabled): # noqa: N802, D102 - # self.ouput_textedit.setEnabled(enabled) - self.main_tab.setTabEnabled(1, enabled) - self.main_process1.setTabEnabled(0, enabled) - self.main_process1.setTabEnabled(1, enabled) - self.main_process1.setTabEnabled(2, enabled) - self.main_process1.setTabEnabled(3, enabled) - self.run_button.setEnabled(enabled) - # self.results_tabs_widget.setEnabled(enabled) - # self.stop_button.setEnabled(True) - - # @pyqtSlot(bytes) - def updateRunOuput(self, string): # noqa: N802, D102 - string = string.decode() - - if 'Time of Single run is' in string: - self.endSimulation() - elif 'Error' in string: - self.errorInSimulation() - - self.ouput_textedit.appendPlainText(string) - - # running code for the project - - def endSimulation(self): # noqa: N802, D102 - end_message = ( - '\n-------------------\nSIMULATION FINISHED\n-------------------\n' - ) - self.setAllTabsEnabled(True) - self.if_run_in_progress = False - self.ouput_textedit.appendPlainText(end_message) - - def errorInSimulation(self): # noqa: N802, D102 - end_message = '\n-------------\nERROR OCCURRED\n-------------\n' - self.setAllTabsEnabled(True) - self.if_run_in_progress = False - self.errorMSG( - 'REWET', - 'An error happened during the simulation. Please look at the log for further information.', - ) - self.ouput_textedit.appendPlainText(end_message) - - def stopRun(self): # noqa: N802, D102 - if self.if_run_in_progress == False: # noqa: E712 - return - if type(self.rewet_sub_process) != type(None): # noqa: E721 - self.rewet_sub_process.terminate() - termination_message = '\n-------------\nRUN CANCELLED\n-------------\n' - self.setAllTabsEnabled(True) - self.if_run_in_progress = False - self.ouput_textedit.appendPlainText(termination_message) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Designer.py deleted file mode 100644 index 2ee3f9090..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Designer.py +++ /dev/null @@ -1,27 +0,0 @@ -"""Created on Fri Oct 28 14:09:49 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from PyQt5 import QtGui, QtWidgets - -from .Scenario_Dialog_Window import Ui_Scenario_Dialog - - -class Scenario_Dialog_Designer(Ui_Scenario_Dialog): # noqa: D101 - def __init__(self): - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.last_probability = 1 - self.probability_line.setValidator( - QtGui.QDoubleValidator( - 0.0, 1, 3, notation=QtGui.QDoubleValidator.StandardNotation - ) - ) - self.probability_line.textChanged.connect(self.probabilityValidatorHelper) - - def probabilityValidatorHelper(self, text): # noqa: N802, D102 - if float(text) > 1: - self.probability_line.setText(self.last_probability) - else: - self.last_probability = text diff --git a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.py deleted file mode 100644 index 27dc08f30..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.py +++ /dev/null @@ -1,84 +0,0 @@ -# Form implementation generated from reading ui file 'Scenario_Dialog_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Scenario_Dialog: # noqa: D101 - def setupUi(self, Scenario_Dialog): # noqa: N802, N803, D102 - Scenario_Dialog.setObjectName('Scenario_Dialog') - Scenario_Dialog.resize(351, 241) - self.buttonBox = QtWidgets.QDialogButtonBox(Scenario_Dialog) - self.buttonBox.setGeometry(QtCore.QRect(260, 40, 81, 241)) - self.buttonBox.setOrientation(QtCore.Qt.Vertical) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.scenario_name_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.scenario_name_line.setGeometry(QtCore.QRect(110, 40, 113, 20)) - self.scenario_name_line.setObjectName('scenario_name_line') - self.pipe_damage_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.pipe_damage_line.setGeometry(QtCore.QRect(110, 70, 113, 20)) - self.pipe_damage_line.setObjectName('pipe_damage_line') - self.node_damage_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.node_damage_line.setGeometry(QtCore.QRect(110, 100, 113, 20)) - self.node_damage_line.setObjectName('node_damage_line') - self.pump_damage_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.pump_damage_line.setGeometry(QtCore.QRect(110, 130, 113, 20)) - self.pump_damage_line.setObjectName('pump_damage_line') - self.label = QtWidgets.QLabel(Scenario_Dialog) - self.label.setGeometry(QtCore.QRect(20, 40, 91, 16)) - self.label.setObjectName('label') - self.label_2 = QtWidgets.QLabel(Scenario_Dialog) - self.label_2.setGeometry(QtCore.QRect(20, 70, 71, 16)) - self.label_2.setObjectName('label_2') - self.label_3 = QtWidgets.QLabel(Scenario_Dialog) - self.label_3.setGeometry(QtCore.QRect(20, 100, 71, 16)) - self.label_3.setObjectName('label_3') - self.label_4 = QtWidgets.QLabel(Scenario_Dialog) - self.label_4.setGeometry(QtCore.QRect(20, 130, 71, 16)) - self.label_4.setObjectName('label_4') - self.label_5 = QtWidgets.QLabel(Scenario_Dialog) - self.label_5.setGeometry(QtCore.QRect(20, 160, 81, 16)) - self.label_5.setObjectName('label_5') - self.label_6 = QtWidgets.QLabel(Scenario_Dialog) - self.label_6.setGeometry(QtCore.QRect(20, 190, 61, 16)) - self.label_6.setObjectName('label_6') - self.tank_damage_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.tank_damage_line.setGeometry(QtCore.QRect(110, 160, 113, 20)) - self.tank_damage_line.setObjectName('tank_damage_line') - self.probability_line = QtWidgets.QLineEdit(Scenario_Dialog) - self.probability_line.setGeometry(QtCore.QRect(110, 190, 113, 20)) - self.probability_line.setObjectName('probability_line') - - self.retranslateUi(Scenario_Dialog) - self.buttonBox.accepted.connect(Scenario_Dialog.accept) - self.buttonBox.rejected.connect(Scenario_Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(Scenario_Dialog) - - def retranslateUi(self, Scenario_Dialog): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Scenario_Dialog.setWindowTitle(_translate('Scenario_Dialog', 'New Scenario')) - self.label.setText(_translate('Scenario_Dialog', 'Scenario Name')) - self.label_2.setText(_translate('Scenario_Dialog', 'Pipe Damage')) - self.label_3.setText(_translate('Scenario_Dialog', 'Nodal Damage')) - self.label_4.setText(_translate('Scenario_Dialog', 'Pump Damage')) - self.label_5.setText(_translate('Scenario_Dialog', 'Tank Damage')) - self.label_6.setText(_translate('Scenario_Dialog', 'Probability')) - self.probability_line.setText(_translate('Scenario_Dialog', '1')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Scenario_Dialog = QtWidgets.QDialog() - ui = Ui_Scenario_Dialog() - ui.setupUi(Scenario_Dialog) - Scenario_Dialog.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.ui deleted file mode 100644 index aca7c0c6f..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Scenario_Dialog_Window.ui +++ /dev/null @@ -1,209 +0,0 @@ - - - Scenario_Dialog - - - - 0 - 0 - 351 - 241 - - - - New Scenario - - - - - 260 - 40 - 81 - 241 - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 110 - 40 - 113 - 20 - - - - - - - 110 - 70 - 113 - 20 - - - - - - - 110 - 100 - 113 - 20 - - - - - - - 110 - 130 - 113 - 20 - - - - - - - 20 - 40 - 91 - 16 - - - - Scenario Name - - - - - - 20 - 70 - 71 - 16 - - - - Pipe Damage - - - - - - 20 - 100 - 71 - 16 - - - - Nodal Damage - - - - - - 20 - 130 - 71 - 16 - - - - Pump Damage - - - - - - 20 - 160 - 81 - 16 - - - - Tank Damage - - - - - - 20 - 190 - 61 - 16 - - - - Probability - - - - - - 110 - 160 - 113 - 20 - - - - - - - 110 - 190 - 113 - 20 - - - - 1 - - - - - - - buttonBox - accepted() - Scenario_Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Scenario_Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Simulation_Tab_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Simulation_Tab_Designer.py deleted file mode 100644 index 96a06d102..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Simulation_Tab_Designer.py +++ /dev/null @@ -1,159 +0,0 @@ -"""Created on Thu Oct 27 19:00:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os -import tempfile - -from PyQt5 import QtGui, QtWidgets - - -class Simulation_Tab_Designer: # noqa: D101 - def __init__(self): - """These are variables that are shared between ui and settings.""" # noqa: D401 - self.setSimulationSettings(self.settings) - - """ - Reassignment of shared variables. - """ - self.result_folder_addr = os.getcwd() # noqa: PTH109 - self.temp_folder_addr = tempfile.mkdtemp() - - """ - ui value assignments. - """ - self.setSimulationUI() - - """ - Field Validators. - """ - self.simulation_time_line.setValidator( - QtGui.QIntValidator(0, 10000 * 24 * 3600) - ) - self.simulation_time_step_line.setValidator( - QtGui.QIntValidator(0, 10000 * 24 * 3600) - ) - - """ - Signals connection. - """ - self.result_directory_browser_button.clicked.connect( - self.ResultFileBrowserClicked - ) - self.temp_browser_button.clicked.connect(self.tempFileBrowserClicked) - self.simulation_time_line.textChanged.connect( - self.SimulationTimeValidatorHelper - ) - self.simulation_time_step_line.textChanged.connect( - self.SimulationTimeValidatorHelper - ) - - def getSimulationSettings(self): # noqa: N802, D102 - if self.result_folder_addr == '': - self.errorMSG('REWET', 'Result folder must be provided') - return False - if self.temp_folder_addr == '': - self.errorMSG('REWET', 'Temp folder must be provided') - return False - - self.simulation_time = int(self.simulation_time_line.text()) - self.simulation_time_step = int(self.simulation_time_step_line.text()) - if self.single_radio.isChecked(): - self.number_of_damages = 'single' - elif self.multiple_radio.isChecked(): - self.number_of_damages = 'multiple' - else: - raise ValueError( # noqa: TRY003 - 'Borh of Run-Type Buttons are not selected which is an error.' # noqa: EM101 - ) - # self.result_folder_addr -- already set - # self.temp_folder_addr -- already set - - if self.save_time_step_yes_radio.isChecked(): - self.save_time_step = True - elif self.save_time_step_no_radio.isChecked(): - self.save_time_step = False - else: - raise ValueError( # noqa: TRY003 - 'Both of Time-Save Buttons are not selected which is an error.' # noqa: EM101 - ) - - self.settings.process['RUN_TIME'] = self.simulation_time - self.settings.process['simulation_time_step'] = self.simulation_time_step - self.settings.process['number_of_damages'] = self.number_of_damages - self.settings.process['result_directory'] = self.result_folder_addr - self.settings.process['temp_directory'] = self.temp_folder_addr - self.settings.process['save_time_step'] = self.save_time_step - - return True - - def setSimulationUI(self): # noqa: N802, D102 - self.simulation_time_line.setText(str(int(self.simulation_time))) - self.simulation_time_step_line.setText(str(int(self.simulation_time_step))) - self.result_folder_addr_line.setText(self.result_folder_addr) - self.temp_folder_addr_line.setText(self.temp_folder_addr) - - if self.number_of_damages == 'single': - self.single_radio.setChecked(True) - elif self.number_of_damages == 'multiple': - self.multiple_radio.setChecked(True) - else: - raise ValueError('Unknown runtype: ' + repr(self.number_of_damages)) - - if self.save_time_step == True: # noqa: E712 - self.save_time_step_yes_radio.setChecked(True) - elif self.save_time_step == False: # noqa: E712 - self.save_time_step_no_radio.setChecked(True) - else: - raise ValueError( - 'Unknown time save value: ' + repr(self.save_time_step_no_radio) - ) - - def setSimulationSettings(self, settings): # noqa: N802, D102 - self.simulation_time = settings.process['RUN_TIME'] - self.simulation_time_step = settings.process['simulation_time_step'] - self.number_of_damages = settings.process['number_of_damages'] - self.result_folder_addr = settings.process['result_directory'] - self.temp_folder_addr = settings.process['temp_directory'] - self.save_time_step = settings.process['save_time_step'] - - def ResultFileBrowserClicked(self): # noqa: N802, D102 - directory = QtWidgets.QFileDialog.getExistingDirectory( - self.asli_MainWindow, 'Select Directory' - ) - if directory == '': - return - self.result_folder_addr = directory - self.result_folder_addr_line.setText(self.result_folder_addr) - - def tempFileBrowserClicked(self): # noqa: N802, D102 - directory = QtWidgets.QFileDialog.getExistingDirectory( - self.asli_MainWindow, 'Select Directory' - ) - if directory == '': - return - self.temp_folder_addr = directory - self.temp_folder_addr_line.setText(self.temp_folder_addr) - - def SimulationTimeValidatorHelper(self, text): # noqa: N802, D102 - try: - simulation_time = int(float(self.simulation_time_line.text())) - except: # noqa: E722 - simulation_time = 0 - try: - simulation_time_step = int(float(self.simulation_time_step_line.text())) - except: # noqa: E722 - simulation_time_step = 0 - - if text == self.simulation_time_line.text(): - sim_time_changed = True - else: - sim_time_changed = False - # print(simulation_time_step) - # print(simulation_time) - if simulation_time_step > simulation_time: - if sim_time_changed: - self.simulation_time_line.setText(str(simulation_time_step)) - else: - self.simulation_time_step_line.setText(str(simulation_time)) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Designer.py deleted file mode 100644 index 5a97e19d0..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Designer.py +++ /dev/null @@ -1,128 +0,0 @@ -"""Created on Thu Jan 5 16:31:32 2023 - -@author: snaeimi -""" # noqa: N999, D400 - -import os - -import geopandas as gpd -import pandas as pd -from GUI.Subsitute_Layer_Window import Ui_subsitite_layer_dialoge -from PyQt5 import QtWidgets - - -class Subsitute_Layer_Designer(Ui_subsitite_layer_dialoge): # noqa: D101 - def __init__( - self, - subsitute_layer_addr, - subsitute_layer, - iUse_substitute_layer, # noqa: N803 - demand_node_layers, - ): - super().__init__() - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - - self.current_substitute_directory = '' - self.subsitute_layer = subsitute_layer - self.old_subsitute_layer = subsitute_layer - self.subsitute_layer_addr = subsitute_layer_addr - self.demand_node_layers = demand_node_layers - self.iUse_substitute_layer = iUse_substitute_layer - self.demand_node_layers.to_file(r'Northridge\demand_node_layer.shp') - self.subsitute_layer_addr_line.setText(self.subsitute_layer_addr) - if type(self.subsitute_layer) != type(None): # noqa: E721 - self.subsitute_layer_projection_name_line.setText( - self.subsitute_layer.crs.name - ) - - apply_button = self.Subsitute_buttonBox.button( - QtWidgets.QDialogButtonBox.Apply - ) - apply_button.clicked.connect(self.applyNewSubsituteLayer) - ok_button = self.Subsitute_buttonBox.button(QtWidgets.QDialogButtonBox.Ok) - ok_button.clicked.connect(self.applyNewSubsituteLayer) - - self.population_browser_button.clicked.connect( - self.substituteLayerBrowseButton - ) - - self.iUse_sub_checkbox.setChecked(self.iUse_substitute_layer) - self.iUse_sub_checkbox.stateChanged.connect( - self.iUseSubstituteCheckBoxStateChanged - ) - - def iUseSubstituteCheckBoxStateChanged(self, state): # noqa: N802, D102 - if state == 0: - self.iUse_substitute_layer = False - elif state == 2: # noqa: PLR2004 - self.iUse_substitute_layer = True - - def applyNewSubsituteLayer(self): # noqa: N802, D102 - # demand_node_layers = self.createGeopandasPointDataFrameForNodes(self, self.wn, self.demand_node_name) - if type(self.subsitute_layer) == type(None): # noqa: E721 - return - - def substituteLayerBrowseButton(self): # noqa: N802, D102 - file = QtWidgets.QFileDialog.getOpenFileName( - self._window, - 'Open file', - self.current_substitute_directory, - 'Shapefile file (*.shp)', - ) - - if file[0] == '': - return - split_addr = os.path.split(file[0]) - self.current_substitute_directory = split_addr[0] - - self.subsitute_layer_addr_line.setText(file[0]) - - self.subsitute_layer = gpd.read_file(file[0]) - self.subsitute_layer_addr = file[0] - self.subsitute_layer_addr_line.setText(file[0]) - self.subsitute_layer_projection_name_line.setText( - self.subsitute_layer.crs.name - ) - - self.sub_error_text_edit.clear() - self.demand_node_layers = self.demand_node_layers.set_crs( - crs=self.subsitute_layer.crs - ) - joined_map = gpd.sjoin(self.subsitute_layer, self.demand_node_layers) - - number_list = pd.Series(index=self.demand_node_layers.index, data=0) - for ind, val in joined_map['index_right'].iteritems(): # noqa: B007 - number_list.loc[val] = number_list.loc[val] + 1 - - number_list = number_list[number_list > 1] - number_list = number_list.sort_values(ascending=False) - - text = '' - if len(number_list) > 0: - text += 'The following nodes is joined with more than 1 substitute layer feature\n' - - for ind, num in number_list.iteritems(): - text += repr(ind) + ' : ' + repr(num) + '\n' - - text += '\n\n' - - index_number_list = pd.Series( - index=self.subsitute_layer.index.unique(), data=0 - ) - for ind in joined_map.index.to_list(): - index_number_list.loc[ind] = index_number_list.loc[ind] + 1 - - index_number_list = index_number_list[index_number_list > 1] - index_number_list = index_number_list.sort_values(ascending=False) - - if len(index_number_list) > 0: - text += 'The following substitute layer feature have multiple nodes\n' - i = 1 - for ind, num in index_number_list.iteritems(): - st = self.subsitute_layer.loc[ind] - st = st.drop('geometry') - text += repr(st) + ' : ' + repr(num) + '\n' - text += '---------- ' + repr(i) + ' ----------' - i += 1 - self.sub_error_text_edit.setText(text) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.py deleted file mode 100644 index 6e6cdf1a2..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.py +++ /dev/null @@ -1,115 +0,0 @@ -# Form implementation generated from reading ui file 'Subsitute_Layer_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_subsitite_layer_dialoge: # noqa: D101 - def setupUi(self, subsitite_layer_dialoge): # noqa: N802, D102 - subsitite_layer_dialoge.setObjectName('subsitite_layer_dialoge') - subsitite_layer_dialoge.resize(403, 407) - self.Subsitute_buttonBox = QtWidgets.QDialogButtonBox( - subsitite_layer_dialoge - ) - self.Subsitute_buttonBox.setGeometry(QtCore.QRect(110, 360, 261, 32)) - self.Subsitute_buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.Subsitute_buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Apply - | QtWidgets.QDialogButtonBox.Cancel - | QtWidgets.QDialogButtonBox.Ok - ) - self.Subsitute_buttonBox.setObjectName('Subsitute_buttonBox') - self.subsitute_layer_addr_line = QtWidgets.QLineEdit(subsitite_layer_dialoge) - self.subsitute_layer_addr_line.setGeometry(QtCore.QRect(20, 40, 261, 20)) - self.subsitute_layer_addr_line.setReadOnly(True) - self.subsitute_layer_addr_line.setObjectName('subsitute_layer_addr_line') - self.population_browser_button = QtWidgets.QPushButton( - subsitite_layer_dialoge - ) - self.population_browser_button.setGeometry(QtCore.QRect(290, 40, 81, 23)) - self.population_browser_button.setObjectName('population_browser_button') - self.label_27 = QtWidgets.QLabel(subsitite_layer_dialoge) - self.label_27.setGeometry(QtCore.QRect(20, 20, 121, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_27.setFont(font) - self.label_27.setObjectName('label_27') - self.groupBox = QtWidgets.QGroupBox(subsitite_layer_dialoge) - self.groupBox.setGeometry(QtCore.QRect(20, 70, 351, 61)) - self.groupBox.setObjectName('groupBox') - self.subsitute_layer_projection_name_line = QtWidgets.QLineEdit( - self.groupBox - ) - self.subsitute_layer_projection_name_line.setGeometry( - QtCore.QRect(110, 30, 231, 20) - ) - self.subsitute_layer_projection_name_line.setReadOnly(True) - self.subsitute_layer_projection_name_line.setObjectName( - 'subsitute_layer_projection_name_line' - ) - self.label_28 = QtWidgets.QLabel(self.groupBox) - self.label_28.setGeometry(QtCore.QRect(10, 30, 121, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_28.setFont(font) - self.label_28.setObjectName('label_28') - self.iUse_sub_checkbox = QtWidgets.QCheckBox(subsitite_layer_dialoge) - self.iUse_sub_checkbox.setGeometry(QtCore.QRect(20, 150, 141, 17)) - self.iUse_sub_checkbox.setObjectName('iUse_sub_checkbox') - self.sub_error_text_edit = QtWidgets.QTextEdit(subsitite_layer_dialoge) - self.sub_error_text_edit.setGeometry(QtCore.QRect(25, 191, 341, 151)) - self.sub_error_text_edit.setObjectName('sub_error_text_edit') - self.label_29 = QtWidgets.QLabel(subsitite_layer_dialoge) - self.label_29.setGeometry(QtCore.QRect(30, 170, 121, 16)) - font = QtGui.QFont() - font.setPointSize(8) - font.setBold(False) - font.setWeight(50) - self.label_29.setFont(font) - self.label_29.setObjectName('label_29') - - self.retranslateUi(subsitite_layer_dialoge) - self.Subsitute_buttonBox.accepted.connect(subsitite_layer_dialoge.accept) - self.Subsitute_buttonBox.rejected.connect(subsitite_layer_dialoge.reject) - QtCore.QMetaObject.connectSlotsByName(subsitite_layer_dialoge) - - def retranslateUi(self, subsitite_layer_dialoge): # noqa: N802, D102 - _translate = QtCore.QCoreApplication.translate - subsitite_layer_dialoge.setWindowTitle( - _translate('subsitite_layer_dialoge', 'Dialog') - ) - self.population_browser_button.setText( - _translate('subsitite_layer_dialoge', 'Browse') - ) - self.label_27.setText( - _translate('subsitite_layer_dialoge', 'Subsitute Layer File') - ) - self.groupBox.setTitle( - _translate('subsitite_layer_dialoge', 'Projection System') - ) - self.label_28.setText( - _translate('subsitite_layer_dialoge', 'Subsitute Projection') - ) - self.iUse_sub_checkbox.setText( - _translate('subsitite_layer_dialoge', 'Use the substitute Layer') - ) - self.label_29.setText(_translate('subsitite_layer_dialoge', 'Warnings')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - subsitite_layer_dialoge = QtWidgets.QDialog() - ui = Ui_subsitite_layer_dialoge() - ui.setupUi(subsitite_layer_dialoge) - subsitite_layer_dialoge.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.ui deleted file mode 100644 index aae14c563..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Subsitute_Layer_Window.ui +++ /dev/null @@ -1,203 +0,0 @@ - - - subsitite_layer_dialoge - - - - 0 - 0 - 403 - 407 - - - - Dialog - - - - - 110 - 360 - 261 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 20 - 40 - 261 - 20 - - - - true - - - - - - 290 - 40 - 81 - 23 - - - - Browse - - - - - - 20 - 20 - 121 - 16 - - - - - 8 - 50 - false - - - - Substitute Layer File - - - - - - 20 - 70 - 351 - 61 - - - - Projection System - - - - - 110 - 30 - 231 - 20 - - - - true - - - - - - 10 - 30 - 121 - 16 - - - - - 8 - 50 - false - - - - Substitute Projection - - - - - - - 20 - 150 - 141 - 17 - - - - Use the substitute Layer - - - - - - 25 - 191 - 341 - 151 - - - - - - - 30 - 170 - 121 - 16 - - - - - 8 - 50 - false - - - - Warnings - - - - - - - Subsitute_buttonBox - accepted() - subsitite_layer_dialoge - accept() - - - 248 - 254 - - - 157 - 274 - - - - - Subsitute_buttonBox - rejected() - subsitite_layer_dialoge - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Symbology_Designer.py deleted file mode 100644 index ccf65f5b0..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Designer.py +++ /dev/null @@ -1,303 +0,0 @@ -"""Created on Fri Jan 6 00:08:01 2023 - -@author: snaeimi -""" # noqa: N999, D400 - -import sys - -import geopandas as gpd -import mapclassify -import matplotlib.pylab as plt -import pandas as pd -from GUI.Symbology_Window import Ui_Symbology_Dialog -from matplotlib.backends.backend_qt5agg import FigureCanvas -from PyQt5 import QtCore, QtWidgets - - -class Symbology_Designer(Ui_Symbology_Dialog): # noqa: D101 - def __init__(self, sym, data, val_column): - super().__init__() - self._window = QtWidgets.QDialog() - self.setupUi(self._window) - self.sym = sym - self.val_column = val_column - self.plotted_map = data - self.data = data[val_column] - self.current_item_value = None - self.fig, self.ax1 = plt.subplots() - self.legend_widget = FigureCanvas(self.fig) - lay = QtWidgets.QVBoxLayout(self.sample_legend_widget) - lay.setContentsMargins(0, 0, 0, 0) - lay.addWidget(self.legend_widget) - self.initializeForm() - - self.method_combo.currentTextChanged.connect(self.methodChanged) - self.range_table.currentItemChanged.connect(self.currentItemChanged) - self.range_table.itemChanged.connect(self.tableDataChanged) - # self.range_table.currentItemChanged.connect(self.currentItemChanged) - self.remove_button.clicked.connect(self.removeButtonClicked) - self.color_combo.currentTextChanged.connect(self.colorChanged) - self.no_clases_line.editingFinished.connect( - self.numberOfClassEditingFinished - ) - self.add_up_button.clicked.connect(lambda: self.addByButton('UP')) - self.add_below_button.clicked.connect(lambda: self.addByButton('DOWN')) - - self.sample_legend_widget # noqa: B018 - - def initializeForm(self): # noqa: N802, D102 - self.method_combo.setCurrentText(self.sym['Method']) - if ( - self.sym['Method'] == 'FisherJenks' - or self.sym['Method'] == 'EqualInterval' - ): - self.no_clases_line.setText(str(self.sym['kw']['k'])) - else: - self.no_clases_line.clear() - self.no_clases_line.setEnabled(False) - self.updateTable() - # self.updateLegendSample() - - def addByButton(self, add_location): # noqa: N802, D102 - to_be_added_row = None # noqa: F841 - selected_item_list = self.range_table.selectedItems() - if len(selected_item_list) == 0: - return - else: # noqa: RET505 - selected_row = selected_item_list[0].row() - - if add_location == 'UP': - old_value = float(self.range_table.item(selected_row, 0).text()) - if selected_row == 0: - other_side_value = float( - self.range_table.item(selected_row, 1).text() - ) - else: - other_side_value = float( - self.range_table.item(selected_row - 1, 0).text() - ) - elif add_location == 'DOWN': - old_value = float(self.range_table.item(selected_row, 1).text()) - if selected_row == (self.range_table.rowCount() - 1): - other_side_value = float( - self.range_table.item(selected_row, 1).text() - ) - else: - other_side_value = float( - self.range_table.item(selected_row + 1, 1).text() - ) - - bins = self.class_data.bins.tolist() - # bins[bins==old_value] = new_item_value - bins.append((old_value + other_side_value) / 2) - bins.sort() - kw = {'bins': bins} - self.bins = bins - self.sym['kw'] = kw - - if self.sym['Method'] != 'UserDefined': - self.method_combo.blockSignals(True) # noqa: FBT003 - self.sym['Method'] = 'UserDefined' - self.no_clases_line.setEnabled(False) - self.method_combo.setCurrentText('User Defined') - self.method_combo.blockSignals(False) # noqa: FBT003 - self.updateTable() - - def numberOfClassEditingFinished(self): # noqa: N802, D102 - k = float(self.no_clases_line.text()) - k = int(k) - kw = {'k': k} - self.sym['kw'] = kw - self.updateTable() - - def colorChanged(self, text): # noqa: N802, D102 - self.sym['Color'] = text - self.updateLegendSample() - - def updateLegendSample(self): # noqa: N802, D102 - fig, ax = plt.subplots() - self.plotted_map.plot( - ax=ax, - cax=self.ax1, - column=self.val_column, - cmap=self.sym['Color'], - legend=True, - ) - self.legend_widget.draw() - # self.mpl_map.canvas.fig.tight_layout() - - def updateTable(self): # noqa: N802, D102 - self.range_table.blockSignals(True) # noqa: FBT003 - self.clearRangeTable() - if self.sym['Method'] == 'FisherJenks': - self.class_data = mapclassify.FisherJenks(self.data, self.sym['kw']['k']) - elif self.sym['Method'] == 'EqualInterval': - self.class_data = mapclassify.EqualInterval( - self.data, self.sym['kw']['k'] - ) - elif self.sym['Method'] == 'UserDefined': - self.class_data = mapclassify.UserDefined( - self.data, self.sym['kw']['bins'] - ) - else: - raise ValueError('Unknown symbology method: ' + repr(self.sym['Method'])) - min_val = self.data.min() - max_val = self.data.max() - - bins = [min_val] - bins.extend(self.class_data.bins.tolist()) - bins.append(max_val) - - bins = pd.Series(bins) - bins = bins.unique() - bins = bins.tolist() - - for i in range(len(bins) - 1): - number_of_rows = self.range_table.rowCount() - self.range_table.insertRow(number_of_rows) - beg_item = QtWidgets.QTableWidgetItem(str(bins[i])) - end_item = QtWidgets.QTableWidgetItem(str(bins[i + 1])) - count_item = QtWidgets.QTableWidgetItem(str(self.class_data.counts[i])) - - if i == 0: - beg_item.setFlags(QtCore.Qt.NoItemFlags) - - if i == len(bins) - 2: - end_item.setFlags(QtCore.Qt.NoItemFlags) - - count_item.setFlags(QtCore.Qt.NoItemFlags) - - self.range_table.setItem(number_of_rows, 0, beg_item) - self.range_table.setItem(number_of_rows, 1, end_item) - self.range_table.setItem(number_of_rows, 2, count_item) - - self.range_table.blockSignals(False) # noqa: FBT003 - self.updateLegendSample() - - def clearRangeTable(self): # noqa: N802, D102 - for i in range(self.range_table.rowCount()): # noqa: B007 - self.range_table.removeRow(0) - - def methodChanged(self, text): # noqa: N802, D102 - print(text) # noqa: T201 - if text == 'FisherJenks': - self.sym['Method'] = 'FisherJenks' - elif text == 'Equal Interval': - self.sym['Method'] = 'EqualInterval' - elif text == 'User Defined': - self.sym['Method'] = 'UserDefined' - - if text == 'FisherJenks' or text == 'Equal Interval': # noqa: PLR1714 - k = float(self.no_clases_line.text()) - k = int(k) - kw = {'k': k} - elif text == 'User Defined': - self.no_clases_line.setEnabled(False) - # bins = self.getUserDefinedBins() - try: - kw = {'bins': self.bins} - except: # noqa: E722 - kw = {'bins': self.class_data} - else: - raise # noqa: PLE0704 - - self.sym['kw'] = kw - self.updateTable() - - def currentItemChanged(self, current, previous): # noqa: ARG002, N802, D102 - if current != None: # noqa: E711 - self.current_item_value = float(current.text()) - print('cur ' + repr(self.current_item_value)) # noqa: T201 - - def tableDataChanged(self, item): # noqa: N802, D102 - # row = item.row() - # col = item.column() - - # item_text = self.range_table.item(row, col).text() - previous_item_value = float(self.current_item_value) - try: - new_item_value = float(item.text()) - if new_item_value < self.data.min() or new_item_value > self.data.max(): - raise # noqa: PLE0704 - except: # noqa: E722 - self.range_table.item(item.row(), item.column()).setText( - str(previous_item_value) - ) - return - - bins = self.class_data.bins - bins[bins == previous_item_value] = new_item_value - bins.sort() - kw = {'bins': bins} - self.bins = bins - self.sym['kw'] = kw - - if self.sym['Method'] != 'UserDefined': - self.method_combo.blockSignals(True) # noqa: FBT003 - self.sym['Method'] = 'UserDefined' - self.no_clases_line.setEnabled(False) - self.method_combo.setCurrentText('User Defined') - self.method_combo.blockSignals(False) # noqa: FBT003 - self.updateTable() - - return - - def findBeginingRowFor(self, value): # noqa: N802, D102 - if self.range_table.rowCount() == 0: - raise # noqa: PLE0704 - - for i in range(self.range_table.rowCount() - 1): - current_item_value = float(self.range_table.item(i, 0).text()) - next_item_value = float(self.range_table.item(i + 1, 0).text()) - if value >= current_item_value and next_item_value < current_item_value: - return i - return self.range_table.rowCount() - 1 - - def findEndingRowFor(self, value): # noqa: N802, D102 - if self.range_table.rowCount() == 0: - raise # noqa: PLE0704 - - for i in range(self.range_table.rowCount() - 1): - current_item_value = float(self.range_table.item(i, 1).text()) - next_item_value = float(self.range_table.item(i + 1, 1).text()) - if value > current_item_value and next_item_value >= current_item_value: - return i + 1 - return self.range_table.rowCount() - 1 - - def removeButtonClicked(self): # noqa: N802, D102 - selected_item_list = self.range_table.selectedItems() - if len(selected_item_list) == 0: - return - selected_row = selected_item_list[0].row() - self.removeRow(selected_row) - - def removeRow(self, row): # noqa: N802, D102 - if row == 0 and self.range_table.rowCount() >= 2: # noqa: PLR2004 - item_text = self.range_table.item(row, 0).text() - self.range_table.removeRow(0) - self.range_table.item(0, 0).setText(item_text) - elif ( - row == self.range_table.rowCount() - 1 - and self.range_table.rowCount() >= 2 # noqa: PLR2004 - ): - item_text = self.range_table.item(row, 1).text() - self.range_table.removeRow(row) - self.range_table.item(row - 1, 1).setText(item_text) - elif self.range_table.rowCount() == 1: - self.range_table.removeRow(0) - else: - beg_text = self.range_table.item(row, 0).text() - end_text = self.range_table.item(row, 1).text() - self.range_table.removeRow(row) - self.range_table.item(row - 1, 1).setText(beg_text) - self.range_table.item(row, 0).setText(end_text) - - -if __name__ == '__main__': - symbology = {'Method': 'FisherJenks', 'kw': {'k': 5}} - s = gpd.read_file('ss2.shp') - print(s.columns) # noqa: T201 - app = QtWidgets.QApplication(sys.argv) - ss = Symbology_Designer(symbology, s['restoratio']) - ss._window.show() # noqa: SLF001 - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.py b/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.py deleted file mode 100644 index 23e3340b0..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.py +++ /dev/null @@ -1,147 +0,0 @@ -# Form implementation generated from reading ui file 'Symbology_Window.ui' # noqa: N999, D100 -# -# Created by: PyQt5 UI code generator 5.12.3 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Symbology_Dialog: # noqa: D101 - def setupUi(self, Symbology_Dialog): # noqa: N802, N803, D102 - Symbology_Dialog.setObjectName('Symbology_Dialog') - Symbology_Dialog.resize(491, 410) - self.buttonBox = QtWidgets.QDialogButtonBox(Symbology_Dialog) - self.buttonBox.setGeometry(QtCore.QRect(180, 360, 161, 31)) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok - ) - self.buttonBox.setObjectName('buttonBox') - self.range_table = QtWidgets.QTableWidget(Symbology_Dialog) - self.range_table.setGeometry(QtCore.QRect(30, 80, 311, 261)) - self.range_table.setSelectionMode( - QtWidgets.QAbstractItemView.SingleSelection - ) - self.range_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - self.range_table.setObjectName('range_table') - self.range_table.setColumnCount(3) - self.range_table.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - self.range_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.range_table.setHorizontalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.range_table.setHorizontalHeaderItem(2, item) - self.range_table.horizontalHeader().setStretchLastSection(True) - self.method_combo = QtWidgets.QComboBox(Symbology_Dialog) - self.method_combo.setGeometry(QtCore.QRect(30, 40, 111, 22)) - self.method_combo.setObjectName('method_combo') - self.method_combo.addItem('') - self.method_combo.addItem('') - self.method_combo.addItem('') - self.label = QtWidgets.QLabel(Symbology_Dialog) - self.label.setGeometry(QtCore.QRect(30, 20, 47, 13)) - self.label.setObjectName('label') - self.add_below_button = QtWidgets.QPushButton(Symbology_Dialog) - self.add_below_button.setGeometry(QtCore.QRect(350, 110, 61, 23)) - self.add_below_button.setObjectName('add_below_button') - self.remove_button = QtWidgets.QPushButton(Symbology_Dialog) - self.remove_button.setGeometry(QtCore.QRect(350, 140, 61, 23)) - self.remove_button.setObjectName('remove_button') - self.no_clases_line = QtWidgets.QLineEdit(Symbology_Dialog) - self.no_clases_line.setGeometry(QtCore.QRect(220, 40, 61, 20)) - self.no_clases_line.setObjectName('no_clases_line') - self.label_2 = QtWidgets.QLabel(Symbology_Dialog) - self.label_2.setGeometry(QtCore.QRect(220, 20, 61, 16)) - self.label_2.setObjectName('label_2') - self.sample_legend_widget = QtWidgets.QWidget(Symbology_Dialog) - self.sample_legend_widget.setGeometry(QtCore.QRect(350, 220, 131, 111)) - self.sample_legend_widget.setObjectName('sample_legend_widget') - self.color_combo = QtWidgets.QComboBox(Symbology_Dialog) - self.color_combo.setGeometry(QtCore.QRect(350, 190, 91, 22)) - self.color_combo.setObjectName('color_combo') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.color_combo.addItem('') - self.label_3 = QtWidgets.QLabel(Symbology_Dialog) - self.label_3.setGeometry(QtCore.QRect(350, 170, 81, 20)) - self.label_3.setObjectName('label_3') - self.add_up_button = QtWidgets.QPushButton(Symbology_Dialog) - self.add_up_button.setGeometry(QtCore.QRect(350, 80, 61, 23)) - self.add_up_button.setObjectName('add_up_button') - - self.retranslateUi(Symbology_Dialog) - self.buttonBox.accepted.connect(Symbology_Dialog.accept) - self.buttonBox.rejected.connect(Symbology_Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(Symbology_Dialog) - - def retranslateUi(self, Symbology_Dialog): # noqa: N802, N803, D102 - _translate = QtCore.QCoreApplication.translate - Symbology_Dialog.setWindowTitle(_translate('Symbology_Dialog', 'Dialog')) - item = self.range_table.horizontalHeaderItem(0) - item.setText(_translate('Symbology_Dialog', 'Begining')) - item = self.range_table.horizontalHeaderItem(1) - item.setText(_translate('Symbology_Dialog', 'End')) - item = self.range_table.horizontalHeaderItem(2) - item.setText(_translate('Symbology_Dialog', 'Counts')) - self.method_combo.setItemText( - 0, _translate('Symbology_Dialog', 'FisherJenks') - ) - self.method_combo.setItemText( - 1, _translate('Symbology_Dialog', 'Equal Interval') - ) - self.method_combo.setItemText( - 2, _translate('Symbology_Dialog', 'User Defined') - ) - self.label.setText(_translate('Symbology_Dialog', 'Method')) - self.add_below_button.setText(_translate('Symbology_Dialog', 'Add-Below')) - self.remove_button.setText(_translate('Symbology_Dialog', 'Remove')) - self.label_2.setText(_translate('Symbology_Dialog', 'No. of clasess')) - self.color_combo.setItemText(0, _translate('Symbology_Dialog', 'Blues')) - self.color_combo.setItemText(1, _translate('Symbology_Dialog', 'Greens')) - self.color_combo.setItemText(2, _translate('Symbology_Dialog', 'Greys')) - self.color_combo.setItemText(3, _translate('Symbology_Dialog', 'Reds')) - self.color_combo.setItemText(4, _translate('Symbology_Dialog', 'Oranges')) - self.color_combo.setItemText(5, _translate('Symbology_Dialog', 'binary')) - self.color_combo.setItemText(6, _translate('Symbology_Dialog', 'gist_grey')) - self.color_combo.setItemText(7, _translate('Symbology_Dialog', 'Seismic')) - self.color_combo.setItemText(8, _translate('Symbology_Dialog', 'hsv')) - self.color_combo.setItemText(9, _translate('Symbology_Dialog', 'Pastel1')) - self.color_combo.setItemText(10, _translate('Symbology_Dialog', 'Pastel2')) - self.color_combo.setItemText(11, _translate('Symbology_Dialog', 'Set1')) - self.color_combo.setItemText(12, _translate('Symbology_Dialog', 'Set2')) - self.color_combo.setItemText(13, _translate('Symbology_Dialog', 'Set3')) - self.color_combo.setItemText(14, _translate('Symbology_Dialog', 'tab10')) - self.color_combo.setItemText(15, _translate('Symbology_Dialog', 'tab20')) - self.color_combo.setItemText(16, _translate('Symbology_Dialog', 'tab20b')) - self.color_combo.setItemText(17, _translate('Symbology_Dialog', 'tab20c')) - self.label_3.setText(_translate('Symbology_Dialog', 'Color Scheme')) - self.add_up_button.setText(_translate('Symbology_Dialog', 'Add-Up')) - - -if __name__ == '__main__': - import sys - - app = QtWidgets.QApplication(sys.argv) - Symbology_Dialog = QtWidgets.QDialog() - ui = Ui_Symbology_Dialog() - ui.setupUi(Symbology_Dialog) - Symbology_Dialog.show() - sys.exit(app.exec_()) diff --git a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.ui b/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.ui deleted file mode 100644 index d6cbf10b3..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Symbology_Window.ui +++ /dev/null @@ -1,325 +0,0 @@ - - - Symbology_Dialog - - - - 0 - 0 - 491 - 410 - - - - Dialog - - - - - 180 - 360 - 161 - 31 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 30 - 80 - 311 - 261 - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - true - - - - Beginning - - - - - End - - - - - Counts - - - - - - - 30 - 40 - 111 - 22 - - - - - FisherJenks - - - - - Equal Interval - - - - - User Defined - - - - - - - 30 - 20 - 47 - 13 - - - - Method - - - - - - 350 - 110 - 61 - 23 - - - - Add-Below - - - - - - 350 - 140 - 61 - 23 - - - - Remove - - - - - - 220 - 40 - 61 - 20 - - - - - - - 220 - 20 - 61 - 16 - - - - No. of clasess - - - - - - 350 - 220 - 131 - 111 - - - - - - - 350 - 190 - 91 - 22 - - - - - Blues - - - - - Greens - - - - - Greys - - - - - Reds - - - - - Oranges - - - - - binary - - - - - gist_grey - - - - - Seismic - - - - - hsv - - - - - Pastel1 - - - - - Pastel2 - - - - - Set1 - - - - - Set2 - - - - - Set3 - - - - - tab10 - - - - - tab20 - - - - - tab20b - - - - - tab20c - - - - - - - 350 - 170 - 81 - 20 - - - - Color Scheme - - - - - - 350 - 80 - 61 - 23 - - - - Add-Up - - - - - - - buttonBox - accepted() - Symbology_Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Symbology_Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/modules/systemPerformance/REWET/REWET/GUI/Tank_Damage_Discovery_Designer.py b/modules/systemPerformance/REWET/REWET/GUI/Tank_Damage_Discovery_Designer.py deleted file mode 100644 index b3c772eb5..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/Tank_Damage_Discovery_Designer.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Created on Tue Nov 1 23:25:30 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -from .Damage_Discovery_Designer import Damage_Discovery_Designer - - -class Tank_Damage_Discovery_Designer(Damage_Discovery_Designer): # noqa: D101 - def __init__(self, tank_damage_discovery_model): - super().__init__(tank_damage_discovery_model) - self._window.setWindowTitle('Tank Damage Discovery') - self.leak_based_radio.setEnabled(False) diff --git a/modules/systemPerformance/REWET/REWET/GUI/__init__.py b/modules/systemPerformance/REWET/REWET/GUI/__init__.py deleted file mode 100644 index b74acee6d..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# noqa: N999, D104 diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/NSF_Official_logo.svg b/modules/systemPerformance/REWET/REWET/GUI/resources/NSF_Official_logo.svg deleted file mode 100644 index 4b4b6e7d3..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/resources/NSF_Official_logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource.qrc b/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource.qrc deleted file mode 100644 index 7646d2b36..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource.qrc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource_rc.py b/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource_rc.py deleted file mode 100644 index 4589a32af..000000000 --- a/modules/systemPerformance/REWET/REWET/GUI/resources/REWET_Resource_rc.py +++ /dev/null @@ -1,732 +0,0 @@ -# Resource object code # noqa: INP001, D100 -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.12.9) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b'\ -\x00\x00\x07\x42\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x01\x20\x00\x00\x00\x20\x08\x02\x00\x00\x00\x3d\x96\x32\x63\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x06\xd7\x49\x44\x41\x54\x78\x5e\xed\x9c\x3d\x8f\ -\x4e\x5d\x14\x86\x1f\xef\x0f\x18\x41\x37\xd3\xa1\x20\x4c\x33\x83\ -\x86\x28\x11\x95\x42\x42\xb4\x8a\x89\x69\x27\x99\x49\x4c\x4b\x41\ -\xa1\x14\x0a\x35\x11\x85\x86\x04\x85\xc2\x5b\x48\x7c\x64\x84\x44\ -\xc3\x34\x44\x65\x86\x7f\x30\xef\x65\xdf\xdb\x7a\xf7\xb3\xcf\x87\ -\xf3\xcc\x9c\x3d\x92\xc9\xba\x8a\xc7\xfe\xde\xf7\x5a\x6b\xaf\x7d\ -\xce\x11\xb1\x6d\x6d\x6d\x6d\xe0\x38\x4e\x19\xfe\x89\x7f\x3a\x8e\ -\x53\x00\x4f\x30\xc7\x29\x88\x27\x98\xe3\x14\xc4\x13\xcc\x71\x0a\ -\xe2\x09\xe6\x38\x05\xf1\x04\x73\x9c\x82\x78\x82\x39\x4e\x41\x3c\ -\xc1\x1c\xa7\x20\x9e\x60\x8e\x53\x90\xad\x90\x60\x2b\x2b\x2b\xdb\ -\x86\xa1\xf1\xf1\xe3\xc7\xb1\x12\x38\x75\xea\x94\x46\x5e\xbf\x7e\ -\xfd\xfc\xf9\xf3\x61\xde\x5f\x60\x71\x71\x31\x0a\x0a\x20\x86\xc6\ -\xc3\x87\x0f\xc7\x7a\xe0\xdf\x00\x82\x29\xef\xdd\xbb\x77\x79\x79\ -\x59\x73\xb7\x06\x59\x5c\x14\x8b\xcc\x2d\xb7\x6f\xdf\xa6\x11\xc3\ -\x67\x67\x67\xe5\xa2\xcd\x27\x3b\x54\x3b\x77\xee\xa4\xb1\x2a\x5e\ -\x27\x8a\x5e\xaa\xb5\x52\xb7\x42\x82\xed\xda\xb5\xeb\xd2\xa5\x4b\ -\xb7\x6e\xdd\x5a\x0b\x9c\x3c\x79\x92\xc6\xd3\xa7\x4f\xef\xd9\xb3\ -\x67\x69\x69\x89\x16\x7e\xa7\xa7\xa7\xf1\xc5\x8d\x1b\x37\xe8\xfa\ -\xf9\xf3\x67\x98\xf7\x17\xb8\x78\xf1\xe2\x8e\x1d\x3b\xa4\x13\xc1\ -\x07\x0f\x1e\xa4\x71\x6e\x6e\xee\xdc\xb9\x73\x6a\xa4\xb0\x7f\xff\ -\xfe\x2b\x57\xae\x5c\xbb\x76\xed\xfb\xf7\xef\x24\xd8\x83\x07\x0f\ -\x34\x77\x6b\x90\xc6\xe5\xd1\xa3\x47\x53\x53\x53\x34\xa6\x6e\xb9\ -\x7c\xf9\xf2\x81\x03\x07\xde\xbd\x7b\x87\xe1\xab\xab\xab\x9a\xb5\ -\xf9\xa4\x87\x8a\x40\x1c\x39\x72\x84\xc6\xaa\xf8\x8f\x1f\x3f\xbe\ -\x7d\xfb\x16\x9d\x54\x17\x16\x16\x34\x77\x88\x60\xd4\x68\xbc\x78\ -\xf1\x22\x4e\x4e\xe0\x40\xc4\xee\xd1\x61\xae\x16\x61\xe5\xd8\x14\ -\xac\xc2\xe9\x20\x7b\x40\x63\x04\xed\xe9\x8e\x98\xfd\xf9\xf3\x67\ -\x46\x5a\x23\x55\x1a\x29\xe0\xa3\x74\x59\xca\x64\x60\xac\xac\x97\ -\xcc\x03\x6c\x74\xf7\xee\xdd\xd8\xf7\x3b\xc3\x0d\x72\x06\x5b\xd4\ -\xc5\x30\xc2\x46\xc1\x32\x0a\x68\xa1\x9d\x31\xea\x4a\xa1\x25\x15\ -\xbf\x0e\x32\xa9\x22\x55\x3b\x2a\x5d\x82\x55\xf5\x0f\xe7\x4f\x23\ -\x2d\x2e\xac\x63\x2b\x98\x5b\xb2\xd0\x30\x06\x62\x65\xbd\xb0\x42\ -\xd4\x11\x38\x74\xe8\x90\x9d\xa8\xaa\xce\xd4\x33\x54\x51\xcb\x18\ -\xd3\x50\x2b\x5e\xd0\x55\x7b\xae\xda\x12\x8c\x55\x9a\xce\x22\xd7\ -\x0c\x42\x63\x65\x6d\x8d\xb2\x79\x70\x7d\xb0\x02\x7b\xa5\x8b\xb0\ -\x05\x01\xe3\x37\xd6\xc3\x9d\x81\x17\x74\x58\x71\x04\x65\x79\x0a\ -\xdb\x82\x7f\x7e\x61\x2b\x68\x80\xb0\xf3\x0d\xf8\xa5\xc9\xa8\x91\ -\x48\x3d\xa0\x10\x22\x43\x55\xb6\xa3\x2a\x25\x0a\x89\x65\x0e\x85\ -\xa0\xe8\x57\x98\xd5\x02\x0c\x50\x63\x6a\x2c\x60\x5d\xd6\x52\xa5\ -\x25\x46\x46\x2a\x55\x99\x90\x1d\x8e\x51\xe9\x12\xac\x74\x53\xac\ -\xa6\x57\xe5\x34\x2e\x6a\x01\x73\x4b\x66\x0b\xd6\x41\xac\x6c\x00\ -\x94\x48\x1b\xe6\x73\xb5\x29\x49\x44\xaa\x93\xbd\xd0\xa0\x38\xa6\ -\x87\xca\xdc\x55\x2b\x5e\x60\x82\x1d\x80\x94\x75\xbe\x22\xfe\xf8\ -\xf1\xe3\xc4\x89\x13\xb1\x12\x9e\xa7\x13\x13\x13\xb1\xf2\x1b\xbe\ -\x22\x78\xd0\xc7\x4a\xe0\xde\xbd\x7b\xbc\x6d\xc7\xca\x30\x3a\x64\ -\x1f\x3e\x7c\x50\x95\x89\x6f\xde\xbc\xa1\x70\xf4\xe8\x51\xb5\xc0\ -\x97\x2f\x5f\xf0\x05\x7b\x51\xd6\xbb\xfb\xcb\x97\x2f\xf9\x7d\xf6\ -\xec\x99\x1e\x08\x38\x68\x6c\x6c\xec\xd7\xd0\xc1\xe0\xe1\xc3\x87\ -\x7a\xbe\x13\x33\x4d\xf9\x23\x68\x43\x61\xac\x04\x90\xa1\x8f\xb7\ -\x2a\x78\x93\x6f\x27\x95\xcf\x9e\x3d\xcb\xef\xb7\x6f\xdf\x54\xfd\ -\xfa\xf5\x2b\xbf\xfb\xf6\xed\xe3\x77\xf7\xee\xdd\x38\xca\xbe\xa3\ -\x58\x5f\x97\x82\x49\x62\x0b\x5e\x30\x68\x21\x8a\xdb\xb7\x6f\x57\ -\x23\xd0\x7e\xff\xfe\xfd\xab\x57\xaf\xc6\xfa\x06\x40\xaa\x05\x8b\ -\x7d\x79\xdb\x39\x76\xec\x98\xaa\x46\xef\xc1\x4a\x37\xbd\x70\xe1\ -\x02\x07\x46\xeb\x5b\x5c\x2c\xa9\xc0\xdc\x82\xbb\x62\xd3\x9f\x18\ -\x49\x30\x62\x26\x27\x27\x29\x60\xfe\x99\x33\x67\xa8\xaa\x1d\x9a\ -\xe2\x98\x1e\xaa\xf1\xf1\xf1\xd0\x5f\x2f\x1e\xd8\x77\x66\x66\xa6\ -\x5e\x3c\xa3\x9b\x60\xe9\xa6\xdb\x11\x17\x2b\xad\xd9\x4f\x5b\x56\ -\x21\xdd\xed\x9d\xa1\x5a\x4d\xd1\x55\xcd\x76\x76\x05\xea\x82\x44\ -\x1e\xf6\xab\x05\x30\xd8\x06\xc8\x47\xd2\xc0\x60\x69\xe0\x7e\x92\ -\x60\xdd\xd3\xda\x8b\x5f\xdc\x41\x41\x30\xd2\x6e\xac\x0c\x46\x32\ -\x0b\x9d\xb5\xd5\x8c\xb4\x2b\x93\xca\x16\xe9\x1d\xc9\x76\x12\x80\ -\x5a\x66\xa9\x91\xb9\xd2\x8c\xd5\xf6\xba\xc8\x30\xd3\x6c\x37\x2e\ -\x03\x42\x67\x3d\x2d\x31\x32\xcc\x15\x2d\x64\xd1\xc9\xaa\x29\xd2\ -\xf6\xc7\x60\x31\xdd\x1e\x71\xac\xa6\x93\x56\xfb\xfc\xa4\xaa\xde\ -\x2a\x69\xc4\x33\x46\x12\x9c\x6a\x63\xc1\x34\x3a\xcc\x62\xae\xca\ -\xa9\x15\x18\x95\x79\xbe\x56\x3c\xb0\xa0\xf6\xad\x95\xba\x9e\x04\ -\xd3\xe1\x36\x6a\xad\x12\x66\x76\x8b\xfd\xc0\x51\x63\x80\x6d\xa7\ -\x72\x76\x4c\x81\x15\x14\x33\xd6\xe1\xd4\x2a\x4f\xe4\x14\x43\x87\ -\x15\x53\x63\x3d\xa0\xa3\x0c\xb1\x1e\xa8\x7a\x0a\x58\x59\x1e\xb7\ -\x42\xec\x18\x86\x5e\x56\x50\x24\x10\xc0\xc8\xd4\xb9\x68\x50\x46\ -\x31\x80\x02\xbd\x1a\x89\x60\x6d\x2d\x58\x84\x98\xc5\x4a\x80\x91\ -\x61\x81\xff\x5f\x1a\x21\x0b\x73\x46\x53\x8c\x0c\x49\x35\xec\xd0\ -\x57\xb1\x18\x59\x21\x76\x0c\xd3\x25\x58\xda\x14\xeb\x28\xa7\xfe\ -\x51\x5c\x32\xc1\x72\x4b\x66\xa6\xb2\xce\x88\xad\xc3\x74\x17\x2c\ -\x6d\xe8\xa1\xcc\x6a\xe6\x04\xe9\xac\xc6\x91\x72\xd8\x76\x68\xdf\ -\x5a\xf1\x6c\xad\x91\x22\xb6\x26\xe4\x4d\xd8\x19\xc7\x56\x30\x17\ -\xb0\xa8\x79\x53\xa7\xbc\x05\x19\xdf\x62\x3f\x70\x22\x31\x12\xab\ -\x50\x8f\x17\x58\x93\x5f\x3b\xa6\x42\xbe\x10\xac\x46\x97\xe2\xd7\ -\x3b\x6c\x24\xc1\x28\x8f\x4d\x15\x14\x27\x81\x2b\xb2\x91\xcc\x8d\ -\x7d\x83\x01\x3a\x15\xbf\x1e\xe9\x12\x23\x03\xa9\x16\xa3\x4d\x0b\ -\x56\xe6\x9f\xaa\xaa\xbe\xe8\x28\x38\x4a\x09\xe9\x91\x5e\xac\xed\ -\x71\xec\x85\xfc\x1b\x6c\x7e\x7e\x3e\xf6\x54\x6e\x47\xba\x34\xe6\ -\xfd\xfb\xf7\xf6\x7a\xfd\xea\xd5\x2b\x15\x36\xc2\xeb\xd7\xaf\x79\ -\x7f\xe5\xf3\xe9\xc9\x93\x27\x77\xee\xdc\x99\x9b\x9b\xe3\x5d\x99\ -\xc6\xe3\xc7\x8f\xc7\x11\xe1\x73\x0b\x3f\x4a\x09\x1f\x2d\x37\x6f\ -\xde\xec\xf8\x65\x55\x82\xe7\xcf\x9f\x13\x36\x94\x10\x2d\xc4\xe8\ -\xef\x70\x05\x1f\x06\x7c\x6f\x28\xde\x78\x0f\xcd\xdd\xbf\x2b\x3a\ -\xd2\x25\x46\x06\x52\x37\x3f\x58\xe6\x1f\xf8\xf4\xe9\x53\x55\xd5\ -\x66\xf2\xf4\xe9\x53\x12\x09\x25\xf8\x6a\x65\x65\x25\xfd\xfe\x6c\ -\x89\x63\x6f\x04\x27\xd4\x93\x05\xcf\xe0\xd2\x4a\x73\xdd\x9e\x66\ -\x55\x74\xc1\x70\xda\xac\x10\x3b\x12\xb0\x4d\x46\x72\x11\xa2\x47\ -\x3b\x72\x47\x52\x4e\xc7\x33\x26\xbd\x23\x0b\xc1\x8e\xe8\x44\xad\ -\x15\x62\xc7\x30\x74\x29\x66\x90\xdd\xd0\xb4\xd3\xab\x32\xd3\xdb\ -\x3d\xbc\x71\x9a\x62\x64\x20\xc6\xde\x88\xda\xe9\x31\x58\x4c\x6f\ -\x72\x5d\x8f\x74\x11\x4c\xa3\x69\x93\xce\xf4\x09\xc6\xac\xa6\x38\ -\xf6\xc5\xc8\x09\x26\xcf\x9a\x31\x1c\xfa\xa6\x00\x67\x66\x37\x79\ -\x81\x57\x5b\xbd\xf8\x82\xad\xcc\xd6\x94\xd9\x4b\xed\xda\xb4\x84\ -\xfd\x29\x6c\x8d\x42\x3b\x19\x59\xd5\xd0\x0b\xba\xc5\x29\xf3\x00\ -\xb7\x8f\x55\xab\x11\xed\x9d\xf6\x04\x93\xd4\x2e\x09\xd6\x63\xb0\ -\x32\xff\x14\xa2\xbb\x60\xc4\xc4\xca\x70\x16\xb5\xc7\xb1\x2f\x46\ -\x4e\x30\x74\x20\x2b\xa5\xe9\xdc\x33\xd2\x9c\x2e\xf0\x82\x85\x47\ -\x60\x9e\x16\x49\xe3\x61\x8d\xb6\x3b\x05\xb5\x14\x0d\x1b\x86\x64\ -\x11\xa2\x5a\xf5\x80\x94\x80\xaa\x18\x45\xd9\x5e\x42\xd4\x65\x3e\ -\x21\xa2\xa4\x1c\x99\xa6\x6a\xef\xd4\xc6\xc8\x90\x18\x88\xf5\x66\ -\x7a\x0c\x96\xaa\xa0\x6a\x21\x46\x12\x6c\xda\x98\x45\x1e\x4a\xbf\ -\xba\x40\x5d\x69\x1c\x7b\xc4\xff\x57\x29\xc7\x29\x88\xff\x6b\x7a\ -\xc7\x29\x88\x27\x98\xe3\x14\xc4\x13\xcc\x71\x0a\xe2\x09\xe6\x38\ -\x05\xf1\x04\x73\x9c\x82\x78\x82\x39\x4e\x41\x3c\xc1\x1c\xa7\x20\ -\x9e\x60\x8e\x53\x10\x4f\x30\xc7\x29\xc6\x60\xf0\x1f\x89\x59\x21\ -\xd8\x7f\xb3\x61\x57\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ -\x82\ -\x00\x00\x02\x7e\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x41\x00\x00\x00\x14\x08\x02\x00\x00\x00\x5d\xd6\xc7\x56\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x13\x49\x44\x41\x54\x58\x47\xed\x96\xbd\x8d\ -\x02\x31\x10\x46\x97\xeb\x00\x42\x22\x24\xc8\x91\x10\x22\x22\xa7\ -\x04\x68\x01\x4a\xa0\x03\xa8\x00\x24\x72\x22\x42\x12\x12\x02\x1a\ -\x58\x0a\x80\x90\x08\x68\x61\xef\x69\x3f\x6b\xd6\xb7\x3f\x88\x5b\ -\xdd\x49\x20\xf1\x82\xbb\xf1\x8c\x3d\x33\x9f\xed\xb5\xa8\x44\x51\ -\x14\xbc\x39\x5f\xee\xff\x3b\xf3\xd1\xf0\x3f\x9c\xcf\xe7\xd1\x68\ -\x54\x89\x99\x4c\x26\x72\x2e\x97\xcb\x56\xab\x85\xa7\x56\xab\x1d\ -\x8f\x47\x39\xc5\xcb\x69\xb8\xdd\x6e\xdd\x6e\xb7\xd3\xe9\xf0\xa1\ -\x6e\xb7\xdb\x46\xa3\x81\x73\x3e\x9f\xaf\x56\xab\xcd\x66\x83\xb3\ -\xd9\x6c\xb6\xdb\x6d\x4d\x76\xe0\xf5\x09\xc3\x70\x38\x1c\x2a\xc4\ -\xec\xf5\x7a\xed\x02\xbf\x67\x36\x9b\x29\x8f\xa0\x33\x92\x2b\x74\ -\x38\x1c\x9c\x37\xc6\x2f\x34\x9d\x4e\x69\x40\xb6\xb8\x5e\xaf\xcc\ -\xb1\xb5\x59\x7e\x68\x40\x37\xb3\xa9\xcd\x32\xd6\x54\xab\x55\x8a\ -\xb9\x58\x29\xe8\x9b\x9e\x30\x48\x48\x67\xf4\x2a\x3f\xe0\x27\x2a\ -\x5b\x6a\x4f\xa7\x13\x36\x73\x68\x43\x7e\x81\x3c\x9b\x99\x4b\xa2\ -\x81\x32\x34\x4d\x3a\x37\x8e\xa2\xc1\x60\xa0\xbc\x3e\x38\x53\x5b\ -\x42\x0d\x35\x9a\x85\x84\xb6\xc1\x18\x34\x2a\x1b\x90\x34\x1e\x8f\ -\x65\x53\x85\x90\xf6\x0b\x83\x4e\xe4\x17\xb4\x54\x94\x5f\x24\x49\ -\x99\x4a\x49\x37\x28\x86\x56\x98\x66\x32\x52\x43\x1f\x9c\xb6\xbb\ -\x40\x1f\xfe\x39\xf8\xf2\x74\xfe\x76\x0e\xf2\xe3\x94\x48\x86\x9c\ -\x03\xc2\x20\x77\x5b\x13\x0d\x2c\x7e\x2c\xd7\xb0\xbe\x1f\x08\x80\ -\xc5\x62\xa1\xa6\xa9\x8d\x4d\x97\x76\x49\x7c\x79\x38\x49\x62\xa5\ -\xc9\xc9\x2a\xa2\x26\x92\xe5\xf6\x89\xe6\x5e\x2a\xa7\xc1\x3f\xcd\ -\x67\x50\xf7\x50\x24\x00\xac\x30\xb0\x7f\x7e\x72\x49\x12\xb6\xf1\ -\xa5\x71\x6f\xeb\xe5\x72\xe1\x6f\xbd\x5e\xd7\xf0\x4f\xd8\xed\x76\ -\xf4\x4a\x0d\x6e\x29\x2f\x66\xbf\xdf\x77\x81\x20\xd8\xef\xf7\x7a\ -\x7c\x10\x76\xbf\xdf\x7b\xbd\x9e\x0b\x94\x23\x56\xe2\x1e\xbb\xec\ -\x55\xcb\xc5\xae\x90\x19\x2e\xe0\xa1\xdb\xa2\x50\xf6\x90\x59\x25\ -\x79\xc0\x39\xf8\x0f\x49\x09\x9c\x06\xee\x1c\x79\x75\x29\x75\x7d\ -\x39\x7d\x85\x52\xa4\xfa\x2e\x92\x41\x2a\xdb\x20\xf0\x1b\xd5\x17\ -\x6c\x92\xf8\x70\x8b\x6a\x3d\x49\x52\x86\xd4\xfa\x98\xe0\xc1\x1d\ -\xa5\x24\x22\xdd\x20\x86\x99\xa9\xc7\x40\xa7\x0a\xd6\x1c\xab\x90\ -\xaa\xbe\x15\x02\x85\x58\x8e\x6d\xc7\x52\x82\xcf\x6f\xef\xd7\xe0\ -\xa3\xe1\x35\x78\x7f\x0d\x41\xf0\x0d\xf7\xde\xa9\x12\x11\xdc\x6c\ -\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x02\xb7\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x44\x00\x00\x00\x17\x08\x02\x00\x00\x00\x3d\x6b\x7e\xbc\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x4c\x49\x44\x41\x54\x58\x47\xed\x96\x31\xb2\ -\x29\x51\x10\x86\xe7\xbe\x1d\x60\x07\x08\x85\x28\x81\x44\x64\x09\ -\xec\x40\xd9\x81\x62\x05\xac\x40\xd9\x00\x1b\x20\x90\xa8\x42\x20\ -\x14\x4a\x24\x02\x11\xb6\xe0\x7d\x6f\xfe\xf3\xda\x99\xe1\xde\xaa\ -\x3b\xd1\x94\xf2\x05\x9c\xd3\x7d\xa6\x4f\xff\xdd\x6d\xee\xfd\xba\ -\xdf\xef\xc1\xbb\xf0\xc7\x7d\xbf\x05\x29\x15\x53\xa9\x54\xbe\x42\ -\xb2\xd9\xec\x68\x34\x92\xf1\x7a\xbd\xca\x08\xc5\x62\x71\xb1\x58\ -\xc8\xfe\x80\x31\x4b\x21\xd3\xe9\xb4\xd5\x6a\xb1\xd8\x6c\x36\x99\ -\x4c\x86\xad\xec\xdd\x6e\x77\x3c\x1e\xb3\xe0\x93\xe4\x8f\xc7\xa3\ -\xec\x22\xd2\x19\xa7\x3a\x04\xe9\x56\x92\xc4\x6c\xb7\x5b\x17\x2e\ -\x84\x98\xb3\xd9\xcc\xf9\xa2\xd7\xd1\x81\xc1\x60\xe0\x1c\x41\xb0\ -\x5e\xaf\x1b\x8d\x06\x8b\x7a\xbd\xde\xeb\xf5\x4e\xa7\x93\xec\xcb\ -\xe5\xb2\x56\xab\xb1\xe8\x74\x3a\xcd\x66\xf3\x7c\x3e\xcb\xee\x70\ -\xa2\x42\xe6\xf3\x39\x96\xcb\xe5\xc2\x9a\x62\x50\x92\x7e\xbf\x2f\ -\x57\x62\x88\x50\x2e\x97\xb5\x1e\x0e\x87\xc4\xb7\x72\xfa\xd7\xd1\ -\x01\xd6\xd6\x81\x42\xa1\xb0\xdf\xef\xb5\x26\x02\x0f\xb2\xe0\x41\ -\x52\x92\x11\x08\xcb\x53\x6e\x13\x12\x11\x43\x2c\xbb\x18\x88\x12\ -\x53\x2b\xb0\xdb\xad\x82\x8b\xa9\x93\xdb\x44\x61\x5a\x98\x0d\xad\ -\xc9\x86\x80\x96\x01\xa3\x42\xd2\x5a\x03\x6b\x25\x4d\x34\xb3\x23\ -\x15\x01\x7a\x84\xf3\x16\x4a\xe3\xa7\x42\x18\x91\x5c\x39\x6a\xa7\ -\x41\xd5\xb2\x0a\x19\x58\xfc\x39\x8e\x6d\x63\xf8\x2e\xb5\xc2\x3a\ -\xe3\xeb\x24\x2d\xeb\x0c\x92\x64\x27\x32\xc5\xb5\x33\xd4\x4b\x07\ -\x88\xf3\xf2\xc6\x88\x18\xea\xe1\x9f\x90\x98\x98\x7a\x61\x02\x7e\ -\x56\x82\xd7\xb2\x57\x06\xfe\xdc\xda\x83\x4a\x5a\x43\x21\x55\xc2\ -\x7a\x05\x2a\x84\xe0\x24\x5b\xd9\x7d\x1e\x62\x34\x03\x56\x36\x20\ -\x10\xf7\xb9\xcd\x13\x92\x61\x09\xbd\x44\xef\x1c\x11\xab\x94\x74\ -\x0a\x82\x70\xd7\xcb\xaa\xfd\x8a\xc7\xdb\xec\x70\x38\x70\x5f\x3e\ -\x9f\x77\xfb\x20\x98\x4c\x26\xed\x76\xdb\x6d\x12\xb1\x5a\xad\xec\ -\x0d\x7b\xbb\xdd\xaa\xd5\xaa\x73\x04\xc1\x6e\xb7\x43\x03\x2e\xb5\ -\xa2\x54\x2a\xe5\x72\x39\xb9\x92\x13\x4a\xfa\x07\x03\xe0\xff\x60\ -\xd4\x16\xbf\x51\x3e\x36\x5d\xb6\x70\x8e\x28\xb8\xf4\x67\x01\xfc\ -\x99\x01\x44\x4a\x27\x70\xef\x77\xef\x8f\x5f\xf1\x10\xc3\x20\xea\ -\x62\xf2\x23\xfa\x0f\x29\xc6\x04\x7c\xa7\x47\x53\xae\x17\x11\xf8\ -\x19\xab\x1b\xa6\x8d\x67\xfd\xb2\x26\xc6\x85\x50\x38\x41\x66\x5c\ -\x4c\x8a\x72\x3d\x43\x12\x31\x2f\xdb\xe7\xd2\xba\x70\xff\xb3\xd4\ -\x15\xaa\x17\x87\xe5\x92\x54\xfd\x5c\xad\x51\x89\xf9\xfc\xd7\x9c\ -\x56\x3e\x62\xd2\xca\x47\x4c\x5a\xf9\x88\x49\x2b\x6f\x24\x26\x08\ -\xfe\x02\x7d\x51\xf9\x70\x59\x9e\xf7\x68\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x09\xff\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x01\x68\x00\x00\x00\x26\x08\x02\x00\x00\x00\x66\xa2\x96\x2a\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x09\x94\x49\x44\x41\x54\x78\x5e\xed\x9d\xcd\x8b\ -\xce\xdf\x1b\xc7\x67\xbe\xff\x80\xa7\xad\x24\x2c\x28\x22\x19\x0a\ -\x29\xca\xf3\x46\x79\xcc\x4a\x8d\x05\xb6\x53\x33\xe5\x21\x1b\xc5\ -\xcc\x52\x88\x62\x4d\x13\x65\x43\x86\x62\x41\x92\xa7\x48\xb2\xc1\ -\x02\x4b\x4f\xf1\x07\xcc\xf7\x75\x7f\xde\xc7\xd5\xb9\x3f\x4f\xee\ -\xf3\x99\x7b\x16\xa3\xeb\xb5\x98\xdf\xb9\xce\x39\x9f\x73\xae\xa7\ -\x73\xdd\xe7\xa8\x6f\xbf\xde\xf1\xf1\xf1\x1e\xc7\x71\x9c\x14\xfe\ -\x0b\xff\xeb\x38\x8e\xd3\x31\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\xe3\ -\x38\xc9\x78\xe1\x70\x1c\x27\x19\x2f\x1c\x8e\xe3\x24\xe3\x85\xc3\ -\x71\x9c\x64\xbc\x70\x38\x8e\x93\x8c\x17\x0e\xc7\x71\x92\xf1\xc2\ -\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x47\x1a\x97\x2e\x5d\ -\x5a\xb0\x60\x41\x10\xfe\x50\xda\xf9\x0f\xd0\xd7\xd7\xd7\xfb\x87\ -\x7d\xfb\xf6\x7d\xfb\xf6\x8d\xce\x63\xc7\x8e\x85\xae\xde\x5e\x26\ -\xbc\x7e\xfd\x5a\x93\xa7\x3a\x0a\x22\x46\xcd\x9c\x39\x53\x46\x7d\ -\xfc\xf8\x11\xab\x65\xe9\x91\x23\x47\x34\x6d\xaa\x73\xfb\xf6\x6d\ -\x59\x04\x5b\xb6\x6c\xb1\xf0\xc5\x61\xc5\x58\xc5\xba\x06\x2f\x1c\ -\x09\x90\x49\x0f\x1e\x3c\xf8\xf0\xe1\x43\x90\x33\x4a\x3b\xff\x0d\ -\x06\x06\x06\xf6\xee\xdd\x3b\x3e\x3e\xfe\xf5\xeb\xd7\xe7\xcf\x9f\ -\xbf\x7b\xf7\x8e\xce\xfe\xfe\xfe\x19\x33\x66\xd0\x09\xf3\xe7\xcf\ -\x1f\x1b\x1b\xd3\xe4\x29\xcd\xc8\xc8\xc8\xe5\xcb\x97\x6f\xdc\xb8\ -\x21\xa3\x96\x2e\x5d\xca\xc9\x59\xb1\x62\xc5\xf2\xe5\xcb\xe9\xb9\ -\x75\xeb\xd6\xdc\xb9\x73\xc3\xd4\x29\xce\xb6\x6d\xdb\x30\xf0\xd5\ -\xab\x57\xc4\x74\xde\xbc\x79\x3b\x77\xee\x54\xbf\x85\x95\x4c\x7e\ -\xf6\xec\xd9\x89\x13\x27\xd4\x5f\x49\x2b\xfe\x05\x34\x74\xf4\xe8\ -\x51\x89\x0f\x1f\x3e\x54\x0f\x8d\x58\x14\xf8\x17\xcf\x6a\xe6\x64\ -\x70\xf8\xf0\xe1\xcd\x9b\x37\x07\xa1\x29\xac\x20\x6d\x83\x9c\x21\ -\x43\xd0\x1f\x27\x9a\x68\xe0\xdf\x9c\x5d\x2c\xa2\x02\x11\xe4\x8c\ -\xd2\xce\x06\xe4\x76\x07\x0c\x97\x62\xcd\xb0\x05\x87\x87\x87\x43\ -\x57\x86\x5c\x71\xf5\xea\xd5\x58\x34\xe2\x4d\x69\x6b\x1a\x4b\xe1\ -\x0d\xf5\xd3\x43\x3f\x0d\xac\xc6\x75\x0c\xb5\xa6\x4e\x0c\x34\x64\ -\x7d\x29\x80\x3e\xa1\xb7\x11\x5a\x44\x70\x12\x2c\x87\x21\x67\x29\ -\x35\x51\x16\xf1\x17\x91\xb3\xa4\x69\x82\x0f\x55\x34\xbb\x02\x06\ -\x6a\x53\xc1\xca\xb9\xed\x1a\x50\x65\x0e\xe4\xb6\x23\x4c\xb6\x1d\ -\x51\xb3\xba\x0f\x8c\xaa\x41\x58\xcd\x5e\x62\xfa\xd7\x28\x94\xa7\ -\x3b\x07\x86\x2f\x89\x65\x90\xb3\x1c\x8a\x63\x40\x1b\x6d\x68\xa0\ -\xab\xb4\x9c\xa4\xda\xa1\x94\x8d\x35\x69\x06\x7a\xca\xd1\xe6\x5c\ -\x50\x4f\xac\xb9\xd9\x05\x98\x1c\xbb\x18\x33\x2f\x5e\xbc\x48\x23\ -\x3e\x2d\xa5\x9d\xa5\xb0\x17\x93\x83\x50\x41\xbc\x3b\xab\xb1\xbb\ -\x16\x6f\x0c\x0b\xb2\x6f\x1c\x38\x8c\x65\x59\xdb\x05\x74\x6c\xe4\ -\x04\xd2\x2b\xde\x14\xb7\x33\x04\x74\x5a\xe6\xe1\x16\x75\x82\x55\ -\x9f\x2a\x3a\xb1\x1a\x65\x40\xde\x63\x71\x3e\x51\x7f\x33\x30\x04\ -\xc5\x14\x65\xd6\x8c\x95\x8c\x2d\xe5\xfc\x60\x9d\x2a\x20\x13\x62\ -\x87\x08\x46\xe3\xc4\xa8\xa7\x43\x33\x15\x08\xb6\xe6\x88\xe2\x52\ -\x1a\x1a\x6a\x46\x95\x39\xc2\xb6\x63\x1a\xdb\xd9\x09\x8a\x0b\x84\ -\x56\x50\x9b\x6f\x2d\xee\xac\xf9\xd7\x28\x94\x3f\x55\x3e\x7f\xfe\ -\x7c\xfc\xf8\xf1\xef\xdf\xbf\xdb\x13\x88\x0b\xf9\xd6\xad\x5b\xd5\ -\x86\x1f\x3f\x7e\x6c\xda\xb4\x89\xc6\xac\x59\xb3\x06\x07\x07\xd1\ -\xf2\xec\xd9\xb3\x1a\xea\x2e\xe7\xce\x9d\x3b\x75\xea\x14\x7e\x09\ -\x72\x04\x2a\xf1\x48\xcb\x3d\xc6\x78\x9e\xf1\x8a\x0b\x42\xc4\x97\ -\x2f\x5f\x36\x6c\xd8\x40\x43\xf7\x6d\xe0\x4d\x3b\x7d\xfa\x74\x1a\ -\xab\x56\xad\x52\x0f\xb0\x91\xec\x82\xfd\xfb\xf7\x63\xa6\x3c\xc0\ -\xdf\xa1\xa1\xa1\x43\x87\x0e\xf1\x02\xe4\xd2\xae\x09\xa5\x9d\x13\ -\xc1\xbc\x0a\x6b\xd7\xae\xe5\xb1\xad\x76\x0c\x6f\xd1\x6b\xd7\xae\ -\x05\x21\x03\x35\xf0\x43\x10\xda\xc1\x1c\xac\x7e\xf1\xe2\x85\x44\ -\x7c\x75\xf2\xe4\xc9\x95\x2b\x57\xda\x2e\x80\x67\xf8\x2b\x27\x70\ -\x45\x67\x94\x97\x17\x6d\x96\x25\x01\x94\x25\x3c\xf5\x71\x57\x6b\ -\x76\x4f\x0f\xbb\xab\x88\x90\x82\x24\x89\x3a\x1b\xc3\x1b\x01\x25\ -\xef\xdc\xb9\x83\xbd\x88\xf8\x9c\xfb\xb3\x86\x0c\x02\x9a\xfb\x27\ -\x06\x0c\xc1\x64\x12\x20\xc8\x11\xa4\x2e\x87\x84\xb4\xa4\xcd\x9a\ -\xb4\x3f\x7d\xfa\xa4\x21\x59\xba\x70\xe1\x42\xfe\xb2\x0b\x4e\xd0\ -\x0a\x4c\x88\x1d\x22\xd0\x2a\x4e\x8c\x89\x43\x70\xd7\xac\x59\x43\ -\x83\xad\xcf\x9f\x3f\x8f\x78\xfd\xfa\x75\x0d\x19\xa9\x29\xcd\xdf\ -\xa2\x39\x02\xfd\x97\x2c\x59\x42\x03\x57\xec\xd8\xb1\x03\x51\xfd\ -\x37\x6f\xde\x44\x54\xfb\xca\x95\x2b\x14\x08\xb5\x09\xeb\xc6\x8d\ -\x1b\xd5\xe6\x2c\xeb\xb0\xd4\x50\x5e\x38\x48\x9d\x45\x8b\x16\x91\ -\x2e\xa3\xa3\xa3\xea\x79\xfa\xf4\xa9\x42\x2b\xee\xde\xbd\x2b\xb5\ -\xc4\xee\xdd\xbb\x99\x10\x84\xee\x81\x31\x3c\x32\x67\xcf\x9e\x1d\ -\xe4\x76\x70\x16\xc4\x8e\xc6\xc5\x3c\xcf\x4a\xe3\xfd\xe4\xc9\x93\ -\xc5\x8b\x17\xe3\xa6\x5f\xbf\x7e\x21\xf2\x09\x6f\xda\xf5\xeb\xd7\ -\x5b\x92\x09\xec\x52\x74\x41\x81\xd1\x73\xf7\xe0\xc1\x83\xf6\xc3\ -\xc5\x22\x6f\xdf\xbe\x2d\xed\xd4\x87\x8d\x61\x77\x55\x67\x32\x00\ -\x5b\xf8\x51\xda\xb5\x6b\x97\x86\x8c\x3d\x7b\xf6\x30\x64\xb5\x83\ -\xe3\x8d\x15\x07\x0e\x1c\x90\x98\xe3\xe7\xcf\x9f\xab\x57\xaf\x36\ -\xff\x90\x28\x03\x03\x03\x44\x2a\x8e\x1d\x9e\xa1\xee\x9b\x13\xde\ -\xbf\x7f\x8f\xcf\x69\x8c\x8d\x8d\xe9\x38\xa1\x0c\x15\x04\x65\x68\ -\x3f\x7a\xf4\x88\xbf\xf2\x09\xe7\x4d\x9d\x8d\x61\x91\x33\x67\xce\ -\x9c\x3e\x7d\xda\x76\x27\xc7\x2e\x5c\xb8\xa0\xb6\x41\x40\x09\xab\ -\xd5\x0e\xbe\x22\xe8\x8a\xbe\x7a\x62\x48\x5d\xab\x02\xcc\xe4\xc0\ -\xcc\x99\x33\x47\x22\x96\x12\x6e\xfb\x8a\x35\xd5\x66\x02\x9e\x67\ -\xb2\x56\xd6\xf1\x63\xe6\xbd\x7b\xf7\x68\x14\xcb\x56\x03\x58\x13\ -\x4d\x74\xc8\x01\x7b\x49\x98\x97\x2f\x5f\x4a\x34\x32\x9b\x12\x52\ -\xba\xd4\x1c\x20\x2b\x28\x4c\xfc\x06\x48\x7c\xf3\xe6\x0d\x33\x69\ -\xb0\x2c\x96\xd2\x4f\x83\x5f\x02\x9c\xcf\x45\x89\x7e\xc2\xca\xaf\ -\x14\x9f\x2b\xf1\x18\xed\xef\xef\xcf\x3e\xad\x46\x79\x9f\x43\x37\ -\x37\x6e\x2c\xec\x47\x83\x5f\x18\xec\xcc\x46\x5a\xa8\x7a\xf1\x37\ -\xc8\xd9\x8d\x5d\x9f\xe4\xe0\x2b\xed\x52\xa4\xfe\x62\x0f\xdc\xa3\ -\xb4\xa6\x2e\x9c\xea\x2c\xc2\x15\x8b\x69\x4c\xb6\x46\x18\x68\x87\ -\xeb\x19\x0a\xa3\x8f\xae\x94\x4c\x66\x59\x3a\xe3\xdb\x1d\x66\xb2\ -\x91\x56\xc0\x76\x4e\x85\x2e\x7b\xb2\x42\x1e\xa0\x52\xb4\xb4\xcf\ -\xc4\x62\x27\xed\x2a\x6c\xeb\x2a\xe4\x55\x03\xdd\xaa\x6c\xd1\x83\ -\x82\x4d\xad\x11\x06\xda\x61\x54\x66\xb2\x1a\xa2\xcc\x97\x8d\x71\ -\xec\xd8\xc8\xae\xd0\xcc\x67\x41\x1a\x6c\x9d\x69\xd1\x82\x1e\xfa\ -\xa5\x0c\x1e\x0e\xbd\x9d\x3d\xd4\xeb\xad\x96\xdf\xaa\xcc\x8c\x61\ -\x0e\x5b\x4b\x0d\x35\xc2\x40\x01\x73\x08\xba\x31\x13\xd4\x0f\x16\ -\xee\xd8\x52\x44\xd6\x64\x48\x46\xd9\x7c\x16\xd1\x61\xab\xf1\xb0\ -\xf1\xd7\xe0\x6a\xb5\x20\x64\xf0\x49\xfc\x84\x8c\x41\x37\xd4\x40\ -\x2b\x6b\x84\x81\x76\xaa\xcc\x01\x1e\x1d\xda\x8e\x6f\x69\x63\x85\ -\x5e\x34\xec\x98\x59\xd9\x22\x0e\x1f\xbb\xa8\x33\x8e\x75\x3d\x25\ -\xb9\xae\x84\x53\x9b\xb5\x10\xd9\x3b\xf6\x4b\xa9\x17\xd0\x23\x08\ -\x5d\x82\x1d\x65\x2d\x0a\x48\x0d\xf5\x17\x91\xd7\x6a\x5c\x0c\x4a\ -\x08\x1c\xc7\xb2\x2c\x85\xc2\x88\xb9\x9c\x90\x8b\x05\x06\xd6\xa7\ -\x42\x27\xb0\x4b\x58\xae\x40\xb1\x6e\xa2\x89\x94\x04\x9d\xf6\xe2\ -\x1c\x03\x13\x50\x3e\xa7\x7f\x0e\xcc\x61\x14\x9f\xb0\x14\x22\x01\ -\x62\x41\x4b\x29\x83\x45\x32\x8d\x5a\xc4\xc9\xd4\x98\xce\xad\x26\ -\x70\x0a\x44\x27\x60\x08\xfe\x41\x5b\x4b\xce\x22\x4a\x15\xc1\x4c\ -\x22\x18\xa7\x44\x6c\x29\x8b\xd8\x31\x6b\x46\x52\x70\xd9\x2e\xa7\ -\x36\xd3\x88\x45\x10\x0a\x30\x19\x6d\xeb\x53\xba\xc6\x1c\xe2\x18\ -\x06\xb2\xdf\xb6\x9a\x44\x6a\x4c\xc9\x53\x85\x2b\x10\x77\x51\xb5\ -\xd1\x60\x74\x74\x94\xeb\x1f\x37\x5e\xf5\x00\x37\x9f\xf8\x4d\xc8\ -\xf5\x86\x6b\xad\x3d\x9c\xba\x02\x6b\x0e\x0d\x0d\x6d\xdf\xbe\xbd\ -\xb7\xb7\x77\xd9\xb2\x65\xf4\xfc\xfe\xfd\x5b\x43\x0d\xe0\xe6\xc6\ -\x69\xa1\x31\x6d\xda\xb4\xfb\xf7\xef\xb3\x32\xf7\x61\xb6\x88\xaf\ -\x73\x80\x99\x56\xfe\xb8\xb1\x0f\x0e\x0e\x86\x81\xa6\xf0\x74\xd7\ -\x6a\x40\xfc\xe2\x4a\x14\xbf\xfb\x04\x5e\xed\xeb\xeb\x53\x9b\x51\ -\xe6\x3f\x7e\xfc\x58\x62\x33\xf4\xde\xd4\x2b\x60\x64\x64\x84\xbb\ -\x28\xcb\xe2\x8a\x38\x76\xba\xd3\x5a\xb1\xe0\x05\x64\xa1\x6f\x4c\ -\xe7\x56\x13\x02\xbb\x5d\x77\x05\x52\x97\xe3\xc4\x46\x2a\x97\x3c\ -\x4e\xed\x11\x14\x5b\x8a\x56\x4c\x9b\xe0\xd6\x49\xc1\xe5\x1d\xb1\ -\x6e\xdd\xba\x20\x64\x6f\x70\xfe\xda\xbf\x29\x34\xa0\xde\x1c\xde\ -\x23\xaa\x4a\x68\xc5\xbb\xa3\xa8\x4f\x17\xc8\x2c\x6d\x03\x3d\x2c\ -\x93\x74\xb9\x80\xb8\xf2\x51\x08\xe3\x1f\x3a\xe6\xdb\x4f\x65\x0e\ -\x86\xc2\x36\x05\xea\xab\x20\x1f\xc6\x5b\xd4\xcc\xa7\xd6\xaa\x30\ -\x5b\x23\x0c\x44\xe0\x3e\xf9\x91\x2b\x0c\x4b\x29\xc6\xac\xaf\x24\ -\x33\x10\xe3\x4d\xbb\x0b\x16\xc5\xb9\x55\x24\xf6\xaa\xf2\xbe\xea\ -\x17\x89\xe8\x48\x55\x6b\x84\x81\x76\xcc\x3a\x56\xa6\x2d\xcf\x10\ -\xca\x78\x59\xda\xf4\x04\x61\x12\xa8\xb7\x9a\xd1\xdc\xef\x70\x15\ -\x28\x8f\x15\x4c\xb6\x46\x18\x68\x87\xba\x6f\xa5\x9f\x39\xac\xaf\ -\x36\x60\xa9\x39\x04\x8f\xe1\x5e\xb5\xbb\x42\xbd\x99\x8a\xa6\xdd\ -\x08\x10\xd1\xa4\xea\x9d\x02\x96\xc9\xd6\x08\x03\x11\x35\xe6\x90\ -\x15\x88\x3a\xc2\x6c\x4a\x7b\x32\x6e\x1c\x79\xf7\xc9\x48\xd3\x55\ -\x22\xda\x4b\x04\xf5\x48\x2d\xce\x21\x2e\x23\xf3\x24\x76\x0b\x96\ -\x8d\xb3\x59\xc6\xeb\xd9\x92\x23\xe7\xd9\x2a\x47\xd3\xa9\xcf\xf1\ -\xa0\x15\x41\x34\x8f\xed\x52\x4d\x99\x0c\x17\x8b\x4e\x72\xcb\x82\ -\xcd\x64\xd2\x22\xbe\x7c\x1a\xcc\x61\xc8\x8a\x45\x4e\x34\x30\xc7\ -\xac\x63\x35\x15\x0b\xac\xcb\x79\x92\x39\x8c\x06\x61\x12\xa8\xb7\ -\x9a\x21\x33\x13\x43\x50\xa6\xd4\xff\x38\x87\x21\x82\x5b\x2a\x1a\ -\xf2\xa1\x6d\x97\x3b\x4e\xb1\xa5\x5d\x3f\x4e\xf5\x66\xe2\x70\x1d\ -\x72\x34\x44\x2b\x32\x90\xf9\xb4\x35\x9a\xa3\xf3\x94\xae\x32\x47\ -\xff\x90\xa1\x36\xb0\x5d\x8d\x6e\x8d\xc9\x17\x0e\xb4\x61\x57\xd3\ -\x09\x28\xe1\x71\x75\xc4\x12\x26\x08\x74\x62\xa8\xca\x05\xcd\xc0\ -\x7e\xbc\xcc\xca\xe6\x08\xed\x85\xa7\x24\x1a\xf8\xab\x58\xb6\x51\ -\x2f\x3e\x18\x80\xd7\xb4\x42\x90\x33\xac\xd3\x7c\x2a\x11\x24\x76\ -\x9d\xfa\xdc\x8a\xbd\x8a\xf9\xf8\xbc\xb4\x6a\x00\x8b\xe4\xca\x34\ -\x62\x1c\x2f\xa1\xa5\x72\x3b\xaa\x13\x24\x16\x9d\xd0\x75\xea\xad\ -\x26\x73\x62\xc3\x8b\x56\x08\x02\x9a\xab\x8c\x7c\xc8\xe4\x9c\x8b\ -\xe8\xd1\x3a\xca\x1c\x1d\x27\x5d\x40\x8a\x96\x92\x60\x64\x54\x95\ -\x93\x53\xa9\x31\x13\x55\xd9\x48\xbb\x03\xed\xf8\xc6\x97\x23\x35\ -\xa5\x8b\xe6\x60\xbb\x86\xcc\x99\x7c\x4e\x46\xd9\x69\xea\x16\xfe\ -\x7f\x8f\xe0\x38\x4e\x32\xfe\xdf\xaa\x38\x8e\x93\x8c\x17\x0e\xc7\ -\x71\x92\xf1\xc2\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\ -\xe3\x38\xc9\x78\xe1\x70\x1c\x27\x19\x2f\x1c\x8e\xe3\x24\xe3\x85\ -\xc3\x71\x9c\x64\xbc\x70\x38\x8e\x93\x8c\x17\x0e\xc7\x71\x92\xf1\ -\xc2\xe1\x38\x4e\x32\x5e\x38\x1c\xc7\x49\xc6\x0b\x87\xe3\x38\xc9\ -\x78\xe1\x70\x1c\x27\x91\x9e\x9e\xff\x01\xcb\x50\x49\xc4\xb5\x83\ -\x05\xaf\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x02\xd7\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x45\x00\x00\x00\x1b\x08\x02\x00\x00\x00\xa5\x6b\xd5\xf9\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\x6c\x49\x44\x41\x54\x58\x47\xed\x98\xb1\xce\ -\x29\x51\x10\xc7\xb9\x6f\xe0\xf2\x06\x14\x12\x25\x9d\x8a\x02\x89\ -\xde\x55\x6a\x91\x48\x68\x24\x3c\x01\x85\xda\x1b\xf0\x02\xb4\x0a\ -\x0a\x05\x09\x89\x12\x05\x2d\x11\x4f\xb0\xf7\x97\x9d\x73\x8f\xb5\ -\xbb\xf7\xcb\x0d\xb7\x58\x5f\xf6\x57\x9c\x6f\x66\xf6\xec\xec\xf9\ -\xcf\xcc\x12\x5f\xd0\x30\x8c\xc0\x37\xe2\x87\xfa\xfb\x5d\xf0\xf5\ -\x78\x9b\x0f\xd0\x73\xbd\x5e\x63\xb1\xd8\x78\x3c\x56\xbe\x89\x6b\ -\x10\x3e\x40\xcf\x60\x30\xe0\xe8\xa7\xd3\x49\xf9\x26\xae\x41\x70\ -\xd7\x73\x3c\x1e\x83\xc1\xe0\x62\xb1\x50\xfe\x4b\xf4\xfb\x7d\x92\ -\xd8\xf2\x50\xd7\x9f\x26\xdb\xed\x56\x22\xb2\x47\x20\xce\x5d\x12\ -\x17\xa6\xd3\x29\x6b\x36\x9b\x15\x57\x70\x0d\x2a\xf8\xbc\x76\x92\ -\xcf\xe7\xa3\xd1\xe8\x68\x34\x52\xfe\xab\xa4\x52\x29\x52\x4d\x26\ -\x13\xe5\x1b\x46\xa7\xd3\x09\x85\x42\xac\xca\x37\x0c\xae\x72\x8c\ -\xcb\xe5\x82\xcd\x13\xb1\x37\x9b\x8d\x5c\x22\x48\x06\x56\xf6\x90\ -\xe7\x8b\xa0\xc6\xa5\x3f\x94\x33\x99\x4c\xba\x76\x13\x0a\x85\x82\ -\x2e\xad\xc0\x10\x77\xbb\x5d\xe5\x3c\x43\x51\x58\x77\xbb\x9d\xb8\ -\xdc\xb8\x5e\xaf\x31\xd2\xe9\xb4\x44\xe0\x7c\x3e\x73\xbe\x70\x38\ -\x8c\x5d\x2e\x97\x59\x97\xcb\xa5\x79\x25\x50\xaf\xd7\x57\xab\x55\ -\x24\x12\x29\x16\x8b\x12\x01\xd7\xa0\xc6\x45\x4f\xb3\xd9\x6c\xb5\ -\x5a\xca\x71\x50\xa9\x54\x32\x99\x8c\x96\x84\x98\x5a\xad\x56\x2a\ -\x95\xc4\xb5\xc2\x1e\xf4\x30\x15\xf7\xfb\x5d\x22\xed\x76\xbb\xd1\ -\x68\xdc\x6e\xb7\x78\x3c\x2e\x11\x98\xcd\x66\xb9\x5c\x4e\x6c\xe6\ -\x9c\x35\x91\x48\xb0\x92\xf9\x70\x38\x48\xdf\xe6\xf3\xf9\x7e\xbf\ -\x67\x56\x5d\x83\xe6\xad\x7f\x30\xbb\xf4\xa0\xd7\xeb\xc9\x98\xd1\ -\x4a\x6c\x09\xda\x60\x03\x33\xc3\x54\x68\x43\x5d\x78\x66\x38\x1c\ -\xb2\x81\x24\x32\x15\x62\x13\x44\xa4\x6c\x10\xc8\x20\x03\x49\x1e\ -\x1a\x05\xd8\x9c\x55\x8e\x87\x81\x2b\x7d\xae\x56\xab\xce\xa0\xed\ -\x90\x4f\x7a\xd0\xad\x27\xf2\x97\x89\xd8\x4e\x44\xc9\x17\x62\x80\ -\xdb\xa9\xa5\x4c\xb9\x1e\x7a\x82\x1c\x4b\xed\x30\x35\xc8\x11\x81\ -\x6c\x5c\x92\xda\xbf\xcc\x93\x1e\x5d\x00\xc1\xf9\xb6\x69\xfe\x45\ -\x8f\xf4\x41\x2a\xad\xdb\x4e\x50\x0c\x81\x76\x91\x44\x39\xff\x83\ -\x87\x1e\x1e\x6c\x9d\x04\x3d\x27\x4e\x44\x0c\x4a\xb4\xa1\x2e\x58\ -\x20\x9b\xb4\x97\x7a\xeb\xd2\xd0\x2e\x6c\xeb\x7e\x5b\xbb\xde\xe7\ -\xa1\x87\x79\xb0\x56\x8e\xc7\xc8\x28\xdb\xb0\x69\xf8\x9b\x24\x3e\ -\x91\xf5\x87\xb2\xd6\x40\x8d\xb0\xf5\x44\x89\x54\xdb\x0b\xf0\x26\ -\x4a\x0f\x75\x22\xb5\x2e\x95\x3c\x18\xe4\x4d\xb5\xe2\x1c\x71\x24\ -\x59\xbf\x4f\x40\x66\x0c\xe4\xc5\x15\x74\x50\xb7\x1d\x43\x22\xd6\ -\x6d\x6f\xe2\xff\xfe\xf1\x36\xbe\x1e\x6f\xe3\xeb\xf1\x36\xbe\x1e\ -\x6f\xe3\xeb\xf1\x36\x9f\xa7\x87\x1f\xc8\xb6\xff\x31\x3c\x08\x04\ -\x7e\x03\x32\xd4\x1d\x05\x0b\xb9\xf1\x3b\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x03\x31\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x48\x00\x00\x00\x18\x08\x02\x00\x00\x00\xd6\x01\x2c\xe7\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x02\xc6\x49\x44\x41\x54\x58\x47\xed\x97\x3f\x4e\ -\x6a\x41\x14\x87\x2f\x6f\x01\x88\xb8\x83\x27\x25\x09\x8d\x46\x13\ -\x12\x12\x4d\x00\x4b\x3a\x12\x76\xa0\x4b\xc0\x15\xb8\x01\x94\x84\ -\x5e\x3a\x68\x90\x00\x25\x14\x2a\x0d\x54\x90\x18\xad\x2c\x35\x06\ -\x36\x80\x1f\xf7\x37\x8e\xf7\x5e\x88\xef\xc5\x50\x88\xe1\x2b\x86\ -\x73\xce\xcc\x9d\xf3\x67\xce\x4c\x42\x68\x36\x9b\x39\xbf\x91\x3f\ -\xe6\xf7\xd7\xb1\x49\x6c\xdd\xd8\x24\xb6\x6e\xfc\xf4\xc4\x6e\x6e\ -\x6e\x42\x1f\xc4\x62\xb1\x6a\xb5\x8a\xf1\xf5\xf5\xd5\x98\x42\xa1\ -\x68\x34\x7a\x7e\x7e\xae\xc5\x3e\x78\xee\x7f\x38\xbb\xbb\xbb\x83\ -\xc1\x00\xe1\xea\xea\x2a\x9b\xcd\xca\x78\x7a\x7a\x8a\x8a\xc0\xd4\ -\xd2\x2c\x82\x27\x76\x72\x72\x62\x4a\xe1\x42\x91\xa8\x99\x99\xfb\ -\x16\x76\x43\xa3\xbb\xf4\x7a\x3d\x2c\xfb\xfb\xfb\xd4\xde\xaa\x16\ -\xaf\xd3\xa7\xa7\x27\xc6\x44\x22\xc1\xca\xe1\x70\x78\x7c\x7c\x2c\ -\x7b\xbb\xdd\x4e\xa7\xd3\x08\xb7\xb7\xb7\x64\x2b\xa3\x0f\x93\xe0\ -\x07\x2f\x2f\x2f\x18\x1b\x8d\x86\x64\x0a\xb3\xbd\xbd\xad\xa9\xef\ -\xc1\x26\x72\x8c\x60\x4c\xb3\x99\x2c\xf2\x22\x8a\xc5\xe2\xde\xde\ -\x9e\x64\xaf\xd3\xeb\xeb\xeb\x79\x94\x2e\xd8\x65\x7c\x7c\x7c\x34\ -\x26\xc7\xe1\x2b\xef\xce\x96\xe0\x89\x4d\x26\x13\xc6\x83\x83\x03\ -\xc6\x9d\x9d\x9d\x54\x2a\xe5\x9a\x7d\x50\x45\xce\x41\xc5\xb6\x9c\ -\x9d\x9d\x2d\x3d\xdb\xe7\xe7\x67\x95\x79\x34\x1a\xc9\x52\x2e\x97\ -\x23\x91\x08\x82\xbc\x08\x62\xcd\x64\x32\x92\x0b\x85\xc2\xdb\xdb\ -\x1b\xe7\x83\x5c\xaf\xd7\xd5\x72\x2c\xb8\xbc\xbc\xd4\x01\x76\x3a\ -\x9d\x7c\x3e\x8f\x51\xc7\x80\x3a\xff\xcc\x4f\x30\xb1\xfb\xfb\x7b\ -\xca\x49\x4a\xc8\x04\x4a\xb8\xa5\x52\x49\x53\x96\xbf\x2e\xde\xdc\ -\x58\xd6\xef\xf7\xbd\x81\x5a\x68\x95\x78\x3c\xce\x9e\xd3\xe9\x14\ -\x95\x4f\x2a\x95\xca\xd1\xd1\x11\x37\x47\x5e\x04\xad\x95\x4c\x26\ -\x25\x53\x0b\x46\xb5\x1f\xf6\xc3\xc3\x43\xd4\xf1\x78\xcc\xb8\xb5\ -\xb5\xc5\x58\xab\xd5\xd8\x41\x2b\x29\x41\x38\x1c\x46\x0e\xe2\x9e\ -\xdb\x27\x1c\xb7\x99\x70\x1c\xfa\xc1\xdb\x2d\x01\x58\xa9\x36\xb0\ -\x82\x99\xf0\x43\x69\x29\x36\x89\x5d\x5c\x5c\xa0\xb2\xb8\xdb\xed\ -\x62\xb4\x7d\x05\x7a\x00\xb4\x03\x1e\xf1\x4b\x67\x22\x33\x2a\x12\ -\xc0\x85\x82\x61\x34\x26\xc7\xa1\x3a\xda\x76\x91\x60\x62\x2c\xd5\ -\xf7\xb8\xc1\x3d\x01\xc9\xbe\x14\x82\x23\x88\x2f\xb2\x02\x66\x19\ -\x09\x91\x08\x48\x40\x1b\xf2\x15\x97\xc7\x9d\x9f\x43\xb3\x99\x48\ -\xbf\x8c\xf5\xff\x61\x07\x5f\x62\xc4\xc7\xd6\x14\x58\x2a\xa5\x45\ -\x95\xbc\x94\x7f\x26\x46\x26\xba\x0c\x78\x22\x25\x60\x73\xf0\x7a\ -\x01\xd6\x68\xd9\x0a\xf1\xdd\xb1\xbb\xbb\x3b\x0a\xc6\xfd\x91\xda\ -\x6c\x36\x89\x5b\xf2\x22\xba\x57\x0f\x0f\x0f\xbc\xda\x8b\x6f\x89\ -\x68\xb5\x5a\xba\x0c\x5c\x33\x64\x5e\x11\x36\xe7\x1a\xb3\xad\xf5\ -\x02\x5c\xa4\x5c\x2e\x67\x94\x55\x61\x12\x74\xa1\x61\x6c\xe5\xf4\ -\xce\xaa\xd7\x17\x09\xdc\xab\x80\x6a\xc1\xa8\xc6\xe6\xf0\x29\x99\ -\x16\x70\x6e\xea\x4f\xa1\x3b\xc3\x02\xa3\xaf\x88\xcf\xc4\x68\x1b\ -\xef\xf9\xe0\x5b\xef\xec\x22\x74\xd1\x62\xc2\xe4\xa6\x1c\x2c\xf3\ -\x46\x77\x31\xba\x8b\x35\xda\x8b\x24\x15\xa4\xae\x8a\xcd\x3f\xe8\ -\x75\x63\x93\xd8\xba\xb1\x49\x6c\xbd\x70\x9c\x77\x69\xcd\x78\xc7\ -\x7f\xf6\xa6\x43\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ -\ -\x00\x00\x04\x57\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x83\x00\x00\x00\x17\x08\x02\x00\x00\x00\xa7\x08\x6b\x64\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x03\xec\x49\x44\x41\x54\x68\x43\xed\x98\x3d\x2f\ -\x74\x41\x14\xc7\xd7\xf3\x05\xbc\x75\x0a\x05\x8d\x44\x21\x11\x2f\ -\x8d\x4a\x81\xa8\x25\x44\xab\x5a\xad\x84\x84\xf8\x00\x5a\x09\xe1\ -\x13\xac\x42\xa1\xa1\x91\x50\xd0\x69\xa8\xb6\x59\x2a\xd9\xca\xcb\ -\x47\xe0\xb7\xf3\x9f\xe7\xec\xec\xdc\x67\x37\xbb\x5c\x9e\x5b\xdc\ -\x5f\x71\xcd\x9c\x39\x77\xe6\x3f\x73\xce\x9c\xbb\xd1\xf5\xf1\xf1\ -\x51\xc8\xc9\x00\x7f\xfc\xdf\x9c\xff\x4d\x1e\x89\xac\x90\xe9\x48\ -\x5c\x5c\x5c\x74\x05\xac\xac\xac\x60\x9c\x9c\x9c\xf4\x7d\xc7\xc3\ -\xc3\x03\xc6\xdb\xdb\xdb\x85\x85\x05\x9e\xee\xbd\xdf\xe6\xf5\xf5\ -\xd5\xab\x71\xf4\xf5\xf5\x61\xdc\xd9\xd9\xf1\x7d\xc7\xf1\xf1\xf1\ -\xd3\xd3\xd3\xfa\xfa\x3a\x6d\x1c\xd8\x9a\xde\x35\x32\x1d\x89\xc5\ -\xc5\xc5\xe1\xe1\xe1\xfb\xfb\x7b\x3e\x66\xe7\xe7\xe7\xe3\xe3\xe3\ -\x18\x37\x36\x36\x96\x97\x97\xb1\xc0\xc4\xc4\xc4\xd8\xd8\xd8\xc9\ -\xc9\xc9\xf3\xf3\x73\xa5\x52\xd1\x5b\xbf\x4f\x7f\x7f\x7f\xb1\x58\ -\x3c\x3a\x3a\x42\xd2\xcb\xcb\xcb\xd4\xd4\x14\xc6\xb5\xb5\xb5\xde\ -\xde\x5e\xe9\xdc\xde\xde\x1e\x1d\x1d\x3d\x3d\x3d\x45\x2d\x5d\x9c\ -\xf7\xf7\xf7\xf5\x6e\x1d\xb9\x8a\x9b\x9b\x1b\x6f\x0d\x28\x95\x4a\ -\x7e\xb8\x73\xe6\xe7\xe7\x35\x89\xef\x3b\xb4\x0a\x87\x88\x68\xeb\ -\x1a\x1c\x3d\x87\x2e\xcf\xc7\xc7\x47\xba\x34\xf6\xf6\xf6\x70\x93\ -\x91\x6d\x20\x89\x77\x2d\x1e\x82\xb5\xcc\xe7\xcb\x98\x60\xc1\x12\ -\x12\x09\x49\x9d\xe1\xc9\xd0\x45\x2d\x3e\x48\x95\x85\x51\xa4\xd2\ -\x60\x4e\x59\x0c\x86\xcc\xcd\x68\x38\x23\x20\x7a\x9c\x91\xda\x88\ -\x20\xaa\xdf\xd9\x1e\x33\x68\x6f\xb6\x1f\x90\xc5\x8e\x1b\xc2\x45\ -\x51\x6f\xa9\x84\x62\xb7\xeb\x1a\xb2\x00\x7b\x96\x25\xda\x4c\x2a\ -\x91\x40\x27\x33\x4b\x9b\xf2\x40\xa7\x29\x42\x9d\xac\x8e\x27\x3e\ -\xb4\x79\x3a\x45\x35\x4c\x03\x2f\xca\x12\x45\x82\x25\xa2\x1c\x12\ -\x71\x75\x62\xd2\xb9\xb9\x39\xb5\xb9\x74\x5c\xb4\x99\x99\x19\x75\ -\x05\xc5\x8e\x8a\x4c\x65\xf4\x7d\x07\xe5\x2f\x59\xf8\x80\xa2\x31\ -\x3b\x3b\x4b\xa3\x5c\x2e\xcb\x42\xb9\xec\xe9\xe9\xa1\x31\x3d\x3d\ -\x2d\x0b\x84\x8b\xae\xae\xae\xbe\xbf\xbf\xab\xfa\x9f\x9d\x9d\xe9\ -\xca\xdb\xae\xb0\xbf\xbd\xbd\x61\x61\xc3\x83\x83\x83\x32\xb6\xa6\ -\x53\xc1\x3c\x47\x46\x46\x78\x0e\x0d\x0d\xa1\x8a\xd7\xdd\x48\x0d\ -\x74\xf2\x95\x52\x7b\x69\x69\x89\x67\xb5\x5a\xe5\x79\x79\x79\xa9\ -\xc3\x25\x3c\x03\x03\x03\x6e\xbc\x40\xcd\x54\x5d\x65\x1e\x59\x00\ -\x19\xbb\xbb\xbb\x07\x07\x07\xbe\x1f\x82\x6b\x08\xf9\xa8\xf7\x5b\ -\xc0\xb9\x58\x6d\x49\x76\x43\x38\x47\xf2\x8b\xa4\x50\x96\xe1\x83\ -\x27\x46\xd5\x1c\x83\x45\xed\x8a\xe8\x1e\xd0\xc0\x39\x79\x23\xd9\ -\x6a\x94\x62\x02\x67\xe6\x0c\xef\x59\x48\x47\x82\x43\x6d\xb8\xe1\ -\xec\x3b\x4e\xa7\x55\x24\xd6\x42\xa7\xee\x04\x92\xa2\x0b\x8a\xec\ -\xe4\xd9\xb2\x22\xb3\x69\x5d\xae\x97\x8c\x46\x83\x37\x31\xa8\x05\ -\xe7\x2f\xcd\x36\x06\xb6\x99\x16\xbb\x02\x32\x05\xad\x26\x14\x67\ -\x24\x62\x0c\xb7\xa7\x45\x35\x03\x2b\xb2\x5b\xa9\xe4\x89\x3d\x3c\ -\x77\x7c\x9c\xae\x7a\x05\x10\x2a\x14\xe2\x9f\x71\x82\xf6\x05\x4b\ -\x1b\xb2\x69\x20\x46\x67\x0d\xd2\xa9\x6e\xa8\x53\x21\x01\xe7\xe5\ -\x61\x09\x2c\x51\x78\x98\x50\x9e\x90\xd4\xd9\xf0\x3e\x19\xc1\x14\ -\x6a\x5b\xa3\x19\x12\xda\x62\x57\xa0\x49\x50\x8c\x26\x76\xa2\xe5\ -\xc3\xcc\x02\x16\xf5\xea\xdc\x67\x30\x52\x9f\x22\xed\x08\xc6\xc1\ -\x4b\x29\x14\xf0\xb7\x30\x40\xa4\x33\xdc\x42\x2a\x34\x7c\x27\xae\ -\xaf\xaf\xad\x5e\xdf\xdd\xdd\xa9\xf1\x65\xa8\xe9\x28\xa6\xd1\xdd\ -\xdd\x7d\x75\x75\xb5\xb5\xb5\x75\x78\x78\x48\xd9\xe5\x33\xa0\xdf\ -\x79\x82\x45\xed\x0b\xc6\x2f\xd1\xcd\xcd\x4d\x3f\xf0\xeb\x20\x18\ -\x6d\x2a\xce\x24\x0d\x51\x09\x4b\xbc\xe9\xe4\x46\xf2\xad\x0a\xb7\ -\x90\x0e\xee\x04\x3c\xac\xdd\xa2\x22\x85\x90\x2f\x4a\x2e\x6b\xf8\ -\x81\x00\xb2\x9b\x3c\xa2\xa1\xfb\xab\x64\x27\x95\x58\xc5\x8d\x7b\ -\xe8\xa6\x9e\x5f\x49\xda\x11\x8c\x5a\xd3\x86\xa4\xe4\xe1\x68\x3b\ -\xf0\x13\x77\xb7\xbe\x98\xce\xab\x9d\x48\x44\x9b\x69\xb6\x37\x8c\ -\x9a\x8d\x24\x42\xba\x1c\xc8\x35\xec\x6e\xbc\x86\x16\x8d\xea\x7e\ -\xea\xb4\x2f\xd8\xca\x37\x75\x29\x14\x16\xe9\x64\x86\x64\xa1\xff\ -\x26\xf5\x48\xb0\x92\xf0\xfd\x26\x20\x31\xf9\xdd\x47\x59\x14\x42\ -\x52\x26\x39\x9b\x19\x2d\xa1\xd4\x05\x75\x7f\x82\x4e\x05\x9b\x36\ -\xb2\x87\xd8\xe8\x53\xa1\x21\xd0\x90\x6e\x8c\x5d\x91\x54\xc8\xff\ -\x2b\x9e\x15\xf2\xff\xc5\x66\x85\x3c\x12\x59\x21\x8f\x44\x56\xc8\ -\x23\x91\x15\xf2\x48\x64\x85\x3c\x12\x59\x21\x8f\x44\x36\x28\x14\ -\x3e\x01\x89\x4c\x9e\x9b\x1b\x93\x9b\xc9\x00\x00\x00\x00\x49\x45\ -\x4e\x44\xae\x42\x60\x82\ -\x00\x00\x04\xc2\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x85\x00\x00\x00\x1b\x08\x02\x00\x00\x00\xdd\xd4\xdb\x58\ -\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\ -\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\ -\xa8\x64\x00\x00\x04\x57\x49\x44\x41\x54\x68\x43\xed\x99\x3b\x2f\ -\x6d\x41\x14\xc7\x8f\xfb\x01\x08\x3a\xe5\xa5\x91\x10\x8d\x47\x41\ -\x24\x14\x88\x4a\xe1\x55\x4a\x54\xb4\x12\x05\x4a\x0d\x9f\x80\x44\ -\x4f\x21\x51\x79\x17\x0a\x0a\xaf\x08\x51\xd0\x10\x89\x44\xe5\x11\ -\x9f\xe0\xdc\xdf\xd9\xff\xb9\x73\x67\xcf\x39\x1b\xd7\x3d\x64\x92\ -\xbb\x7f\xc5\x58\x6b\xcd\x6b\xcd\x5a\x33\x6b\x0b\x25\xd9\x6c\x36\ -\x93\x12\x0c\x3f\xcc\xcf\x94\x30\x48\xf3\x11\x16\x69\x3e\xc2\x22\ -\xcd\x47\x58\xa4\xf9\x08\x8b\xa0\xf3\x31\x3d\x3d\x5d\xe2\x30\x3f\ -\x3f\x8f\xb1\xa9\xa9\xc9\xe8\x11\x07\x07\x07\x18\x6f\x6f\x6f\xc7\ -\xc7\xc7\x35\xe0\xfb\x79\x7a\x7a\x32\xde\xfc\x26\xc9\xb8\xb2\xb2\ -\x52\x53\x53\x83\xdc\xd3\xd3\x13\x4d\xf5\x09\x3a\x1f\xa3\xa3\xa3\ -\xe5\xe5\xe5\xfc\x46\x0e\x0b\x0b\x0b\x75\x75\x75\x18\x27\x26\x26\ -\x86\x86\x86\x64\x44\xa8\xad\xad\xbd\xb8\xb8\x58\x5d\x5d\x7d\x7e\ -\x7e\xd6\xac\xef\xa7\xb2\xb2\x72\x6c\x6c\x0c\x0f\xe5\x55\x77\x77\ -\x77\x92\x71\x66\x66\xe6\xe8\xe8\xe8\xe6\xe6\xe6\xf8\xf8\x58\x37\ -\xc9\x47\xa3\xc5\xdc\xdc\x9c\xb1\x3a\xec\xef\xef\x9b\xee\xbf\x47\ -\x2b\xe0\x8a\xd1\x23\xb4\x0b\xbe\xba\xaa\x85\xc1\xe7\xe7\xe7\xea\ -\x5a\x5e\x5e\xd6\x30\x9b\x00\xc0\x82\xfd\xf1\xf1\xd1\xae\x20\x58\ -\x07\x8c\xf2\x59\x3c\x67\x1a\x1b\x1b\xad\x33\xc4\xc1\x58\x23\xaa\ -\xab\xab\x71\x43\x5d\x80\x4a\x94\x19\xec\xfa\x50\xd0\x28\x58\x99\ -\x23\x18\xc5\x21\x96\x0f\x60\xdc\xd4\xd4\x94\x64\x26\xb0\x71\xc1\ -\x69\x1f\x64\x7d\x7d\x9d\xf8\xb2\xa6\xd1\xb3\x59\xfc\xc3\x4b\x6f\ -\x59\xbb\x29\x46\x64\x1b\x7d\x22\x1e\x9d\x3d\x17\x17\x59\x40\xd3\ -\xc1\xfa\x29\x72\xd9\xf8\xe7\x7c\x80\xeb\x0c\x9e\xb0\x9d\xec\x80\ -\xdd\x7a\xc2\x5e\xf8\xc0\x71\x90\x69\xe5\x12\x70\x64\x0d\x28\x68\ -\x14\x3c\x1a\xcf\x62\xf1\xeb\xd5\xcb\xcb\x4b\x6b\x6b\xab\x64\x5e\ -\x1c\xe5\x82\x56\xaa\xd8\xd8\xd8\xa0\x52\x1b\x25\x82\x42\x49\x35\ -\xa4\x82\x1b\xdd\xe1\xfe\xfe\xbe\xb3\xb3\xf3\xf4\xf4\xd4\xe8\x51\ -\x10\x39\x12\xb8\xcb\xe2\xba\x36\xc5\x38\x30\x30\xb0\xb3\xb3\x23\ -\x3b\xd5\x56\xd7\xd3\x0e\xa6\x34\x51\x97\xb0\x70\x5b\xcb\xca\xca\ -\x64\x7c\x17\xdc\x63\xa2\x51\x22\x58\x99\x8f\x93\x51\xe2\xe0\x4c\ -\x7d\x7d\x3d\x02\x9b\xf6\xf5\xf5\xb9\x61\x45\xe6\xeb\x25\xb9\xbf\ -\xbf\x9f\xf6\xe1\xe1\x81\x76\x77\x77\x57\x77\x88\x24\x95\x96\x96\ -\x46\xfd\x85\x8d\xc0\xd6\x78\xde\xdb\xdb\x6b\xf4\x38\xb1\x7c\x10\ -\x53\xb6\xd4\xd0\xe1\xe1\x61\x1d\x5e\x5d\x96\x96\x96\x96\x93\x93\ -\x13\x9b\x12\x25\xe3\x67\x84\x2c\x2e\x7b\x7b\x7b\x7c\x03\x10\x18\ -\x46\x4b\xc5\xac\xa8\xa8\x40\xb0\xa7\x02\x76\xe1\x12\xb0\xac\xd4\ -\xbb\xbb\xbb\xe6\xe6\x66\x04\x95\xd7\x86\x86\x06\xda\x91\x91\x91\ -\xc5\xc5\x45\x84\xed\xed\xed\xae\xae\x2e\x84\xb6\xb6\x36\x46\xba\ -\x51\x3e\x3b\x3b\x7b\x7d\x7d\x35\x4a\x1c\xa6\x77\x74\x74\xd8\xc1\ -\x44\x04\xff\x07\x07\x07\xa5\xba\xc8\x19\x39\x00\x97\x97\x97\xf6\ -\x39\x02\x17\xa5\xbd\xbd\x5d\xf2\xf5\xf5\x35\x6d\x55\x55\x15\xed\ -\xda\xda\x1a\xeb\x23\x70\xd8\xd9\xd9\xd9\x5c\x77\x82\x91\xad\x69\ -\x89\x2d\xd7\xfa\xfd\xef\x07\x05\xd1\x58\x33\x19\xfb\x21\xcd\x47\ -\x55\x85\x62\x62\x05\xd3\x91\x07\xbd\xb4\xac\xa6\x8f\x10\x2a\x53\ -\x58\xd9\xad\xbc\x3c\x5e\x0d\xa3\x0b\x99\xc1\x7a\xcb\x18\x23\x47\ -\x0c\x3c\x14\x06\x18\x25\xc2\x7a\xe8\x55\x76\x19\x3d\xd8\x91\xf1\ -\x2c\x62\x05\xd3\x11\x07\x07\x54\xa0\x3c\x67\x80\x29\xa8\xdc\x57\ -\x64\x8c\x2c\xa2\xb2\x86\x1c\x6d\x6b\xd0\x9b\x28\x68\x74\x9f\x1a\ -\x14\xfc\x30\xc7\xbc\x27\xb2\x0a\x2e\xde\x78\x1f\x61\x0f\x06\x10\ -\x2f\x7c\x7a\x23\x19\x1c\x40\xbd\x8c\x64\x6f\x8e\xc7\xcb\x75\x4f\ -\x25\xf0\x55\xfe\x01\x23\xed\xf9\x8b\x8e\x32\x01\x49\xc9\x00\xd7\ -\x19\x22\xe0\x86\x4c\xe9\x11\xe4\xcc\xbd\x52\x45\x24\x56\xaf\x28\ -\x44\x7a\x8f\x94\xce\xad\xad\x2d\x19\x3f\xcd\xe1\xe1\xa1\xaa\x0d\ -\xab\x6d\x6e\x6e\x2e\x2d\x2d\x4d\x4e\x4e\x5e\x5d\x5d\x71\x18\xb7\ -\xb8\x51\x04\x38\xaa\xbc\xc1\x81\xa4\xc2\xfa\x3d\x58\x67\xb8\x3a\ -\xd4\x58\xaa\xa2\xe9\x88\x6a\xaf\xae\x39\x49\xa2\x8c\xdb\x9a\x56\ -\x64\xa2\x38\xe4\x50\x35\xb0\x37\x17\x21\xe9\x89\xe8\x71\x70\xf7\ -\xad\x60\x3a\xe2\xd8\xdf\x5c\x79\xd7\xac\xac\xbb\xc6\x60\x9d\x4a\ -\xe4\x3f\x97\x2f\xe2\x23\xf5\x4a\xce\xa8\x4b\xb5\xc5\x7d\x1f\xcc\ -\xb2\xf7\x86\x2b\x45\xc2\x24\x17\x97\x3f\xf9\x50\x4d\x94\xac\x40\ -\x17\xdc\xd2\xcb\x41\x52\x4a\xb0\x73\x1e\x5a\x64\xd6\x51\x0e\x50\ -\xd9\x42\x65\x57\x28\x55\x46\xf9\x32\xbc\x1c\x24\xa5\xc4\x73\xc6\ -\x0d\xba\xbe\x07\x36\x3d\x9c\xf7\xed\x7a\xfe\x69\xcc\xf6\x0a\x2b\ -\x5b\xba\xb8\xb7\xc3\x82\x67\x5e\xe9\x64\x2e\xce\x79\x77\x1c\x0b\ -\x2b\x78\x4e\xcb\x68\x57\xa6\x95\xfa\x45\x67\xb3\x10\x3e\xdd\x0c\ -\x0b\x47\x70\xaf\x05\xe4\x3b\xc3\x2c\xd2\x26\x57\xd5\x05\xea\x62\ -\x3a\xb2\x7d\x2e\x45\x24\xfd\xff\x60\x58\x04\xfd\xf7\xab\xff\x90\ -\x34\x1f\x61\x91\xe6\x23\x2c\xd2\x7c\x84\x45\x9a\x8f\xb0\x48\xf3\ -\x11\x16\x69\x3e\xc2\x22\xcd\x47\x48\x64\x32\xbf\x00\x43\x56\xb8\ -\x32\x46\xab\x27\xb2\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ -\x82\ -' - -qt_resource_name = b'\ -\x00\x11\ -\x08\x7a\x74\xd5\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x6d\x00\x6f\x00\x64\x00\x65\x00\x6c\x00\x5f\x00\x64\x00\x61\x00\x6d\x00\x61\x00\x67\x00\x65\ -\ -\x00\x11\ -\x0e\xfd\xfe\xa7\ -\x00\x73\ -\x00\x65\x00\x63\x00\x6f\x00\x6e\x00\x64\x00\x5f\x00\x64\x00\x61\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\ -\x00\x0a\ -\x0b\x3c\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x43\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x39\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x44\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x10\ -\x02\x88\x45\x47\ -\x00\x66\ -\x00\x69\x00\x72\x00\x73\x00\x74\x00\x5f\x00\x64\x00\x61\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x3e\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x41\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x3b\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x42\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x37\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x46\x00\x2e\x00\x70\x00\x6e\x00\x67\ -\x00\x0a\ -\x0b\x3a\xfc\x07\ -\x00\x6e\ -\x00\x6f\x00\x64\x00\x65\x00\x5f\x00\x45\x00\x2e\x00\x70\x00\x6e\x00\x67\ -' - -qt_resource_struct_v1 = b'\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x02\ -\x00\x00\x00\x84\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x83\ -\x00\x00\x00\xde\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x96\ -\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x09\xc8\ -\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x20\xf1\ -\x00\x00\x00\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x19\x61\ -\x00\x00\x00\x50\x00\x00\x00\x00\x00\x01\x00\x00\x07\x46\ -\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x16\x86\ -\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -' - -qt_resource_struct_v2 = b'\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x84\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x83\ -\x00\x00\x01\x84\x35\xad\xa6\xc2\ -\x00\x00\x00\xde\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x96\ -\x00\x00\x01\x84\x35\xa2\x0c\xbc\ -\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x09\xc8\ -\x00\x00\x01\x84\x35\xa1\x87\x1b\ -\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x20\xf1\ -\x00\x00\x01\x84\x35\xa1\xc0\x5d\ -\x00\x00\x00\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x19\x61\ -\x00\x00\x01\x84\x35\xa0\xfc\x02\ -\x00\x00\x00\x50\x00\x00\x00\x00\x00\x01\x00\x00\x07\x46\ -\x00\x00\x01\x84\x35\xa1\x3f\xd3\ -\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x16\x86\ -\x00\x00\x01\x84\x35\xa0\xb2\x82\ -\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x84\x35\xae\x2b\x19\ -' - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - - -def qInitResources(): # noqa: N802, D103 - QtCore.qRegisterResourceData( - rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data - ) - - -def qCleanupResources(): # noqa: N802, D103 - QtCore.qUnregisterResourceData( - rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data - ) - - -qInitResources() diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/UDPrimaryLogo2945web.jpg b/modules/systemPerformance/REWET/REWET/GUI/resources/UDPrimaryLogo2945web.jpg deleted file mode 100644 index 24be5af11..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/UDPrimaryLogo2945web.jpg and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/both_logos.jpg b/modules/systemPerformance/REWET/REWET/GUI/resources/both_logos.jpg deleted file mode 100644 index 4829523a7..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/both_logos.jpg and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/first_damage.png b/modules/systemPerformance/REWET/REWET/GUI/resources/first_damage.png deleted file mode 100644 index d2b9a2f88..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/first_damage.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_A.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_A.png deleted file mode 100644 index 788f2aa05..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_A.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_B.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_B.png deleted file mode 100644 index 7207f484f..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_B.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_C.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_C.png deleted file mode 100644 index 1440d7da6..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_C.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_D.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_D.png deleted file mode 100644 index 84102f9b8..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_D.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_E.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_E.png deleted file mode 100644 index 85fe8c5f8..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_E.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/node_F.png b/modules/systemPerformance/REWET/REWET/GUI/resources/node_F.png deleted file mode 100644 index f7f4008cc..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/node_F.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/second_damage.png b/modules/systemPerformance/REWET/REWET/GUI/resources/second_damage.png deleted file mode 100644 index 3edf16b4c..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/second_damage.png and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/resources/us_nsf.jpg b/modules/systemPerformance/REWET/REWET/GUI/resources/us_nsf.jpg deleted file mode 100644 index 2198cda19..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/resources/us_nsf.jpg and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/GUI/wqw.xlsx b/modules/systemPerformance/REWET/REWET/GUI/wqw.xlsx deleted file mode 100644 index 7998affe8..000000000 Binary files a/modules/systemPerformance/REWET/REWET/GUI/wqw.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/Input/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/Input/CMakeLists.txt deleted file mode 100644 index d4229651d..000000000 --- a/modules/systemPerformance/REWET/REWET/Input/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ - -simcenter_add_python_script(SCRIPT GUI_Input_Interface.py) -simcenter_add_python_script(SCRIPT Input_IO.py) -simcenter_add_python_script(SCRIPT Policy_IO.py) -simcenter_add_python_script(SCRIPT Settings.py) \ No newline at end of file diff --git a/modules/systemPerformance/REWET/REWET/Input/GUI_Input_Interface.py b/modules/systemPerformance/REWET/REWET/Input/GUI_Input_Interface.py deleted file mode 100644 index c997df316..000000000 --- a/modules/systemPerformance/REWET/REWET/Input/GUI_Input_Interface.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Created on Mon Oct 10 15:04:40 2022 - -This is the input module, an interface between all inputs from GUI, TEXT-based -inputs and the mail code. - -@author: snaeimi -""" # noqa: INP001, D400 - - -class input: # noqa: A001, D101 - def __init__(self, settings, registry): - pass - - def convertShiftFromDictToPandasTable(self, dict_data): # noqa: ARG002, N802, D102 - shift_name_list = list(shift_data) # noqa: F821 - shift_begining_list = [shift_data[i][0] for i in shift_name_list] # noqa: F821, F841 - shift_end_list = [shift_data[i][1] for i in shift_name_list] # noqa: F821, F841 diff --git a/modules/systemPerformance/REWET/REWET/Input/Input_IO.py b/modules/systemPerformance/REWET/REWET/Input/Input_IO.py deleted file mode 100644 index 8260a9a72..000000000 --- a/modules/systemPerformance/REWET/REWET/Input/Input_IO.py +++ /dev/null @@ -1,345 +0,0 @@ -import json # noqa: INP001, D100 -import os -import pickle - -import pandas as pd - - -# Read files From json ##################### -def read_pipe_damage_seperate_json_file(directory, pipe_file_name): - """Read pipe damage of a single scenario. - - Args: - ---- - directory (path): damage scenarios path - pipe_file_name (str): pipe damage file name - - Raises - ------ - ValueError: _description_ - RuntimeError: _description_ - - Returns - ------- - Pandas.Series: Pipe Damage - - """ - pipe_damaage = [] - pipe_time = [] - - file_dest = os.path.join(directory, pipe_file_name) # noqa: PTH118 - - with open(file_dest) as f: # noqa: PTH123 - read_file = json.load(f) - - if not isinstance(read_file, list): - raise ValueError('Wrong input in PIPE damage file') # noqa: EM101, TRY003, TRY004 - - for each_damage in read_file: - pipe_time.append(each_damage.get('time')) - - cur_damage = { - 'pipe_ID': each_damage.get('Pipe_ID'), - 'damage_loc': each_damage.get('Loc'), - 'type': each_damage.get('Type'), - 'Material': each_damage.get('Material'), - } - - pipe_damaage.append(cur_damage) - - return pd.Series(index=pipe_time, data=pipe_damaage) - - -def read_node_damage_seperate_json_file(directory, node_file_name): - """Read node damage of a single scenario. - - Args: - ---- - directory (path): damage scenarios path - pipe_file_name (str): node damage file name - - Raises - ------ - ValueError: _description_ - RuntimeError: _description_ - - Returns - ------- - Pandas.Series: node Damage - - """ - node_damage = [] - node_time = [] - - file_dest = os.path.join(directory, node_file_name) # noqa: PTH118 - - with open(file_dest) as f: # noqa: PTH123 - read_file = json.load(f) - - if not isinstance(read_file, list): - raise ValueError('Wrong input in NODE damage file') # noqa: EM101, TRY003, TRY004 - - for each_damage in read_file: - node_time.append(each_damage.get('time')) - - cur_damage = { - 'node_name': each_damage.get('Node_ID'), - 'Number_of_damages': each_damage.get('Number_of_Damages'), - 'node_Pipe_Length': each_damage.get('Pipe Length'), - } - - node_damage.append(cur_damage) - - return pd.Series(index=node_time, data=node_damage) - - -def read_tank_damage_seperate_json_file(directory, tank_file_name): - """Read tank damage of a single scenario. - - Args: - ---- - directory (path): tank scenarios path - pipe_file_name (str): tank damage file name - - Raises - ------ - ValueError: _description_ - RuntimeError: _description_ - - Returns - ------- - Pandas.Series: tank Damage - - """ - tank_damage = [] - tank_time = [] - - file_dest = os.path.join(directory, tank_file_name) # noqa: PTH118 - - with open(file_dest) as f: # noqa: PTH123 - read_file = json.load(f) - - if not isinstance(read_file, list): - raise ValueError('Wrong input in TANK damage file') # noqa: EM101, TRY003, TRY004 - - for each_damage in read_file: - tank_time.append(each_damage.get('time')) - - cur_damage = { - 'Tank_ID': each_damage.get('Tank_ID'), - 'Restore_time': each_damage.get('Restore_time'), - } - - tank_time.append(cur_damage) - - return pd.Series(index=tank_time, data=tank_damage) - - -def read_pump_damage_seperate_json_file(directory, pump_file_name): - """Read pump damage of a single scenario. - - Args: - ---- - directory (path): pump scenarios path - pipe_file_name (str): pump damage file name - - Raises - ------ - ValueError: _description_ - RuntimeError: _description_ - - Returns - ------- - Pandas.Series: pump Damage - - """ - pump_damage = [] - pump_time = [] - - file_dest = os.path.join(directory, pump_file_name) # noqa: PTH118 - - with open(file_dest) as f: # noqa: PTH123 - read_file = json.load(f) - - if not isinstance(read_file, list): - raise ValueError('Wrong input in PUMP damage file') # noqa: EM101, TRY003, TRY004 - - for each_damage in read_file: - pump_time.append(each_damage.get('time')) - - cur_damage = { - 'PUMP_ID': each_damage.get('Pump_ID'), - 'Restore_time': each_damage.get('Restore_time'), - } - - pump_time.append(cur_damage) - - return pd.Series(index=pump_time, data=pump_damage) - - -# Read files From Pickle ##################### -def read_pipe_damage_seperate_pickle_file(directory, all_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, all_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _all_damages = pickle.load(f) # noqa: S301 - - return _all_damages # noqa: RET504 - - -def read_node_damage_seperate_pickle_file(directory, all_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, all_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _node_damages = pickle.load(f) # noqa: S301 - - return _node_damages # noqa: RET504 - - -def read_tank_damage_seperate_pickle_file(directory, tank_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, tank_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _tank_damages = pickle.load(f) # noqa: S301 - - return _tank_damages # noqa: RET504 - - -def read_pump_damage_seperate_pickle_file(directory, pump_damages_file_name): # noqa: D103 - file_dest = os.path.join(directory, pump_damages_file_name) # noqa: PTH118 - with open(file_dest, 'rb') as f: # noqa: PTH123 - _pump_damages = pickle.load(f) # noqa: S301 - - return _pump_damages # noqa: RET504 - - -# Read files From Excel ##################### - - -def read_pipe_damage_seperate_EXCEL_file(directory, pipe_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, pipe_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.sort_values( - ['pipe_id', 'time', 'damage_loc'], - ascending=[True, True, False], - ignore_index=True, - inplace=True, # noqa: PD002 - ) - unique_time = ss.groupby(['pipe_id']).time.unique() - if 1 in [ - 0 if len(i) <= 1 else 1 for i in unique_time - ]: # checks if there are any pipe id with more than two unique time values - raise ValueError( # noqa: TRY003 - 'All damage location for one pipe should happen at the same time' # noqa: EM101 - ) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.pipe_id = ss.pipe_id.astype(str) - return pd.Series(ss.to_dict('records'), index=ss.index) - - -def read_node_damage_seperate_EXCEL_file(directory, node_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, node_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.node_name = ss.node_name.astype(str) - return pd.Series(ss.to_dict('records'), index=ss.index) - - -def read_tank_damage_seperate_EXCEL_file(directory, tank_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, tank_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - # ss.set_index('Tank_ID', inplace=True) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.Tank_ID = ss.Tank_ID.astype(str) - # ss = ss['Tank_ID'] - - return ss - - -def read_pump_damage_seperate_EXCEL_file(directory, pump_damages_file_name): # noqa: N802, D103 - ss = None - file_dest = os.path.join(directory, pump_damages_file_name) # noqa: PTH118 - ss = pd.read_excel(file_dest) - ss.set_index('time', inplace=True) # noqa: PD002 - ss.Pump_ID = ss.Pump_ID.astype(str) - return ss - - -def read_damage_list(list_file_addr, file_directory, iCheck=False): # noqa: FBT002, ARG001, N803 - """Reads damage scenario list. - - Parameters - ---------- - list_file_addr : Address to the target list file - DESCRIPTION. - file_directory : TYPE - DESCRIPTION. - iCheck : TYPE, optional - DESCRIPTION. The default is False. Checks if all damage files are found. - - Raises - ------ - RuntimeError - if file not found. - - Returns - ------- - damage_list : Pandas Dataframe - DESCRIPTION. - - """ # noqa: D401 - damage_list = None - error_file_name = [] - - with open(list_file_addr, 'rb') as f: # noqa: PTH123 - damage_list = pd.read_excel(f) - - iError = False # noqa: N806 - temp = damage_list['Pipe Damage'].tolist() - - if iCheck == False: # noqa: E712 - return damage_list - - for file_name in temp: - if not os.path.exists(file_name): # noqa: PTH110 - iError = True # noqa: N806 - error_file_name.append(file_name) - - if iError: - raise RuntimeError( - 'The Following files could not be found: ' + repr(error_file_name) - ) - return damage_list - - -# Save Results ##################### - - -def save_single(settings, result, name, restoration_data): # noqa: D103 - result_file_directory = settings.process['result_directory'] - # print(result_file_directory) - result_name = name + '.res' - settings_name = name + '.xlsx' - - file_dest = os.path.join(result_file_directory, result_name) # noqa: PTH118 - print('Saving: ' + str(file_dest)) # noqa: T201 - with open(file_dest, 'wb') as f: # noqa: PTH123 - pickle.dump(result, f) - - process_set = pd.Series(settings.process.settings) - scenario_set = pd.Series(settings.scenario.settings) - _set = pd.Series( - process_set.to_list() + scenario_set.to_list(), - index=process_set.index.to_list() + scenario_set.index.to_list(), - ) - file_dest = os.path.join(result_file_directory, settings_name) # noqa: PTH118 - _set.to_excel(file_dest) - - if settings.process['dmg_rst_data_save']: - # file_dest = os.path.join(result_file_directory, 'restoration_file.pkl') - # rest_data_out = pd.DataFrame.from_dict(restoration_data) - # rest_data_out.to_pickle(file_dest) - file_dest = os.path.join(result_file_directory, name + '_registry.pkl') # noqa: PTH118 - print('Saving: ' + str(file_dest)) # noqa: T201 - with open(file_dest, 'wb') as f: # noqa: PTH123 - pickle.dump(restoration_data, f) diff --git a/modules/systemPerformance/REWET/REWET/Input/Policy_IO.py b/modules/systemPerformance/REWET/REWET/Input/Policy_IO.py deleted file mode 100644 index 68935d5a0..000000000 --- a/modules/systemPerformance/REWET/REWET/Input/Policy_IO.py +++ /dev/null @@ -1,975 +0,0 @@ -"""Created on Wed Dec 19 19:10:35 2020 - -This is the Restoration Policy Reader/Writtter Module. - -@author: snaeimi -""" # noqa: INP001, D400 - -import logging -from collections import OrderedDict - -import pandas as pd - -ELEMENTS = ['PIPE', 'DISTNODE', 'GNODE', 'TANK', 'PUMP', 'RESERVOIR'] - -logger = logging.getLogger(__name__) - - -# the following function is borrowed from WNTR -def _split_line(line): - _vc = line.split(';', 1) - _cmnt = None - _vals = None - if len(_vc) == 0: - pass - elif len(_vc) == 1: - _vals = _vc[0].split() - elif _vc[0] == '': - _cmnt = _vc[1] - else: - _vals = _vc[0].split() - _cmnt = _vc[1] - return _vals, _cmnt - - -class restoration_data: # noqa: D101 - def __init__(self): - self.files = {} - self.shift = {} - self.entity = {} - self.entity_rule = {} - self.sequence = {} - self.agents = [] - self.group = {} - self.priority = [] - self.jobs = [] - self.jobs_default = [] - self.time_overwrite = {} - self.final_method = {} - self.once = {} - - for el in ELEMENTS: - self.group[el] = OrderedDict() - - -class RestorationIO: # noqa: D101 - def __init__(self, definition_file_name): - """Needs a file that contains: - - Parameters - ---------- - restoratio_model : Restoration object - restoration model to be defined by files - definition_file : str - path for tegh definition file. - - Returns - ------- - None. - - """ # noqa: D400, DOC202, RUF100 - # some of the following lines have been adopted from WNTR - self.rm = restoration_data() - - self.crew_data = {} - - expected_sections = [ - '[FILES]', - '[ENTITIES]', - '[JOBS]', - '[AGENTS]', - '[GROUPS]', - '[PRIORITIES]', - '[SHIFTS]', - '[SEQUENCES]', - '[DEFINE]', - '[DAMAGE GROUPS]', - '[EFFECTS]', - '[CREWS]', - ] - - self.config_file_comment = [] - self.edata = [] - - self.sections = OrderedDict() - for sec in expected_sections: - self.sections[sec] = [] - - section = None - lnum = 0 - edata = {'fname': definition_file_name} - with open(definition_file_name, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - edata['lnum'] = lnum - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.startswith('['): # noqa: RET507 - vals = line.split() - sec = vals[0].upper() - edata['sec'] = sec - if sec in expected_sections: - section = sec - continue - else: # noqa: RET507 - raise RuntimeError( - '%(fname)s:%(lnum)d: Invalid section "%(sec)s"' % edata - ) - elif section is None and line.startswith(';'): - self.config_file_comment.append(line[1:]) - continue - elif section is None: - raise RuntimeError( - '%(fname)s:%(lnum)d: Non-comment outside of valid section!' - % edata - ) - # We have text, and we are in a section - self.sections[section].append((lnum, line)) - - # Parse each of the sections - self._read_files() - self._read_shifts() - self._read_entities() - self._read_agents() - self._read_groups() - self._read_sequences() - self._read_priorities() - self._read_jobs() - self._read_define() - # self._read_config() - - def _read_files(self): - edata = OrderedDict() - self.file_name = [] - self._file_data = {} - self._file_handle_address = {} - for lnum, line in self.sections['[FILES]']: - edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 2: # noqa: PLR2004 - edata['key'] = words[0] - raise RuntimeError( - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' - % edata - ) - file_handle = words[0] - file_address = words[1] - - self._file_handle_address[file_handle] = file_address - - for file_handle, file_address in self._file_handle_address.items(): - self._file_data[file_handle] = self._read_each_file(file_address) - self.rm.files = self._file_data - - def _read_each_file(self, file_address, method=0): - lnum = 0 - iTitle = True # noqa: N806 - data_temp = None - if method == 0: - try: - raise # noqa: PLE0704 - with open(file_address, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.startswith(';'): # noqa: RET507 - # comment - continue - else: - lnum += 1 - vals = line.split() - if iTitle == True: # noqa: E712 - iTitle = False # noqa: N806 - data_temp = pd.DataFrame(columns=vals) - else: - data_temp.loc[lnum - 2] = vals - except: # noqa: E722 - data_temp = self._read_each_file(file_address, method=1) - elif method == 1: - data_temp = pd.read_csv(file_address) - else: - raise ValueError('Uknown method: ' + str(method)) - return data_temp - - def _read_shifts(self): - for lnum, line in self.sections['[SHIFTS]']: # noqa: B007 - # edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 3: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' # noqa: EM101 - ) - shift_name = words[0] - shift_begining = int(words[1]) * 3600 - shift_ending = int(words[2]) * 3600 - - self.rm.shift[shift_name] = (shift_begining, shift_ending) - - def _read_entities(self): # noqa: C901 - """Reads damage group definitions and updates the Restoration Model - object data. - - Raises - ------ - RuntimeError - If the number of damages are not right. - ValueError - If the input data is not correctly provided. - - If the input data is not correctly provided. - - Returns - ------- - None. - - """ # noqa: D205, D401, DOC202, RUF100 - # Entities is kept for legacy compatibility with the first version - damage_group_data = self.sections.get( - '[ENTITIES]', self.sections.get('[Damage Group]') - ) - - for lnum, line in damage_group_data: - arg1 = None - arg2 = None - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 2 and len(words) != 4: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' # noqa: EM101 - ) - entity_name = words[0] - element = words[1].upper() - - if element not in ELEMENTS: - raise ValueError('Unknown element line number ' + str(lnum)) - - # if entity_name in self.rm.entity: - # raise ValueError('Entity already defined') - - if len(words) == 4: # noqa: PLR2004 - arg1 = words[2] - arg2 = words[3] - - # if (element=='PIPE' and arg1 not in self.rm._registry._pipe_damage_table.columns and arg1!='FILE' and arg1!='NOT_IN_FILE') and (element=='DISTNODE' and arg1 not in self.rm._registry._node_damage_table.columns): - # raise ValueError('Argument 1('+arg1+') is not recognized in line number: ' + str(lnum)) - - if arg1 == None: # noqa: E711 - self.rm.entity[entity_name] = element - ent_rule = [('ALL', None, None)] - - if entity_name not in self.rm.entity_rule: - self.rm.entity_rule[entity_name] = ent_rule - else: - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - # sina: take care of this in registry opening - # self.rm._registry.addAttrToElementDamageTable(element ,entity_name , True) - - elif arg1 == 'FILE' or arg1 == 'NOT_IN_FILE': # noqa: PLR1714 - name_list = self.rm.files[arg2]['ElementID'].unique().tolist() - ent_rule = [(arg1, None, name_list)] - self.rm.entity[entity_name] = element - - if entity_name not in self.rm.entity_rule: - self.rm.entity_rule[entity_name] = ent_rule - # self.rm._registry.addAttrToElementDamageTable(element ,entity_name , True) - else: - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - else: - if ':' in arg2: - split_arg = arg2.split(':') - - if len(split_arg) != 2: # noqa: PLR2004 - raise ValueError( - 'There must be two parts: PART1:PART2. Now there are ' - + repr( - len(split_arg) - + ' parts. Line number is ' - + repr(lnum) - ) - ) - if split_arg[0] == '': - raise ValueError( - 'The first part is Empty in line ' + repr(lnum) - ) - if split_arg[1] == '': - raise ValueError( - 'The second part is Empty in line ' + repr(lnum) - ) - else: - raise ValueError( - 'There must be two parts as a condition, separated with ":". Example: PART1:PART2 \nPart1 can be one of the following: EQ, BG, LT, BG-EQ, and LT-EQ. Line number: ' - + repr(lnum) - ) - - rest_of_args = arg2.split(':') - arg2 = rest_of_args[0] - arg3 = rest_of_args[1] - - try: - temp_arg3 = float(arg3) - except: # noqa: E722 - temp_arg3 = str(arg3) - - arg3 = temp_arg3 - ent_rule = [(arg1, arg2, arg3)] - if entity_name not in self.rm.entity: - self.rm.entity[entity_name] = element - self.rm.entity_rule[entity_name] = ent_rule - # self.rm._registry.addAttrToElementDamageTable(element ,entity_name , True) - else: - if self.rm.entity[entity_name] != element: - raise ValueError( - 'Element must not change in an added condition. Line ' - + str(lnum) - ) - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - def _read_sequences(self): - # sina: there is a part that you need to add in restroation init - for lnum, line in self.sections['[SEQUENCES]']: # noqa: B007 - words, comments = _split_line(line) - if words is not None and len(words) > 0: - # if len(words) != 2 or len(words)!=4: - # raise RuntimeError('%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' % edata) - element = words[0].upper() - seq = [] - for arg in words[1:]: - seq.append(arg) # noqa: PERF402 - if element in self.rm.sequence: - raise ValueError('Element already in sequences') # noqa: EM101, TRY003 - if element not in ELEMENTS: - raise ValueError( - 'The Element ' - + repr(element) - + ' is not a recognized element' - ) - self.rm.sequence[element] = seq - - def _read_agents(self): - agent_file_handle = {} - group_names = {} - group_column = {} - - crews_data = self.sections.get('[AGENTS]', self.sections.get('CREWS')) - for lnum, line in crews_data: # noqa: B007 - # edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - _group_name = None - _group_column = None - - if len(words) < 3: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - 'less than three argument is not valid for crew definition' # noqa: EM101 - ) - agent_type = words[0] - if words[1].upper() == 'FILE': - agent_file_handle[words[0]] = words[2] - else: - raise ValueError('Unknown key') # noqa: EM101, TRY003 - if len(words) >= 4: # noqa: PLR2004 - group_data = words[3] - _group_name = group_data.split(':')[0] - _group_column = group_data.split(':')[1] - - group_names[agent_type] = _group_name - group_column[agent_type] = _group_column - - for agent_type, file_handle in agent_file_handle.items(): - data = self._file_data[file_handle] - - # print(file_handle) - # print(self._file_data[file_handle]) - - agent_number = data['Number'] - j = 0 - for lnum, line in data.iterrows(): # noqa: B007 - # try: - num = int(agent_number[j]) - # except : - # print('exception') - # pass - _r = range(num) - - for i in _r: - agent_name = agent_type + str(j) + str(i) - predefinitions = line.to_dict() - definitions = {} - definitions['cur_x'] = predefinitions['Curr.-X-Coord'] - definitions['cur_y'] = predefinitions['Curr.-Y-Coord'] - definitions['base_x'] = predefinitions['Home-X-Coord'] - definitions['base_y'] = predefinitions['Home-Y-Coord'] - definitions['shift_name'] = predefinitions['Shift'] - - group_name_temp = None - if group_names[agent_type] != None: # noqa: E711 - definitions['group'] = predefinitions[ - group_column[agent_type] - ] - group_name_temp = group_names[agent_type] - else: - group_name_temp = 'default' - definitions['group'] = 'Default' - - definitions['group_name'] = group_name_temp - self.rm.agents.append((agent_name, agent_type, definitions)) - j += 1 # noqa: SIM113 - - def _read_groups(self): - for lnum, line in self.sections['[GROUPS]']: - words, comments = _split_line(line) - - if words is not None and len(words) > 0: - if not len(words) >= 6: # noqa: PLR2004 - raise ValueError('error in line: ' + str(lnum)) - group_name = words[0] - element_type = words[1] - argument = words[2] - file_handler = words[3] - element_col_ID = words[4] # noqa: N806 - pipe_col_ID = words[5] # noqa: N806 - - if element_type not in ELEMENTS: - raise ValueError( - 'Unknown element type: ' - + repr(element_type) - + ', in line: ' - + repr(lnum) - ) - if argument != 'FILE': - raise ValueError( - 'the Only acceptable argument is FILE. Not: ' - + repr(argument) - + '. Line: ' - + repr(lnum) - ) - - data = self.rm.files[file_handler] - - if pipe_col_ID not in data: - raise ValueError( - repr(pipe_col_ID) - + 'not in file handle=' - + repr(file_handler) - ) - - group_list = data[pipe_col_ID] - group_list.index = data[element_col_ID] - - if element_type not in self.rm.group: - raise ValueError( - 'This error must never happen: ' + repr(element_type) - ) - - if group_name in self.rm.group[element_type]: - raise ValueError( - 'The Group is already identified: ' - + repr(group_name) - + ' in line: ' - + repr(lnum) - ) - - self.rm.group[element_type][group_name] = group_list - - def _read_priorities(self): # noqa: C901 - for lnum, line in self.sections['[PRIORITIES]']: - words, comments = _split_line(line) - - if words is not None and len(words) > 0: - if not len(words) >= 3: # noqa: PLR2004 - raise ValueError('error in line: ' + str(lnum)) - agent_type = words[0] - - priority = None - try: - priority = int(words[1]) - except: # noqa: E722 - print('exeption handled in _read_priorities') # noqa: T201 - if type(priority) != int: # noqa: E721 - raise ValueError( - 'Priority casting failed:' - + str(priority) - + 'in line: ' - + repr(lnum) - ) - arg = [] - for word in words[2:]: - temp = None # noqa: F841 - if word.find(':') != -1: - split_temp = word.split(':') - arg.append((split_temp[0], split_temp[1])) - if split_temp[1] not in self.rm.entity: - raise ValueError( - 'Entity value is used which is not defined before: ' - + split_temp[1] - + ', Line: ' - + str(lnum) - ) - if ( - split_temp[0] - not in self.rm.sequence[self.rm.entity[split_temp[1]]] - ): - raise ValueError( - 'There is no action: ' - + repr(split_temp[0]) - + ' in element: ' - + repr(self.rm.entity[split_temp[1]]) - ) - else: - arg.append(word) - if word not in ['EPICENTERDIST', 'WaterSource']: - raise ValueError('Unnown value in line: ' + str(lnum)) - - self.rm.priority.append((agent_type, priority, arg)) - - def _read_jobs(self): - for lnum, line in self.sections['[JOBS]']: - words, comments = _split_line(line) - - if words is not None and len(words) > 0: - if not len(words) >= 3: # noqa: PLR2004 - raise ValueError( - 'Not enough arguments. error in line: ' + str(lnum) - ) - agent_type = words[0] - - action_entity = words[1] - if not action_entity.find(':') != -1: - raise ValueError( - 'There must be an action and entity separated by : in line ' - + str(lnum) - ) - split_temp = action_entity.split(':') - action = split_temp[0] - entity = split_temp[1] - - definer_arg = words[2] - if not definer_arg.find(':') != -1: - raise ValueError( - 'There must be an Time Definer and Argument separated by : in line ' - + str(lnum) - ) - split_temp = definer_arg.split(':') - definer = split_temp[0] - argument = split_temp[1] - - if definer.upper() == 'FIXED': - try: - argument = int(argument) - except: # noqa: E722 - print('exeption handled in _read_jobs') # noqa: T201 - else: - raise ValueError('Definer is not recognized: ' + definer) - - effect = None - if len(words) >= 4: # noqa: PLR2004 - effect = words[3] - - self.rm.jobs.append((agent_type, entity, action, argument, effect)) - - def _read_define(self): # noqa: C901, PLR0912 - job = {} # noqa: F841 - - effect_data = self.sections.get('[DEFINE]', self.sections.get('[EFFECTS]')) - for lnum, line in effect_data: - words, comments = _split_line(line) - if words is not None and len(words) > 0: - # if not len(words) >= 3: - # raise ValueError('Not enough arguments. error in line: ' + str(lnum)) - job_name = words[0] - - try: - method_name = float(words[1]) - except: # noqa: E722 - method_name = words[1] - - res_list = [] - flag = False - - if method_name == 'FILE': - file_data = self._read_file_effect(words[2:], job_name) - self.rm.jobs.append((job_name, 'DATA', file_data)) - continue - - method_data_list = words[2:] - for method_data in method_data_list: - res = {} - definition = method_data.split(':') - - i = 0 - if len(definition) % 2 != 1: - raise ValueError('Error in line ' + str(lnum)) - - main_arg = None - - while i < len(definition): - arg = definition[i].upper() - if i == 0: - main_arg = arg - i += 1 - res['EFFECT'] = main_arg - continue - val = definition[i + 1].upper() - - if main_arg == 'RECONNECT': - if arg == 'PIPESIZE': - if 'PIPESIZEFACTOR' in res: - raise ValueError( # noqa: TRY003 - 'Either pipe size or pipe size factor can be defined' # noqa: EM101 - ) - res['PIPESIZE'] = float(val) - - elif arg == 'PIPESIZEFACTOR': - if 'PIPESIZE' in res: - raise ValueError( # noqa: TRY003 - 'Either pipe size or pipe size factor can be defined' # noqa: EM101 - ) - val = float(val) - if val > 1 or val < 0: - raise ValueError( - 'Pipe Size Factor must be bigger than 0 and less than or eqal to 1: ' - + str(val) - ) - res['PIPESIZEFACTOR'] = float(val) - elif arg == 'CV': - if val == 'TRUE' or val == '1': # noqa: PLR1714 - val = True - elif val == 'FALSE' or val == '0': # noqa: PLR1714 - val = False - else: - raise ValueError( - 'Unrecognized value for CV in line ' - + str(lnum) - + ': ' - + val - + ( - 'Value for CV must be either True or False' - ) - ) - res['CV'] = val - elif arg == 'PIPELENGTH': - try: - val == float(val) # noqa: B015 - except Exception as e: - print( # noqa: T201 - 'The value for PIPELENGTH must be a number' - ) - raise e # noqa: TRY201 - res['PIPELENGTH'] = val - elif arg == 'PIPEFRICTION': - try: - val == float(val) # noqa: B015 - except Exception as e: - print( # noqa: T201 - 'The value for PIPEFRICTION must be a number' - ) - raise e # noqa: TRY201 - res['PIPEFRICTION'] = val - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - elif main_arg == 'ADD_RESERVOIR': - if arg == 'PUMP': - res['PUMP'] = float(val) - - elif arg == 'CV': - if val == 'TRUE' or val == '1': # noqa: PLR1714 - val = True - elif val == 'FALSE' or val == '0': # noqa: PLR1714 - val = False - else: - raise ValueError( - 'Unrecognized value for CV in line ' - + str(lnum) - + ': ' - + val - + ( - 'Value for CV must be either True or False' - ) - ) - res['CV'] = val - elif arg == 'ADDEDELEVATION': - val = float(val) - res['ADDEDELEVATION'] = float(val) - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - elif main_arg == 'REMOVE_LEAK': - if arg == 'LEAKFACTOR': - val = float(val) - if val > 1 or val <= 0: - raise ValueError( - 'Leak factor must be bigger than 0 and less than or eqal to 1: ' - + str(val) - ) - res['LEAKFACTOR'] = val - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - - elif main_arg == 'COL_CLOSE_PIPE': - raise ValueError( # noqa: TRY003 - 'REPAIR at this stage does not accept any argument' # noqa: EM101 - ) - - elif main_arg == 'ISOLATE_DN': - if arg == 'PIDR': # Post Incident Demand Ratio - if ( - val[0] != '(' - or val[-1] != ')' - or val.find(',') == -1 - ): - ValueError( # noqa: PLW0133 - 'After PIDR the format must be like (CONDIION,VALUE)' - ) - - val = val.strip('(').strip(')') - val_split = val.split(',') - _con = val_split[0].upper() - _con_val = float(val_split[1]) - - if not ( - _con == 'BG' # noqa: PLR1714 - or _con == 'EQ' - or _con == 'LT' - or _con == 'BG-EQ' - or _con == 'LT-EQ' - ): - raise ValueError( - 'Condition is not recognized:' + str(_con) - ) - - if _con_val < 0: - raise ValueError( - 'PIDR condition value cannot be less than zero-->' - + repr(_con_val) - ) - - res['PIDR'] = (_con, _con_val) - - elif main_arg == 'REPAIR': - raise ValueError( # noqa: TRY003 - 'REPAIR at this stage does not accept any argument' # noqa: EM101 - ) - - elif method_name.upper() == 'DEFAULT': - try: # noqa: SIM105 - arg = int(arg) - except: # noqa: S110, E722 - pass - - if main_arg == 'METHOD_PROBABILITY': - val = float(val) - - if val < 0: - raise ValueError( - 'Probability cannot be less than zero. ' # noqa: ISC003 - + ' In line ' - + lnum - + ' probability: ' - + val - ) - elif val > 1: # noqa: RET506 - raise ValueError( - 'Probability cannot be bigger than 1. ' # noqa: ISC003 - + ' In line ' - + lnum - + ' probability: ' - + val - ) - temp = { - 'effect_definition_name': job_name, - 'method_name': arg, - 'argument': main_arg, - 'value': val, - } - self.rm.jobs_default.append(temp) - # temp={'effect_definition_name':effect_name, 'method_name':arg,'argument':'METHOD_PROBABILITY','value':val} - elif main_arg == 'FINALLY': - if val.upper() == 'NULL': - val = None - else: - val = None - print( # noqa: T201 - 'WARNING: At default line in FINAL section, the third argument is not NULL: ' - + str(val) - + 'The value is ignored antywhere' - ) - self.rm.final_method[job_name] = arg - elif main_arg == 'ONLYONCE': - try: # noqa: SIM105 - val = float(val) - except: # noqa: S110, E722 - pass - - if job_name in self.rm.once: - self.rm.once[job_name].append(val) - else: - self.rm.once[job_name] = [val] - else: - raise ValueError( - 'Unrecognized argument in line ' - + str(lnum) - + ': ' - + arg - ) - - flag = True - else: - raise ValueError( - 'Unrecognized argument in line ' - + str(lnum) - + ': ' - + arg - ) - - i += 2 - res_list.append(res) - if flag == False: # noqa: E712 - self.rm.jobs.append((job_name, method_name, res_list)) - - # for self.rm.effects.pruneData() - - def _read_file_effect(self, file_info, effect_name): - res = {} - - file_handle = file_info[0] - file_data = file_info[1:] - - data = self.rm.files[file_handle] - - # columns_to_remove = data.columns.tolist() - aliases = {} - - for pair in file_data: - if not pair.find(':'): - raise ValueError('Error in file info. Not Pair: ' + pair) - _arg, val = pair.split(':') - arg = _arg.upper() - - if arg in res: - raise ValueError('Argument already added: ' + _arg) - - if val not in data.columns: - raise ValueError('Value not in file: ' + val) - if ( - arg == 'ELEMENT_NAME' # noqa: PLR1714 - or arg == 'METHOD_NAME' - or arg == 'METHOD_PROBABILITY' - ): - aliases[arg] = val - res[arg] = data[val].to_dict() - - elif arg == 'FIXED_TIME_OVERWRITE': - time_overwrite_data = data[val].to_list() - # self.rm.jobs._job_list[self.rm.jobs._job_list['effect']==effect_name] - temp_list_for_effect_name = [effect_name] * data[val].size - _key = list( - zip( - temp_list_for_effect_name, - data[aliases['METHOD_NAME']], - data[aliases['ELEMENT_NAME']], - ) - ) - - time_overwrite_data = [ - {'FIXED_TIME_OVERWRITE': int(time_overwrite_data[i] * 3600)} - for i in range(len(time_overwrite_data)) - ] - self.rm.time_overwrite.update( - pd.Series(index=_key, data=time_overwrite_data).to_dict() - ) - - else: - raise ValueError('Unrecognized argument in pair: ' + _arg) - res = pd.DataFrame(res) - # print(res) - return res # noqa: RET504 - - def _read_demand_nodes(self): - titles = [] # noqa: F841 - ntitle = 0 - lnum = 0 - dtemp = [] - with open(self._demand_Node_file_name, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - words = line.split() - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.upper().startswith('NODEID'): # noqa: RET507 - title = words.copy() - ntitle = len( - words - ) # we need this to confirm that every line has data for every title(column) - continue - elif nwords != ntitle: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d: Number of data does not match number of titles' # noqa: EM101 - ) - elif nwords == ntitle: - dtemp.append(words) - else: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d:This error must nnever happen' # noqa: EM101 - ) - self.demand_node = pd.DataFrame(dtemp, columns=title) - - def _read_crew(self): - titles = [] # noqa: F841 - ntitle = 0 - lnum = 0 - dtemp = [] - with open(self._crew_file_name[-1], encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - words = line.split() - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.upper().startswith('DISTYARDID'): # noqa: RET507 - title = words.copy() - ntitle = len( - words - ) # we need this to confirm that every line has data for every title(column) - continue - elif nwords != ntitle: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d: Number of data does not match number of titles' # noqa: EM101 - ) - elif nwords == ntitle: - dtemp.append(words) - else: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d:This error must nnever happen' # noqa: EM101 - ) - self.crew_data[self._crew_file_type[-1]] = pd.DataFrame( - dtemp, columns=title - ) diff --git a/modules/systemPerformance/REWET/REWET/Input/Settings.py b/modules/systemPerformance/REWET/REWET/Input/Settings.py deleted file mode 100644 index 25eadd019..000000000 --- a/modules/systemPerformance/REWET/REWET/Input/Settings.py +++ /dev/null @@ -1,582 +0,0 @@ -import json # noqa: INP001, D100 -import pickle -import warnings - -import numpy as np -import pandas as pd - -list_default_headers = [ - 'Scenario Name', - 'Pipe Damage', - 'Nodal Damage', - 'Pump Damage', - 'Tank Damage', - 'Probability', -] - -acceptable_override_list = ['POINTS'] - - -class base: # noqa: D101 - def __init__(self): - self.settings = {} - - def __getitem__(self, key): # noqa: D105 - return self.settings[key] - - def __setitem__(self, key, data): # noqa: D105 - self.settings[key] = data - - -class Process_Settings(base): # noqa: D101 - def __init__(self): - super().__init__() - """ - simulation settings - """ - self.settings['RUN_TIME'] = (5 + 24 * 1) * 3600 # seconds - self.settings['minimum_simulation_time'] = (10 + 24 * 2) * 3600 # seconds - self.settings['simulation_time_step'] = 3600 # seconds - self.settings['number_of_damages'] = ( - 'multiple' # single or multiple. If single, indicate single damage files. If multiple, indicate "pipe_damage_file_list" - ) - self.settings['result_directory'] = 'Result' # "Net3//Result" - self.settings['temp_directory'] = 'RunFiles' - self.settings['save_time_step'] = True - self.settings['last_sequence_termination'] = ( - True # sina needs to be applied in GUI - ) - self.settings['node_demand_temination'] = ( - False # sina needs to be applied in GUI - ) - self.settings['node_demand_termination_time'] = ( - 3 * 3600 - ) # sina needs to be applied in GUI - self.settings['node_demand_termination_ratio'] = ( - 0.95 # sina needs to be applied in GUI - ) - self.settings['record_restoration_agent_logs'] = ( - True # sina needs to be applied in GUI - ) - self.settings['record_damage_table_logs'] = ( - True # sina needs to be applied in GUI - ) - - """ - Hydraulic settings - """ - self.settings['WN_INP'] = ( - 'Example/net3.inp' # 'giraffe386-4-1.inp' #"Anytown.inp"#'giraffe386-4-1.inp' #"Net3/net3.inp" - ) - self.settings['demand_ratio'] = 1 - self.settings['solver'] = ( - 'ModifiedEPANETV2.2' # sina needs to be implemented - ) - # self.settings['hydraulic_time_step'] = 3600 - self.settings['solver_type'] = 'ModifiedEPANETV2.2' - - """ - Damage settings - """ - - self.settings['pipe_damage_file_list'] = ( - 'Example/example_list.xlsx' # "Nafiseh Damage Data/9_final_akhar/list_1_final.xlsx" #"preprocess/list2-3.xlsx"#"preprocess/list2-3.xlsx" #"list_akhar_with_prob_pgv_epicenter_1.xlsx"#"preprocess/list2-3.xlsx" #"Net3/list.xlsx" #"preprocess/list2-3.xlsx" #"list_W147_6.xlsx" #'Nafiseh Damage Data/list.xlsx' - ) - self.settings['pipe_damage_file_directory'] = ( - r'Example\Damages' # 'Nafiseh Damage Data/9_final_akhar'#"" #'Net3' #'Nafiseh Damage Data/out'"X:\\Sina Naeimi\\anytown_damage\\" - ) - self.settings['pump_damage_relative_time'] = ( - True # needs to be implemented in the code - ) - self.settings['tank_damage_relative_time'] = ( - True # needs to be implemented in the code - ) - - """ - Restoration settings - """ - self.settings['Restoration_on'] = True - self.settings['minimum_job_time'] = 3600 # sina needs to be implemented - - """ - None GUI settings - """ - # self.settings['job_assign_time_limit' ]=None # time in seconds or None - self.settings['maximun_worker_idle_time'] = 60 - self.settings['number_of_proccessor'] = 1 - - self.settings['dmg_rst_data_save'] = True - self.settings['Parameter_override'] = ( - True # 'starter/settings.xlsx' #this is for settings sensitivity analysis - ) - self.settings['mpi_resume'] = True # ignores the scenarios that are done - self.settings['ignore_empty_damage'] = False - self.settings['result_details'] = 'extended' - self.settings['negative_node_elmination'] = True - self.settings['nne_flow_limit'] = 0.5 - self.settings['nne_pressure_limit'] = -5 - self.settings['Virtual_node'] = True - self.settings['damage_node_model'] = ( - 'equal_diameter_emitter' # "equal_diameter_reservoir" - ) - - self.settings['limit_result_file_size'] = -1 # in Mb. 0 means no limit - - -class Scenario_Settings(base): # noqa: D101 - def __init__(self): - super().__init__() - """ - Hydraulic settings - """ - self.settings['minimum_pressure'] = 8 - self.settings['required_pressure'] = 25 - self.settings['pressure_exponent'] = 0.75 # sina add it to the code and GUI - # Sina also take care of the nodal damage formula in terms of exponents [Urgent] - self.settings['hydraulic_time_step'] = 900 - - """ - Damage settings - """ - self.settings['Pipe_damage_input_method'] = 'excel' # excel or pickle - self.settings['pipe_damage_model'] = { - 'CI': { - 'alpha': -0.0038, - 'beta': 0.1096, - 'gamma': 0.0196, - 'a': 2, - 'b': 1, - }, - 'DI': { - 'alpha': -0.0079, - 'beta': 0.0805, - 'gamma': 0.0411, - 'a': 2, - 'b': 1, - }, - 'STL': { - 'alpha': -0.009, - 'beta': 0.0808, - 'gamma': 0.0472, - 'a': 2, - 'b': 1, - }, - 'CON': { - 'alpha': -0.0083, - 'beta': 0.0738, - 'gamma': 0.0431, - 'a': 2, - 'b': 1, - }, - 'RS': { - 'alpha': -0.0088, - 'beta': 0.0886, - 'gamma': 0.0459, - 'a': 2, - 'b': 1, - }, - } # sina needs to be implemented - self.settings['default_pipe_damage_model'] = { - 'alpha': -0.0038, - 'beta': 0.1096, - 'gamma': 0.0196, - 'a': 2, - 'b': 1, - } - self.settings['node_damage_model'] = { - 'x': 0.9012, - 'a': 0.0036, - 'aa': 1, - 'b': 0, - 'bb': 0, - 'c': -0.877, - 'cc': 1, - 'd': 0, - 'dd': 0, - 'e': 0.0248, - 'ee1': 1, - 'ee2': 1, - 'f': 0, - 'ff1': 0, - 'ff2': 0, - 'damage_node_model': 'equal_diameter_emitter', - } # sina needs to be implemented - # Sina, there is no x in the GUI. Implement it - """ - Restoration settings - """ # noqa: W291 - self.settings['Restoraion_policy_type'] = ( - 'script' # sina needs to be implemented in the code - ) - self.settings['Restortion_config_file'] = ( - 'Example/exampe_config.txt' # "config-ghab-az-tayid.txt" #'X:\\Sina Naeimi\\anytown_damage\\config-base_base.txt'#'config-base_hydsig.txt' #'Net3/config.txt' # - ) - self.settings['pipe_damage_discovery_model'] = { - 'method': 'leak_based', - 'leak_amount': 0.025, - 'leak_time': 3600 * 12, - } # sina needs to be implemented - self.settings['node_damage_discovery_model'] = { - 'method': 'leak_based', - 'leak_amount': 0.001, - 'leak_time': 3600 * 12, - } # sina needs to be implemented - self.settings['pump_damage_discovery_model'] = { - 'method': 'time_based', - 'time_discovery_ratio': pd.Series([1], index=[3600 * n for n in [0]]), - } # sina needs to be implemented - self.settings['tank_damage_discovery_model'] = { - 'method': 'time_based', - 'time_discovery_ratio': pd.Series([1], index=[3600 * n for n in [0]]), - } # sina needs to be implemented - self.settings['Gnode_damage_discovery_model'] = { - 'method': 'time_based', - 'time_discovery_ratio': pd.Series([1], index=[3600 * n for n in [0]]), - } # Sina GNode Discovery is not here! Must be appleid in the GUI - self.settings['reservoir_damage_discovery_model'] = { - 'method': 'time_based', - 'time_discovery_ratio': pd.Series([1], index=[3600 * n for n in [0]]), - } # Sina GNode Discovery is not here! Must be appleid in the GUI - self.settings['crew_out_of_zone_travel'] = ( - False # sina needs to be implemented in the code - ) - self.settings['crew_travel_speed'] = ( - 16.66666 # unit: ft/s approximately 18 km/h. The unit is [coordinate unit] per seconds. # sina needs to be implemented in the code - ) - - self.settings['equavalant_damage_diameter'] = 1 - self.settings['pipe_damage_diameter_factor'] = 1 - - -class Settings: # noqa: D101 - def __init__(self): - self.process = Process_Settings() - self.scenario = Scenario_Settings() - self.overrides = {} - - def __setitem__(self, key, data): # noqa: D105 - if key in self.process.settings: - self.process.settings[key] = data - elif key in self.scenario.settings: - self.scenario.settings[key] = data - else: - raise AttributeError(repr(key) + ' is not in the Settings.') - - def __getitem__(self, key): # noqa: D105 - if key in self.process.settings: - if self.scenario != None: # noqa: E711 - if key in self.scenario.settings: - raise ValueError( - str(key) + ' in both the process and scenario settings.' - ) - - return self.process.settings[key] - elif self.scenario != None: # noqa: RET505, E711 - if key in self.scenario.settings: - return self.scenario.settings[key] - - raise ValueError(str(key) + ' NOT in either process and scenario settings.') - - def __contains__(self, key): # noqa: D105 - if key in self.process.settings: - return True - elif self.scenario != None: # noqa: RET505, E711 - if key in self.scenario.settings: - return True - - return False - - def importJsonSettings(self, json_file_path): # noqa: N802 - """Read a settinsg json file and import the data - - Args: - ---- - json_file_path (path): JSON file path - - """ # noqa: D400 - with open(json_file_path) as f: # noqa: PTH123 - settings_data = json.load(f) - - if not isinstance(settings_data, dict): - raise ValueError( # noqa: TRY003, TRY004 - 'Wrong JSON file type for the settings. The settings JSOn file must be an OBJECT file type.' # noqa: EM101 - ) - - for key, val in settings_data.items(): - if key not in self: - raise ValueError( # noqa: TRY003 - f'REWET settinsg does not have "{key}" as a settings key' # noqa: EM102 - ) - - print(key, val) # noqa: T201 - if ( - key - in [ - 'pipe_damage_discovery_model', - 'node_damage_discovery_model', - 'pump_damage_discovery_model', - 'tank_damage_discovery_model', - ] - and val['method'] == 'time_based' - ): - val['time_discovery_ratio'] = pd.Series( - [line[0] for line in val['time_discovery_ratio']], - index=[line[1] for line in val['time_discovery_ratio']], - ) - - self[key] = val - - def importProject(self, project_addr): # noqa: N802, D102 - with open(project_addr, 'rb') as f: # noqa: PTH123 - project = pickle.load(f) # noqa: S301 - # for k in project.project_settings.scenario.settings: - # new_value = project.project_settings.scenario[k] - # old_value = self.scenario[k] - # print(k + ": " + repr(new_value) + " --> " + repr(old_value) + "\n"+"-----" + repr(type(new_value)) ) - self.process = project.project_settings.process - self.scenario = project.project_settings.scenario - - def initializeScenarioSettings(self, scenario_index): # noqa: C901, N802, D102 - if self.process['Parameter_override'] == False: # noqa: E712 - return - - list_file = pd.read_excel(self['pipe_damage_file_list']) - columns = list_file.columns - parametrs_list = columns.drop(list_default_headers) - - for parameter_name in parametrs_list: - # to prevent unnamed columns appearing in the warnings - if 'Unnamed' in parameter_name: - continue - override_value = list_file.loc[scenario_index, parameter_name] - scenario_name = list_file.loc[scenario_index, 'Scenario Name'] - - if parameter_name in self: - try: - if type(override_value) != str and np.isnan(override_value): # noqa: E721 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The value for ' - + repr(parameter_name) - + ' is empty. The override is IGNORED!' - ) - continue - except: # noqa: S110, E722 - pass - - if override_value == '': - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The value for ' - + repr(parameter_name) - + ' is empty. The override is IGNORED!' - ) - continue - - self[parameter_name] = override_value - else: - splited_parameter_name = parameter_name.split(':') - number_of_words = len(splited_parameter_name) - - override_key1 = splited_parameter_name[0] - override_key2 = splited_parameter_name[1] - - if number_of_words != 2: # noqa: PLR2004 - raise ValueError( - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The parameter ' - + repr(parameter_name) - + ' is not an acceptable parameter' - ) - - if override_key1 == None: # noqa: E711 - raise ValueError( - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + repr(parameter_name) - + ' is not an acceptable parameter' - ) - - if override_key1.upper() not in acceptable_override_list: - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + repr(override_key1) - + ' is not an acceptable parameter. The override is IGNORED!' - + '\n' - + 'Acceptable override parameters are ' - + repr(acceptable_override_list) - ) - continue - - try: - if type(override_value) != str and np.isnan(override_value): # noqa: E721 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The value for ' - + repr(parameter_name) - + ' is empty. The override is IGNORED!' - ) - continue - except: # noqa: S110, E722 - pass - - if override_value == '': - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The value for ' - + repr(parameter_name) - + ' is empty. The override is IGNORED!' - ) - continue - - if override_key1.upper() == 'POINTS': - if override_key2 == None: # noqa: E711 - raise ValueError( - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'You should provide a Points Group Name for POINTS override key. WARNING: If POINTS Group Name mismatch, it may not take any effect' - + '\n' - ) - - point_list = self.getOverridePointsList( - override_value, scenario_name - ) - if len(point_list) > 0: - if 'POINTS' in self.overrides: - self.overrides['POINTS'][override_key2] = point_list - else: - self.overrides['POINTS'] = {override_key2: point_list} - else: - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + 'The Override Point Group has no valid input; thus, the override is ignored!' - ) - - # ============================================================================= - # elif override_key1.upper() == "CREWSPEED": - # if override_key2 == None: - # raise ValueError("REWET Input ERROR in scenario: " + repr(scenario_name) + "\n" + "You should provide a Crew Speed for CREWSPEED override key." + "\n") - # - # crew_speed = self.getOverrideCrewSpeed(override_value, scenario_name) - # if crew_speed != None: - # self.overrides["CREWSPEED"] = crew_speed - # else: - # warnings.warn("REWET Input ERROR in scenario: " + repr(scenario_name) + "\n" + "SPEEDCREW is not valid; thus, the override is ignored!") - # ============================================================================= - else: - raise ValueError('Unknown overrise key') # noqa: EM101, TRY003 - - def getOverridePointsList(self, points_list_str, scenario_name): # noqa: N802, D102 - point_list = [] - - points_list_str = points_list_str.strip() - points_list_str = points_list_str.split() - - for word in points_list_str: - if ':' not in word: - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + word - + " must be two numbeers speerated by one ':' showing X:Y coordinate. " - + word - + ' is ignored!' - ) - continue - - splited_word = word.split(':') - - if len(splited_word) > 2: # noqa: PLR2004 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + word - + " must be two numbeers speerated by ONE ':' showing X:Y coordinate. " - + word - + ' is ignored!' - ) - continue - - x_coord = splited_word[0] - y_coord = splited_word[1] - - try: - x_coord = float(x_coord) - except: # noqa: E722 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + x_coord - + ' in ' - + word - + " must be a number speerated by ONE ':' showing X:Y coordinate. " - + word - + ' is ignored!' - ) - continue - - try: - y_coord = float(y_coord) - except: # noqa: E722 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + y_coord - + ' in ' - + word - + " must be a number speerated by ONE ':' showing X:Y coordinate. " - + word - + ' is ignored!' - ) - continue - - point_list.append((x_coord, y_coord)) - - return point_list - - def getOverrideCrewSpeed(self, crew_speed_str, scenario_name): # noqa: N802, D102 - crew_speed_str = crew_speed_str.strip() - - if len(crew_speed_str.split()) > 1: - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + crew_speed_str - + ' must be ONE single number. Space detected!' - ) - return None - - try: - crew_speed = float(crew_speed_str) - except: # noqa: E722 - warnings.warn( # noqa: B028 - 'REWET Input ERROR in scenario: ' - + repr(scenario_name) - + '\n' - + crew_speed - + ' must be a number.' - ) - return None - - return crew_speed diff --git a/modules/systemPerformance/REWET/REWET/Main_GUI.py b/modules/systemPerformance/REWET/REWET/Main_GUI.py deleted file mode 100644 index ba6823a4c..000000000 --- a/modules/systemPerformance/REWET/REWET/Main_GUI.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Created on Thu Nov 10 21:46:04 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import os -import sys - -if __name__ == '__main__': - from GUI.Opening_Designer import Opening_Designer - - opening_designer = Opening_Designer() - print(os.getpid()) # noqa: T201 - sys.exit(opening_designer.run()) diff --git a/modules/systemPerformance/REWET/REWET/Output/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/Output/CMakeLists.txt deleted file mode 100644 index 4b085e23b..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -simcenter_add_python_script(SCRIPT Crew_Report.py) -simcenter_add_python_script(SCRIPT Curve.py) -simcenter_add_python_script(SCRIPT GUI_Curve_API.py) -simcenter_add_python_script(SCRIPT Helper.py) -simcenter_add_python_script(SCRIPT Map.py) -simcenter_add_python_script(SCRIPT Raw_Data.py) -simcenter_add_python_script(SCRIPT Result_Time.py) diff --git a/modules/systemPerformance/REWET/REWET/Output/Crew_Report.py b/modules/systemPerformance/REWET/REWET/Output/Crew_Report.py deleted file mode 100644 index ade0ecae5..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Crew_Report.py +++ /dev/null @@ -1,195 +0,0 @@ -"""Created on Thu Oct 27 15:45:10 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - -import pandas as pd - - -class Crew_Report: # noqa: D101 - def __init__(self): - pass - - def getCrewForTime(self, scn_name, time): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - - crew_table = reg.restoration_log_book._agent_state_log_book # noqa: SLF001 - crew_table = crew_table.set_index('Time') - crew_table = crew_table.loc[time] - return crew_table # noqa: RET504 - - def getCrewTableAt(self, scn_name, time, crew_type_name, crew_zone=None): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - # crew_type = self.getCrewForTime(scn_name, time) - crew_table = reg.restoration_log_book.crew_history[time] - typed_crew_table = crew_table[crew_table['type'] == crew_type_name] - - if crew_zone is not None: - if type(crew_zone) == str: # noqa: E721 - typed_crew_table = typed_crew_table[ - typed_crew_table['group'] == crew_zone - ] - elif type(crew_zone) == list: # noqa: E721 - i = 0 - for crew_zone_value in crew_zone: - if i == 0: - res = typed_crew_table['group'] == crew_zone_value - else: - res = (typed_crew_table['group'] == crew_zone_value) | res - i += 1 # noqa: SIM113 - typed_crew_table = typed_crew_table[res] - else: - raise ValueError('Unknown crew_zone type: ' + repr(type(crew_zone))) - - return typed_crew_table - - def getCrewAvailabilityThroughTime( # noqa: N802, D102 - self, - scn_name, - crew_type_name, - crew_zone=None, - ): - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - crew_table = reg.restoration_log_book.crew_history - time_list = list(crew_table.keys()) - time_list.sort() - - crew_number = pd.Series() - - for time in time_list: - crew_table_time = self.getCrewTableAt( - scn_name, time, crew_type_name, crew_zone - ) - total_number = len(crew_table_time) - available_number_time = crew_table_time[ - (crew_table_time['available'] == True) # noqa: E712 - | (crew_table_time['active'] == True) # noqa: E712 - ] - crew_number.loc[time] = len(available_number_time) - - return total_number, crew_number - - def getCrewOnShiftThroughTime( # noqa: N802, D102 - self, - scn_name, - crew_type_name, - crew_zone=None, - not_on_shift=False, # noqa: FBT002 - ): - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - crew_table = reg.restoration_log_book.crew_history - time_list = list(crew_table.keys()) - time_list.sort() - - crew_number = pd.Series() - - for time in time_list: - crew_table_time = self.getCrewTableAt( - scn_name, time, crew_type_name, crew_zone - ) - total_number = len(crew_table_time) - - if not_on_shift == False: # noqa: E712 - available_number_time = crew_table_time[ - crew_table_time['active'] == True # noqa: E712 - ] - elif not_on_shift == True: # noqa: E712 - available_number_time = crew_table_time[ - crew_table_time['active'] == False # noqa: E712 - ] - else: - raise ValueError('Unnown not on shift' + repr(not_on_shift)) - crew_number.loc[time] = len(available_number_time) - - return total_number, crew_number - - def getCrewWorkingThroughTime( # noqa: N802, D102 - self, - scn_name, - crew_type_name, - crew_zone=None, - not_on_working=False, # noqa: FBT002 - ): - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - crew_table = reg.restoration_log_book.crew_history - time_list = list(crew_table.keys()) - time_list.sort() - - crew_number = pd.Series() - - for time in time_list: - crew_table_time = self.getCrewTableAt( - scn_name, time, crew_type_name, crew_zone - ) - total_number = len(crew_table_time) - # available_number_time = crew_table_time[crew_table_time['available']==True] - available_number_time = crew_table_time[ - crew_table_time['active'] == True # noqa: E712 - ] - if not_on_working == False: # noqa: E712 - available_number_time = available_number_time[ - available_number_time['ready'] == False # noqa: E712 - ] - elif not_on_working == True: # noqa: E712 - available_number_time = available_number_time[ - available_number_time['ready'] == True # noqa: E712 - ] - else: - raise ValueError('Unnown not on shift' + repr(not_on_working)) - crew_number.loc[time] = len(available_number_time) - - return total_number, crew_number - - def getCrewCompleteStatusReport(self, scn_name, crew_type_name, crew_zone=None): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - crew_table = reg.restoration_log_book.crew_history - time_list = list(crew_table.keys()) - time_list.sort() - - crew_report = pd.DataFrame( - index=time_list, - columns=[ - 'Reported', - 'Not-reported', - 'Total_not-reported', - 'on-duty', - 'off-duty', - 'idle', - 'busy', - ], - data=0, - ) - - for time in time_list: - crew_table_time = self.getCrewTableAt( - scn_name, time, crew_type_name, crew_zone - ) - - for agent_index, agent_row in crew_table_time.iterrows(): # noqa: B007 - if agent_row['data'].isOnShift(time): - crew_report.loc[time, 'on-duty'] += 1 - else: - crew_report.loc[time, 'off-duty'] += 1 - - # iAvailable = agent_row['available'] - if agent_row['available'] or agent_row['active']: - crew_report.loc[time, 'Reported'] += 1 - if agent_row['active'] and agent_row['ready']: - crew_report.loc[time, 'idle'] += 1 - elif agent_row['active'] and agent_row['ready'] == False: # noqa: E712 - crew_report.loc[time, 'busy'] += 1 - else: - crew_report.loc[time, 'Total_not-reported'] += 1 - if agent_row['data'].isOnShift(time): - crew_report.loc[time, 'Not-reported'] += 1 - if agent_row['active'] == True: # noqa: E712 - print('time=' + str(time)) # noqa: T201 - print(agent_row) # noqa: T201 - - return crew_report diff --git a/modules/systemPerformance/REWET/REWET/Output/Curve.py b/modules/systemPerformance/REWET/REWET/Output/Curve.py deleted file mode 100644 index ef7d06e3b..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Curve.py +++ /dev/null @@ -1,552 +0,0 @@ -"""Created on Tue Oct 25 14:30:01 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - -import pandas as pd - -from .Helper import hhelper - - -class Curve: # noqa: D101 - def __init__(): - pass - - def getPipeStatusByAction(self, scn_name, action): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - sequence = reg.retoration_data['sequence']['PIPE'] - if action not in sequence: - raise ValueError('the action is not in the sequence: ' + str(action)) - pipe_damage_table_time_series = reg._pipe_damage_table_time_series # noqa: SLF001 - time_action_done = {} - for time in pipe_damage_table_time_series: - current_pipe_damage_table = pipe_damage_table_time_series[time] - current_action_damage = current_pipe_damage_table[action] - number_of_all = len(current_action_damage) - if number_of_all < 1: - continue - current_action_damage = current_action_damage[ - ~current_action_damage.isna() - ] - current_action_damage_true = current_action_damage[ - current_action_damage == True # noqa: E712 - ] - unique_done_orginal_element_list = ( - ( - current_pipe_damage_table.loc[current_action_damage_true.index][ - 'Orginal_element' - ] - ) - .unique() - .tolist() - ) - current_pipe_damage_table = current_pipe_damage_table.set_index( - 'Orginal_element' - ) - current_action_damage = current_pipe_damage_table.loc[ - unique_done_orginal_element_list - ] - - number_of_done = len(current_action_damage) - time_action_done[time] = number_of_done / number_of_all - - return pd.Series(time_action_done) - - def getNodeStatusByAction(self, scn_name, action): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - sequence = reg.retoration_data['sequence']['DISTNODE'] - if action not in sequence: - raise ValueError('the action is not in the sequence: ' + str(action)) - node_damage_table_time_series = reg._node_damage_table_time_series # noqa: SLF001 - time_action_done = {} - for time in node_damage_table_time_series: - current_node_damage_table = node_damage_table_time_series[time] - current_action_damage = current_node_damage_table[action] - number_of_all = len(current_action_damage) - if number_of_all < 1: - continue - current_action_damage = current_action_damage[ - ~current_action_damage.isna() - ] - current_action_damage_true = current_action_damage[ - current_action_damage == True # noqa: E712 - ] - unique_done_orginal_element_list = ( - ( - current_node_damage_table.loc[current_action_damage_true.index][ - 'Orginal_element' - ] - ) - .unique() - .tolist() - ) - current_node_damage_table = current_node_damage_table.set_index( - 'Orginal_element' - ) - current_action_damage = current_node_damage_table.loc[ - unique_done_orginal_element_list - ] - - number_of_done = len(current_action_damage) - time_action_done[time] = number_of_done / number_of_all - - return pd.Series(time_action_done) - - def getPumpStatus(self, scn_name): # noqa: N802, D102 - self.loadScneariodata(scn_name) - res = self.data[scn_name] - reg = self.registry[scn_name] - time_list = res.node['demand'].index - pump_damage = reg.damage.damaged_pumps - pump_damage_time = pump_damage.index - - time_action_done = {} - for time in time_list: - done_list = pump_damage_time[pump_damage_time >= time] - time_action_done[time] = len(done_list) / len(pump_damage_time) - - return pd.Series(time_action_done) - - def getTankStatus(self, scn_name): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - time_list = reg.time_list - tank_damage = reg.damage.tamk_damage - tank_damage_time = tank_damage.index - - time_action_done = {} - for time in time_list: - done_list = tank_damage_time[tank_damage_time >= time] - time_action_done[time] = len(done_list) / len(tank_damage_time) - - return pd.Series(time_action_done) - - def getInputWaterFlowCurve( # noqa: C901, N802, D102 - self, - scn_name, - tank_name_list=None, - reservoir_name_list=None, - mode='all', - ): - self.loadScneariodata(scn_name) - res = self.data[scn_name] - - if tank_name_list == None: # noqa: E711 - tank_name_list = self.wn.tank_name_list - - not_known_tank = set(tank_name_list) - set(self.wn.tank_name_list) - if len(not_known_tank) > 0: - raise ValueError( - 'The following tanks in the input are not known in the water network' - + repr(tank_name_list) - ) - - if reservoir_name_list == None: # noqa: E711 - reservoir_name_list = self.wn.reservoir_name_list - - not_known_reservoir = set(reservoir_name_list) - set( - self.wn.reservoir_name_list - ) - if len(not_known_reservoir) > 0: - raise ValueError( - 'The following reservoirs in the input are not known in the water network' - + repr(reservoir_name_list) - ) - - outbound_flow = pd.Series(0, index=res.node['demand'].index) - inbound_flow = pd.Series(0, index=res.node['demand'].index) - # inbound_flow = 0 - # outbound_flow = 0 - - waterFlow = None # noqa: N806 - - for tank_name in tank_name_list: - if tank_name in res.node['demand'].columns: - flow_in_time = res.node['demand'][tank_name] - else: - continue - for time, flow in flow_in_time.iteritems(): - # print(flow) - if flow > 0: - outbound_flow.loc[time] += -1 * flow - elif flow < 0: - inbound_flow.loc[time] += -1 * flow - - if mode == 'all': - waterFlow = outbound_flow + inbound_flow # noqa: N806 - elif mode == 'out': - waterFlow = outbound_flow # noqa: N806 - elif mode == 'in': - waterFlow = inbound_flow # noqa: N806 - else: - raise ValueError('Unnown mode: ' + repr(mode)) - - for reservoir_name in reservoir_name_list: - if reservoir_name in res.node['demand'].columns: - flow_in_time = res.node['demand'][reservoir_name] - else: - continue - for time, flow in flow_in_time.iteritems(): - # print(flow) - if flow > 0: - outbound_flow.loc[time] += -1 * flow - elif flow < 0: - inbound_flow.loc[time] += -1 * flow - - if mode == 'all': - waterFlow = outbound_flow + inbound_flow # noqa: N806 - elif mode == 'out': - waterFlow = outbound_flow # noqa: N806 - elif mode == 'in': - waterFlow = inbound_flow # noqa: N806 - else: - raise ValueError('Unnown mode: ' + repr(mode)) - - return waterFlow - - def getOveralDemandSatisfied(self, scn_name, pure=False): # noqa: FBT002, N802, D102 - self.loadScneariodata(scn_name) - if pure == False: # noqa: E712 - demand_node_name_list = self.demand_node_name_list - else: - demand_node_name_list = [] - for node_name in self.wn.junction_name_list: - if ( - self.wn.get_node(node_name).demand_timeseries_list[0].base_value - > 0 - ): - demand_node_name_list.append(node_name) - - sat_node_demands = ( - self.data[scn_name].node['demand'].filter(demand_node_name_list) - ) - # sat_node_demands = sat_node_demands.applymap(hhelper) - s = sat_node_demands.sum(axis=1) - - return s # noqa: RET504 - - def getWaterLeakingFromNode(self, scn_name): # noqa: N802, D102 - self.loadScneariodata(scn_name) - res = self.data[scn_name] - sum_amount = 0 - try: - res = res.node['leak'] - sum_amount = res.sum(axis=1) - except: # noqa: E722 - sum_amount = 0 - return sum_amount - - def getWaterLeakingFromPipe(self, scn_name, mode='all'): # noqa: N802, D102 - self.loadScneariodata(scn_name) - reg = self.registry[scn_name] - res = self.data[scn_name] - - damage_location_list = reg._pipe_damage_table # noqa: SLF001 - - if mode == 'leak' or mode == 'break': # noqa: PLR1714 - damage_location_list = damage_location_list[ - damage_location_list['damage_type'] == mode - ] - elif mode == 'all': - pass - else: - raise ValueError('The mode is not recognized: ' + repr(mode)) - - break_damage_table = damage_location_list[ - damage_location_list['damage_type'] == 'break' - ] - pipe_B_list = self.registry[scn_name]._pipe_break_history.loc[ # noqa: SLF001, N806 - break_damage_table.index, 'Node_B' - ] - - damage_location_list = damage_location_list.index - wanted_nodes = pipe_B_list.to_list() - wanted_nodes.extend(damage_location_list.to_list()) - - available_nodes = set(res.node['demand'].columns) - wanted_nodes = set(wanted_nodes) - - not_available_nodes = wanted_nodes - available_nodes - available_nodes = wanted_nodes - not_available_nodes - - leak_from_pipe = res.node['demand'][available_nodes] - - leak = leak_from_pipe < -0.1 # noqa: PLR2004 - if leak.any().any(): - raise ValueError('There is negative leak') # noqa: EM101, TRY003 - - return leak_from_pipe.sum(axis=1) - - def getSystemServiceabilityIndexCurve(self, scn_name, iPopulation='No'): # noqa: N802, N803, D102 - s4 = self.getRequiredDemandForAllNodesandtime(scn_name) - sat_node_demands = ( - self.data[scn_name].node['demand'].filter(self.demand_node_name_list) - ) - sat_node_demands = sat_node_demands.applymap(hhelper) - - if iPopulation == 'Yes': - s4 = s4 * self._population_data - sat_node_demands = sat_node_demands * self._population_data - elif iPopulation == 'No': - pass - else: - raise ValueError('unknown iPopulation value: ' + repr(iPopulation)) - - s = sat_node_demands.sum(axis=1) / s4.sum(axis=1) - - for time_index, val in s.iteritems(): - if val < 0: - val = 0 # noqa: PLW2901 - elif val > 1: - val = 1 # noqa: PLW2901 - s.loc[time_index] = val - - return s - - def getBSCIndexPopulation_4( # noqa: N802, D102 - self, - scn_name, - bsc='DL', - iPopulation=False, # noqa: FBT002, N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=1, - ): - if bsc == 'DL': - return self.getDLIndexPopulation_4( - scn_name, - iPopulation=iPopulation, - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - elif bsc == 'QN': # noqa: RET505 - return self.getQNIndexPopulation_4( - scn_name, - iPopulation=iPopulation, - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - else: - raise ValueError(f'BSC input is not recognizable: {bsc}') # noqa: EM102, TRY003 - - def getDLIndexPopulation_4( # noqa: C901, N802, D102 - self, - scn_name, - iPopulation='No', # noqa: N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=1, - ): - if type(leak_ratio) != float: # noqa: E721 - leak_ratio = float(leak_ratio) - - self.loadScneariodata(scn_name) - res = self.data[scn_name] - - if type(self._population_data) == type(None) or iPopulation == False: # noqa: E712, E721 - pop = pd.Series(index=self.demand_node_name_list, data=1) - elif type(self._population_data) == type(None) and iPopulation == True: # noqa: E712, E721 - raise ValueError('Population data is not available') # noqa: EM101, TRY003 - else: - pop = self._population_data - - total_pop = pop.sum() - - result = [] - refined_result = res.node['demand'][self.demand_node_name_list] - demands = self.getRequiredDemandForAllNodesandtime(scn_name) - demands = demands[self.demand_node_name_list] - - union_ = ( - set(res.node['leak'].columns).union(set(self.demand_node_name_list)) - - (set(res.node['leak'].columns) - set(self.demand_node_name_list)) - - (set(self.demand_node_name_list) - set(res.node['leak'].columns)) - ) - union_ = list(union_) - leak_res = res.node['leak'][union_] - - leak_data = [] - - if consider_leak: - for name in leak_res: - demand_name = demands[name] - leak_res_name = leak_res[name].dropna() - time_list = set(leak_res[name].dropna().index) - time_list_drop = set(demands.index) - time_list - demand_name = demand_name.drop(time_list_drop) - leak_more_than_criteria = leak_res_name >= leak_ratio * demand_name - if leak_more_than_criteria.any(0): - leak_data.append(leak_more_than_criteria) - leak_data = pd.DataFrame(leak_data).transpose() - - s = refined_result > demands * 0.1 - for name in s: - if name in leak_data.columns: - leak_data_name = leak_data[name] - for time in leak_data_name.index: - if leak_data_name.loc[time] == True: # noqa: E712 - s.loc[time, name] = False - - s = s * pop[s.columns] - - if ratio == False: # noqa: E712 - total_pop = 1 - else: - total_pop = pop.sum() - - result = s.sum(axis=1) / total_pop - - return result # noqa: RET504 - - def getQNIndexPopulation_4( # noqa: C901, N802, D102 - self, - scn_name, - iPopulation=False, # noqa: FBT002, N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=0.75, - ): - if type(leak_ratio) != float: # noqa: E721 - leak_ratio = float(leak_ratio) - - self.loadScneariodata(scn_name) - res = self.data[scn_name] - - if type(self._population_data) == type(None) or iPopulation == False: # noqa: E712, E721 - pop = pd.Series(index=self.demand_node_name_list, data=1) - elif type(self._population_data) == type(None) and iPopulation == True: # noqa: E712, E721 - raise ValueError('Population data is not available') # noqa: EM101, TRY003 - else: - pop = self._population_data - - result = [] - union_ = ( - set(res.node['leak'].columns).union(set(self.demand_node_name_list)) - - (set(res.node['leak'].columns) - set(self.demand_node_name_list)) - - (set(self.demand_node_name_list) - set(res.node['leak'].columns)) - ) - union_ = list(union_) - refined_result = res.node['demand'][self.demand_node_name_list] - demands = self.getRequiredDemandForAllNodesandtime(scn_name) - demands = demands[self.demand_node_name_list] - - leak_res = res.node['leak'][union_] - leak_data = [] - if consider_leak: - for name in leak_res: - demand_name = demands[name] - leak_res_name = leak_res[name].dropna() - time_list = set(leak_res_name.index) - time_list_drop = set(demands.index) - time_list - demand_name = demand_name.drop(time_list_drop) - leak_more_than_criteria = leak_res_name >= leak_ratio * demand_name - if leak_more_than_criteria.any(0): - leak_data.append(leak_more_than_criteria) - leak_data = pd.DataFrame(leak_data).transpose() - - s = refined_result + 0.00000001 >= demands # sina bug - - for name in s: - if name in leak_data.columns: - leak_data_name = leak_data[name] - for time in leak_data_name.index: - if leak_data_name.loc[time] == True: # noqa: E712 - s.loc[time, name] = False - - s = s * pop[s.columns] - if ratio == False: # noqa: E712 - total_pop = 1 - else: - total_pop = pop.sum() - - result = s.sum(axis=1) / total_pop - - return result # noqa: RET504 - - def getQuantityExceedanceCurve( # noqa: N802, D102 - self, - iPopulation='No', # noqa: ARG002, N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=0.75, - result_type='mean', - daily=False, # noqa: FBT002 - min_time=0, - max_time=999999999999999, - ): - all_scenarios_qn_data = self.AS_getQNIndexPopulation( - iPopulation='No', - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - exceedance_curve = self.PR_getCurveExcedence( - all_scenarios_qn_data, - result_type=result_type, - daily=daily, - min_time=min_time, - max_time=max_time, - ) - columns_list = exceedance_curve.columns.to_list() - - dmg_vs_ep_list = {} - - for i in range(0, len(columns_list), 2): - dmg_col = columns_list[i] - ep_col = columns_list[i + 1] - dmg_vs_ep_list[dmg_col] = ep_col - res = {} - - for dmg_col in dmg_vs_ep_list: - ep_col = dmg_vs_ep_list[dmg_col] - exceedance_curve_temp = exceedance_curve.set_index(dmg_col) - exceedance_curve_temp = exceedance_curve_temp[ep_col] - res[dmg_col] = exceedance_curve_temp - - return res - - def getDeliveryExceedanceCurve( # noqa: N802, D102 - self, - iPopulation='No', # noqa: N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=0.75, - result_type='mean', - daily=False, # noqa: FBT002 - min_time=0, - max_time=999999999999999, - ): - all_scenarios_qn_data = self.AS_getDLIndexPopulation( - iPopulation=iPopulation, - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - exceedance_curve = self.PR_getCurveExcedence( - all_scenarios_qn_data, - result_type=result_type, - daily=daily, - min_time=min_time, - max_time=max_time, - ) - columns_list = exceedance_curve.columns.to_list() - - dmg_vs_ep_list = {} - - for i in range(0, len(columns_list), 2): - dmg_col = columns_list[i] - ep_col = columns_list[i + 1] - dmg_vs_ep_list[dmg_col] = ep_col - res = {} - - for dmg_col in dmg_vs_ep_list: - ep_col = dmg_vs_ep_list[dmg_col] - exceedance_curve_temp = exceedance_curve.set_index(dmg_col) - exceedance_curve_temp = exceedance_curve_temp[ep_col] - res[dmg_col] = exceedance_curve_temp - - return res diff --git a/modules/systemPerformance/REWET/REWET/Output/GUI_Curve_API.py b/modules/systemPerformance/REWET/REWET/Output/GUI_Curve_API.py deleted file mode 100644 index 85c68db92..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/GUI_Curve_API.py +++ /dev/null @@ -1,126 +0,0 @@ -"""Created on Thu Nov 10 19:12:46 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - -import pickle - - -def getDummyDataForQNExeedanceCurve(): # noqa: N802, D103 - with open('qn_data.pkl', 'rb') as f: # noqa: PTH123 - dummy_data = pickle.load(f) # noqa: S301 - return dummy_data # noqa: RET504 - - -""" -This section is for single scenario results. - -""" - - -""" -This section is for multi-scenarios (probabilistic) results. - -""" - - -def QNExceedanceCurve(pr, percentage_list, time_type, time_shift=0): # noqa: N802 - """Gets Project Result object, and returns Exceedance probability and Quantity - outage for the given percentages. Caution: the current version only accept - one percentage in the percentage list. - - Parameters - ---------- - pr : Project Result Object - DESCRIPTION. - percentage_List : list - the percentage. - time_type : 'second', 'hour' or 'day' - time_shift : in seconds, shift time representing the time before the event - - Excdance probability and outage for each percentage - ------- - None. - - """ # noqa: D205, D401 - data = getDummyDataForQNExeedanceCurve() - - if len(percentage_list) > 1: - raise ValueError( # noqa: TRY003 - 'the current version only accept one percentage in the percentage list' # noqa: EM101 - ) - - if type(time_shift) != int: # noqa: E721 - raise ValueError( - 'Time shift must be integer type: ' + repr(type(time_shift)) + '.' - ) - - if time_shift < 0: - raise ValueError('Time shift ust be bigger than or equal to zero.') # noqa: EM101, TRY003 - - res = {} - for percentage in percentage_list: - temp_res = pr.PR_getBSCPercentageExcedanceCurce(data, percentage) - - if time_type.lower() == 'seconds': - pass - elif time_type.lower() == 'hour': - pr.convertTimeSecondToHour(temp_res, 'restore_time', time_shift) - elif time_type.lower() == 'day': - pr.convertTimeSecondToDay(temp_res, 'restore_time', time_shift) - else: - raise ValueError('Uknown time_type: ' + repr(time_type)) - - res[percentage] = temp_res - return res # noqa: DOC201, RUF100 - - -def DLExceedanceCurve(pr, percentage_list, time_type, time_shift=0): # noqa: N802 - """Gets Project Result object, and returns Exceedance probability and Delivery - outage for the given percentages. Caution: the current version only accept - one percentage in the percentage list. - - Parameters - ---------- - pr : Project Result Object - DESCRIPTION. - percentage_List : list - the percentage. - time_type : 'second', 'hour' or 'day' - time_shift : in seconds, shift time representing the time before the event - - Excdance probability and outage for each percentage - ------- - None. - - """ # noqa: D205, D401 - data = getDummyDataForQNExeedanceCurve() - - if len(percentage_list) > 1: - raise ValueError( # noqa: TRY003 - 'the current version only accept one percentage in the percentage list' # noqa: EM101 - ) - - if type(time_shift) != int: # noqa: E721 - raise ValueError( - 'Time shift must be integer type: ' + repr(type(time_shift)) + '.' - ) - - if time_shift < 0: - raise ValueError('Time shift ust be bigger than or equal to zero.') # noqa: EM101, TRY003 - - res = {} - for percentage in percentage_list: - temp_res = pr.PR_getBSCPercentageExcedanceCurce(data, percentage) - - if time_type.lower() == 'seconds': - pass - elif time_type.lower() == 'hour': - pr.convertTimeSecondToHour(temp_res, 'restore_time', time_shift) - elif time_type.lower() == 'day': - pr.convertTimeSecondToDay(temp_res, 'restore_time', time_shift) - else: - raise ValueError('Uknown time_type: ' + repr(time_type)) - - res[percentage] = temp_res - return res # noqa: DOC201, RUF100 diff --git a/modules/systemPerformance/REWET/REWET/Output/Helper.py b/modules/systemPerformance/REWET/REWET/Output/Helper.py deleted file mode 100644 index 137949784..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Helper.py +++ /dev/null @@ -1,65 +0,0 @@ -"""Created on Mon Oct 24 18:10:31 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - -# import numba -import operator -from functools import reduce # Valid in Python 2.6+, required in Python 3 - -import numpy as np - - -def hhelper(x): # noqa: D103 - if x < 0: - return 0 - else: # noqa: RET505 - return x - - -# @numba.jit() -def EPHelper(prob_mat, old): # noqa: N802, D103 - if old == False: # prob_mat = prob_mat.tolist() # noqa: E712 - # one_minus_p_list = 1-prob_mat - one_minus_p_list = [1 - p for p in prob_mat] - pi_one_minus_p_list = [ - 1 - reduce(operator.mul, one_minus_p_list[: i + 1], 1) - for i in range(len(one_minus_p_list)) - ] - # pi_one_minus_p_list = [rr.apply(lambda x: [x[i] * x[1], raw=True) - return pi_one_minus_p_list # noqa: RET504 - # pi_one_minus_p_list.iloc[0] = one_minus_p_list.iloc[0] - - # return (pd.Series(1.00, index=pi_one_minus_p_list.index) - pi_one_minus_p_list, prob_mat) - else: # noqa: RET505 - ep_mat = np.ndarray(prob_mat.size) - for i in np.arange(prob_mat.size): - j = 0 - pi_one_minus_p = 1 - while j <= i: - p = prob_mat[j] - one_minus_p = 1 - p - pi_one_minus_p *= one_minus_p - j += 1 - ep_mat[i] = 1 - pi_one_minus_p - return ep_mat - - -def helper_outageMap(pandas_list): # noqa: N802, D103 - false_found_flag = False - b_list = pandas_list.tolist() - i = 0 - for b_value in b_list: - if b_value == False: # noqa: E712 - false_found_flag = True - break - i += 1 - - return false_found_flag, i - - -def hhelper(x): # noqa: D103, F811 - if x < 0: - return 0 - else: # noqa: RET505 - return x diff --git a/modules/systemPerformance/REWET/REWET/Output/Map.py b/modules/systemPerformance/REWET/REWET/Output/Map.py deleted file mode 100644 index c35ba5c8e..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Map.py +++ /dev/null @@ -1,606 +0,0 @@ -"""Created on Mon Oct 24 09:43:00 2022 -This file includes all Map Related Results. - -Class: - Map: inherieted by Project_Result{ - - functions: - loadShapeFile - joinTwoShapeFiles - createGeopandasPointDataFrameForNodes - getDLQNExceedenceProbabilityMap - getOutageTimeGeoPandas_4 -} - -@author: snaeimi -""" # noqa: INP001, D205 - -import warnings - -import geopandas as gpd -import numpy as np -import pandas as pd -import shapely -from Output import Helper - -# import time - - -class Map: # noqa: D101 - def __init__(self): - pass - - # def loadShapeFile(shapeFileAddr='Northridge\GIS\Demand\demand_polygons.shp'): - def loadShapeFile( # noqa: N802, D102 - self, - shapeFileAddr=r'Northridge\GIS\Demand\demand_polygons.shp', # noqa: N803 - ): - shape_file = gpd.read_file(shapeFileAddr) - return shape_file # noqa: RET504 - - def joinTwoShapeFiles(self, first, second): # noqa: N802, D102 - second = second.set_crs(crs=first.crs) - joined_map = gpd.sjoin(first, second) - - return joined_map # noqa: RET504 - - def createGeopandasPointDataFrameForNodes(self): # noqa: N802, D102 - s = gpd.GeoDataFrame(index=self.demand_node_name_list) - point_list = [] - point_name_list = [] - - for name in self.demand_node_name_list: - coord = self.wn.get_node(name).coordinates - point_list.append(shapely.geometry.Point(coord[0], coord[1])) - point_name_list.append(name) - s.geometry = point_list - return s - - def getDLQNExceedenceProbabilityMap(self, data_frame, ihour, param): # noqa: N802, D102 - data = data_frame.transpose() - scn_prob_list = self.scenario_prob - # DLQN_dmg = pd.DataFrame(data=0, index=data.index, columns=data.columns) - - scn_prob = [scn_prob_list[scn_name] for scn_name in data.index] - data['prob'] = scn_prob - - res_dict_list = [] - tt = 0 - if ihour: - for node_name in data_frame.index: - loop_dmg = data[[node_name, 'prob']] - loop_dmg = loop_dmg.sort_values(node_name, ascending=False) - # t1 = time.time() - # loop_ep = Helper.EPHelper(loop_dmg['prob'].to_numpy()) - loop_ep = Helper.EPHelper(loop_dmg['prob'].to_numpy(), old=False) - # loop_ep_2 = Helper.EPHelper(loop_dmg['prob'].to_numpy(), old=True) - # return (loop_ep, loop_ep_2) - # t2 = time.time() - # dt = t2-t1 - # tt += dt - loop_dmg['ep'] = loop_ep - inter_ind = param - if inter_ind >= loop_dmg['ep'].max(): - max_ind = loop_dmg[loop_dmg['ep'] == loop_dmg['ep'].max()].index[ - 0 - ] - # max_ind = loop_dmg.idxmax() - inter_value = loop_dmg.loc[max_ind, node_name] - elif inter_ind <= loop_dmg['ep'].min(): - min_ind = loop_dmg[loop_dmg['ep'] == loop_dmg['ep'].min()].index[ - 0 - ] - # min_ind = loop_dmg.idxmin() - inter_value = loop_dmg.loc[min_ind, node_name] - else: - loop_dmg.loc['inter', 'ep'] = inter_ind - - loop_dmg = loop_dmg.sort_values('ep') - ep_list = loop_dmg['ep'].to_list() - inter_series = pd.Series( - index=ep_list, data=loop_dmg[node_name].to_list() - ) - inter_series = inter_series.interpolate(method='linear') - inter_value = inter_series.loc[inter_ind] - if type(inter_value) != np.float64: # noqa: E721 - inter_value = inter_value.mean() - - res_dict_list.append({'node_name': node_name, 'res': inter_value}) - - else: - for node_name in data_frame.index: - loop_dmg = data[[node_name, 'prob']] - - loop_dmg = loop_dmg.sort_values(node_name, ascending=False) - loop_ep = Helper.EPHelper(loop_dmg['prob'].to_numpy()) - loop_dmg['ep'] = loop_ep - inter_ind = param - if inter_ind >= loop_dmg[node_name].max(): - max_ind = loop_dmg[ - loop_dmg[node_name] == loop_dmg[node_name].max() - ].index[0] - inter_value = loop_dmg.loc[max_ind, 'ep'] - elif inter_ind <= loop_dmg[node_name].min(): - min_ind = loop_dmg[ - loop_dmg[node_name] == loop_dmg[node_name].min() - ].index[0] - inter_value = loop_dmg.loc[min_ind, 'ep'] - else: - loop_dmg.loc['inter', node_name] = inter_ind - - loop_dmg = loop_dmg.sort_values(node_name) - hour_list = loop_dmg[node_name].to_list() - - inter_series = pd.Series( - index=hour_list, data=loop_dmg['ep'].to_list() - ) - inter_series = inter_series.interpolate(method='linear') - inter_value = inter_series.loc[inter_ind] - if type(inter_value) != np.float64: # noqa: E721 - inter_value = inter_value.mean() - - res_dict_list.append({'node_name': node_name, 'res': inter_value}) - - res = pd.DataFrame.from_dict(res_dict_list) - res = res.set_index('node_name')['res'] - - s = self.createGeopandasPointDataFrameForNodes() - s['res'] = res - - # polygon = gpd.read_file('Northridge\GIS\Demand\demand_polygons.shp') - # s = s.set_crs(epsg=polygon.crs.to_epsg()) - # joined_map = gpd.sjoin(polygon, s) - # joined_map.plot(column='res', legend=True, categorical=True, cmap='Accent', ax=ax) - # ax.get_legend().set_title('Hours without service') - # ax.get_legend()._loc=3 - # props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) - print(tt) # noqa: T201 - return s - - def getOutageTimeGeoPandas_4( # noqa: C901, N802, D102 - self, - scn_name, - LOS='DL', # noqa: N803 - iConsider_leak=False, # noqa: FBT002, N803 - leak_ratio=0, - consistency_time_window=7200, - ): - # print(repr(LOS) + " " + repr(iConsider_leak)+" "+ repr(leak_ratio)+" "+repr(consistency_time_window ) ) - self.loadScneariodata(scn_name) - res = self.data[scn_name] - map_res = pd.Series(data=0, index=self.demand_node_name_list, dtype=np.int64) - - demands = self.getRequiredDemandForAllNodesandtime(scn_name) - refined_res = res.node['demand'][self.demand_node_name_list] - union_ = set(res.node['leak'].columns).union( - set(self.demand_node_name_list) - - (set(res.node['leak'].columns)) - - set(self.demand_node_name_list) - ) - (set(self.demand_node_name_list) - set(res.node['leak'].columns)) - leak_res = res.node['leak'][union_] - - leak_data = [] - if iConsider_leak: - for name in leak_res: - demand_name = demands[name] - current_leak_res = leak_res[name].dropna() - time_list = set(current_leak_res.dropna().index) - time_list_drop = set(demands.index) - time_list - demand_name = demand_name.drop(time_list_drop) - leak_more_than_criteria = ( - current_leak_res >= leak_ratio * demand_name - ) - if leak_more_than_criteria.any(0): - leak_data.append(leak_more_than_criteria) - leak_data = pd.DataFrame(leak_data).transpose() - - demands = demands[self.demand_node_name_list] - - if LOS == 'DL': - DL_res_not_met_bool = refined_res <= demands * 0.01 # noqa: N806 - elif LOS == 'QN': - DL_res_not_met_bool = refined_res < demands * 0.98 # noqa: N806 - - time_window = consistency_time_window + 1 - time_list = DL_res_not_met_bool.index.to_list() - time_list.reverse() - - for time in time_list: - past_time_beg = time - time_window - window_data = DL_res_not_met_bool.loc[past_time_beg:time] - window_data = window_data.all() - window_data_false = window_data[window_data == False] # noqa: E712 - DL_res_not_met_bool.loc[time, window_data_false.index] = False - - for name in DL_res_not_met_bool: - if name in leak_data.columns: - leak_data_name = leak_data[name] - for time in leak_data_name.index: - if leak_data_name.loc[time] == True: # noqa: E712 - DL_res_not_met_bool.loc[time, name] = True - - all_node_name_list = refined_res.columns - only_not_met_bool = DL_res_not_met_bool.any(0) - only_not_met_any = all_node_name_list[only_not_met_bool] - DL_res_not_met = DL_res_not_met_bool.filter(only_not_met_any) # noqa: N806 - DL_res_MET = ~DL_res_not_met # noqa: N806 - time_window = 2 - - for name in only_not_met_any: - rolled_DL_res_MET = ( # noqa: N806 - DL_res_MET[name].rolling(time_window, center=True).sum() - ) - rolled_DL_res_MET = rolled_DL_res_MET.sort_index(ascending=False) # noqa: N806 - rolled_DL_res_MET.dropna(inplace=True) # noqa: PD002 - - false_found, found_index = Helper.helper_outageMap( - rolled_DL_res_MET.ge(time_window - 1) - ) - # if name == "SM323": - # return DL_res_MET[name], rolled_DL_res_MET, false_found, rolled_DL_res_MET.index[found_index], rolled_DL_res_MET.ge(time_window-1), found_index - if false_found == False: # noqa: E712 - latest_time = 0 - else: - if DL_res_MET[name].iloc[-1] == False: # noqa: E712 - latest_time = DL_res_MET.index[-1] - else: - latest_time = rolled_DL_res_MET.index[found_index] - latest_time = rolled_DL_res_MET.index[found_index] - - map_res.loc[name] = latest_time - - # map_res = map_res/(3600*24) - geopandas_df = self.createGeopandasPointDataFrameForNodes() - geopandas_df.loc[map_res.index.to_list(), 'restoration_time'] = ( - map_res.to_list() - ) - - return geopandas_df - - def getOutageTimeGeoPandas_5( # noqa: C901, N802, D102 - self, - scn_name, - bsc='DL', - iConsider_leak=False, # noqa: FBT002, N803 - leak_ratio=0, - consistency_time_window=7200, - sum_time=False, # noqa: FBT002 - ): - self.loadScneariodata(scn_name) - res = self.data[scn_name] - map_res = pd.Series(data=0, index=self.demand_node_name_list, dtype=np.int64) - - required_demand = self.getRequiredDemandForAllNodesandtime(scn_name) - delivered_demand = res.node['demand'][self.demand_node_name_list] - common_nodes_leak = list( - set(res.node['leak'].columns).intersection( - set(self.demand_node_name_list) - ) - ) - leak_res = res.node['leak'][common_nodes_leak] - - common_nodes_demand = list( - set(delivered_demand.columns).intersection( - set(self.demand_node_name_list) - ) - ) - delivered_demand = delivered_demand[common_nodes_demand] - required_demand = required_demand[common_nodes_demand] - - required_demand.sort_index(inplace=True) # noqa: PD002 - delivered_demand.sort_index(inplace=True) # noqa: PD002 - leak_res.sort_index(inplace=True) # noqa: PD002 - - # return delivered_demand, required_demand, leak_res - - if bsc == 'DL': - bsc_res_not_met_bool = ( - delivered_demand.fillna(0) <= required_demand * 0.0001 - ) - elif bsc == 'QN': - bsc_res_not_met_bool = ( - delivered_demand.fillna(0) < required_demand * 0.9999 - ) - else: - raise ValueError('Unknown BSC= ' + str(bsc)) - - if iConsider_leak: - # return leak_res, required_demand - leak_res_non_available_time_list = set( - required_demand[leak_res.columns].index - ) - set(leak_res.index) - if len(leak_res_non_available_time_list) > 0: - leak_res_non_available_time_list = list( - leak_res_non_available_time_list - ) - temp_data = pd.DataFrame( - [ - [0 for i in leak_res.columns] - for j in range(len(leak_res_non_available_time_list)) - ], - index=leak_res_non_available_time_list, - columns=leak_res.columns, - ) - # leak_res.loc[leak_res_non_available_time_list, : ] = temp_data - leak_res = leak_res.append(temp_data) - leak_res.sort_index(inplace=True) # noqa: PD002 - leak_criteria_exceeded = ( - leak_res.fillna(0) >= leak_ratio * required_demand[leak_res.columns] - ) - combined_negative_result = ( - bsc_res_not_met_bool | leak_criteria_exceeded - ).dropna(axis=1) - # return combined_negative_result - bsc_res_not_met_bool.loc[:, combined_negative_result.columns] = ( - combined_negative_result - ) - - # end_time = delivered_demand.min() - end_time = delivered_demand.index.max() - if consistency_time_window > 1: - time_beg_step_list = np.arange(0, end_time, consistency_time_window) - - # time_beg_step_list = np.append(time_beg_step_list, [end_time]) - time_end_step_list = time_beg_step_list # + consistency_time_window - window_bsc_not_met = pd.DataFrame( - index=time_end_step_list, - columns=bsc_res_not_met_bool.columns, - dtype=bool, - ) - # return bsc_res_not_met_bool#, delivered_demand, required_demand - for step_time_beg in time_beg_step_list: - step_time_end = step_time_beg + consistency_time_window - window_data = bsc_res_not_met_bool.loc[step_time_beg:step_time_end] - if len(window_data) > 0: - window_data = window_data.all() - window_bsc_not_met.loc[step_time_beg, window_data.index] = ( - window_data - ) - else: - # print(step_time_beg) - window_bsc_not_met.drop(step_time_beg, inplace=True) # noqa: PD002 - else: - window_bsc_not_met = bsc_res_not_met_bool - - pre_incident = (window_bsc_not_met.loc[: 3600 * 3]).any() - non_incident = pre_incident[pre_incident == False].index # noqa: E712 - - not_met_node_name_list = window_bsc_not_met.any() - - # ("****************") - # print(not_met_node_name_list[not_met_node_name_list==True]) - - not_met_node_name_list = not_met_node_name_list[ - not_met_node_name_list == True # noqa: E712 - ] - not_met_node_name_list = not_met_node_name_list.index - - if sum_time: - time_difference = ( - window_bsc_not_met.index[1:] - window_bsc_not_met.index[:-1] - ) - timed_diference_window_bsc_not_met = ( - time_difference * window_bsc_not_met.iloc[1:].transpose() - ).transpose() - timed_diference_window_bsc_not_met.iloc[0] = 0 - sum_window_bsc_not_met = timed_diference_window_bsc_not_met.sum() - return sum_window_bsc_not_met # noqa: RET504 - - window_bsc_not_met = window_bsc_not_met[not_met_node_name_list] - cut_time = window_bsc_not_met.index.max() - non_incident = list( - set(non_incident).intersection(set(not_met_node_name_list)) - ) - for step_time, row in window_bsc_not_met[non_incident].iterrows(): - if step_time <= 14400: # noqa: PLR2004 - continue - - if row.any() == False: # noqa: E712 - print(step_time) # noqa: T201 - cut_time = step_time - break - - window_bsc_not_met = window_bsc_not_met.loc[:cut_time] - window_bsc_not_met = window_bsc_not_met.loc[:cut_time] - - # return window_bsc_not_met - # print(not_met_node_name_list) - time_bsc_not_met_time = window_bsc_not_met.sort_index( - ascending=False - ).idxmax() - map_res.loc[time_bsc_not_met_time.index] = time_bsc_not_met_time - - never_reported_nodes = set(self.demand_node_name_list) - set( - common_nodes_demand - ) - number_of_unreported_demand_nodes = len(never_reported_nodes) - if number_of_unreported_demand_nodes > 0: - warnings.warn( # noqa: B028 - 'REWET WARNING: there are ' - + str(number_of_unreported_demand_nodes) - + 'unreported nodes' - ) - map_res.loc[never_reported_nodes] = end_time - - map_res = map_res / (3600 * 24) - return map_res # noqa: RET504 - - s = gpd.GeoDataFrame(index=self.demand_node_name_list) - point_list = [] - point_name_list = [] - - for name in self.demand_node_name_list: - coord = self.wn.get_node(name).coordinates - point_list.append(shapely.geometry.Point(coord[0], coord[1])) - point_name_list.append(name) - - s.geometry = point_list - - s.loc[map_res.index.to_list(), 'restoration_time'] = map_res.to_list() - - polygon = gpd.read_file(r'Northridge\GIS\Demand\demand_polygons.shp') - s = s.set_crs(crs=polygon.crs) - joined_map = gpd.sjoin(polygon, s) - # return joined_map - # joined_map.loc[map_res.index.to_list(), 'restoration_time'] = (map_res/3600/24).to_list() - - return joined_map # noqa: RET504 - - def percentOfEffectNodes( # noqa: C901, N802, D102 - self, - scn_name, - bsc='QN', - iConsider_leak=True, # noqa: FBT002, N803 - leak_ratio=0.75, - consistency_time_window=7200, - ): - self.loadScneariodata(scn_name) - res = self.data[scn_name] - map_res = pd.Series(data=0, index=self.demand_node_name_list, dtype=np.int64) - - required_demand = self.getRequiredDemandForAllNodesandtime(scn_name) - delivered_demand = res.node['demand'][self.demand_node_name_list] - common_nodes_leak = set(res.node['leak'].columns).intersection( - set(self.demand_node_name_list) - ) - leak_res = res.node['leak'][common_nodes_leak] - - common_nodes_demand = list( - set(delivered_demand.columns).intersection( - set(self.demand_node_name_list) - ) - ) - delivered_demand = delivered_demand[common_nodes_demand] - required_demand = required_demand[common_nodes_demand] - - required_demand.sort_index(inplace=True) # noqa: PD002 - delivered_demand.sort_index(inplace=True) # noqa: PD002 - leak_res.sort_index(inplace=True) # noqa: PD002 - - # return delivered_demand, required_demand, leak_res - - if bsc == 'DL': - bsc_res_not_met_bool = ( - delivered_demand.fillna(0) <= required_demand * 0.1 - ) - elif bsc == 'QN': - bsc_res_not_met_bool = ( - delivered_demand.fillna(0) < required_demand * 0.98 - ) - else: - raise ValueError('Unknown BSC= ' + str(bsc)) - - if iConsider_leak: - # return leak_res, required_demand - leak_res_non_available_time_list = set( - required_demand[leak_res.columns].index - ) - set(leak_res.index) - if len(leak_res_non_available_time_list) > 0: - leak_res_non_available_time_list = list( - leak_res_non_available_time_list - ) - temp_data = pd.DataFrame( - [ - [0 for i in leak_res.columns] - for j in range(len(leak_res_non_available_time_list)) - ], - index=leak_res_non_available_time_list, - columns=leak_res.columns, - ) - # leak_res.loc[leak_res_non_available_time_list, : ] = temp_data - leak_res = leak_res.append(temp_data) - leak_res.sort_index(inplace=True) # noqa: PD002 - leak_criteria_exceeded = ( - leak_res.fillna(0) >= leak_ratio * required_demand[leak_res.columns] - ) - combined_negative_result = ( - bsc_res_not_met_bool | leak_criteria_exceeded - ).dropna(axis=1) - # return combined_negative_result - bsc_res_not_met_bool.loc[:, combined_negative_result.columns] = ( - combined_negative_result - ) - - # end_time = delivered_demand.min() - end_time = delivered_demand.index.max() - time_beg_step_list = np.arange(0, end_time, consistency_time_window) - - # time_beg_step_list = np.append(time_beg_step_list, [end_time]) - time_end_step_list = time_beg_step_list # + consistency_time_window - window_bsc_not_met = pd.DataFrame( - index=time_end_step_list, - columns=bsc_res_not_met_bool.columns, - dtype=bool, - ) - # return bsc_res_not_met_bool#, delivered_demand, required_demand - for step_time_beg in time_beg_step_list: - step_time_end = step_time_beg + consistency_time_window - window_data = bsc_res_not_met_bool.loc[step_time_beg:step_time_end] - if len(window_data) > 0: - window_data = window_data.all() - window_bsc_not_met.loc[step_time_beg, window_data.index] = ( - window_data - ) - else: - # print(step_time_beg) - window_bsc_not_met.drop(step_time_beg, inplace=True) # noqa: PD002 - # return window_bsc_not_met - pre_incident = (window_bsc_not_met.loc[: 3600 * 3]).any() - non_incident = pre_incident[pre_incident == False].index # noqa: E712 - - number_of_good_nodes = len(non_incident) - - not_met_node_name_list = window_bsc_not_met.any() - - # ("****************") - # print(not_met_node_name_list[not_met_node_name_list==True]) - - not_met_node_name_list = not_met_node_name_list[ - not_met_node_name_list == True # noqa: E712 - ] - not_met_node_name_list = not_met_node_name_list.index - window_bsc_not_met = window_bsc_not_met[not_met_node_name_list] - - cut_time = window_bsc_not_met.index.max() - non_incident = list( - set(non_incident).intersection(set(not_met_node_name_list)) - ) - for step_time, row in window_bsc_not_met[non_incident].iterrows(): - if step_time <= 14400: # noqa: PLR2004 - continue - - if row.any() == False: # noqa: E712 - print(step_time) # noqa: T201 - cut_time = step_time - break - - cut_time = 24 * 3600 - window_bsc_not_met = window_bsc_not_met.loc[:cut_time] - window_bsc_not_met = window_bsc_not_met.loc[:cut_time] - - number_of_bad_node_at_damage = ( - window_bsc_not_met[non_incident].loc[14400].sum() - ) - percent_init = number_of_bad_node_at_damage / number_of_good_nodes * 100 - # return window_bsc_not_met - # print(not_met_node_name_list) - time_bsc_not_met_time = window_bsc_not_met.sort_index( - ascending=False - ).idxmax() - map_res.loc[time_bsc_not_met_time.index] = time_bsc_not_met_time - - never_reported_nodes = set(self.demand_node_name_list) - set( - common_nodes_demand - ) - number_of_unreported_demand_nodes = len(never_reported_nodes) - if number_of_unreported_demand_nodes > 0: - warnings.warn( # noqa: B028 - 'REWET WARNING: there are ' - + str(number_of_unreported_demand_nodes) - + 'unreported nodes' - ) - map_res.loc[never_reported_nodes] = end_time - - map_res = map_res / (3600 * 24) - percent = (map_res.loc[non_incident] > 0).sum() / number_of_good_nodes * 100 - return np.round(percent_init, 2), np.round(percent, 2) diff --git a/modules/systemPerformance/REWET/REWET/Output/Raw_Data.py b/modules/systemPerformance/REWET/REWET/Output/Raw_Data.py deleted file mode 100644 index d9a9c267b..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Raw_Data.py +++ /dev/null @@ -1,138 +0,0 @@ -"""Created on Mon Oct 24 18:27:03 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - - -class Raw_Data: # noqa: D101 - def __init__(): - pass - - def saveDetailedDemandNodeData( # noqa: N802, D102 - self, - scn_name, - data_type, - file_address, - file_type, - ): - if data_type not in ['pressure', 'head', 'demand', 'quality']: - raise ValueError( - 'data type is not recognized for demand nodes: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.demand_node_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedJunctionData(self, scn_name, data_type, file_address, file_type): # noqa: N802, D102 - if data_type not in ['pressure', 'head', 'demand', 'quality']: - raise ValueError( - 'data type is not recognized for junctiosn: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.junction_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedTankData(self, scn_name, data_type, file_address, file_type): # noqa: N802, D102 - if data_type not in ['pressure', 'head', 'demand', 'quality']: - raise ValueError( - 'data type is not recognized for tanks: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.tank_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedReservoirData( # noqa: N802, D102 - self, - scn_name, - data_type, - file_address, - file_type, - ): - if data_type not in ['pressure', 'head', 'demand', 'quality']: - raise ValueError( - 'data type is not recognized for demand nodes: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.tank_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedPipeData(self, scn_name, data_type, file_address, file_type): # noqa: N802, D102 - if data_type not in [ - 'linkquality', - 'flowrate', - 'headloss', - 'velocity', - 'status', - 'setting', - 'frictionfact', - 'rxnrate', - ]: - raise ValueError( - 'data type is not recognized for pipes: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.pipe_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedPumpData(self, scn_name, data_type, file_address, file_type): # noqa: N802, D102 - if data_type not in [ - 'linkquality', - 'flowrate', - 'headloss', - 'velocity', - 'status', - 'setting', - 'frictionfact', - 'rxnrate', - ]: - raise ValueError( - 'data type is not recognized for pumps: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.pump_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def saveDetailedValveData(self, scn_name, data_type, file_address, file_type): # noqa: N802, D102 - if data_type not in [ - 'linkquality', - 'flowrate', - 'headloss', - 'velocity', - 'status', - 'setting', - 'frictionfact', - 'rxnrate', - ]: - raise ValueError( - 'data type is not recognized for valves: ' + repr(data_type) - ) - data = self.getDetailedData(scn_name, data_type) - data = data[self.wn.valve_name_list] - self.saveDataFrame(data, file_address, file_type=file_type) - - def getDetailedData(self, scn_name, data_type): # noqa: N802, D102 - cur_scn_data = None - if data_type in [ - 'linkquality', - 'flowrate', - 'headloss', - 'velocity', - 'status', - 'setting', - 'frictionfact', - 'rxnrate', - ]: - cur_scn_data = self.data[scn_name].link[data_type] - elif data_type in ['pressure', 'head', 'demand', 'quality']: - cur_scn_data = self.data[scn_name].node[data_type] - else: - raise ValueError('Unknown Data Type For output') # noqa: EM101, TRY003 - return cur_scn_data - - def saveDataFrame(dataframe, file_address, file_type='xlsx'): # noqa: N802, N805, D102 - if file_type == 'xlsx': - dataframe.to_excel(file_address) - elif file_type == 'csv': - dataframe.to_csv(file_address) - else: - raise ValueError('Unknown file type: ' + repr(file_type)) diff --git a/modules/systemPerformance/REWET/REWET/Output/Result_Time.py b/modules/systemPerformance/REWET/REWET/Output/Result_Time.py deleted file mode 100644 index f0267634f..000000000 --- a/modules/systemPerformance/REWET/REWET/Output/Result_Time.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Created on Thu Nov 10 18:00:55 2022 - -@author: snaeimi -""" # noqa: INP001, D400 - -import numpy as np -import pandas as pd - - -class Result_Time: # noqa: D101 - def __init__(): - pass - - def convertTimeSecondToDay(self, data, column, time_shift=0): # noqa: N802, D102 - data.loc[:, column] = data.loc[:, column] - time_shift - data.loc[:, column] = data.loc[:, column] / 24 / 3600 - - def convertTimeSecondToHour(self, data, column, time_shift=0): # noqa: N802, D102 - data.loc[:, column] = data.loc[:, column] - time_shift - data.loc[:, column] = data.loc[:, column] / 3600 - - def averageOverDaysCrewTotalReport(self, crew_report): # noqa: N802, D102 - time_max_seconds = crew_report.index.max() - time_max_days = int(np.ceil(time_max_seconds / 24 / 3600)) - daily_crew_report = pd.DataFrame( - index=[i + 1 for i in range(time_max_days)], - columns=crew_report.columns, - ) - for day in range(time_max_days): - daily_crew = crew_report.loc[day * 24 * 3600 : (day + 1) * 24 * 3600] - daily_crew_report.loc[day + 1] = daily_crew.mean() - return daily_crew_report diff --git a/modules/systemPerformance/REWET/REWET/Project.py b/modules/systemPerformance/REWET/REWET/Project.py deleted file mode 100644 index a3faf81ad..000000000 --- a/modules/systemPerformance/REWET/REWET/Project.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Created on Mon Jan 9 09:03:57 2023 - -@author: snaeimi -""" # noqa: N999, D400 - - -class Project: # noqa: D101 - def __init__(self, project_settings, scenario_list): - self.scenario_list = scenario_list - self.project_settings = project_settings diff --git a/modules/systemPerformance/REWET/REWET/README.md b/modules/systemPerformance/REWET/REWET/README.md deleted file mode 100644 index 410b198c9..000000000 --- a/modules/systemPerformance/REWET/REWET/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# REWET - -REstoration of Water after Event Tool (REWET) is a tool for the simulation of functionality in water distribution networks after natural hazard events. It is designed to support any network with the state-of-art hydraulic simulation capabilities and damage modeling in mind. - -## Installation -The current release of REWET (V0.1) only support Windows AMD64 systems. - -To install the package, first install the dependencies. Installing Anacodna for managing the dependencies is strongly advised.To install the latest version of Anaconda, please visit -Use the package manager please [click here](https://www.anaconda.com). - -After installing anaconda, open up the conda bash. To create a virtual environment * using Anaconda, type: - -```bash -conda create --name myenv -``` -Replaces myAnaconda asks if you - -## Usage - -```python -import foobar - -# returns 'words' -foobar.pluralize('word') - -# returns 'geese' -foobar.pluralize('goose') - -# returns 'phenomenon' -foobar.singularize('phenomena') -``` - -## Contributing - -Pull requests are welcome. For major changes, please open an issue first -to discuss what you would like to change. - -Please make sure to update tests as appropriate. - -## License -No Liciense yet diff --git a/modules/systemPerformance/REWET/REWET/Report_Reading.py b/modules/systemPerformance/REWET/REWET/Report_Reading.py deleted file mode 100644 index e490739a5..000000000 --- a/modules/systemPerformance/REWET/REWET/Report_Reading.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Created on Tue Oct 4 16:07:24 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import datetime - - -def parseTimeStamp(time_stamp): # noqa: N802, D103 - striped_time_stamp = time_stamp.split(':') - hour = striped_time_stamp[0] - minute = striped_time_stamp[1] - second = striped_time_stamp[2] - - hour = int(hour) - minute = int(minute) - second = int(second) - - return (hour, minute, minute) - - -class Report_Reading: # noqa: D101 - def __init__(self, file_addr): - self.file_data = {} - self.maximum_trial_time = [] - with open(file_addr, encoding='utf-8') as f: # noqa: PTH123 - lnum = 0 - for line in f: - # self.file_data[lnum] = line - if 'Maximum trials exceeded at' in line: - time_str = ( - line.split('WARNING: Maximum trials exceeded at ')[1] - .split(' hrs')[0] - .split(',')[0] - ) - - x = parseTimeStamp(time_str) - time_sec = datetime.timedelta( - hours=x[0], minutes=x[1], seconds=x[2] - ).total_seconds() - time_sec = int(time_sec) - self.maximum_trial_time.append(time_sec) - elif 'System unbalanced at' in line: - time_str = ( - line.split('System unbalanced at ')[1] - .split(' hrs')[0] - .split(',')[0] - ) - x = parseTimeStamp(time_str) - time_sec = datetime.timedelta( - hours=x[0], minutes=x[1], seconds=x[2] - ).total_seconds() - time_sec = int(time_sec) - self.maximum_trial_time.append(time_sec) - lnum += 1 # noqa: SIM113 diff --git a/modules/systemPerformance/REWET/REWET/Result_Project.py b/modules/systemPerformance/REWET/REWET/Result_Project.py deleted file mode 100644 index 7ac0b92cb..000000000 --- a/modules/systemPerformance/REWET/REWET/Result_Project.py +++ /dev/null @@ -1,698 +0,0 @@ -"""Created on Sun Oct 23 15:00:31 2022 - -@author: snaeimi -""" # noqa: N999, D400 - -import copy -import os -import pickle -from collections import OrderedDict - -import numpy as np -import pandas as pd -import wntrfr -from Output.Crew_Report import Crew_Report -from Output.Curve import Curve - -# import Report_Reading -from Output.Map import Helper, Map -from Output.Raw_Data import Raw_Data -from Output.Result_Time import Result_Time - - -class Project_Result(Map, Raw_Data, Curve, Crew_Report, Result_Time): # noqa: D101 - def __init__( - self, - project_file_addr, - result_directory=None, - ignore_not_found=False, # noqa: FBT002 - to_neglect_file=None, - node_col='', - result_file_dir=None, - iObject=False, # noqa: FBT002, N803 - ): - if iObject == False: # noqa: E712 - self.readPorjectFile(project_file_addr) - else: - self.project = copy.deepcopy(project_file_addr) - - if result_file_dir != None: # noqa: E711 - self.project.project_settings.process.settings['result_directory'] = ( - result_file_dir - ) - # self.project.scenario_list = io.read_damage_list(self.project.project_settings.process['pipe_damage_file_list' ], self.project.project_settings.process['pipe_damage_file_directory']) - # print(self.project.scenario_list) - self.project.scenario_list = self.project.scenario_list.set_index( - 'Scenario Name' - ) - - self.demand_node_name_list = [] - self._list = [] - self.pipe_damages = {} - self.node_damages = {} - self.pump_damages = {} - self.tank_damages = {} - # self.time_size = {} - self.demand_node_size = {} - self.index_to_scen_name = {} - self.data = OrderedDict() - self.registry = OrderedDict() - self.scenario_prob = {} - # self.scenario_set = {} - self.empty_scenario_name_list = set() - self._delivery_data = None - self._quality_data = None - self._DLQNIndexPopulation = {} - self._population_data = None - self.exceedance_map_intermediate_data = None - self.rest_data = None - self._RequiredDemandForAllNodesandtime = {} - self.demand_ratio = self.project.project_settings.process['demand_ratio'] - self.scn_name_list_that_result_file_not_found = [] - self.wn = wntrfr.network.WaterNetworkModel( - self.project.project_settings.process['WN_INP'] - ) - - self.result_directory = self.project.project_settings.process[ - 'result_directory' - ] - - if result_directory is not None: - self.result_directory = result_directory - - to_neglect = [] - # sina hereeeee bug dadi amedane - if to_neglect_file != None and False: # noqa: SIM223, E711 - raise # noqa: PLE0704 - file_data = pd.read_excel(to_neglect_file) - to_neglect = file_data[node_col].to_list() - - for node_name in self.wn.junction_name_list: - node = self.wn.get_node(node_name) - if ( - node.demand_timeseries_list[0].base_value > 0 - and node_name not in to_neglect - ): - self.demand_node_name_list.append(node_name) - - self.node_name_list = self.wn.node_name_list.copy() - ret_val = self.checkForNotExistingFile(ignore_not_found) - self.prepareData() - return ret_val # noqa: PLE0101 - - def readPorjectFile(self, project_file_addr): # noqa: N802, D102 - print(project_file_addr) # noqa: T201 - with open(project_file_addr, 'rb') as f: # noqa: PTH123 - self.project = pickle.load(f) # noqa: S301 - - def loadPopulation(self, popuation_data, node_id_header, population_header): # noqa: N802, D102 - pop = popuation_data.copy() - pop = pop.set_index(node_id_header) - pop = pop[population_header] - self._population_data = pop - - def checkForNotExistingFile(self, ignore_not_found): # noqa: N802, D102 - self.scn_name_list_that_result_file_not_found = [] - - result_directory = self.result_directory - # print(self.project.scenario_list) - for scn_name, row in self.project.scenario_list.iterrows(): # noqa: B007 - scenario_registry_file_name = scn_name + '_registry.pkl' - # print(result_directory) - # print(scenario_registry_file_name) - registry_file_data_addr = os.path.join( # noqa: PTH118 - result_directory, scenario_registry_file_name - ) - if not os.path.exists(registry_file_data_addr): # noqa: PTH110 - self.scn_name_list_that_result_file_not_found.append(scn_name) - - if len(self.scn_name_list_that_result_file_not_found) > 0: - if ignore_not_found: - # print(str(len(self.scn_name_list_that_result_file_not_found)) +" out of "+ repr(len(self.project.scenario_list)) +" Result Files are not found and ignored" ) - # print(self.scn_name_list_that_result_file_not_found) - pass - # self.project.scenario_list.drop(self.scn_name_list_that_result_file_not_found, inplace=True) - else: - raise ValueError( - 'Res File Not Found: ' - + repr(self.scn_name_list_that_result_file_not_found) - + ' in ' - + repr(result_directory) - ) - - def prepareData(self): # noqa: N802, D102 - i = 0 - # result_directory = self.project.project_settings.process['result_directory'] - # self.project.scenario_list = self.project.scenario_list.iloc[0:20] - for scn_name, row in self.project.scenario_list.iterrows(): # noqa: B007 - self._RequiredDemandForAllNodesandtime[scn_name] = None - # settings_file_name = scn_name+'.xlsx' - # settings_file_addr = os.path.join(result_directory, settings_file_name) - # scenario_set = pd.read_excel(settings_file_addr) - # self.scenario_set[scn_name] = scenario_set - - self.data[scn_name] = None - self.registry[scn_name] = None - - # self.time_size[scn_name] = len(self.data[scn_name].node['demand'].index) - self.index_to_scen_name[i] = scn_name - i += 1 # noqa: SIM113 - - self.scenario_prob[scn_name] = self.project.scenario_list.loc[ - scn_name, 'Probability' - ] - - """ - ATTENTION: We need probability for any prbablistic result - """ - - def loadScneariodata(self, scn_name): # noqa: N802, D102 - if self.data[scn_name] != None: # noqa: E711 - return - print('loading scenario ' + str(scn_name)) # noqa: T201 - result_directory = self.result_directory - # scenario_registry_file_name = scn_name+"_registry.pkl" - # registry_file_data_addr = os.path.join(result_directory, scenario_registry_file_name) - scenario_registry_file_name = scn_name + '_registry.pkl' - reg_addr = os.path.join(result_directory, scenario_registry_file_name) # noqa: PTH118 - try: - with open(reg_addr, 'rb') as f: # noqa: PTH123 - # print(output_addr) - reg_file_data = pickle.load(f) # noqa: S301 - self.registry[scn_name] = reg_file_data - res_file_data = self.registry[scn_name].result - except: # noqa: E722 - scenario_registry_file_name = scn_name + '.res' - res_addr = os.path.join(result_directory, scenario_registry_file_name) # noqa: PTH118 - with open(res_addr, 'rb') as f: # noqa: PTH123 - res_file_data = pickle.load(f) # noqa: S301 - # scenario_registry_file_name = scn_name+".res" - # res_addr = os.path.join(result_directory, scenario_registry_file_name) - # with open(res_addr, 'rb') as f: - # print(output_addr) - # res_file_data = pickle.load(f) - # res_file_data.node['head'] = None - # res_file_data.node['quality'] = None - # res_file_data = self.registry[scn_name].result - self.remove_maximum_trials(res_file_data) - self.data[scn_name] = res_file_data - - def readData(self): # noqa: N802, D102 - # i=0 - self.project.scenario_list = self.project.scenario_list.iloc[0:2] - result_directory = self.result_directory - - for scn_name, row in self.project.scenario_list.iterrows(): # noqa: B007 - self._RequiredDemandForAllNodesandtime[scn_name] = None - scenario_registry_file_name = scn_name + '_registry.pkl' - registry_file_data_addr = os.path.join( # noqa: PTH118 - result_directory, scenario_registry_file_name - ) - - with open(registry_file_data_addr, 'rb') as f: # noqa: PTH123 - if not os.path.exists(registry_file_data_addr): # noqa: PTH110 - raise ValueError( - 'Registry File Not Found: ' + str(registry_file_data_addr) - ) - self.registry[scn_name] = pickle.load(f) # noqa: S301 - - # self.pipe_damages[scn_name] = current_scenario_registry.damage.pipe_all_damages - # self.node_damages[scn_name] = current_scenario_registry.node_damage - # self.pump_damages[scn_name] = current_scenario_registry.damaged_pumps - # self.tank_damages[scn_name] = current_scenario_registry.tank_damage - - # res_addr = os.path.join(result_directory, scn_name+'.res') - - # with open(res_addr, 'rb') as f: - # print(output_addr) - # res_file_data = pickle.load(f) - - # settings_file_name = scn_name+'.xlsx' - # settings_file_addr = os.path.join(result_directory, settings_file_name) - # scenario_set = pd.read_excel(settings_file_addr) - # self.scenario_set[scn_name] = scenario_set - - # res_file_data.node['head'] = None - # res_file_data.node['quality'] = None - res_file_data = self.registry[scn_name] - self.remove_maximum_trials(res_file_data) - self.data[scn_name] = res_file_data - # self.time_size[scn_name] = len(self.data[scn_name].node['demand'].index) - # self.index_to_scen_name[i] = scn_name - # i+=1 - - self.scenario_prob[scn_name] = self.project.scenario_list.loc[ - scn_name, 'Probability' - ] - - """ - ATTENTION: We need probability for any prbablistic result - """ - print(str(scn_name) + ' loaded') # noqa: T201 - - def remove_maximum_trials(self, data): # noqa: D102 - all_time_list = data.maximum_trial_time - result_time_list = data.node['demand'].index.to_list() - result_time_max_trailed_list = [ - time for time in result_time_list if time in all_time_list - ] - - for att in data.node: - all_time_list = data.maximum_trial_time - result_time_list = data.node[att].index.to_list() - result_time_max_trailed_list = list( - set(result_time_list).intersection(set(all_time_list)) - ) - result_time_max_trailed_list.sort() - if len(result_time_max_trailed_list) > 0: - # print(result_time_max_trailed_list) - att_data = data.node[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.node[att] = att_data - - for att in data.link: - all_time_list = data.maximum_trial_time - result_time_list = data.link[att].index.to_list() - result_time_max_trailed_list = [ - time for time in result_time_list if time in all_time_list - ] - att_data = data.link[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.link[att] = att_data - - flow_balance = data.node['demand'].sum(axis=1) - - time_to_drop = flow_balance[abs(flow_balance) >= 0.01].index # noqa: PLR2004 - - # result_time_list = data.node['demand'].index.to_list() - # = [ time for time in result_time_list if time in all_time_list] - - for att in data.node: - # all_time_list = data.maximum_trial_time - result_time_list = data.node[att].index.to_list() - result_time_max_trailed_list = list( - set(result_time_list).intersection(set(time_to_drop)) - ) - result_time_max_trailed_list.sort() - if len(result_time_max_trailed_list) > 0: - # print(result_time_max_trailed_list) - att_data = data.node[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.node[att] = att_data - - for att in data.link: - # all_time_list = data.maximum_trial_time - result_time_list = data.link[att].index.to_list() - result_time_max_trailed_list = list( - set(result_time_list).intersection(set(time_to_drop)) - ) - result_time_max_trailed_list.sort() - if len(result_time_max_trailed_list) > 0: - att_data = data.link[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.link[att] = att_data - - def remove_maximum_trials_demand_flow(self, data): # noqa: D102 - flow_balance = data.node['demand'].sum(axis=1) - - time_to_drop = flow_balance[abs(flow_balance) >= 0.01].index # noqa: PLR2004 - - # result_time_list = data.node['demand'].index.to_list() - # = [ time for time in result_time_list if time in all_time_list] - - for att in data.node: - # all_time_list = data.maximum_trial_time - result_time_list = data.node[att].index.to_list() - result_time_max_trailed_list = [ - time for time in result_time_list if time in time_to_drop - ] - print(result_time_max_trailed_list) # noqa: T201 - att_data = data.node[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.node[att] = att_data - - for att in data.link: - # all_time_list = data.maximum_trial_time - result_time_list = data.link[att].index.to_list() - result_time_max_trailed_list = [ - time for time in result_time_list if time in time_to_drop - ] - att_data = data.link[att] - att_data.drop(result_time_max_trailed_list, inplace=True) # noqa: PD002 - data.link[att] = att_data - - def readPopulation( # noqa: N802, D102 - self, - population_xlsx_addr='demandNode-Northridge.xlsx', - demand_node_header='NodeID', - population_header='#Customer', # noqa: ARG002 - ): - pop = pd.read_excel(population_xlsx_addr) - pop = pop.set_index(demand_node_header) - pop = pop['#Customer'] - self._population_data = pop - demand_node_without_population = [ - node_name - for node_name in self.demand_node_name_list - if node_name not in pop.index - ] - if len(demand_node_without_population) > 0: - raise ValueError( - 'The following demand nodes are not population data: ' - + repr(demand_node_without_population) - ) - - def getRequiredDemandForAllNodesandtime(self, scn_name): # noqa: N802 - """********** - ATTENTION: We Assume that all scenarios have the same time indexing - ********** - - Calculates and return required demands for all nodes in all the times steps - - Returns - ------- - req_node_demand : Pandas DataFrame - Demand for all nodes and in all time - - """ # noqa: D205, D400 - self.loadScneariodata(scn_name) - demand_ratio = self.demand_ratio - if type(self._RequiredDemandForAllNodesandtime[scn_name]) != type(None): # noqa: E721 - return self._RequiredDemandForAllNodesandtime[scn_name] - undamaged_wn = self.wn - time_index = self.data[scn_name].node['demand'].index - # req_node_demand = pd.DataFrame(index=time_index.unique()) - default_pattern = undamaged_wn.options.hydraulic.pattern - node_pattern_list = pd.Series( - index=undamaged_wn.junction_name_list, dtype=str - ) - _size = len(self.demand_node_name_list) - i = 0 - # req_node_demand = req_node_demand.transpose() - - all_base_demand = [] - all_node_name_list = [] - - while i < _size: - node_name = self.demand_node_name_list[i] - # print(i) - i += 1 - node = undamaged_wn.get_node(node_name) - pattern_list = node.demand_timeseries_list.pattern_list() - if pattern_list[0] != None: # noqa: E711 - node_pattern_list[node_name] = pattern_list[0].name - elif pattern_list[0] == None and default_pattern != None: # noqa: E711 - node_pattern_list[node_name] = str(default_pattern) - else: - node_pattern_list[node_name] = None - base_demand = node.base_demand * demand_ratio - all_base_demand.append([base_demand for i in time_index]) - all_node_name_list.append(node_name) - # temp=pd.DataFrame(data = base_demand, index = time_index, columns = [node_name]) - # req_node_demand = req_node_demand.append(temp.transpose()) - # constant_base_demand = [constant_base_demand for i in time_index] - node_pattern_list = node_pattern_list.dropna() - - patterns_list = node_pattern_list.unique() - multiplier = pd.DataFrame(index=time_index, columns=patterns_list) - - for pattern_name in iter(patterns_list): - cur_pattern = undamaged_wn.get_pattern(pattern_name) - time_index = time_index.unique() - for time in iter(time_index): - multiplier[pattern_name].loc[time] = cur_pattern.at(time) - - variable_base_demand = [] # noqa: F841 - variable_node_name_list = [] # noqa: F841 - for node_name, pattern_name in node_pattern_list.items(): - cur_node_req_demand = ( - multiplier[pattern_name] - * undamaged_wn.get_node(node_name) - .demand_timeseries_list[0] - .base_value - * demand_ratio - ) - - all_node_name_list.append(node_name) - all_base_demand.append(cur_node_req_demand.to_list()) - # cur_node_req_demand.name = node_name - # cur_node_req_demand=pd.DataFrame(cur_node_req_demand).transpose() - # req_node_demand = req_node_demand.append(cur_node_req_demand) - # variable_base_demand = np.array(variable_base_demand).transpose().tolist() - req_node_demand = pd.DataFrame( - columns=time_index, index=all_node_name_list, data=all_base_demand - ) - req_node_demand = req_node_demand.transpose() - # constant_node_demand_df = pd.DataFrame(data = constant_base_demand, index = time_index, columns = constant_node_name_list) - # variable_node_demand_df = pd.DataFrame(data = variable_base_demand, index = time_index, columns = variable_node_name_list) - # if len(variable_base_demand) > 0 and len(variable_base_demand) == 0: - # req_node_demand = constant_node_demand_df - # elif len(variable_base_demand) == 0 and len(variable_base_demand) > 0: - # req_node_demand = variable_base_demand - # elif len(variable_base_demand) == 0 and len(variable_base_demand) == 0: - # req_node_demand = constant_node_demand_df - # else: - # req_node_demand = pd.concat([constant_node_demand_df.transpose(), variable_node_demand_df.transpose()]).transpose() - - # print(len(all_node_name_list)) - # print(len(constant_base_demand)) - # print(len(variant_base_demand)) - # print("************************") - # all_base_demand = constant_base_demand - - # req_node_demand = pd.DataFrame(index=time_index, columns=all_node_name_list, data=all_base_demand) - # req_node_demand = req_node_demand.transpose() - self._RequiredDemandForAllNodesandtime[scn_name] = req_node_demand.filter( - self.demand_node_name_list - ) - return self._RequiredDemandForAllNodesandtime[scn_name] - self._RequiredDemandForAllNodesandtime[scn_name] = req_node_demand.filter( - self.demand_node_name_list - ) - return self._RequiredDemandForAllNodesandtime[scn_name] - - def AS_getDLIndexPopulation( # noqa: N802, D102 - self, - iPopulation='No', # noqa: N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=0.75, - ): - scenario_list = list(self.data.keys()) - all_scenario_DL_data = {} # noqa: N806 - for scn_name in scenario_list: - cur_scn_DL = self.getDLIndexPopulation_4( # noqa: N806 - scn_name, - iPopulation=iPopulation, - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - cur_scn_DL = cur_scn_DL.to_dict() # noqa: N806 - all_scenario_DL_data[scn_name] = cur_scn_DL - - return pd.DataFrame.from_dict(all_scenario_DL_data) - - def AS_getQNIndexPopulation( # noqa: N802, D102 - self, - iPopulation='No', # noqa: N803 - ratio=False, # noqa: FBT002 - consider_leak=False, # noqa: FBT002 - leak_ratio=0.75, - ): - scenario_list = list(self.data.keys()) - all_scenario_QN_data = {} # noqa: N806 - for scn_name in scenario_list: - self.loadScneariodata(scn_name) - cur_scn_QN = self.getQNIndexPopulation_4( # noqa: N806 - scn_name, - iPopulation=iPopulation, - ratio=ratio, - consider_leak=consider_leak, - leak_ratio=leak_ratio, - ) - cur_scn_QN = cur_scn_QN.to_dict() # noqa: N806 - all_scenario_QN_data[scn_name] = cur_scn_QN - - return pd.DataFrame.from_dict(all_scenario_QN_data) - - def AS_getOutage_4( # noqa: N802, D102 - self, - LOS='DL', # noqa: N803 - iConsider_leak=False, # noqa: FBT002, N803 - leak_ratio=0, - consistency_time_window=7200, - ): - scenario_list = list(self.data.keys()) - all_scenario_outage_data = {} - i = 0 - for scn_name in scenario_list: - cur_scn_outage = self.getOutageTimeGeoPandas_4( - scn_name, - LOS=LOS, - iConsider_leak=iConsider_leak, - leak_ratio=leak_ratio, - consistency_time_window=consistency_time_window, - ) - cur_scn_outage = cur_scn_outage['restoration_time'].to_dict() - all_scenario_outage_data[scn_name] = cur_scn_outage - i += 1 # noqa: SIM113 - - return pd.DataFrame.from_dict(all_scenario_outage_data) - - def PR_getBSCPercentageExcedanceCurce(self, data_frame, restoration_percentage): # noqa: N802, D102 - max_time = data_frame.max().max() - - restore_time = {} - - if type(self._population_data) == type(None): # noqa: E721 - demand_node_name_list = data_frame.index - population = pd.Series(index=demand_node_name_list, data=1) - else: - population = self._population_data - population = population.loc[data_frame.index] - - population_dataframe = dict( - zip( - data_frame.columns, - [population.to_dict() for i in data_frame.columns], - ) - ) - population_dataframe = pd.DataFrame.from_dict(population_dataframe) - total_population = population.sum() - - for t in range(0, int(max_time), 3600): - satisfies_nodes_scnearios = data_frame <= t - satisfies_nodes_scnearios = ( - satisfies_nodes_scnearios * population_dataframe - ) - scenario_percentages = ( - satisfies_nodes_scnearios.sum() / total_population * 100 - ) - satisfied_scenarios = ( - scenario_percentages[scenario_percentages >= restoration_percentage] - ).index - already_recorded_scenarios = set(restore_time.keys()) - new_scenarios = set(satisfied_scenarios) - already_recorded_scenarios - - new_record = dict( - zip(new_scenarios, [t for k in range(len(new_scenarios))]) - ) - restore_time.update(new_record) - - already_recorded_scenarios = set(restore_time.keys()) - unsatisfied_scenarios = ( - set(self.scenario_prob.keys()) - already_recorded_scenarios - ) - new_record = dict( - zip( - unsatisfied_scenarios, [t for k in range(len(unsatisfied_scenarios))] - ) - ) - restore_time.update(new_record) - - restore_data = pd.DataFrame.from_dict({'restore_time': restore_time}) - - restore_data['restore_time'] = restore_data.loc[ - list(self.scenario_prob.keys()), 'restore_time' - ] - restore_data['prob'] = list(self.scenario_prob.values()) - restore_data.sort_values('restore_time', ascending=False, inplace=True) # noqa: PD002 - ep_mat = Helper.EPHelper(restore_data['prob'].to_numpy()) - restore_data['EP'] = ep_mat - - return restore_data - - def PR_getCurveExcedence( # noqa: C901, N802, D102 - self, - data_frame, - result_type='mean', - daily=False, # noqa: FBT002 - min_time=0, - max_time=24 * 3600 * 1000, - ): - data_size = len(data_frame.columns) - table_temp = [] - - for i in np.arange(data_size): - scn_name = data_frame.columns[i] - prob = self.scenario_prob[scn_name] - cur_scn_data = data_frame[scn_name] - dmg_index_list = [] - - cur_scn_data = cur_scn_data[cur_scn_data.index >= min_time] - cur_scn_data = cur_scn_data[cur_scn_data.index <= max_time] - - if daily == True: # noqa: E712 - cur_scn_data = self.getResultSeperatedDaily(cur_scn_data) - - if result_type == 'mean': - cur_mean_res = cur_scn_data.mean() - if type(cur_mean_res) != pd.core.series.Series: # noqa: E721 - temp_res = {'mean_dmg': cur_mean_res} - dmg_index_list.append('mean_dmg') - else: - temp_res = {} - for day_time, value in cur_mean_res.iteritems(): - temp_dmg_index = 'mean_dmg_' + day_time - temp_res.update({temp_dmg_index: value}) - dmg_index_list.append(temp_dmg_index) - elif result_type == 'min': - dmg_min_res = cur_scn_data.min() - if type(dmg_min_res) != pd.core.series.Series: # noqa: E721 - temp_res = {'min_dmg': dmg_min_res} - dmg_index_list.append('min_dmg') - else: - temp_res = {} - for day_time, value in dmg_min_res.iteritems(): - temp_dmg_index = 'min_dmg_' + day_time - temp_res.update({temp_dmg_index: value}) - dmg_index_list.append(temp_dmg_index) - elif result_type == 'max': - dmg_max_res = cur_scn_data.min() - if type(dmg_max_res) != pd.core.series.Series: # noqa: E721 - temp_res = {'max_dmg': dmg_max_res} - dmg_index_list.append('max_dmg') - else: - temp_res = {} - for day_time, value in dmg_max_res.iteritems(): - temp_dmg_index = 'max_dmg_' + day_time - temp_res.update({temp_dmg_index: value}) - dmg_index_list.append(temp_dmg_index) - else: - raise ValueError('Unknown group method: ' + repr(result_type)) - - loop_res = {'prob': prob, 'index': scn_name} - loop_res.update(temp_res) - table_temp.append(loop_res) - - table = pd.DataFrame.from_dict(table_temp).set_index('index') - res = pd.DataFrame( - index=[i for i in range(len(table.index))], # noqa: C416 - dtype=np.float64, - ) - for dmg_name in dmg_index_list: - select_columns = ['prob'] - select_columns.extend([dmg_name]) - loop_table = table[select_columns] - loop_table.sort_values(dmg_name, inplace=True) # noqa: PD002 - - ep_mat = Helper.EPHelper(loop_table['prob'].to_numpy()) - res[dmg_name] = loop_table[dmg_name].to_numpy() - res[dmg_name + '_EP'] = ep_mat - - return res - - def getResultSeperatedDaily(self, data, begin_time=0): # noqa: N802, D102 - data = data[data.index >= begin_time] - data.index = (data.index - begin_time) / (24 * 3600) - - res_data = [] - res_day = [] - - for day_iter in range(np.int64(np.ceil(np.max(data.index)))): - day_data = data[(data.index >= day_iter) & (data.index <= day_iter + 1)] - res_data.append(day_data.to_list()) - res_day.append(str(day_iter) + '-' + str(day_iter + 1)) - - return pd.DataFrame(res_data, index=res_day).transpose() diff --git a/modules/systemPerformance/REWET/REWET/Sim/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/Sim/CMakeLists.txt deleted file mode 100644 index ee163a9c8..000000000 --- a/modules/systemPerformance/REWET/REWET/Sim/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ - -simcenter_add_python_script(SCRIPT Simulation.py) diff --git a/modules/systemPerformance/REWET/REWET/Sim/Simulation.py b/modules/systemPerformance/REWET/REWET/Sim/Simulation.py deleted file mode 100644 index af697af48..000000000 --- a/modules/systemPerformance/REWET/REWET/Sim/Simulation.py +++ /dev/null @@ -1,627 +0,0 @@ -import math # noqa: INP001, D100 -import os - -import numpy as np -import pandas as pd -from EnhancedWNTR.sim.epanet import EpanetSimulator -from EnhancedWNTR.sim.results import SimulationResults - - -class Hydraulic_Simulation: # noqa: D101 - def __init__( - self, - wn, - settings, - current_stop_time, - worker_rank, - prev_isolated_junctions, - prev_isolated_links, - ): - self.wn = wn - self.nne_flow_criteria = settings.process['nne_flow_limit'] - self.nne_pressure_criteria = settings.process['nne_pressure_limit'] - self.minimum_pressure = 8 - self.required_pressure = 25 - self.current_stop_time = current_stop_time - self.worker_rank = worker_rank - - self.wn.options.hydraulic.demand_model = 'PDA' - - temp_folder = settings['temp_directory'] - if type(temp_folder) != str: # noqa: E721 - raise ValueError('temp folder type is not str') # noqa: EM101, TRY003 - - if settings['save_time_step'] == True: # noqa: E712 - if temp_folder == '': - self.temp_directory = ( - str(worker_rank) + '_' + repr(current_stop_time) - ) - else: - self.temp_directory = os.path.join( # noqa: PTH118 - temp_folder, str(worker_rank) + '_' + repr(current_stop_time) - ) - - elif settings['save_time_step'] == False: # noqa: E712 - if temp_folder == '': - self.temp_directory = str(worker_rank) - else: - self.temp_directory = os.path.join(temp_folder, str(worker_rank)) # noqa: PTH118 - else: - raise ValueError( - "Unknown value for settings 'save_time_step': " + repr() - ) - self._prev_isolated_junctions = prev_isolated_junctions - self._prev_isolated_links = prev_isolated_links - - def removeNonDemandNegativeNodeByPythonMinorLoss(self, maximum_iteration): # noqa: N802, D102 - current_stop_time = self.current_stop_time - minimum_pressure = self.minimum_pressure # noqa: F841 - required_pressure = self.required_pressure # noqa: F841 - temp_file_dest = self.temp_directory - orginal_c_dict = {} - for itrr in range(maximum_iteration): - print(itrr) # noqa: T201 - sim = EpanetSimulator(self.wn) - self.s = sim - self._prev_isolated_junctions, self._prev_isolated_links = ( - sim._get_isolated_junctions_and_links( # noqa: SLF001 - self._prev_isolated_junctions, self._prev_isolated_links - ) - ) - - sim.manipulateTimeOrder(current_stop_time, current_stop_time) - rr, i_run_successful = sim.run_sim( - file_prefix=temp_file_dest, - start_time=current_stop_time, - iModified=False, - ) - new_closed_pipes, ifinish = sim.now_temp_2( - rr, - self._prev_isolated_links, - self._prev_isolated_junctions, - self.nne_flow_criteria, - self.nne_pressure_criteria, - ) - - if ifinish: - break - - new_pipe_altered_name_list = new_closed_pipes.keys() - # print(str(list(new_pipe_altered_name_list)[0]) + " " + str(new_closed_pipes[list(new_pipe_altered_name_list)[0]])) - new_c_altered = [ - pipe_name - for pipe_name in new_pipe_altered_name_list - if pipe_name not in orginal_c_dict - ] - for pipe_name in new_c_altered: - if ( - pipe_name not in orginal_c_dict - ): # in order not tohange original C to something very new in the last oteration - orginal_c_dict[pipe_name] = new_closed_pipes[pipe_name] - return orginal_c_dict - - def isolateReservoirs(self, isolated_nodes): # noqa: N802, D102 - for reservoir_name, reservoir in self.wn.reservoirs(): - if self.wn._node_reg.get_usage(reservoir_name) == None: # noqa: SLF001, E711 - reservoir._is_isolated = True # noqa: SLF001 - isolated_nodes.add(reservoir_name) - return isolated_nodes - - def isolateTanks(self, isolated_nodes): # noqa: N802, D102 - for tank_name, tank in self.wn.tanks(): - if self.wn._node_reg.get_usage(tank_name) == None: # noqa: SLF001, E711 - tank._is_isolated = True # noqa: SLF001 - isolated_nodes.add(tank_name) - return isolated_nodes - - def removeNonDemandNegativeNodeByPythonClose(self, maximum_iteration): # noqa: N802, D102 - current_stop_time = self.current_stop_time - minimum_pressure = self.minimum_pressure # noqa: F841 - required_pressure = self.required_pressure # noqa: F841 - temp_file_dest = self.temp_directory - self.closed_pipes = {} - for itrr in range(maximum_iteration): - print(itrr) # noqa: T201 - sim = EpanetSimulator(self.wn) - self._prev_isolated_junctions, self._prev_isolated_links = ( - sim._get_isolated_junctions_and_links( # noqa: SLF001 - self._prev_isolated_junctions, self._prev_isolated_links - ) - ) - sim.manipulateTimeOrder(current_stop_time, current_stop_time) - rr, i_run_successful = sim.run_sim( - file_prefix=temp_file_dest, - start_time=current_stop_time, - iModified=False, - ) - new_closed_pipes, ifinish = sim.closePipeNNN( - rr, - self._prev_isolated_links, - self._prev_isolated_junctions, - self.nne_flow_criteria, - self.nne_pressure_criteria, - ) - - if ifinish: - break - - new_pipe_altered_name_list = new_closed_pipes.keys() - new_c_altered = [ - pipe_name - for pipe_name in new_pipe_altered_name_list - if pipe_name not in self.closed_pipes - ] - for pipe_name in new_c_altered: - self.closed_pipes[pipe_name] = new_closed_pipes[pipe_name] - # self.closed_pipes = orginal_c_dict - # return orginal_c_dict - - def rollBackPipeMinorLoss(self, altered_pipes): # noqa: N802, D102 - for pipe_name in altered_pipes: - self.wn.get_link(pipe_name).minor_loss = altered_pipes[pipe_name] - - def rollBackPipeClose(self): # noqa: N802, D102 - altered_pipes = self.closed_pipes - for pipe_name in altered_pipes: - pipe = self.wn.get_link(pipe_name) - pipe.initial_status = altered_pipes[pipe_name] - - def performSimulation(self, next_event_time, iModified): # noqa: N802, N803, D102 - current_stop_time = self.current_stop_time - minimum_pressure = self.minimum_pressure # noqa: F841 - required_pressure = self.required_pressure # noqa: F841 - temp_file_dest = self.temp_directory - sim = EpanetSimulator(self.wn) - # self.s=sim - self._prev_isolated_junctions, self._prev_isolated_links = ( - sim._get_isolated_junctions_and_links( # noqa: SLF001 - self._prev_isolated_junctions, self._prev_isolated_links - ) - ) - self._prev_isolated_junctions = self.isolateReservoirs( - self._prev_isolated_junctions - ) - self._prev_isolated_junctions = self.isolateTanks( - self._prev_isolated_junctions - ) - print('***********') # noqa: T201 - print(len(self._prev_isolated_junctions)) # noqa: T201 - print(len(self._prev_isolated_links)) # noqa: T201 - print('-----------') # noqa: T201 - sim.manipulateTimeOrder( - current_stop_time, next_event_time - ) # , change_time_step=True, min_correction_time_step=self._min_correction_time) - rr, i_run_successful = sim.run_sim( - file_prefix=temp_file_dest, - start_time=current_stop_time, - iModified=iModified, - ) - return rr, i_run_successful - - def estimateRun(self, next_event_time, iModified): # noqa: N802, N803, D102 - current_stop_time = self.current_stop_time - minimum_pressure = self.minimum_pressure # noqa: F841 - required_pressure = self.required_pressure # noqa: F841 - - sim = EpanetSimulator(self.wn) - duration = self.wn.options.time.duration - report_time_step = self.wn.options.time.report_timestep - sim.manipulateTimeOrder(current_stop_time, current_stop_time) - - temp_file_dest = self.temp_directory - self._prev_isolated_junctions, self._prev_isolated_links = ( - sim._get_isolated_junctions_and_links( # noqa: SLF001 - self._prev_isolated_junctions, self._prev_isolated_links - ) - ) - self._prev_isolated_junctions = self.isolateReservoirs( - self._prev_isolated_junctions - ) - self._prev_isolated_junctions = self.isolateTanks( - self._prev_isolated_junctions - ) - rr, i_run_successful = sim.run_sim( - file_prefix=temp_file_dest, - start_time=current_stop_time, - iModified=iModified, - ) - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = report_time_step - rr = self.approximateNewResult(rr, current_stop_time, next_event_time, 0) - - return rr, i_run_successful - - def estimateWithoutRun(self, result, next_event_time): # noqa: N802, D102 - current_stop_time = self.current_stop_time - minimum_pressure = self.minimum_pressure # noqa: F841 - required_pressure = self.required_pressure # noqa: F841 - - time = result.node['demand'].index.to_list() - unreliable_time_list = result.maximum_trial_time - time.reverse() - - last_valid_time = -1 - for checked_last_time in time: - if checked_last_time not in unreliable_time_list: - last_valid_time = checked_last_time - break - - if last_valid_time == -1: - raise ValueError('Last reliabale time is not found') # noqa: EM101, TRY003 - - time_step = min( - self.wn.options.time.hydraulic_timestep, - self.wn.options.time.report_timestep, - ) - time_step = int(time_step) - end_time = next_event_time - end_time = int(end_time) - # result_node_head = {} - # result_node_demand = {} - # result_node_pressure = {} - result_node_status = {} - result_node_setting = {} - result_node_flowrate = {} - - sim = EpanetSimulator(self.wn) - - self._prev_isolated_junctions, self._prev_isolated_links = ( - sim._get_isolated_junctions_and_links( # noqa: SLF001 - self._prev_isolated_junctions, self._prev_isolated_links - ) - ) - self._prev_isolated_junctions = self.isolateReservoirs( - self._prev_isolated_junctions - ) - self._prev_isolated_junctions = self.isolateTanks( - self._prev_isolated_junctions - ) - - # available_node_list = [node_name for node_name in self.wn.node_name_list if self.wn.get_node(node_name)._is_isolated == False] - # available_link_list = [link_name for link_name in self.wn.link_name_list if self.wn.get_link(link_name)._is_isolated == False] - - available_node_list = [node_name for node_name in self.wn.node_name_list] # noqa: C416 - available_link_list = [link_name for link_name in self.wn.link_name_list] # noqa: C416 - - available_node_list = [ - node_name - for node_name in available_node_list - if node_name in result.node['demand'].columns - ] - available_link_list = [ - link_name - for link_name in available_link_list - if link_name in result.link['flowrate'].columns - ] - - result_node_head = pd.DataFrame(columns=available_node_list) - result_node_demand = pd.DataFrame(columns=available_node_list) - result_node_pressure = pd.DataFrame(columns=available_node_list) - result_node_leak = pd.DataFrame(columns=available_node_list) - - result_link_status = pd.DataFrame(columns=available_link_list) - result_link_setting = pd.DataFrame(columns=available_link_list) - result_link_flowrate = pd.DataFrame(columns=available_link_list) - - first_step = True - for time_step_iter in range(current_stop_time, end_time + 1, time_step): - # print(result.node['head'].loc[last_valid_time, available_node_list]) - result_node_head.loc[time_step_iter, available_node_list] = result.node[ - 'head' - ].loc[last_valid_time, available_node_list] - result_node_demand.loc[time_step_iter, available_node_list] = ( - result.node['demand'].loc[last_valid_time, available_node_list] - ) - result_node_pressure.loc[time_step_iter, available_node_list] = ( - result.node['pressure'].loc[last_valid_time, available_node_list] - ) - result_node_leak.loc[time_step_iter, available_node_list] = result.node[ - 'leak' - ].loc[last_valid_time, result.node['leak'].columns] - - result_link_status.loc[time_step_iter] = result.link['status'].loc[ - last_valid_time, available_link_list - ] - result_link_setting.loc[time_step_iter] = result.link['setting'].loc[ - last_valid_time, available_link_list - ] - result_link_flowrate.loc[time_step_iter] = result.link['flowrate'].loc[ - last_valid_time, available_link_list - ] - # print("---------------") - # print(result_node_head) - # print("---------------") - if first_step == True: # noqa: E712 - first_step = False - else: - self.updateTankHeadsAndPressure( - result_node_demand, - result_node_head, - result_node_pressure, - time_step_iter, - time_step, - ) - - rr = SimulationResults() - result_node_head = result_node_head.sort_index() - result_node_demand = result_node_demand.sort_index() - result_node_pressure = result_node_pressure.sort_index() - result_node_status = pd.DataFrame.from_dict(result_node_status).sort_index() - result_node_setting = pd.DataFrame.from_dict( - result_node_setting - ).sort_index() - result_node_flowrate = pd.DataFrame.from_dict( - result_node_flowrate - ).sort_index() - - rr.node = { - 'head': result_node_head, - 'demand': result_node_demand, - 'pressure': result_node_pressure, - 'leak': result_node_leak, - } - rr.link = { - 'status': result_link_status, - 'setting': result_link_setting, - 'flowrate': result_link_flowrate, - } - return rr, True - - def updateTankHeadsAndPressure( # noqa: N802 - self, - demand, - head, - pressure, - sim_time, - time_step, - ): # Adapted from the latest version of wntrfr. Courtessy of WNTR: https://github.com/USEPA/WNTR - """Parameters - ---------- - wn: wntrfr.network.WaterNetworkModel - - """ # noqa: D205 - dt = time_step - # print(sim_time) - demand_na = demand.loc[sim_time].isna() - head_na = head.loc[sim_time].isna() - pressure_na = pressure.loc[sim_time].isna() - - for tank_name, tank in self.wn.tanks(): - # checks if the node is isolated. - if tank._is_isolated == True: # noqa: SLF001, E712 - continue - - # checks of this node has been isolated at the last valid time. if - # so, ignores this node, even though it is not isolated at this time - # print(sim_time) - # print(demand_na.loc[tank_name]) - # print(demand.loc[sim_time, tank_name]) - if ( - demand_na.loc[tank_name] - or head_na.loc[tank_name] - or pressure_na.loc[tank_name] - ): - continue - - # With formers checks, this "if statement" must not be needed. - # Just leave it here for now - - if tank_name in demand.columns: - q_net = demand.loc[sim_time, tank_name] - else: - q_net = 0.0 - - dV = q_net * dt # noqa: N806 - - previous_head = head.loc[sim_time, tank_name] - if tank.vol_curve is None: - delta_h = 4.0 * dV / (math.pi * tank.diameter**2) - new_level = previous_head + delta_h - tank.elevation - else: - vcurve = np.array(tank.vol_curve.points) - level_x = vcurve[:, 0] - volume_y = vcurve[:, 1] - - previous_level = previous_head - tank.elevation - - V0 = np.interp(previous_level, level_x, volume_y) # noqa: N806 - V1 = V0 + dV # noqa: N806 - new_level = np.interp(V1, volume_y, level_x) - delta_h = new_level - previous_level - - # checks if the new levels and head are within the tanks limit. - # It ignores the possibility of tank overflow and does not alter the - # tank demand. - if new_level < tank.min_level: - new_level = tank.min_level - new_head = tank.elevation + tank.min_level - elif new_level > tank.max_level: - new_level = tank.max_level - new_head = tank.elevation + tank.max_level - - new_head = previous_head + delta_h - head.loc[sim_time, tank_name] = new_head - pressure.loc[sim_time, tank_name] = new_head - tank.elevation - - def approximateNewResult( # noqa: N802, D102 - self, - rr, - current_stop_time, - end_time, - little_time_step, - ): - time_step = min( - self.wn.options.time.hydraulic_timestep, - self.wn.options.time.report_timestep, - ) - current_stop_time = int(current_stop_time) - end_time = int(end_time) - time_step = int(time_step) - not_isolated_tanks = [ - tank_name - for tank_name, tank in self.wn.tanks() - if tank._is_isolated == False # noqa: SLF001, E712 - ] - # isolated_tanks = [tank_name for tank_name in self.tanks_name_list if tank_name in self._prev_isolated_junctions] - # isolated_nodes = [node_name for node_name in self.node_name_list if node_name in self._prev_isolated_junctions] - tank_heads = rr.node['head'][not_isolated_tanks] - # tank_demands=rr.node['demand'][self.wn.tank_name_list] - if little_time_step == 0: - tank_elevation_list = [ - self.wn.get_node(e).elevation for e in not_isolated_tanks - ] - tank_min_level_list = [ - self.wn.get_node(l).min_level - for l in not_isolated_tanks # noqa: E741 - ] - tank_max_level_list = [ - self.wn.get_node(l).max_level - for l in not_isolated_tanks # noqa: E741 - ] - - tanks_min_heads = [ - tank_elevation_list[i] + tank_min_level_list[i] - for i in range(len(tank_elevation_list)) - ] - tanks_max_heads = [ - tank_elevation_list[i] + tank_max_level_list[i] - for i in range(len(tank_elevation_list)) - ] - - tank_heads_diff = rr.node['demand'][not_isolated_tanks] - tank_heads_diff = tank_heads_diff.iloc[-1] - - tanks_min_heads = pd.Series(tanks_min_heads, not_isolated_tanks) - tanks_max_heads = pd.Series(tanks_max_heads, not_isolated_tanks) - - print(current_stop_time) # noqa: T201 - print(time_step) # noqa: T201 - print(end_time) # noqa: T201 - for time_step_iter in range( - current_stop_time + time_step, end_time + 1, time_step - ): - rr.node['head'].loc[time_step_iter] = rr.node['head'].loc[ - current_stop_time - ] - rr.node['demand'].loc[time_step_iter] = rr.node['demand'].loc[ - current_stop_time - ] - rr.node['pressure'].loc[time_step_iter] = rr.node['pressure'].loc[ - current_stop_time - ] - rr.link['status'].loc[time_step_iter] = rr.link['status'].loc[ - current_stop_time - ] - rr.link['setting'].loc[time_step_iter] = rr.link['setting'].loc[ - current_stop_time - ] - rr.link['flowrate'].loc[time_step_iter] = rr.link['flowrate'].loc[ - current_stop_time - ] - - new_tank_heads = tank_heads.loc[current_stop_time] + ( - tank_heads_diff * (time_step_iter - current_stop_time) - ) - - under_min_heads = new_tank_heads[new_tank_heads < tanks_min_heads] - over_max_heads = new_tank_heads[new_tank_heads > tanks_max_heads] - - new_tank_heads.loc[under_min_heads.index] = tanks_min_heads.loc[ - under_min_heads.index - ] - new_tank_heads.loc[over_max_heads.index] = tanks_min_heads.loc[ - over_max_heads.index - ] - - rr.node['head'].loc[time_step_iter, new_tank_heads.index] = ( - new_tank_heads.to_list() - ) - - # Future updates: updating tank levels based on Newer version of WNTR for tansks with curves - else: - tank_elevation_list = [ - self.wn.get_node(e).elevation for e in not_isolated_tanks - ] - tank_min_level_list = [ - self.wn.get_node(l).min_level - for l in not_isolated_tanks # noqa: E741 - ] - tank_max_level_list = [ - self.wn.get_node(l).max_level - for l in not_isolated_tanks # noqa: E741 - ] - - tanks_min_heads = [ - tank_elevation_list[i] + tank_min_level_list[i] - for i in range(len(tank_elevation_list)) - ] - tanks_max_heads = [ - tank_elevation_list[i] + tank_max_level_list[i] - for i in range(len(tank_elevation_list)) - ] - - tank_heads_diff = ( - tank_heads.loc[current_stop_time + little_time_step] - - tank_heads.loc[current_stop_time] - ) - - tanks_min_heads = pd.Series(tanks_min_heads, not_isolated_tanks) - tanks_max_heads = pd.Series(tanks_max_heads, not_isolated_tanks) - # print(repr(current_stop_time)+' '+repr(time_step)+' '+repr(end_time)+' '+repr(time_step)+' ') - for time_step_iter in range( - int(current_stop_time + time_step), int(end_time + 1), int(time_step) - ): - # print(time_step_iter) - new_tank_heads = tank_heads.loc[current_stop_time] + ( - tank_heads_diff - * (time_step_iter - current_stop_time) - / little_time_step - ) - - under_min_heads = new_tank_heads[new_tank_heads < tanks_min_heads] - over_max_heads = new_tank_heads[new_tank_heads > tanks_max_heads] - - new_tank_heads.loc[under_min_heads.index] = tanks_min_heads.loc[ - under_min_heads.index - ] - new_tank_heads.loc[over_max_heads.index] = tanks_min_heads.loc[ - over_max_heads.index - ] - - rr.node['head'].loc[time_step_iter] = rr.node['head'].loc[ - current_stop_time - ] - rr.node['head'].loc[time_step_iter, new_tank_heads.columns] = ( - new_tank_heads - ) - - rr.node['demand'].loc[time_step_iter] = rr.node['demand'].loc[ - current_stop_time - ] - rr.node['pressure'].loc[time_step_iter] = rr.node['pressure'].loc[ - current_stop_time - ] - rr.link['status'].loc[time_step_iter] = rr.link['status'].loc[ - current_stop_time - ] - rr.link['setting'].loc[time_step_iter] = rr.link['setting'].loc[ - current_stop_time - ] - - rr.node['head'] = rr.node['head'].drop( - current_stop_time + little_time_step - ) - rr.node['demand'] = rr.node['demand'].drop( - current_stop_time + little_time_step - ) - rr.node['pressure'] = rr.node['pressure'].drop( - current_stop_time + little_time_step - ) - rr.link['status'] = rr.link['status'].drop( - current_stop_time + little_time_step - ) - rr.link['setting'] = rr.link['setting'].drop( - current_stop_time + little_time_step - ) - - return rr diff --git a/modules/systemPerformance/REWET/REWET/StochasticModel.py b/modules/systemPerformance/REWET/REWET/StochasticModel.py deleted file mode 100644 index 3291e6fbd..000000000 --- a/modules/systemPerformance/REWET/REWET/StochasticModel.py +++ /dev/null @@ -1,672 +0,0 @@ -"""Created on Wed Apr 8 20:19:10 2020 - -@author: snaeimi -""" # noqa: N999, D400 - -import logging -import os -import pickle -import sys - -import Damage -import EnhancedWNTR.network.model -import pandas as pd -import wntrfr -from EnhancedWNTR.sim.results import SimulationResults -from Sim.Simulation import Hydraulic_Simulation -from timeline import Timeline -from wntrfr.network.model import LinkStatus - -# from wntrplus import WNTRPlus -from wntrfr.utils.ordered_set import OrderedSet - -logger = logging.getLogger(__name__) - - -class StochasticModel: # noqa: D101 - def __init__( - self, - water_network, - damage_model, - registry, - simulation_end_time, - restoration, - mode='PDD', - i_restoration=True, # noqa: FBT002 - ): - if ( - type(water_network) != wntrfr.network.model.WaterNetworkModel # noqa: E721 - and type(water_network) != EnhancedWNTR.network.model.WaterNetworkModel # noqa: E721 - ): - raise ValueError( # noqa: TRY003 - 'Water_network model is not legitimate water Network Model' # noqa: EM101 - ) - if type(damage_model) != Damage.Damage: # noqa: E721 - raise ValueError('damage_model is not a ligitimate Damage Model') # noqa: EM101, TRY003 - self.wn = water_network - self.damage_model = damage_model - self._simulation_time = simulation_end_time - self.timeline = Timeline(simulation_end_time, restoration, registry) - damage_distict_time = self.damage_model.get_damage_distinct_time() - self.timeline.addEventTime(damage_distict_time) - self.timeline.checkAndAmendTime() - - self.simulation_mode = None - if mode == 'PDD' or mode == 'DD': # noqa: PLR1714 - self.simulation_mode = mode - else: - self.simulation_mode = 'PDD' - self._linear_result = registry.result - self.registry = registry - # self.wp = WNTRPlus(restoration._registry) - self.restoration = restoration - self._min_correction_time = 900 - self.simulation_time = 0 - self.restoration_time = 0 - self.iRestoration = i_restoration - self._prev_isolated_junctions = OrderedSet() - self._prev_isolated_links = OrderedSet() - self.first_leak_flag = True - - def runLinearScenario(self, damage, settings, worker_rank=None): # noqa: C901, N802 - """Runs a simple linear analysis of water damage scenario - Parameters - - Water Network object (WN) shall not be altered in any object except restoration - ---------- - damage : Damage Object - - Returns - ------- - Result. - - """ # noqa: D205, D400, D401 - while self.timeline.iContinue(): - sys.stdout.flush() - current_stop_time = self.timeline.getCurrentStopTime() - print('--------------------------------------') # noqa: T201 - print('At stop Time: ' + repr(current_stop_time / 3600)) # noqa: T201 - # ============================================================================= - # Restoration event Block - if ( - self.timeline.iCurenttimeRestorationEvent() - and self.iRestoration == True # noqa: E712 - ): - logger.debug('\t Restoration Event ') - - event_time_list = self.restoration.perform_action( - self.wn, current_stop_time - ) - - self.timeline.addEventTime(event_time_list, event_type='rst') - - # ============================================================================= - # Damage (earthquake) event block - if self.timeline.iCurrentTimeDamageEvent(): - self.ttemp = pd.DataFrame() - self.registry.if_first_event_occured = True - logger.debug('\t DAMAGE EVENT') - # pipe_list = self.restoration.getPipeListForHydraulicSignificant() - if len(self.restoration.getHydSigPipeList()) > 0: - last_demand_node_pressure = None - pipe_list = damage.getPipeDamageListAt(current_stop_time) - for pipe_name in pipe_list: - if last_demand_node_pressure is None: - time_index = self.registry.result.node['pressure'].index - time_index = list( - set(time_index) - - set(self.registry.result.maximum_trial_time) - ) - time_index.sort() - if len(time_index) > 0: - time_index = time_index[-1] - else: - self.registry.hydraulic_significance.loc[ - pipe_name - ] = -1000 - continue - time_index = current_stop_time - demand_node_list = self.registry.demand_node_name_list - demand_node_list = set(demand_node_list).intersection( - self.registry.result.node['pressure'].columns - ) - last_demand_node_pressure = self.registry.result.node[ - 'pressure' - ].loc[time_index, list(demand_node_list)] - last_demand_node_pressure.loc[ - last_demand_node_pressure[ - last_demand_node_pressure < 0 - ].index - ] = 0 - pipe = self.wn.get_link(pipe_name) - initial_pipe_status = pipe.initial_status - if initial_pipe_status == LinkStatus.Closed: - continue - - pipe.initial_status = LinkStatus.Closed - hyd_sim = Hydraulic_Simulation( - self.wn, - settings, - current_stop_time, - worker_rank, - self._prev_isolated_junctions, - self._prev_isolated_links, - ) - self.hyd_temp = hyd_sim - duration = self.wn.options.time.duration - report_time_step = self.wn.options.time.report_timestep - try: # Run with modified EPANET V2.2 - print('Performing method 1') # noqa: T201 - rr, i_run_successful = hyd_sim.performSimulation( - current_stop_time, - True, # noqa: FBT003 - ) - if current_stop_time in rr.maximum_trial_time: - pass - # self.registry.hydraulic_significance.loc[pipe_name] = -20000 - # pipe.initial_status = initial_pipe_status - # self._prev_isolated_junctions = hyd_sim._prev_isolated_junctions - # self._prev_isolated_links = hyd_sim._prev_isolated_links - # continue - demand_node_list = self.registry.demand_node_name_list - demand_node_list = set(demand_node_list).intersection( - rr.node['pressure'].columns - ) - new_node_pressure = rr.node['pressure'].loc[ - current_stop_time, list(demand_node_list) - ] - new_node_pressure.loc[ - new_node_pressure[new_node_pressure < 0].index - ] = 0 - - hydraulic_impact = ( - last_demand_node_pressure - new_node_pressure - ).mean() - self.registry.hydraulic_significance.loc[pipe_name] = ( - hydraulic_impact - ) - - except Exception as epa_err_1: # noqa: TRY302 - raise - if epa_err_1.args[0] == 'EPANET Error 110': - print('Method 1 failed. Performing method 2') # noqa: T201 - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = ( - report_time_step - ) - self.registry.hydraulic_significance.loc[ - pipe_name - ] = -1 - pipe.initial_status = initial_pipe_status - self._prev_isolated_junctions = ( - hyd_sim._prev_isolated_junctions # noqa: SLF001 - ) - self._prev_isolated_links = hyd_sim._prev_isolated_links # noqa: SLF001 - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = report_time_step - damage.applyPipeDamages(self.wn, current_stop_time) - damage.applyNodalDamage(self.wn, current_stop_time) - damage.applyPumpDamages(self.wn, current_stop_time) - damage.applyTankDamages(self.wn, current_stop_time) - - if self.iRestoration == True: # noqa: E712 - event_time_list = self.restoration.initialize( - self.wn, current_stop_time - ) # starts restoration - self.timeline.addEventTime(event_time_list, event_type='rst') - - # ============================================================================= - # This is for updatng the pipe damage log - if settings['record_damage_table_logs'] == True: # noqa: E712 - self.restoration._registry.updatePipeDamageTableTimeSeries( # noqa: SLF001 - current_stop_time - ) - self.restoration._registry.updateNodeDamageTableTimeSeries( # noqa: SLF001 - current_stop_time - ) - # ============================================================================= - # running the model - next_event_time = self.timeline.getNextTime() - logger.debug('next event time is: ' + repr(next_event_time)) # noqa: G003 - - self.wn.implicitLeakToExplicitReservoir(self.registry) - - print('***** Running hydraulic *****') # noqa: T201 - - if type(worker_rank) != str: # noqa: E721 - worker_rank = str(worker_rank) - - hyd_sim = Hydraulic_Simulation( - self.wn, - settings, - current_stop_time, - worker_rank, - self._prev_isolated_junctions, - self._prev_isolated_links, - ) - self.hyd_temp = hyd_sim - duration = self.wn.options.time.duration - report_time_step = self.wn.options.time.report_timestep - try: # Run with modified EPANET V2.2 - print('Performing method 1') # noqa: T201 - rr, i_run_successful = hyd_sim.performSimulation( - next_event_time, - True, # noqa: FBT003 - ) - except Exception as epa_err_1: - if epa_err_1.args[0] == 'EPANET Error 110': - print('Method 1 failed. Performing method 2') # noqa: T201 - try: # Remove Non-Demand Node by Python-Side iterative algorithm with closing - # self.wn.options.time.duration = duration - # self.wn.options.time.report_timestep = report_time_step - # hyd_sim.removeNonDemandNegativeNodeByPythonClose(1000) - # rr, i_run_successful = hyd_sim.performSimulation(next_event_time, False) - # hyd_sim.rollBackPipeClose() - raise - except Exception as epa_err_2: - if True: # epa_err_2.args[0] == 'EPANET Error 110': - try: # Extend result from the result at the begning of the time step with modified EPANET V2.2 - # print("Method 2 failed. Performing method 3") - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = ( - report_time_step - ) - # hyd_sim.rollBackPipeClose() - rr, i_run_successful = hyd_sim.estimateRun( - next_event_time, - True, # noqa: FBT003 - ) - except Exception as epa_err_3: - if epa_err_3.args[0] == 'EPANET Error 110': - print('Method 3 failed. Performing method 4') # noqa: T201 - try: # Extend result from the result at the beginning of the time step with modified EPANET V2.2 - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = ( - report_time_step - ) - rr, i_run_successful = ( - hyd_sim.performSimulation( - next_event_time, - False, # noqa: FBT003 - ) - ) - except Exception as epa_err_4: - if epa_err_4.args[0] == 'EPANET Error 110': - try: - self.wn.options.time.duration = ( - duration - ) - self.wn.options.time.report_timestep = report_time_step - print( # noqa: T201 - 'Method 4 failed. Performing method 5' - ) - # Extend result from the result at the beginning of the time step with modified EPANET V2.2 - rr, i_run_successful = ( - hyd_sim.estimateRun( - next_event_time, - False, # noqa: FBT003 - ) - ) - except Exception as epa_err_5: - if ( - epa_err_5.args[0] - == 'EPANET Error 110' - ): - try: - print( # noqa: T201 - 'Method 5 failed. Performing method 6' - ) - self.wn.options.time.duration = duration - self.wn.options.time.report_timestep = report_time_step - rr, i_run_successful = ( - hyd_sim.estimateWithoutRun( - self._linear_result, - next_event_time, - ) - ) - except Exception as epa_err_6: - print( # noqa: T201 - 'ERROR in rank=' - + repr(worker_rank) - + ' and time=' - + repr(current_stop_time) - ) - raise epa_err_6 # noqa: TRY201 - else: - raise epa_err_5 # noqa: TRY201 - else: - raise epa_err_4 # noqa: TRY201 - else: - raise epa_err_3 # noqa: TRY201 - else: - raise epa_err_2 # noqa: TRY201 - else: - raise epa_err_1 # noqa: TRY201 - self._prev_isolated_junctions = hyd_sim._prev_isolated_junctions # noqa: SLF001 - self._prev_isolated_links = hyd_sim._prev_isolated_links # noqa: SLF001 - print( # noqa: T201 - '***** Finish Running at time ' - + repr(current_stop_time) - + ' ' - + repr(i_run_successful) - + ' *****' - ) - - if i_run_successful == False: # noqa: E712 - continue - self.wn.updateWaterNetworkModelWithResult(rr, self.restoration._registry) # noqa: SLF001 - - self.KeepLinearResult( - rr, - self._prev_isolated_junctions, - node_attributes=['pressure', 'head', 'demand', 'leak'], - link_attributes=['status', 'setting', 'flowrate'], - ) - if self.registry.settings['limit_result_file_size'] > 0: - self.dumpPartOfResult() - # self.wp.unlinkBreackage(self.registry) - self.wn.resetExplicitLeak() - - # ============================================================================= - # self.resoration._registry.updateTankTimeSeries(self.wn, current_stop_time) - self.restoration._registry.updateRestorationIncomeWaterTimeSeries( # noqa: SLF001 - self.wn, current_stop_time - ) - - return self._linear_result - - def KeepLinearResult( # noqa: C901, N802, D102 - self, - result, - isolated_nodes, - node_attributes=None, - link_attributes=None, - iCheck=False, # noqa: FBT002, ARG002, N803 - ): # , iNeedTimeCorrection=False, start_time=None): - if self.registry.if_first_event_occured == False: # noqa: E712 - self.registry.pre_event_demand_met = ( - self.registry.pre_event_demand_met.append(result.node['demand']) - ) - - # if node_attributes == None: - # node_attributes = ['pressure','head','demand','quality'] - # if link_attributes == None: - # link_attributes = ['linkquality', 'flowrate', 'headloss', 'velocity', 'status', 'setting', 'frictionfact', 'rxnrate'] - - just_initialized_flag = False - if self._linear_result == None: # noqa: E711 - just_initialized_flag = True - self._linear_result = result - - self.restoration._registry.result = self._linear_result # noqa: SLF001 - node_result_type_elimination_list = set(result.node.keys()) - set( - node_attributes - ) - link_result_type_elimination_list = set(result.link.keys()) - set( - link_attributes - ) - - for node_result_type in node_result_type_elimination_list: - self._linear_result.node.pop(node_result_type) - - for link_result_type in link_result_type_elimination_list: - self._linear_result.link.pop(link_result_type) - - self._linear_result.node['leak'] = pd.DataFrame(dtype=float) - - active_pipe_damages = self.restoration._registry.active_pipe_damages # noqa: SLF001 - - temp_active = active_pipe_damages.copy() - for virtual_demand_node in active_pipe_damages: - if ( - virtual_demand_node in isolated_nodes - or active_pipe_damages[virtual_demand_node] in isolated_nodes - ): - temp_active.pop(virtual_demand_node) - - virtual_demand_nodes = list(temp_active.keys()) - real_demand_nodes = list(temp_active.values()) - - if len(temp_active) > 0: - # this must be here in the case that a node that is not isolated at - # this step does not have a result. This can happen if the result is - # simulated without run.. For example, in the latest valid result - # some nodes were isolated, but not in the current run. - available_nodes_in_current_result = result.node[ - 'demand' - ].columns.to_list() - not_available_virtual_node_names = set(virtual_demand_nodes) - set( - available_nodes_in_current_result - ) - if len(not_available_virtual_node_names): - not_available_real_node_names = [ - temp_active[virtual_node_name] - for virtual_node_name in not_available_virtual_node_names - ] - virtual_demand_nodes = ( - set(virtual_demand_nodes) - not_available_virtual_node_names - ) - real_demand_nodes = set(real_demand_nodes) - set( - not_available_real_node_names - ) - virtual_demand_nodes = list(virtual_demand_nodes) - real_demand_nodes = list(real_demand_nodes) - - result.node['demand'][real_demand_nodes] = result.node['demand'][ - virtual_demand_nodes - ] - result.node['demand'].drop(virtual_demand_nodes, axis=1, inplace=True) # noqa: PD002 - - active_nodal_damages = self.restoration._registry.active_nodal_damages # noqa: SLF001 - temp_active = active_nodal_damages.copy() - - for virtual_demand_node in active_nodal_damages: - if ( - virtual_demand_node in isolated_nodes - or temp_active[virtual_demand_node] in isolated_nodes - ): - temp_active.pop(virtual_demand_node) - - virtual_demand_nodes = list(temp_active.keys()) - real_demand_nodes = list(temp_active.values()) - - if len(temp_active) > 0: - # this must be here in the case that a node that is not isolated at - # this step has not result. This can happen if the result is being - # simulated without run.. For example, in the latest valid result - # some nodes were isolated, but not in the current run. - available_nodes_in_current_result = result.node[ - 'demand' - ].columns.to_list() - not_available_virtual_node_names = set(virtual_demand_nodes) - set( - available_nodes_in_current_result - ) - if len(not_available_virtual_node_names): - not_available_real_node_names = [ - temp_active[virtual_node_name] - for virtual_node_name in not_available_virtual_node_names - ] - virtual_demand_nodes = ( - set(virtual_demand_nodes) - not_available_virtual_node_names - ) - real_demand_nodes = set(real_demand_nodes) - set( - not_available_real_node_names - ) - virtual_demand_nodes = list(virtual_demand_nodes) - real_demand_nodes = list(real_demand_nodes) - - non_isolated_pairs = dict(zip(virtual_demand_nodes, real_demand_nodes)) - result.node['leak'] = result.node['demand'][virtual_demand_nodes].rename( - non_isolated_pairs, axis=1 - ) - - if just_initialized_flag == False: # noqa: E712 - self._linear_result.maximum_trial_time.extend(result.maximum_trial_time) - - saved_max_time = self._linear_result.node[ - list(self._linear_result.node.keys())[0] # noqa: RUF015 - ].index.max() - to_be_saved_min_time = result.node[ - list(result.node.keys())[0] # noqa: RUF015 - ].index.min() - if ( - abs(to_be_saved_min_time - saved_max_time) != 0 - ): # >= min(self.wn.options.time.hydraulic_timestep, self.wn.options.time.report_timestep): - # logger.error(repr(to_be_saved_min_time)+ ' ' + repr(saved_max_time)) - raise ValueError( - 'saved result and to be saved result are not the same. ' - + repr(saved_max_time) - + ' ' - + repr(to_be_saved_min_time) - ) - for att in node_attributes: - if len(active_nodal_damages) == 0 and att == 'leak': - continue - _leak_flag = False - - leak_first_time_result = None - if ( - att == 'leak' and 'leak' in result.node - ): # the second condition is not needed. It's there only for assurance - former_nodes_list = set(self._linear_result.node['leak'].columns) - to_add_nodes_list = set(result.node[att].columns) - complete_result_node_list = to_add_nodes_list - former_nodes_list - if len(complete_result_node_list) > 0: - _leak_flag = True - - leak_first_time_result = result.node['leak'][ - complete_result_node_list - ].iloc[0] - - if att in result.node: - result.node[att].drop(result.node[att].index[0], inplace=True) # noqa: PD002 - self._linear_result.node[att] = self._linear_result.node[ - att - ].append(result.node[att]) - - if _leak_flag: - self._linear_result.node['leak'].loc[ - leak_first_time_result.name, leak_first_time_result.index - ] = leak_first_time_result - self._linear_result.node['leak'] = self._linear_result.node[ - 'leak' - ].sort_index() - - for att in link_attributes: - result.link[att].drop(result.link[att].index[0], inplace=True) # noqa: PD002 - self._linear_result.link[att] = self._linear_result.link[att].append( - result.link[att] - ) - - def dumpPartOfResult(self): # noqa: C901, N802, D102 - limit_size = self.registry.settings['limit_result_file_size'] - limit_size_byte = limit_size * 1024 * 1024 - - total_size = 0 - - for att in self._linear_result.node: - att_size = sys.getsizeof(self._linear_result.node[att]) - total_size += att_size - - for att in self._linear_result.link: - att_size = sys.getsizeof(self._linear_result.link[att]) - total_size += att_size - - print('total size= ' + repr(total_size / 1024 / 1024)) # noqa: T201 - - if total_size >= limit_size_byte: - dump_result = SimulationResults() - dump_result.node = {} - dump_result.link = {} - for att in self._linear_result.node: - # just to make sure. it obly add tens of micro seconds for each - # att - - self._linear_result.node[att].sort_index(inplace=True) # noqa: PD002 - att_result = self._linear_result.node[att] - if att_result.empty: - continue - # first_time_index = att_result.index[0] - last_valid_time = [] - att_time_index = att_result.index.to_list() - last_valid_time = [ - cur_time - for cur_time in att_time_index - if cur_time not in self._linear_result.maximum_trial_time - ] - last_valid_time.sort() - - if len(last_valid_time) > 0: - last_valid_time = last_valid_time[-2] - else: - print(att_time_index) # noqa: T201 - last_valid_time = att_time_index[-2] - - dump_result.node[att] = att_result.loc[:last_valid_time] - last_valid_time_index = att_result.index.searchsorted( - last_valid_time - ) - self._linear_result.node[att].drop( - att_result.index[: last_valid_time_index + 1], - inplace=True, # noqa: PD002 - ) - - for att in self._linear_result.link: - # just to make sure. it obly add tens of micro seconds for each - # att - self._linear_result.link[att].sort_index(inplace=True) # noqa: PD002 - att_result = self._linear_result.link[att] - if att_result.empty: - continue - # first_time_index = att_result.index[0] - last_valid_time = [] - att_time_index = att_result.index.to_list() - last_valid_time = [ - cur_time - for cur_time in att_time_index - if cur_time not in self._linear_result.maximum_trial_time - ] - last_valid_time.sort() - - if len(last_valid_time) > 0: - last_valid_time = last_valid_time[-2] - else: - last_valid_time = att_time_index[-2] - - dump_result.link[att] = att_result.loc[:last_valid_time] - last_valid_time_index = att_result.index.searchsorted( - last_valid_time - ) - self._linear_result.link[att].drop( - att_result.index[: last_valid_time_index + 1], - inplace=True, # noqa: PD002 - ) - - dump_file_index = len(self.registry.result_dump_file_list) + 1 - - if dump_file_index >= 1: - list_file_opening_mode = 'at' - else: - list_file_opening_mode = 'wt' - - result_dump_file_name = ( - self.registry.scenario_name + '.part' + str(dump_file_index) - ) - result_dump_file_dst = os.path.join( # noqa: PTH118 - self.registry.settings.process['result_directory'], - result_dump_file_name, - ) - - with open(result_dump_file_dst, 'wb') as resul_file: # noqa: PTH123 - pickle.dump(dump_result, resul_file) - - dump_list_file_name = self.registry.scenario_name + '.dumplist' - list_file_dst = os.path.join( # noqa: PTH118 - self.registry.settings.process['result_directory'], - dump_list_file_name, - ) - - with open(list_file_dst, list_file_opening_mode) as part_list_file: # noqa: PTH123 - part_list_file.writelines([result_dump_file_name]) - - self.registry.result_dump_file_list.append(result_dump_file_name) diff --git a/modules/systemPerformance/REWET/REWET/__init__.py b/modules/systemPerformance/REWET/REWET/__init__.py deleted file mode 100644 index 5ecedd637..000000000 --- a/modules/systemPerformance/REWET/REWET/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from REWET import Input # noqa: N999, D104 - -__version__ = '0.1.1' diff --git a/modules/systemPerformance/REWET/REWET/damage_input/example_list.xlsx b/modules/systemPerformance/REWET/REWET/damage_input/example_list.xlsx deleted file mode 100644 index 87c7356c6..000000000 Binary files a/modules/systemPerformance/REWET/REWET/damage_input/example_list.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/damage_input/node.xlsx b/modules/systemPerformance/REWET/REWET/damage_input/node.xlsx deleted file mode 100644 index 1d36e98b2..000000000 Binary files a/modules/systemPerformance/REWET/REWET/damage_input/node.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/damage_input/pipe.xlsx b/modules/systemPerformance/REWET/REWET/damage_input/pipe.xlsx deleted file mode 100644 index d2f580e61..000000000 Binary files a/modules/systemPerformance/REWET/REWET/damage_input/pipe.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/damage_input/pump.xlsx b/modules/systemPerformance/REWET/REWET/damage_input/pump.xlsx deleted file mode 100644 index f508634d7..000000000 Binary files a/modules/systemPerformance/REWET/REWET/damage_input/pump.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/damage_input/tank.xlsx b/modules/systemPerformance/REWET/REWET/damage_input/tank.xlsx deleted file mode 100644 index 974cfcc9e..000000000 Binary files a/modules/systemPerformance/REWET/REWET/damage_input/tank.xlsx and /dev/null differ diff --git a/modules/systemPerformance/REWET/REWET/initial.py b/modules/systemPerformance/REWET/REWET/initial.py deleted file mode 100644 index 06af15b3a..000000000 --- a/modules/systemPerformance/REWET/REWET/initial.py +++ /dev/null @@ -1,605 +0,0 @@ -"""Created on Tue Jun 1 21:04:18 2021 - -@author: snaeimi -""" # noqa: D400 - -import logging -import os -import pickle -import time - -import Damage -import Input.Input_IO as io -import pandas as pd -import StochasticModel -from EnhancedWNTR.network.model import WaterNetworkModel -from Input.Settings import Settings -from Project import Project -from restoration.model import Restoration - -# from wntrfr.network.model import WaterNetworkModel #INote: changed from enhanced wntr to wntr 1. It may break EPANET compatibility -from restoration.registry import Registry - -logging.basicConfig(level=50) - - -class Starter: # noqa: D101 - def createProjectFile(self, project_settings, damage_list, project_file_name): # noqa: N802, D102 - project = Project(project_settings, damage_list) - project_file_addr = os.path.join( # noqa: PTH118 - project_settings.process['result_directory'], project_file_name - ) - with open(project_file_addr, 'wb') as f: # noqa: PTH123 - pickle.dump(project, f) - - def run(self, project_file=None): # noqa: C901 - """Runs the ptogram. It initiates the Settings class and based on the - settings, run the program in either single scenario, multiple serial or - multiple parallel mode. - - Raises - ------ - ValueError - DESCRIPTION. - - Returns - ------- - None. - - """ # noqa: D205, D401, DOC202, RUF100 - settings = Settings() - if project_file is not None: - project_file = str(project_file) - - if type(project_file) == str: # noqa: E721 - if project_file.split('.')[-1].lower() == 'prj': - settings.importProject(project_file) - elif project_file.split('.')[-1].lower() == 'json': - settings.importJsonSettings(project_file) - project_file = None - else: - raise ValueError( - 'The input file has an unrgnizable extension: {}'.format( # noqa: EM103 - project_file.split('.')[-1].lower() - ) - ) - # ============================================================================= - # else: - # raise ValueError("project type unrecognized") - # ============================================================================= - - damage_list = io.read_damage_list( - settings.process['pipe_damage_file_list'], - settings.process['pipe_damage_file_directory'], - ) - settings.process.settings['list'] = damage_list - if project_file is None: - self.createProjectFile(settings, damage_list, 'project.prj') - # raise - if settings.process['number_of_proccessor'] == 1: # Single mode - # get damage list as Pandas Dataframe - if settings.process['number_of_damages'] == 'multiple': - damage_list_size = len(damage_list) - for i in range(damage_list_size): - print(i, flush=True) # noqa: T201 - settings.initializeScenarioSettings( - i - ) # initialize scenario-specific settings for each list/useful for sensitivity analysis - scenario_name = damage_list.loc[i, 'Scenario Name'] - pipe_damage_name = damage_list.loc[i, 'Pipe Damage'] - tank_damage_name = damage_list.loc[i, 'Tank Damage'] - self.run_local_single( - pipe_damage_name, - scenario_name, - settings, - nodal_damage_file_name=damage_list.loc[i, 'Nodal Damage'], - pump_damage_file_name=damage_list.loc[i, 'Pump Damage'], - tank_damage_file_name=tank_damage_name, - ) - - elif settings.process['number_of_damages'] == 'single': - t1 = time.time() - settings.initializeScenarioSettings( - 0 - ) # initialize scenario-specific settings for the first line of damage list - scenario_name = damage_list.loc[0, 'Scenario Name'] - pipe_damage_name = damage_list.loc[0, 'Pipe Damage'] - tank_damage_name = damage_list.loc[0, 'Tank Damage'] - self.run_local_single( - pipe_damage_name, - scenario_name, - settings, - nodal_damage_file_name=damage_list.loc[0, 'Nodal Damage'], - pump_damage_file_name=damage_list.loc[0, 'Pump Damage'], - tank_damage_file_name=tank_damage_name, - ) - t2 = time.time() - print('Time of Single run is: ' + repr((t2 - t1) / 3600) + '(hr)') # noqa: T201 - else: - raise ValueError("Unknown value for settings['number_of_damages']") # noqa: EM101, TRY003 - - elif settings.process['number_of_proccessor'] > 1: - self.run_mpi(settings) - else: - raise ValueError('Number of processor must be equal to or more than 1') # noqa: EM101, TRY003 - - def run_local_single( # noqa: C901 - self, - file_name, - scenario_name, - settings, - worker_rank=None, - nodal_damage_file_name=None, - pump_damage_file_name=None, - tank_damage_file_name=None, - ): - """Runs a single scenario on the local machine. - - Parameters - ---------- - file_name : str - File damage file name. - scenario_name : str - scenario name. - settings : Settings - Settings object. - worker_rank : int, optional - Specifies the rank of the current worker. If the scenario is being run as single or multiple-serial mode, the can be anything. It is used for naming temp files. The default is None. - nodal_damage_file_name : str, optional - nodal damages file name. The default is None. - pump_damage_file_name : TYPE, optional - pump damages file name. The default is None. - tank_damage_file_name : TYPE, optional - Tank damages file name. The default is None. - - Raises - ------ - ValueError - DESCRIPTION. - - Returns - ------- - None. - - """ # noqa: D401 - print( # noqa: T201 - scenario_name - + ' - ' - + file_name - + ' - ' - + nodal_damage_file_name - + ' - ' - + str(pump_damage_file_name), - flush=True, - ) - if settings.process['number_of_proccessor'] > 1 and worker_rank == None: # noqa: E711 - raise ValueError( # noqa: TRY003 - 'for multiple processor analysis, worker_rank_must be provided' # noqa: EM101 - ) - - if type(file_name) != str: # noqa: E721 - file_name = str( - file_name - ) # for number-only names to convert from int/float to str - - if type(tank_damage_file_name) != str: # noqa: E721 - tank_damage_file_name = str( - tank_damage_file_name - ) # for number-only names to convert from int/float to str - - if type(nodal_damage_file_name) != str: # noqa: E721 - nodal_damage_file_name = str( - nodal_damage_file_name - ) # for number-only names to convert from int/float to str - - if type(pump_damage_file_name) != str: # noqa: E721 - pump_damage_file_name = str( - pump_damage_file_name - ) # for number-only names to convert from int/float to str - - if settings.scenario['Pipe_damage_input_method'] == 'pickle': - pipe_damages = io.read_pipe_damage_seperate_pickle_file( - settings.process['pipe_damage_file_directory'], file_name - ) - node_damages = io.read_node_damage_seperate_pickle_file( - settings.process['pipe_damage_file_directory'], - nodal_damage_file_name, - ) - tank_damages = io.read_tank_damage_seperate_pickle_file( - settings.process['pipe_damage_file_directory'], tank_damage_file_name - ) - pump_damages = io.read_pump_damage_seperate_pickle_file( - settings.process['pipe_damage_file_directory'], pump_damage_file_name - ) - elif settings.scenario['Pipe_damage_input_method'] == 'excel': - pipe_damages = io.read_pipe_damage_seperate_EXCEL_file( - settings.process['pipe_damage_file_directory'], file_name - ) - node_damages = io.read_node_damage_seperate_EXCEL_file( - settings.process['pipe_damage_file_directory'], - nodal_damage_file_name, - ) - tank_damages = io.read_tank_damage_seperate_EXCEL_file( - settings.process['pipe_damage_file_directory'], tank_damage_file_name - ) - pump_damages = io.read_pump_damage_seperate_EXCEL_file( - settings.process['pipe_damage_file_directory'], pump_damage_file_name - ) - else: - raise ValueError( # noqa: TRY003 - "Unknown value for settings['Pipe_damage_input_method']" # noqa: EM101 - ) - - if ( - pipe_damages.empty == True # noqa: E712 - and node_damages.empty == True # noqa: E712 - and tank_damages.empty == True # noqa: E712 - and pump_damages.empty == True # noqa: E712 - and settings.process['ignore_empty_damage'] - ): - return 2 # means it didn't run due to lack of any damage in pipe lines - - """ - reads WDN definition and checks set the settinsg defined from settings - """ - wn = WaterNetworkModel(settings.process['WN_INP']) - - delta_t_h = settings['hydraulic_time_step'] - wn.options.time.hydraulic_timestep = int(delta_t_h) - # wn.options.time.pattern_timestep = int(delta_t_h) - # wn.options.time.pattern_timestep = int(delta_t_h) - # Sina What about rule time step. Also one may want to change pattern time step - - demand_node_name_list = [] - for junction_name, junction in wn.junctions(): - if junction.demand_timeseries_list[0].base_value > 0: - junction.demand_timeseries_list[0].base_value = ( - junction.demand_timeseries_list[0].base_value - * settings.process['demand_ratio'] - ) - demand_node_name_list.append(junction_name) - - registry = Registry(wn, settings, demand_node_name_list, scenario_name) - self.registry = registry - self.damage = Damage.Damage(registry, settings.scenario) - # All these data can immigrate to registry - self.registry.damage = self.damage - self.damage.pipe_all_damages = pipe_damages - self.damage.node_damage = node_damages - if tank_damages.empty == False: # noqa: E712 - self.damage.tank_damage = tank_damages['Tank_ID'] - if pump_damages.empty == False: # noqa: E712 - self.damage.damaged_pumps = pump_damages['Pump_ID'] - - restoration = Restoration( - settings.scenario['Restortion_config_file'], registry, self.damage - ) - - restoration.pump_restoration = pump_damages - restoration.tank_restoration = tank_damages - - self.sm = StochasticModel.StochasticModel( - wn, - self.damage, - self.registry, - simulation_end_time=settings.process['RUN_TIME'], - restoration=restoration, - mode='PDD', - i_restoration=settings.process['Restoration_on'], - ) - - result = self.sm.runLinearScenario(self.damage, settings, worker_rank) - self.res = result - io.save_single(settings, result, scenario_name, registry) - return 1 - - def run_mpi(self, settings): # noqa: C901, D102 - import mpi4py - from mpi4py import MPI - - comm = MPI.COMM_WORLD - mpi4py.rc.recv_mprobe = False - - pipe_damage_list = io.read_damage_list( - settings.process['pipe_damage_file_list'], - settings.process['pipe_damage_file_directory'], - ) - - if settings.process['mpi_resume'] == True: # noqa: E712 - pipe_damage_list = pipe_damage_list.set_index('Scenario Name') - # _done_file = pd.read_csv('done.csv') - # _done_file = _done_file.transpose().reset_index().transpose().set_index(0) - file_lists = os.listdir(settings.process['result_directory']) - done_scenario_list = [] - for name in file_lists: - if name.split('.')[-1] != 'res': - continue - split_k = name.split('.res')[:-1] - # print(split_k) - kk = '' - for portiong in split_k: - kk += portiong - if kk not in done_scenario_list and kk in pipe_damage_list.index: - done_scenario_list.append(kk) - - pipe_damage_list = pipe_damage_list.drop(done_scenario_list) - pipe_damage_list = pipe_damage_list.reset_index() - - if comm.rank == 0: - scn_name_list = pipe_damage_list['Scenario Name'].to_list() - file_name_list = pipe_damage_list['Pipe Damage'].to_list() - else: - file_name_list = [] - - if comm.rank == 0: - time_jobs_saved = time.time() - jobs = pd.DataFrame( - columns=[ - 'scenario_name', - 'file_name', - 'worker', - 'Done', - 'time_assigned', - 'time_confirmed', - ] - ) - jobs['scenario_name'] = scn_name_list - jobs['file_name'] = file_name_list - jobs['worker'] = None - jobs['Done'] = 'False' - jobs['time_assigned'] = None - jobs['time_confirmed'] = None - - workers = pd.Series( - data=-1, - index=[ - 1 + i - for i in range(settings.process['number_of_proccessor'] - 1) - ], - ) - - iContinue = True # noqa: N806 - while iContinue: - if (time.time() - time_jobs_saved) > 120: # noqa: PLR2004 - jobs.to_excel( - 'temp-jobs.xlsx' - ) # only for more information about the latest job status for the user in the real time - time_jobs_saved = time.time() - - if comm.iprobe(): - status = MPI.Status() - recieved_msg = comm.recv(status=status) - worker_rank = status.Get_source() - if ( - recieved_msg == 1 or recieved_msg == 2 or recieved_msg == 3 # noqa: PLR1714, PLR2004 - ): # check if the job is done - msg_interpretation = None - if recieved_msg == 1: - msg_interpretation = 'done' - elif recieved_msg == 2: # noqa: PLR2004 - msg_interpretation = 'done w/o simulation' - elif recieved_msg == 3: # noqa: PLR2004 - msg_interpretation = 'exception happened' - - print( # noqa: T201 - 'messaged received= ' - + repr(msg_interpretation) - + ' rank recivied= ' - + repr(worker_rank) - ) - # In both cases it means the jobs is done, only in different ways - else: - raise ValueError( - 'Recieved message from worker is not recognized: ' - + str(recieved_msg) - + ', ' - + str(worker_rank) - ) - - jobs_index = workers.loc[worker_rank] - if recieved_msg == 1: - jobs.loc[jobs_index, 'Done'] = 'True' - elif recieved_msg == 2: # noqa: PLR2004 - jobs.loc[jobs_index, 'Done'] = 'No need' - elif recieved_msg == 3: # noqa: PLR2004 - jobs.loc[jobs_index, 'Done'] = 'exception' - - jobs.loc[jobs_index, 'time_confirmed'] = time.time() - workers.loc[worker_rank] = -1 - - time_began = time.strftime( - '%Y-%m-%d %H:%M:%S', - time.localtime(jobs.loc[jobs_index, 'time_assigned']), - ) - time_end = time.strftime( - '%Y-%m-%d %H:%M:%S', - time.localtime(jobs.loc[jobs_index, 'time_confirmed']), - ) - time_lapsed = ( - jobs.loc[jobs_index, 'time_confirmed'] - - jobs.loc[jobs_index, 'time_assigned'] - ) - with open( # noqa: PTH123 - 'done.csv', 'a', encoding='utf-8', buffering=1000000 - ) as f: # shows the order of done jobs - f.write( - jobs.loc[jobs_index, 'scenario_name'] - + ',' - + jobs.loc[jobs_index, 'file_name'] - + ',' - + str(jobs.loc[jobs_index, 'worker']) - + ',' - + str(time_lapsed) - + ',' - + str(time_began) - + ',' - + str(time_end) - + '\n' - ) - - binary_vector = jobs['worker'].isna() - not_assigned_data = jobs[binary_vector] - free_workers = workers[workers == -1] - time_constraint = False - - if ( - len(not_assigned_data) > 0 - and len(free_workers) > 0 - and time_constraint == False # noqa: E712 - ): - jobs_index = not_assigned_data.index[0] - worker_rank = free_workers.index[0] - print( # noqa: T201 - 'trying to send ' - + repr(jobs_index) - + ' to ' - + repr(worker_rank), - flush=True, - ) - comm.isend(jobs_index, worker_rank, tag=0) - - workers.loc[worker_rank] = jobs_index - jobs.loc[jobs_index, 'worker'] = worker_rank - jobs.loc[jobs_index, 'time_assigned'] = time.time() - - time_began = time.strftime( - '%Y-%m-%d %H:%M:%S', - time.localtime(jobs.loc[jobs_index, 'time_assigned']), - ) - with open( # noqa: PTH123 - 'runing.csv', 'a', encoding='utf-8', buffering=1000000 - ) as f: - f.write( - jobs.loc[jobs_index, 'scenario_name'] - + ',' - + jobs.loc[jobs_index, 'file_name'] - + ',' - + str(jobs.loc[jobs_index, 'worker']) - + ',' - + str(time_began) - + '\n' - ) - - binary_vector = jobs['Done'] == 'False' - iContinue = binary_vector.any() and (not time_constraint) # noqa: N806 - - # Finish workers with sending them a dummy data with tag=100 (death tag) - for i in range(1, settings.process['number_of_proccessor']): - print('Death msg (tag=100) is sent to all workers. RIP!', flush=True) # noqa: T201 - comm.send('None', dest=i, tag=100) - jobs['time_lapsed'] = jobs['time_confirmed'] - jobs['time_assigned'] - jobs['time_assigned'] = jobs.apply( - lambda x: time.strftime( - '%Y-%m-%d %H:%M:%S', time.localtime(x.loc['time_assigned']) - ), - axis=1, - ) - jobs['time_confirmed'] = jobs.apply( - lambda x: time.strftime( - '%Y-%m-%d %H:%M:%S', time.localtime(x.loc['time_confirmed']) - ), - axis=1, - ) - jobs.to_excel('jobs.xlsx') - print('MAIN NODE FINISHED. Going under!', flush=True) # noqa: T201 - - else: - worker_exit_flag = None - while True: - if comm.iprobe(source=0): - status = MPI.Status() - print( # noqa: T201 - 'trying to receive msg. -> rank= ' + repr(comm.rank), - flush=True, - ) - scenario_index = comm.recv(source=0, status=status) - - if status.Get_tag() != 100: # noqa: PLR2004 - scenario_name = pipe_damage_list.loc[ - scenario_index, 'Scenario Name' - ] - settings.initializeScenarioSettings(scenario_index) - print( # noqa: T201 - 'Rank= ' - + repr(comm.rank) - + ' is assigned to ' - + str(scenario_index) - + ' : ' - + str(scenario_name), - flush=True, - ) - # row = pipe_damage_list[pipe_damage_list['scenario_name']==scenario_name] - row = pipe_damage_list.loc[scenario_index] - file_name = row['Pipe Damage'] - nodal_name = row['Nodal Damage'] - pump_damage = row['Pump Damage'] - tank_damage_name = row['Tank Damage'] - try: - run_flag = self.run_local_single( - file_name, - scenario_name, - settings, - worker_rank=repr(scenario_name) - + '_' - + repr(comm.rank), - nodal_damage_file_name=nodal_name, - pump_damage_file_name=pump_damage, - tank_damage_file_name=tank_damage_name, - ) - print( # noqa: T201 - 'run_flag for worker: ' - + repr(comm.rank) - + ' --> ' - + repr(run_flag) - ) - comm.isend(run_flag, dest=0) - except Exception: # noqa: BLE001 - error_dump_file = None - if type(scenario_name) == str: # noqa: E721 - error_dump_file = 'dump_' + scenario_name + '.pkl' - else: - error_dump_file = ( - 'dump_' + repr(scenario_name) + '.pkl' - ) - - with open(error_dump_file, 'wb') as f: # noqa: PTH123 - pickle.dump(self, f) - - comm.isend(3, dest=0) - last_time_message_recv = time.time() - - else: - worker_exit_flag = 'Death message received!' # oh my God! - break - - if (time.time() - last_time_message_recv) > settings.process[ - 'maximun_worker_idle_time' - ]: - worker_exit_flag = 'Maximum time reached.' - break - print( # noqa: T201 - repr(worker_exit_flag) + " I'm OUT -> Rank= " + repr(comm.rank), - flush=True, - ) - - def checkArgument(self, argv): # noqa: N802, D102 - if len(argv) > 2: # noqa: PLR2004 - print('REWET USAGE is as [./REWET Project.prj: optional]') # noqa: T201 - if len(argv) == 1: # noqa: SIM103 - return False - else: # noqa: RET505 - return True - - -if __name__ == '__main__': - import sys - - start = Starter() - if_project = start.checkArgument(sys.argv) - if if_project: - if os.path.exists(sys.argv[1]): # noqa: PTH110 - tt = start.run(sys.argv[1]) - else: - print('Project file address is not valid: ' + repr(sys.argv[1])) # noqa: T201 - else: - tt = start.run() diff --git a/modules/systemPerformance/REWET/REWET/main.py b/modules/systemPerformance/REWET/REWET/main.py deleted file mode 100644 index 7cb8535cb..000000000 --- a/modules/systemPerformance/REWET/REWET/main.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Created on Wed Jan 10 14:23:09 2024 - -@author: snaeimi - -This is the main final to run REWET. This file supersedes initial.py to run -REWET. In order to keep the backward compatibility, the initial.py is kepy, -so one can run initial.py to run REWET. currently, REWET's GUI still works with -initial.py. Main.py is going to be the most developed tool. - -""" # noqa: D400 - -import argparse -import os -import sys - -from initial import Starter - -if __name__ == '__main__': - argParser = argparse.ArgumentParser( # noqa: N816 - prog='REWET V0.2', - description='REstoration tool for Restoration of Water after Event Tool is a package for modeling damages and restoration in water network. You can specify settings in with providing a JSON. An example JSON file is provided in example folder. Modify the example folder and provide its path as an input. If not provided, the default settings values from the input/settings.py will be ran. thus, you can alternatively modify values in settings for a single run.', - ) - - argParser.add_argument('--json', '-j', default=None, help='json settings file') - - argParser.add_argument( - '--project', '-p', default=None, help='REWET project file' - ) - - parse_namespace = argParser.parse_args() - - starter = Starter() - # No file is pacified, so the default values in settings file is going to - # be ran. - - if parse_namespace.json == None and parse_namespace.project == None: # noqa: E711 - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter(action='ignore', category=FutureWarning) - starter.run() - sys.exit(0) - elif parse_namespace.json != None and parse_namespace.project == None: # noqa: E711 - if parse_namespace.json.split('.')[-1].upper() != 'JSON': - print( # noqa: T201 - 'ERROR in json file name: ', - parse_namespace.json, - 'The json file must have json extention', - ) - sys.exit(0) - elif not os.path.exists(parse_namespace.json): # noqa: PTH110 - print('ERROR in json file: ', parse_namespace.json, 'does not exist') # noqa: T201 - else: - starter.run(parse_namespace.json) - - elif parse_namespace.json == None and parse_namespace.project != None: # noqa: E711 - if parse_namespace.project.split('.')[-1].upper() != 'PRJ': - print( # noqa: T201 - 'ERROR in project file name: ', - parse_namespace.project, - 'The project file must have PRJ extention', - ) - sys.exit(0) - elif not os.path.exists(parse_namespace.project): # noqa: PTH110 - print( # noqa: T201 - 'ERROR in project file: ', parse_namespace.project, 'does not exist' - ) - else: - starter.run(parse_namespace.project) - - else: - print( # noqa: T201 - 'ERROR in arguments\n', - 'Either of the json or project file arguments must be used', - ) - -else: - print( # noqa: T201 - 'Main File has been ran with not being the main module (i.e.,\ - __name__ is not "__main__"' - ) diff --git a/modules/systemPerformance/REWET/REWET/repair.py b/modules/systemPerformance/REWET/REWET/repair.py deleted file mode 100644 index 362de0a94..000000000 --- a/modules/systemPerformance/REWET/REWET/repair.py +++ /dev/null @@ -1,936 +0,0 @@ -"""Created on Tue Feb 2 20:22:09 2021 - -@author: snaeimi -""" # noqa: D400 - -import math -from collections import OrderedDict - -from wntrfr.network.model import LinkStatus - -LINK_TYPE_COLLECTIVES = { - 'BYPASS_PIPE', - 'ADDED_PIPE_A', - 'ADDED_PIPE_B', - 'ADDED_PIPE_C', - 'ADDED_PIPE_D', - 'ADDED_PUMP_A', - 'ADDED_PUMP_B', - 'PIPE_CLOSED_FROM_OPEN', - 'PIPE_CLOSED_FROM_CV', -} -NODE_TYPE_COLLECTIVES = { - 'MIDDLE_NODE_A', - 'MIDDLE_NODE_B', - 'ADDED_RESERVOIR_A', - 'ADDED_RESERVOIR_B', -} -NON_COLLECTIVES = { - 'NODE_DEMAND_AFTER', - 'NODE_DEMAND_BEFORE', - 'NODE_A_DEMAND_BEFORE', - 'NODE_A_DEMAND_AFTER', - 'NODE_B_DEMAND_BEFORE', - 'NODE_B_DEMAND_AFTER', - 'NODE_A', - 'NODE_B', - 'NON_COL_ADDED_PIPE', - 'NON_COL_PIPE_CLOSED_FROM_OPEN', - 'NON_COL_PIPE_CLOSED_FROM_CV', -} -NC_FALSE_FLAG = { - 'NODE_A', - 'NODE_B', - 'NODE_A_DEMAND_BEFORE', - 'NODE_A_DEMAND_AFTER', - 'NODE_B_DEMAND_BEFORE', - 'NODE_B_DEMAND_AFTER', - 'NODE_DEMAND_AFTER', - 'NODE_DEMAND_BEFORE', -} - - -class Repair: # noqa: D101 - def __init__(self, registry): - self._registry = registry - - def closeSecondLeakingPipe(self, damage_node_name, wn): # noqa: N802, D102 - if ( - self._registry.getDamageData('PIPE', False).loc[ # noqa: FBT003 - damage_node_name, 'damage_type' - ] - != 'leak' - ): - raise ValueError('Damage type is not leak in node ' + damage_node_name) - - pipe_A_name, pipe_B_name, orginal_pipe_name = self._registry.getLeakData( # noqa: N806 - damage_node_name - ) - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - pipe_B.status = LinkStatus.Closed - pipe_B.initial_status = LinkStatus.Closed - - def bypassPipe( # noqa: N802, D102 - self, - damage_node_name, - middle_pipe_size, - damage_type, - wn, - length=None, - friction=None, - ): - # if self._registry.getDamageData('PIPE',False).loc[damage_node_name,'damage_type'] != 'leak': - # raise ValueError('Damage type is not leak in node '+damage_node_name) - - if damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = self._registry.getLeakData( # noqa: N806 - damage_node_name - ) - elif damage_type == 'break': - pipe_A_name, pipe_B_name, orginal_pipe_name, node_A_name, node_B_name = ( # noqa: N806 - self._registry.getBreakData(damage_node_name) - ) - org_pipe_data = self._registry.getOriginalPipenodes(orginal_pipe_name) - - orginal_node_A_name = org_pipe_data['start_node_name'] # noqa: N806 - orginal_node_B_name = org_pipe_data['end_node_name'] # noqa: N806 - orginal_pipe_length = org_pipe_data['length'] - orginal_pipe_roughness = org_pipe_data['roughness'] - - if length != None: # noqa: E711 - pipe_length = length - else: - pipe_length = orginal_pipe_length - - if friction != None: # noqa: E711 - pipe_friction = friction - else: - pipe_friction = orginal_pipe_roughness - new_pipe_name = orginal_pipe_name + '-Byp' - if middle_pipe_size > 0: - wn.add_pipe( - new_pipe_name, - orginal_node_A_name, - orginal_node_B_name, - length=pipe_length, - diameter=middle_pipe_size, - roughness=pipe_friction, - ) - - # For the sake of multiple damages in one pipe the following line is marked the the line after it is added - - damage_data = self._registry.getDamageData('pipe', iCopy=False) - redefined_damage_data = damage_data[ - damage_data['Orginal_element'] == orginal_pipe_name - ] - - for cur_damage_node_name, cur_damage in redefined_damage_data.iterrows(): - history = OrderedDict() - if middle_pipe_size > 0: - history['BYPASS_PIPE'] = ( - new_pipe_name # Bypass pipe doesn't get removed unless all damages in the original pipe is removed - ) - - cur_damage_type = cur_damage['damage_type'] - if cur_damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = ( # noqa: N806 - self._registry.getLeakData(cur_damage_node_name) - ) - - pipe_B = wn.get_link(pipe_B_name) # noqa: N806, F841 - - elif cur_damage_type == 'break': - pass - - else: - raise ValueError('Unrecognozed damaged type: ' + cur_damage_type) - - self._registry.addFunctionDataToRestorationRegistry( - cur_damage_node_name, history, 'bypass' - ) - - # local reconnection, for instance, for fire truck reconnection - def reconnectPipe(self, damage_node_name, middle_pipe_size, damage_type, wn): # noqa: N802, D102 - history = OrderedDict() - - if damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = self._registry.getLeakData( # noqa: N806 - damage_node_name - ) - - pipe_A = wn.get_link(pipe_A_name) # noqa: N806 - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - if pipe_A.status == 1: - history['NON_COL_PIPE_CLOSED_FROM_OPEN'] = pipe_A_name - elif pipe_A.status == 3: # noqa: PLR2004 - history['NON_COL_PIPE_CLOSED_FROM_CV'] = pipe_A_name - pipe_A.initial_status = LinkStatus(0) - - if middle_pipe_size == None: # noqa: E711 - middle_pipe_size = pipe_A.diameter - - beg_node_of_pipe_A = pipe_A.start_node # noqa: N806 - end_node_of_pipe_B = pipe_B.end_node # noqa: N806 - new_length = pipe_A.length + pipe_B.length - - # For the sake of multiple damages in one pipe the following line is marked the the line after it is added - new_pipe_name = pipe_B_name + '-Red' - - wn.add_pipe( - new_pipe_name, - beg_node_of_pipe_A.name, - end_node_of_pipe_B.name, - length=new_length, - diameter=middle_pipe_size, - roughness=pipe_A.roughness, - ) - - history['NON_COL_ADDED_PIPE'] = new_pipe_name - - elif damage_type == 'break': - pipe_A_name, pipe_B_name, orginal_pipe_name, node_A_name, node_B_name = ( # noqa: N806 - self._registry.getBreakData(damage_node_name) - ) - - pipe_A = wn.get_link(pipe_A_name) # noqa: N806 - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - if middle_pipe_size == None: # noqa: E711 - middle_pipe_size = pipe_A.diameter - - beg_node_of_pipe_A = pipe_A.start_node # noqa: N806 - end_node_of_pipe_B = pipe_B.end_node # noqa: N806 - new_length = pipe_A.length + pipe_B.length - - # For the sake of multiple damages in one pipe the following line is marked the the line after it is added - new_pipe_name = pipe_B_name + '-Red' - - wn.add_pipe( - new_pipe_name, - beg_node_of_pipe_A.name, - end_node_of_pipe_B.name, - length=new_length, - diameter=middle_pipe_size, - roughness=pipe_A.roughness, - ) - history['NON_COL_ADDED_PIPE'] = new_pipe_name - - else: - raise ValueError('Unrecognozed damaged type: ' + damage_type) - - self._registry.addFunctionDataToRestorationRegistry( - damage_node_name, history, 'reconnect' - ) - - def removeLeak(self, damage_node_name, damage_type, wn, factor=1): # noqa: C901, N802, D102 - history = OrderedDict() - - opening = 1 - factor - - damage_data = self._registry.getDamageData('pipe', iCopy=False) - orginal_pipe_name = damage_data.loc[damage_node_name, 'Orginal_element'] - refined_damage_data = damage_data[ - damage_data['Orginal_element'] == orginal_pipe_name - ] - - damaged_node_name_list_on_orginal_pipe = refined_damage_data.index.to_list() - damage_type_list = refined_damage_data['damage_type'].to_dict() - - for cur_damage_node_name in damaged_node_name_list_on_orginal_pipe: - cur_damage_type = damage_type_list[cur_damage_node_name] - - if cur_damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = ( # noqa: N806 - self._registry.getLeakData(cur_damage_node_name) - ) - - node_A = wn.get_node(cur_damage_node_name) # noqa: N806 - - if pipe_B_name in wn.pipe_name_list: - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - if pipe_B.status == 1: - history['PIPE_CLOSED_FROM_OPEN'] = pipe_B_name - elif pipe_B.status == 3: # noqa: PLR2004 - history['PIPE_CLOSED_FROM_CV'] = pipe_B_name - - pipe_B.initial_status = LinkStatus(0) - history['NODE_A_DEMAND_BEFORE'] = node_A._leak_area # noqa: SLF001 - node_A_leak_area = opening * node_A._leak_area # noqa: SLF001, N806 - node_A.add_leak(wn, node_A_leak_area, discharge_coeff=1) - history['NODE_A_DEMAND_AFTER'] = node_A._leak_area # noqa: SLF001 - - if abs(opening) < 0.001: # noqa: PLR2004 - node_A.remove_leak(wn) - history['NODE_A'] = 'REMOVED' - else: - history['NODE_A'] = 'REDUCED' - - elif cur_damage_type == 'break': - ( - pipe_A_name, # noqa: N806 - pipe_B_name, # noqa: N806 - orginal_pipe_name, - node_A_name, # noqa: N806 - node_B_name, # noqa: N806 - ) = self._registry.getBreakData(cur_damage_node_name) - if cur_damage_node_name != node_A_name: - raise ValueError( - 'Cur damage and pipe_name are not the same: ' - + repr(cur_damage_node_name) - + ' - ' - + repr(node_A_name) - ) - - node_A = wn.get_node(cur_damage_node_name) # noqa: N806 - - history['NODE_A_DEMAND_BEFORE'] = node_A._leak_area # noqa: SLF001 - node_A_leak_area = opening * node_A._leak_area # noqa: SLF001, N806 - node_A.add_leak(wn, node_A_leak_area, discharge_coeff=1) - - history['NODE_A_DEMAND_AFTER'] = node_A._leak_area # noqa: SLF001 - - if abs(opening) < 0.001: # noqa: PLR2004 - node_A.remove_leak(wn) - node_A._leak_area = 0 # noqa: SLF001 - history['NODE_A'] = 'REMOVED' - else: - history['NODE_A'] = 'REDUCED' - node_B = wn.get_node(node_B_name) # noqa: N806 - - history['NODE_B_DEMAND_BEFORE'] = node_B._leak_area # noqa: SLF001 - node_B_leak_area = opening * node_B._leak_area # noqa: SLF001, N806 - node_B.add_leak(wn, node_B_leak_area, discharge_coeff=1) - history['NODE_B_DEMAND_AFTER'] = node_B._leak_area # noqa: SLF001 - - if abs(opening) < 0.001: # noqa: PLR2004 - node_B.remove_leak(wn) - node_B._leak_area = 0 # noqa: SLF001 - history['NODE_B'] = 'REMOVED' - else: - history['NODE_B'] = 'REDUCED' - - else: - raise ValueError('Unknown Damage type:' + repr(damage_type)) - - self._registry.addFunctionDataToRestorationRegistry( - damage_node_name, history, 'removeLeak' - ) - - def addReservoir(self, damage_node_name, damage_type, _type, pump, wn): # noqa: C901, N802, D102 - history = OrderedDict() - - if damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = self._registry.getLeakData( # noqa: N806 - damage_node_name - ) - elif damage_type == 'break': - pipe_A_name, pipe_B_name, orginal_pipe_name, node_A_name, node_B_name = ( # noqa: N806 - self._registry.getBreakData(damage_node_name) - ) - else: - raise ValueError( - 'Unknown damage type in ' + damage_node_name + ', ' + damage_type - ) - - pipe_A = wn.get_link(pipe_A_name) # noqa: N806 - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - first_node_pipe_A = pipe_A.start_node # noqa: N806 - second_node_pipe_B = pipe_B.end_node # noqa: N806 - - _coord_A = ( # noqa: N806 - first_node_pipe_A.coordinates[0] + 10, - first_node_pipe_A.coordinates[1] + 10, - ) - new_reservoir_A = first_node_pipe_A.name + '-added' # noqa: N806 - wn.add_reservoir( - new_reservoir_A, - base_head=first_node_pipe_A.elevation, - coordinates=_coord_A, - ) - - _coord_B = ( # noqa: N806 - second_node_pipe_B.coordinates[0] + 10, - second_node_pipe_B.coordinates[1] + 10, - ) - new_reservoir_B = second_node_pipe_B.name + '-added' # noqa: N806 - wn.add_reservoir( - new_reservoir_B, - base_head=second_node_pipe_B.elevation, - coordinates=_coord_B, - ) - history['ADDED_RESERVOIR_A'] = new_reservoir_A - history['ADDED_RESERVOIR_B'] = new_reservoir_B - - if _type == None: # noqa: E711 - _pipe_size = pipe_A.diameter - new_pipe_name_1 = damage_node_name + '-lK1' - new_pipe_name_2 = damage_node_name + '-lK2' - wn.add_pipe( - new_pipe_name_1, - new_reservoir_A, - first_node_pipe_A.name, - diameter=_pipe_size, - length=5, - check_valve=True, - ) - history['ADDED_PIPE_A'] = ( - new_pipe_name_1 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - wn.add_pipe( - new_pipe_name_2, - new_reservoir_B, - second_node_pipe_B.name, - diameter=_pipe_size, - length=5, - check_valve=True, - ) - history['ADDED_PIPE_B'] = ( - new_pipe_name_2 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - - elif _type == 'PUMP': - if 'POWER' in pump: - _power = pump['POWER'] - new_pump_name_1 = damage_node_name + '-RP1' - new_pump_name_2 = damage_node_name + '-RP2' - wn.add_pump( - new_pump_name_1, - new_reservoir_A, - first_node_pipe_A.name, - pump_parameter=_power, - ) - wn.add_pump( - new_pump_name_2, - new_reservoir_B, - second_node_pipe_B.name, - pump_parameter=_power, - ) - history['ADDED_PUMP_A'] = ( - new_pump_name_1 # ÙŒIt Added Pumps is collective now. Won;t be removed till all damaegs in the pipe is removed - ) - history['ADDED_PUMP_B'] = ( - new_pump_name_2 # ÙŒIt Added Pumps is collective now. Won;t be removed till all damaegs in the pipe is removed - ) - else: - raise ValueError('Invalid Pump Type: ' + repr(pump.keys())) - elif _type == 'ADDEDELEVATION': - _pipe_size = pipe_A.diameter - new_pipe_name_1 = damage_node_name + '-RP1' - new_pipe_name_2 = damage_node_name + '-RP2' - - new_valve_name_1 = damage_node_name + '-RV1' - new_valve_name_2 = damage_node_name + '-RV2' - - new_RP_middle_name1 = damage_node_name + '-mn1' # noqa: N806 - new_RP_middle_name2 = damage_node_name + '-mn2' # noqa: N806 - - coord1 = ( - first_node_pipe_A.coordinates[0] + 5, - first_node_pipe_A.coordinates[1] + 5, - ) - coord2 = ( - second_node_pipe_B.coordinates[0] + 5, - second_node_pipe_B.coordinates[1] + 5, - ) - - elavation1 = first_node_pipe_A.elevation - elavation2 = second_node_pipe_B.elevation - - wn.add_junction( - new_RP_middle_name1, elevation=elavation1, coordinates=coord1 - ) - wn.add_junction( - new_RP_middle_name2, elevation=elavation2, coordinates=coord2 - ) - - wn.add_pipe( - new_pipe_name_1, - new_reservoir_A, - new_RP_middle_name1, - diameter=_pipe_size, - length=1, - roughness=100000000, - minor_loss=7, - check_valve=True, - ) - wn.add_pipe( - new_pipe_name_2, - new_reservoir_B, - new_RP_middle_name2, - diameter=_pipe_size, - length=1, - roughness=100000000, - minor_loss=7, - check_valve=True, - ) - - wn.add_valve( - new_valve_name_1, - new_RP_middle_name1, - first_node_pipe_A.name, - valve_type='FCV', - setting=0.2500, - ) - wn.add_valve( - new_valve_name_2, - new_RP_middle_name2, - second_node_pipe_B.name, - valve_type='FCV', - setting=0.2500, - ) - - res_A = wn.get_node(new_reservoir_A) # noqa: N806 - res_B = wn.get_node(new_reservoir_B) # noqa: N806 - - res_A.base_head = res_A.base_head + 20 - res_B.base_head = res_B.base_head + 20 - - history['MIDDLE_NODE_A'] = ( - new_RP_middle_name1 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - history['MIDDLE_NODE_B'] = ( - new_RP_middle_name2 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - history['ADDED_PIPE_A'] = ( - new_pipe_name_1 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - history['ADDED_PIPE_B'] = ( - new_pipe_name_2 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - history['ADDED_PIPE_C'] = ( - new_valve_name_1 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - history['ADDED_PIPE_D'] = ( - new_valve_name_2 # ÙŒIt Added Pipe is collective now. Won't be removed till all damaegs in the pipe is removed - ) - - else: - raise ValueError('Unknown Reservoir type') # noqa: EM101, TRY003 - - damage_data = self._registry.getDamageData('pipe', iCopy=False) - redefined_damage_data = damage_data[ - damage_data['Orginal_element'] == orginal_pipe_name - ] - - for cur_damage_node_name, cur_damage in redefined_damage_data.iterrows(): - cur_damage_type = cur_damage['damage_type'] - if cur_damage_type == 'leak': - pipe_A_name, pipe_B_name, orginal_pipe_name = ( # noqa: N806 - self._registry.getLeakData(cur_damage_node_name) - ) - - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - if pipe_B.status == 1: - history['PIPE_CLOSED_FROM_OPEN'] = pipe_B_name - elif pipe_B.status == 3: # noqa: PLR2004 - history['PIPE_CLOSED_FROM_CV'] = pipe_B_name - - pipe_B.initial_status = LinkStatus(0) - - elif cur_damage_type == 'break': - pass - else: - raise ValueError('Unrecognozed damaged type: ' + cur_damage_type) - - self._registry.addFunctionDataToRestorationRegistry( - damage_node_name, history, 'addReservoir' - ) - - def removeDemand(self, node_name, factor, wn): # noqa: N802, D102 - history = OrderedDict() - - if factor < 0 or factor > 1: - raise ValueError( - 'In node ' + node_name + ' factor is not valid: ' + repr(factor) - ) - - demand_after_removal_factor = 1 - factor - node = wn.get_node(node_name) - cur_demand = node.demand_timeseries_list[0].base_value - # self._registry.getDamageData('DISTNODE', iCopy=False).loc[node_name,'Demand1'] = cur_demand - history['NODE_DEMAND_BEFORE'] = cur_demand - if abs(cur_demand) < 0: - return ValueError( - 'Node ' + repr(node_name) + ' is has zerovalue: ' + repr(cur_demand) - ) - - new_demand = demand_after_removal_factor * cur_demand - node.demand_timeseries_list[0].base_value = new_demand - history['NODE_DEMAND_AFTER'] = new_demand - - self._registry.addFunctionDataToRestorationRegistry( # noqa: RET503 - node_name, history, 'removeDemand' - ) - - def removeExplicitNodalLeak(self, node_name, factor, wn): # noqa: N802, D102 - history = OrderedDict() - damage_data = self._registry.getEquavalantDamageHistory(node_name) - pipe_name = damage_data['new_pipe_name'] - - current_number_of_damages = damage_data['current_number_of_damage'] - if factor == 1: - pipe = wn.get_link(pipe_name) - pipe.cv = False - pipe.initial_status = LinkStatus(0) - history['EXPLICIT_PIPE_CLOSED_FROM_CV'] = pipe_name - else: - ned = self._registry.nodal_equavalant_diameter - pipe = wn.get_link(pipe_name) - diameter = pipe.diameter - diameter = (factor**0.5) * current_number_of_damages * ned - history['EXPLICIT_PIPE_DIAMETER_CHANAGED'] = diameter - pipe.diameter = diameter - - self._registry.addFunctionDataToRestorationRegistry( - node_name, history, 'removeExplicitLeak' - ) - - def removeNodeTemporaryRepair(self, damage_node_name, wn): # noqa: N802, D102 - if_damage_removed = False - - restoration_table = self._registry._restoration_table # noqa: SLF001 - selected_restoration_table = restoration_table[ - restoration_table['node_name'] == damage_node_name - ] - - for ind, rec_id in selected_restoration_table.record_index.items(): # noqa: B007, PERF102 - change_list = self._registry._record_registry[rec_id] # noqa: SLF001 - - for change, name in ((k, change_list[k]) for k in reversed(change_list)): # noqa: B007 - if change == 'removeExplicitLeak': - pass - - elif change == 'NODE_DEMAND_AFTER' or change == 'NODE_DEMAND_BEFORE': # noqa: PLR1714 - if ( - self._registry.settings['damage_node_model'] - == 'Predefined_demand' - ): - self.repair.reduceDemand() - elif ( - self._registry.settings['damage_node_model'] - == 'equal_diameter_emitter' - ) or ( - self._registry.settings['damage_node_model'] - == 'equal_diameter_reservoir' - ): - self.restoreDistributionOrginalDemand(damage_node_name, wn) - else: - raise ValueError('unknow method') # noqa: EM101, TRY003 - - if if_damage_removed == False: # noqa: E712 - self.removeDISTNodeExplicitLeak(damage_node_name, wn) - - def removePipeRepair(self, damaged_node_name, wn, action): # noqa: C901, N802, D102 - restoration_table = self._registry._restoration_table # noqa: SLF001 - selected_restoration_table = restoration_table[ - restoration_table['node_name'] == damaged_node_name - ] - - for ind, rec_id in selected_restoration_table.record_index.items(): - change_list = self._registry._record_registry[rec_id] # noqa: SLF001 - - to_pop_list = [] - - for change, name in ((k, change_list[k]) for k in reversed(change_list)): - flag = True - if change == 'ADDED_PIPE' or change == 'ADDED_PUMP': # noqa: PLR1714 - wn.remove_link(name) - - i_link_collective = False - i_node_collective = False - if change in LINK_TYPE_COLLECTIVES: - i_link_collective = True - if change in NODE_TYPE_COLLECTIVES: - i_node_collective = True - - if i_link_collective or i_node_collective: - damage_data = self._registry.getDamageData('pipe', iCopy=False) - orginal_pipe_name = damage_data.loc[ - damaged_node_name, 'Orginal_element' - ] - refined_damage_data = damage_data[ - (damage_data['Orginal_element'] == orginal_pipe_name) - & (damage_data['discovered'] == True) # noqa: E712 - ] - if (refined_damage_data[action] == True).all(): # noqa: E712 - if i_link_collective: - if ( - change == 'BYPASS_PIPE' # noqa: PLR1714 - or change == 'ADDED_PIPE_A' - or ( - change == 'ADDED_PIPE_B' # noqa: PLR1714 - or change == 'ADDED_PIPE_C' - ) - or ( - change == 'ADDED_PIPE_D' # noqa: PLR1714 - or change == 'ADDED_PUMP_A' - or change == 'ADDED_PUMP_B' - ) - ): - wn.remove_link(name) - elif change == 'PIPE_CLOSED_FROM_OPEN': - if name in wn.pipe_name_list: - wn.get_link(name).initial_status = LinkStatus(1) - elif change == 'PIPE_CLOSED_FROM_CV': - if name in wn.pipe_name_list: - wn.get_link(name).initial_status = LinkStatus(3) - else: - raise ValueError( - 'Unknown change indicator in restoration registry: ' - + repr(change) - ) - - elif i_node_collective: - wn.remove_node(name) - else: - raise ValueError( - 'Unknown change indicator in restoration registry: ' - + repr(change) - ) - - elif change in NON_COLLECTIVES: - if change == 'NON_COL_ADDED_PIPE': - wn.remove_link(name) - elif change == 'NON_COL_PIPE_CLOSED_FROM_OPEN': - wn.get_link(name).initial_status = LinkStatus(1) - elif change in NC_FALSE_FLAG: - flag = False - else: - raise ValueError( - 'Unknown change indicator in restoration registry: ' - + repr(change) - ) - - else: - raise ValueError( - 'Unknown change indicator in restoration registry: ' - + repr(change) - ) - - if flag: - to_pop_list.append(change) - - for pop_key in to_pop_list: - change_list.pop(pop_key) - - if len(change_list) == 0: - restoration_table.drop(ind, inplace=True) # noqa: PD002 - - def repairPipe(self, damage_node_name, damage_type, wn): # noqa: N802, D102 - if damage_type == 'leak': - pipe_A_name, pipe_B_name = self._registry.getCertainLeakData( # noqa: N806 - damage_node_name, wn - ) - - pipe_A = wn.get_link(pipe_A_name) # noqa: N806 - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - end_node_of_pipe_B = pipe_B.end_node # noqa: N806 - new_length = pipe_A.length + pipe_B.length - - pipe_A.length = new_length - pipe_A.end_node = end_node_of_pipe_B - - wn.remove_link(pipe_B_name) - wn.remove_node(damage_node_name, with_control=True) - - elif damage_type == 'break': - pipe_A_name, pipe_B_name, node_A_name, node_B_name = ( # noqa: N806 - self._registry.getCertainBreakData(damage_node_name, wn) - ) - - pipe_A = wn.get_link(pipe_A_name) # noqa: N806 - pipe_B = wn.get_link(pipe_B_name) # noqa: N806 - - end_node_of_pipe_B = pipe_B.end_node # noqa: N806 - new_length = pipe_A.length + pipe_B.length - - pipe_A.length = new_length - pipe_A.end_node = end_node_of_pipe_B - - wn.remove_link(pipe_B_name) - wn.remove_node(node_A_name, with_control=True) - wn.remove_node(node_B_name, with_control=True) - - def restorePumps(self, pump_name_list, wn): # noqa: N802, D102 - for pump_name in pump_name_list: - wn.get_link(pump_name).initial_status = LinkStatus(1) - - def restoreTanks(self, tank_name_list, wn): # noqa: N802, D102 - for tank_name in tank_name_list: - made_up_mid_node_name = tank_name + '_tank_mid' - made_up_pipe_name = tank_name + '_tank_mid_pipe' - - wn.remove_link(made_up_pipe_name) - - link_name_list_connected_to_node = wn.get_links_for_node( - made_up_mid_node_name - ) - - tank_node = wn.get_node(tank_name) - for link_name in link_name_list_connected_to_node: - link = wn.get_link(link_name) - if made_up_mid_node_name == link.start_node.name: - link.start_node = tank_node - elif made_up_mid_node_name == link.end_node.name: - link.end_node = tank_node - - wn.remove_node(made_up_mid_node_name, with_control=True) - - def removeDISTNodeIsolation(self, damaged_node_name, wn): # noqa: N802, D102 - post_incident_node_demand = self._registry.getDamageData('DISTNODE').loc[ - damaged_node_name, 'Demand2' - ] - - node = wn.get_node(damaged_node_name) - node.demand_timeseries_list[0].base_value = post_incident_node_demand - - def restoreDistributionOrginalDemand(self, damaged_node_name, wn): # noqa: N802, D102 - if self._registry.settings['damage_node_model'] == 'Predefined_demand': - pre_incident_node_demand = self._registry.getDamageData( - 'DISTNODE', iCopy=False - ).loc[damaged_node_name, 'Demand1'] - elif ( - self._registry.settings['damage_node_model'] == 'equal_diameter_emitter' - or self._registry.settings['damage_node_model'] - == 'equal_diameter_reservoir' - ): - damage_table = self._registry.getDamageData('DISTNODE', iCopy=False) - virtual_nodes_damage_tabel = damage_table[ - damage_table['virtual_of'] == damaged_node_name - ] - pre_incident_node_demand = virtual_nodes_damage_tabel.iloc[0]['Demand1'] - else: - raise ValueError('unknow method') # noqa: EM101, TRY003 - - node = wn.get_node(damaged_node_name) - node.demand_timeseries_list[0].base_value = pre_incident_node_demand - - def removeDISTNodeExplicitLeak(self, damaged_node_name, wn): # noqa: N802, D102 - temp = self._registry.active_nodal_damages - value_key = {v: k for k, v in temp.items()} - _key = value_key[damaged_node_name] - self._registry.active_nodal_damages.pop(_key) - - temp = self._registry.getEquavalantDamageHistory(damaged_node_name) - pipe_name = temp['new_pipe_name'] - reservoir_name = temp['new_node_name'] - wn.remove_link(pipe_name) - wn.remove_node(reservoir_name, with_control=True) - if reservoir_name in wn.node_name_list: - raise # noqa: PLE0704 - - self._registry.removeEquavalantDamageHistory(damaged_node_name) - - def modifyDISTNodeDemandLinearMode( # noqa: N802, D102 - self, - damage_node_name, - real_node_name, - wn, - repaired_number, - total_number, - ): - damage_table = self._registry.getDamageData('DISTNODE', iCopy=False) - pre_incident_demand = damage_table.loc[damage_node_name, 'Demand1'] - post_incident_demand = damage_table.loc[damage_node_name, 'Demand2'] - delta = ( - (total_number - repaired_number) - / total_number - * (post_incident_demand - pre_incident_demand) - ) - new_demand = pre_incident_demand + delta - node = wn.get_node(real_node_name) - node.demand_timeseries_list[0].base_value = new_demand - - def modifyDISTNodeExplicitLeakEmitter( # noqa: N802, D102 - self, - damage_node_name, - real_node_name, - wn, - repaired_number, - total_number, - ): - nodal_data = self._registry._nodal_data[real_node_name] # noqa: SLF001 - pipe_length = nodal_data['pipe_length'] - mean_pressure = nodal_data['mean_pressure'] - new_node_name = nodal_data['new_node_name'] - orginal_flow = nodal_data['orginal_flow'] - number_of_damages = total_number - repaired_number - cd, mp0 = self._registry.damage.getEmitterCdAndElevation( - real_node_name, - wn, - number_of_damages, - pipe_length, - mean_pressure, - orginal_flow, - ) - node = wn.get_node(new_node_name) - - # print(real_node_name) - if cd >= node._emitter_coefficient: # noqa: SLF001 - raise ValueError( - 'something wrong here: ' - + repr(cd) - + ' - ' - + repr(node._emitter_coefficient) # noqa: SLF001 - + ' ' - + str(damage_node_name) - + ' ' - + str(real_node_name) - ) - - node._emitter_coefficient = cd # noqa: SLF001 - - def modifyDISTNodeExplicitLeakReservoir( # noqa: N802, D102 - self, - damage_node_name, # noqa: ARG002 - real_node_name, - wn, - repaired_number, - total_number, - ): - nodal_data = self._registry._nodal_data[real_node_name] # noqa: SLF001 - pipe_length = nodal_data['pipe_length'] - mean_pressure = nodal_data['mean_pressure'] - pipe_name = nodal_data['new_pipe_name'] - orginal_flow = nodal_data['orginal_flow'] - number_of_damages = total_number - repaired_number - cd, mp0 = self._registry.damage.getEmitterCdAndElevation( - real_node_name, - wn, - number_of_damages, - pipe_length, - mean_pressure, - orginal_flow, - ) - node = wn.get_node(real_node_name) # noqa: F841 - - q = orginal_flow - nd = self._registry.damage.getNd( - mean_pressure, number_of_damages, total_number - ) - equavalant_pipe_diameter = ( # noqa: F841 - ((nd - 1) * q) ** 2 / (0.125 * 9.81 * math.pi**2 * mean_pressure) - ) ** (1 / 4) * 1 - pipe = wn.get_link(pipe_name) - # if equavalant_pipe_diameter >= pipe.diameter: - # raise ValueError("something wrong here: "+repr(equavalant_pipe_diameter)+" - "+repr(pipe.diameter)) - pipe.diameter = pipe.diameter / 2 - - def modifyDISTNodeExplicitLeak( # noqa: N802, D102 - self, - real_damage_node_name, # noqa: ARG002 - virtual_node_name, - wn, - method, - damaged_number, # noqa: ARG002 - ): - if method == 'equal_diameter': - emitter_name = self._registry.virtual_node_data[virtual_node_name][ - 'emitter_node' - ] - node = wn.get_node(emitter_name) # noqa: F841 diff --git a/modules/systemPerformance/REWET/REWET/restoration/CMakeLists.txt b/modules/systemPerformance/REWET/REWET/restoration/CMakeLists.txt deleted file mode 100644 index 393b93cee..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ - -simcenter_add_python_script(SCRIPT base.py) -simcenter_add_python_script(SCRIPT io.py) -simcenter_add_python_script(SCRIPT model.py) -simcenter_add_python_script(SCRIPT registry.py) -simcenter_add_python_script(SCRIPT restorationlog.py) diff --git a/modules/systemPerformance/REWET/REWET/restoration/base.py b/modules/systemPerformance/REWET/REWET/restoration/base.py deleted file mode 100644 index c9cac8ac6..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/base.py +++ /dev/null @@ -1,1764 +0,0 @@ -"""Created on Fri Dec 25 04:00:43 2020 - -@author: snaeimi -""" # noqa: INP001, D400 - -import copy -import logging -import random - -import networkx as nx -import numpy as np -import pandas as pd - -logger = logging.getLogger(__name__) - - -def get_node_name(node_name, table): # noqa: D103 - if 'virtual_of' in table.columns: - real_node_name = table.loc[node_name, 'virtual_of'] - if ( - real_node_name == None or real_node_name == np.nan # noqa: E711, PLR1714 - ): # SINA: probably NP.NAN does not work here. Correct it. - real_node_name = node_name - return real_node_name - else: # noqa: RET505 - return node_name - - -class Coordination: # noqa: D101 - def __init__(self, X=None, Y=None, system=None): # noqa: N803 - self.x = X - self.y = Y - self.system = system - - def set_coord(self, X, Y, system=None): # noqa: ARG002, N803, D102 - self.x = X - self.y = Y - - def get_coord(self): # noqa: D102 - return (self.x, self.y) - - def set_system(self, system): # noqa: D102 - self.system = system - - -class Location: # noqa: D101 - def __init__(self, name, x, y): - self.name = name - self.coord = Coordination(x, y) - - -# ============================================================================= -# class restoration_base(): -# def __init__(self): -# self.coord = coordination() -# self.ID = None -# self.Object_typ = None -# -# ============================================================================= - - -class AgentData: # noqa: D101 - def __init__( - self, - agent_name, - agent_type, - cur_x, - cur_y, - shift_name, - base_name, - base_x, - base_y, - shift_obj, - agent_speed, - ): - if type(agent_type) != str: # noqa: E721 - raise ValueError('agent type must be string') # noqa: EM101, TRY003 - # if type(definition) != pd.Series: - # raise ValueError('definiton must be a Pandas series') - - if type(cur_x) != float: # noqa: E721 - raise ValueError('cur_x must be float') # noqa: EM101, TRY003 - if type(cur_y) != float: # noqa: E721 - raise ValueError('cur_y must be float') # noqa: EM101, TRY003 - if type(base_x) != float: # noqa: E721 - raise ValueError('base_x must be float') # noqa: EM101, TRY003 - if type(base_y) != float: # noqa: E721 - raise ValueError('base_y must be float') # noqa: EM101, TRY003 - - self.name = agent_name - self.agent_type = agent_type - self.current_location = Location('current', cur_x, cur_y) - self.base_location = Location(base_name, base_x, base_y) - self.shift = AgentShift(self.name, shift_name) - self._shifting = shift_obj - self._avg_speed = agent_speed # 20*3/3.6 - self.isWorking = False - self.cur_job_location = None - self.cur_job_action = None - self.cur_job_entity = None - self._time_of_arival = None - self._time_of_job_done = None - self.cur_job_ongoing = None - self.cur_job_effect_definition_name = None - self.cur_job_method_name = None - - def isOnShift(self, time): # noqa: N802 - """Checks if a time is on an agent's shift - - Parameters - ---------- - time : int - time. - - Returns - ------- - bool - Is true if the time is on the agent's shift. - - """ # noqa: D400, D401 - shift_name = self.shift._shift_name # noqa: SLF001 - (time_start, time_finish) = self._shifting.getShiftTimes(shift_name) - - if type(time) != int and type(time) != float: # noqa: E721 - raise ValueError('time must be integer ' + type(time)) - - time = int(time) - time = time % (24 * 3600) - - if time_start > time_finish: - new_time_finish = time_finish + 24 * 3600 - time_finish = new_time_finish - if time < time_start: - time = time + 24 * 3600 - - if time >= time_start and time < time_finish: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - - def getDistanceFromCoordinate(self, destination_coordination): # noqa: N802, D102 - coord = self.current_location.coord.get_coord() - cur_x = coord[0] - cur_y = coord[1] - - dest_x = destination_coordination[0] - dest_y = destination_coordination[1] - - distance = ((cur_x - dest_x) ** 2 + (cur_y - dest_y) ** 2) ** 0.5 - return distance # noqa: RET504 - - def _estimateTimeOfArival(self, destination_coordination): # noqa: N802 - distance_with_method_of_choice = self.getDistanceFromCoordinate( - destination_coordination - ) - time = distance_with_method_of_choice / self._avg_speed - - return time # noqa: RET504 - - def getAgentShiftEndTime(self, cur_time): # noqa: N802, D102 - num_of_days = int(cur_time / (24 * 3600)) - - shift_name = self.shift._shift_name # noqa: SLF001 - (time_start, time_finish) = self._shifting.getShiftTimes(shift_name) - - if time_start < time_finish or cur_time % (24 * 3600) <= time_finish: - return time_finish + 24 * 3600 * num_of_days - else: # noqa: RET505 - return time_finish + 24 * 3600 * (num_of_days + 1) - - def getShiftLength(self): # noqa: N802, D102 - shift_name = self.shift._shift_name # noqa: SLF001 - (time_start, time_finish) = self._shifting.getShiftTimes(shift_name) - - if time_start < time_finish: - return time_finish - time_start - else: # noqa: RET505 - return 24 * 3600 - time_start + time_finish - - def setJob( # noqa: N802, D102 - self, - node_name, - action, - entity, - effect_definition_name, - method_name, - time_arival, - time_done, - iOnGoing, # noqa: N803 - ): - if self.isWorking == True: # noqa: E712 - raise ValueError('The current agent is working') # noqa: EM101, TRY003 - - self.isWorking = True - self.cur_job_location = node_name - self.cur_job_action = action - self.cur_job_entity = entity - self.cur_job_effect_definition_name = effect_definition_name - self.cur_job_method_name = method_name - self.cur_job_ongoing = iOnGoing - self._time_of_arival = time_arival - self.job_end_time = time_done - - -class Agents: # noqa: D101 - def __init__(self, registry, shifting, jobs, restoration_log_book): - # data: is the - # type: agent type - # sybtype: agent sub type - # active: active is true if it is the shift - # ready: read is true if the agent's active and it has nthing to do - self._agents = pd.DataFrame( - columns=['data', 'type', 'group', 'active', 'ready', 'available'] - ) # table that includes all data about agents including attributes for fast refinement, the index is the name of the agent (AKA agent_ID) - self.group_names = {} - self._shifting = shifting - self._jobs = jobs - self.restoration_log_book = restoration_log_book - self.registry = registry - - def addAgent(self, agent_name, agent_type, definition): # noqa: N802 - """Adds agent to the agent list - - Parameters - ---------- - agent_type : str - Given type name - definition : TYPE - DESCRIPTION. - - Returns - ------- - None. - - """ # noqa: D400, D401, DOC202, RUF100 - # number_of_agents = int(definition['Number']) - agent_speed = self.registry.settings['crew_travel_speed'] - temp_agent_data = AgentData( - agent_name, - agent_type, - float(definition['cur_x']), - float(definition['cur_y']), - definition['shift_name'], - definition['group'], - float(definition['base_x']), - float(definition['base_y']), - self._shifting, - agent_speed, - ) - self._agents.loc[agent_name] = [ - temp_agent_data, - agent_type, - definition['group'], - False, - False, - False, - ] - if agent_type not in self.group_names: - self.group_names[agent_type] = definition['group_name'] - - def setActiveAgents(self, active_agent_ID_list): # noqa: N802, N803 - """Set agents active by a list of agents' ID - - Parameters - ---------- - active_agent_ID_list : list - agents ID name - - Returns - ------- - None. - - """ # noqa: D400, DOC202, RUF100 - for active_agent_ID in active_agent_ID_list: # noqa: N806 - self._agents['active'].loc[active_agent_ID] = True - - def getAgentGroupTagList(self, typed_ready_agent): # noqa: N802, D102 - ret = [None] - agent_type = typed_ready_agent['type'].iloc[0] - if 'group' in typed_ready_agent: - ret = typed_ready_agent['group'].unique().tolist() - number_of_groups = len(ret) - if number_of_groups == 0: - raise RuntimeError( - 'There zero group for agent type: ' + repr(agent_type) - ) - if None in ret: - raise RuntimeError('None in agent type: ' + repr(agent_type)) - return ret, self.group_names[agent_type] - - def getAllAgentTypes(self): # noqa: N802, D102 - return self._agents['type'].unique().tolist() - - def getAllAgent(self): # noqa: N802 - """Get a copy of all agent dataframe. - - Returns - ------- - A copy of all agent dataFrame - - """ - return self._agents.copy(deep=True) - - def setChangeShift(self, time, working_check=True): # noqa: FBT002, ARG002, N802, D102 - for name, agent in self._agents.iterrows(): # noqa: B007 - if self._agents.loc[name, 'data'].isOnShift(time): - if ( - self._agents.loc[name, 'active'] == False # noqa: E712 - ): # if agent is active already and is on shift, it means that the agent has been active before the shift change event - if self._agents.loc[name, 'available'] == True: # noqa: E712 - self._agents.loc[name, 'active'] = True - self._agents.loc[name, 'ready'] = True - - else: - if ( - self._agents.loc[name, 'ready'] == True # noqa: E712 - and self._agents.loc[name, 'data'].isWorking == True # noqa: E712 - ): - raise RuntimeError(name + ' is working') - self._agents.loc[name, 'active'] = False - self._agents.loc[name, 'ready'] = False - - def initializeActiveAgents(self, time): # noqa: N802, D102 - for name, agent in self._agents.iterrows(): # noqa: B007 - if self._agents.loc[name, 'data'].isOnShift(time): - self._agents.loc[name, 'active'] = True - else: - self._agents.loc[name, 'active'] = False - - def initializeReadyAgents(self): # noqa: N802, D102 - for name, agent in self._agents.iterrows(): # noqa: B007 - if self._agents.loc[name, 'active'] == True: # noqa: E712 - self._agents.loc[name, 'ready'] = True - else: - self._agents.loc[name, 'ready'] = False - - def getReadyAgents(self): # noqa: N802, D102 - temp = self._agents[ - (self._agents['ready'] == True) & (self._agents['available'] == True) # noqa: E712 - ] - check_temp = temp['active'].all() - if check_temp == False: # noqa: E712 - print(temp[temp['active'] == False]) # noqa: T201, E712 - raise ValueError('At least one agent is ready although is not on shift') # noqa: EM101, TRY003 - - return temp - - def getAvailabilityRatio(self, agent_type, time): # noqa: N802, D102 - if agent_type == 'WQOperator' or agent_type == 'WQWorker': # noqa: PLR1714 - av_data = pd.Series(data=[0, 0.5, 1], index=[0, 4, 24]) - elif agent_type == 'CONT': - av_data = pd.Series(data=[0, 0, 1], index=[0, 48, 49]) - else: - av_data = pd.Series(data=[1, 0.5, 1], index=[0, 4, 48]) - temp = av_data - time = time / 3600 - if time in temp: - return temp[time] - if time > temp.index.max(): - return temp[temp.index.max()] - else: # noqa: RET505 - temp[time] = np.nan - temp.sort_index(inplace=True) # noqa: PD002 - temp.interpolate(method='index', inplace=True) # noqa: PD002 - return temp[time] - - def getDefaultAvailabilityRatio(agent_type, self): # noqa: ARG002, N802, N805, D102 - if agent_type == 'WQOperator' or agent_type == 'WQWorker': # noqa: PLR1714 - return 0 - else: # noqa: RET505 - return 1 - - def assignsJobToAgent( # noqa: C901, N802, D102 - self, - agent_name, - node_name, - entity, - action, - time, - wn, - reminded_time, - number_of_damages, - orginal_element, - ): - if self._agents.loc[agent_name, 'active'] != True: # noqa: E712 - raise ValueError('Agent ' + agent_name + ' is not active') - if self._agents.loc[agent_name, 'ready'] != True: # noqa: E712 - raise ValueError('Agent ' + agent_name + ' is not ready') - - if self._agents.loc[agent_name, 'data'].isOnShift(time) != True: # noqa: E712 - raise ValueError('Agent ' + agent_name + ' is not on shift') - - if self._agents.loc[agent_name, 'data'].isWorking == True: # noqa: E712 - raise ValueError('Agent ' + agent_name + ' is working') - - # logger.debug('Assiging job to '+agent_name) - real_node_name = node_name - if self._jobs._rm.entity[entity] == 'DISTNODE': # noqa: SLF001 - damage_data = self._jobs._rm._registry.getDamageData( # noqa: SLF001 - 'DISTNODE', iCopy=False - ) - if 'virtual_of' in damage_data.columns: - real_node_name = get_node_name(node_name, damage_data) - - coord = wn.get_node(real_node_name).coordinates - agent_type = self._agents.loc[agent_name, 'type'] - - _ETA = self._agents.loc[agent_name, 'data']._estimateTimeOfArival(coord) # noqa: SLF001, N806 - effect_definition_name = self._jobs.getEffectDefinitionName( - agent_type, action, entity - ) - method_name = self._jobs.chooseMethodForCurrentJob( - node_name, effect_definition_name, entity - ) - - if method_name == None: # noqa: E711 - raise ValueError( - 'No method is applicale for ' + repr(effect_definition_name) - ) - - if reminded_time == None: # noqa: E711 - _ETJ = self._jobs.getAJobEstimate( # noqa: N806 - orginal_element, - agent_type, - entity, - action, - method_name, - number_of_damages, - ) - else: - _ETJ = int(reminded_time) # noqa: N806 - if reminded_time < 0: - raise ValueError('Something wrong here: ' + repr(reminded_time)) - - if effect_definition_name != 'CHECK': - method_line = self._jobs._effect_data[effect_definition_name][ # noqa: SLF001 - method_name - ] - else: - method_line = [{'EFFECT': 'CHECK'}] - - effects_only = [i['EFFECT'] for i in method_line] - - collective = None - if 'SKIP' in effects_only: - return (False, 'SKIP', None, collective) - elif 'FASTCHECK' in effects_only: # noqa: RET505 - return (False, 'FASTCHECK', None, collective) - elif 'RECONNECT' in effects_only: - collective = 'BYPASS' - elif 'ADD_RESERVOIR' in effects_only: - collective = 'ADD_RESERVOIR' - elif 'REMOVE_LEAK' in effects_only: - collective = 'REMOVE_LEAK' - elif 'ISOLATE_DN' in effects_only: - collective = 'ISOLATE_DN' - - if _ETA < 0 or _ETJ <= 0: - print( # noqa: T201 - str(_ETA) - + ' ' - + str(effect_definition_name) - + ' ' - + str(orginal_element) - ) - print(str(method_name) + ' ' + str(_ETJ)) # noqa: T201 - raise ValueError('Subzero ETA or sub-equal-zero ETJ') # noqa: EM101, TRY003 - - end_time = time + _ETA + _ETJ - agent_shift_change_time = self._agents.loc[ - agent_name, 'data' - ].getAgentShiftEndTime(time) - shift_length = self._agents.loc[agent_name, 'data'].getShiftLength() - - minimum_job_time = self._jobs._rm._registry.settings['minimum_job_time'] # noqa: SLF001, F841 - if end_time <= agent_shift_change_time: - iget = 'INSIDE_SHIFT' - iOnGoing = False # noqa: N806 - elif ( - end_time > agent_shift_change_time - and (shift_length - 2 * 3600) < _ETJ - and (time + _ETA + 2 * 3600) < agent_shift_change_time - ): - iget = 'OUTSIDE_SHIFT' - iOnGoing = True # noqa: N806 - else: - # logger.warning(agent_name+', '+node_name+', '+repr(end_time)) - iget = 'ShortOfTime' - - if iget == 'ShortOfTime': - return (False, iget, None, collective) - self._agents.loc[agent_name, 'data'].current_location.coord.set_coord( - coord[0], coord[1] - ) - self._agents.loc[agent_name, 'data'].setJob( - node_name, - action, - entity, - effect_definition_name, - method_name, - time + _ETA, - time + _ETA + _ETJ, - iOnGoing, - ) - self._agents.loc[agent_name, 'ready'] = False - self.restoration_log_book.addAgentActionToLogBook( - agent_name, - node_name, - entity, - action, - time, - end_time, - _ETA, - effect_definition_name, - method_name, - iFinished=not iOnGoing, - ) - - return (True, iget, _ETJ, collective) - - def getJobEndTime(self, agent_name, icheck=True): # noqa: FBT002, N802, D102 - end_time = self._agents.loc[agent_name, 'data'].job_end_time - if icheck == True and end_time == None: # noqa: E711, E712 - raise ValueError('No Time is assigned to agent') # noqa: EM101, TRY003 - if ( - icheck == True # noqa: E712 - and self._agents.loc[agent_name, 'data'].isWorking == False # noqa: E712 - ): - raise ValueError('The agent is not working') # noqa: EM101, TRY003 - return end_time - - def getJobArivalTime(self, agent_name, icheck=True): # noqa: FBT002, N802, D102 - arival_time = self._agents.loc[agent_name, 'data']._time_of_arival # noqa: SLF001 - if icheck == True and arival_time == None: # noqa: E711, E712 - raise ValueError('No Time is assigned to agent') # noqa: EM101, TRY003 - if ( - icheck == True # noqa: E712 - and self._agents.loc[agent_name, 'data'].isWorking == False # noqa: E712 - ): - raise ValueError('The agent is not working') # noqa: EM101, TRY003 - return arival_time - - def releaseAgent(self, agent_name): # noqa: N802, D102 - if self._agents.loc[agent_name, 'ready'] == True: # noqa: E712 - raise ValueError(agent_name + ' is already ready') - if self._agents.loc[agent_name, 'active'] != True: # noqa: E712 - raise ValueError(agent_name + ' is not active') - if self._agents.loc[agent_name, 'data'].isWorking == False: # noqa: E712 - raise ValueError(agent_name + ' is not working') - - self._agents.loc[agent_name, 'ready'] = True - - self._agents.loc[agent_name, 'data'].isWorking = False - self._agents.loc[agent_name, 'data'].cur_job_location = None - self._agents.loc[agent_name, 'data'].cur_job_action = None - self._agents.loc[agent_name, 'data'].cur_job_entity = None - self._agents.loc[agent_name, 'data']._time_of_arival = None # noqa: SLF001 - self._agents.loc[agent_name, 'data'].cur_job_effect_definition_name = None - self._agents.loc[agent_name, 'data'].cur_job_method_name = None - self._agents.loc[agent_name, 'data'].job_end_time = None - self._agents.loc[agent_name, 'data'].cur_job_ongoing = None - - -class AgentShift: # noqa: D101 - # , shifting_obj): - def __init__(self, agent_name, name): - self._agent_name = agent_name - self._shift_name = name - # shifting_obj.addAgentShift(self._agent_name, self._shift_name) - - -class Shifting: # noqa: D101 - def __init__(self): - self._all_agent_shift_data = {} - self._shift_data = pd.DataFrame(columns=['begining', 'end']) - - def addShift(self, name, beginning, ending): # noqa: N802 - """Adds a shift to shift registry - - Parameters - ---------- - name : str - Shift's name. - beginning : int - shift's beginning time. - ending : int - shifts ending time. - - Raises - ------ - ValueError - if shift name is already in the registry, - if the name is not string, - if the beginning time is not int, - if the ending time is not int, - if beginning time is bigger than 24*3600, - if ending time is bigger than 24*3600. - - Returns - ------- - None. - - """ # noqa: D400, D401, DOC202, RUF100 - if name in self._shift_data: - raise ValueError('Shift name already registered') # noqa: EM101, TRY003 - if type(beginning) != int and type(beginning) != float: # noqa: E721 - raise ValueError( - 'Beginning time must be integer: ' + str(type(beginning)) - ) - if type(ending) != int and type(ending) != float: # noqa: E721 - raise ValueError('Ending time must be integer: ' + str(type(ending))) - if beginning > 24 * 3600: - raise ValueError( - 'beginning time is bigger than 24*3600' + str(beginning) - ) - if ending > 24 * 3600: - raise ValueError('Ending time is bigger than 24*3600' + str(ending)) - beginning = int(beginning) - ending = int(ending) - - self._shift_data.loc[name] = [beginning, ending] - - def getShiftTimes(self, name): # noqa: N802, D102 - return ( - self._shift_data['begining'].loc[name], - self._shift_data['end'].loc[name], - ) - - def getNextShiftTime(self, time): # noqa: N802, D102 - daily_time = time % (24 * 3600) - num_of_days = int(time / (24 * 3600)) - - next_shift_candidate = pd.Series() - - for shift_name, shift_data in self._shift_data.iterrows(): - beg_time = shift_data[0] - end_time = shift_data[1] - - if beg_time > end_time and daily_time < end_time: - beg_time -= 24 * 3600 - elif beg_time > end_time and daily_time >= end_time: - # beg_time += 24*3600*num_of_days - end_time += 24 * 3600 - - if daily_time < end_time and daily_time >= beg_time: - next_shift_candidate.loc[shift_name] = ( - end_time + 24 * 3600 * num_of_days - ) - change_shift_time = next_shift_candidate.min() - # if beg_time > end_time: - # next_shift_time = time +(change_shift_time - daily_time) - # else: - - return change_shift_time # noqa: RET504 - - def assignShiftToAgent(self, agent_ID, shift_name): # noqa: N802, N803 - """Assigns shift to agent - - Parameters - ---------- - agent_ID : str - Agent's ID. - shift_name : str - Shift's name - - Raises - ------ - ValueError - if agent_ID is already in agent's shift data(probably already assigned, - if shift name does not exist in shift registry. - - Returns - ------- - None. - - """ # noqa: D400, D401, DOC202, RUF100 - if agent_ID in self._all_agent_shift_data: - raise ValueError('The agent ID currently in Agent ALl Shifts') # noqa: EM101, TRY003 - if shift_name not in self._shift_data: - raise ValueError('shift data is not in registered as shifts') # noqa: EM101, TRY003 - - self._all_agent_shift_data[agent_ID] = shift_name - - -class DispatchRule: # noqa: D101 - def __init__(self, settings, method='deterministic', exclude=None): - self.settings = settings - self._rules = {} - self._cumulative = {} - - if 'PIPE' not in exclude: - self._rules['PIPE'] = self.settings['pipe_damage_discovery_model'][ - 'time_discovery_ratio' - ] - # data2=pd.Series([0.90, 0.01, 0.01, 0.04, 0.04, 0, 0], index = [3600*n for n in [0, 12, 24, 36, 48, 60, 72]]) - - if 'DISTNODE' not in exclude: - self._rules['DISTNODE'] = self.settings['node_damage_discovery_model'][ - 'time_discovery_ratio' - ] - # data=pd.Series([0, 0.67, 0.07, 0.07, 0.07, 0.07, 0.05], index = [3600*n for n in [0, 12, 24, 36, 48, 60, 72]]) - - self._rules['GNODE'] = self.settings['Gnode_damage_discovery_model'][ - 'time_discovery_ratio' - ] - self._rules['TANK'] = self.settings['tank_damage_discovery_model'][ - 'time_discovery_ratio' - ] - self._rules['PUMP'] = self.settings['pump_damage_discovery_model'][ - 'time_discovery_ratio' - ] - self._rules['RESERVOIR'] = self.settings['reservoir_damage_discovery_model'][ - 'time_discovery_ratio' - ] - - if method == 'deterministic': - pass - else: - raise ValueError('Unknown dispatch Rule: ' + method) - - # for key in exclude: - # self._rules.pop(key) - - for key, d in self._rules.items(): # noqa: B007, PERF102 - self._cumulative[key] = self._rules[key].cumsum() - - def getDiscoveredPrecentage(self, time): # noqa: N802, D102 - res = {} - for key in self._cumulative: - temp = self._cumulative[key].copy() - if time in temp.index: - res[key] = temp[time] - elif time < temp.index.min(): - res[key] = temp[temp.index.min()] - elif time > temp.index.max(): - res[key] = temp[temp.index.max()] - else: - temp[time] = np.nan - temp.sort_index(inplace=True) # noqa: PD002 - temp.interpolate(method='index', inplace=True) # noqa: PD002 - res[key] = temp[time] - return res - - -class Dispatch: # noqa: D101 - def __init__(self, restoration, settings, discovery_interval=0, method='old'): - self.settings = settings - self.method = method - self.discovery_interval = discovery_interval - self._rm = restoration - self._discovered_entity = {} - self._init_time = self._rm.restoration_start_time - - exclude = [] - - if settings['pipe_damage_discovery_model']['method'] == 'leak_based': - exclude.append('PIPE') - elif settings['pipe_damage_discovery_model']['method'] == 'time_based': - pass - else: - raise ValueError( - 'Unknown pipe damage discovery method in settings: ' - + repr(settings['pipe_damage_discovery_model']['method']) - ) - - if settings['node_damage_discovery_model']['method'] == 'leak_based': - exclude.append('DISTNODE') - elif settings['node_damage_discovery_model']['method'] == 'time_based': - pass - else: - raise ValueError( - 'Unknown Node damage discovery method in settings: ' - + repr(settings['node_damage_discovery_model']['method']) - ) - - self._rules = DispatchRule(settings, exclude=exclude) - self._last_discovered_number = {} - for el in self._rm.ELEMENTS: - if el in exclude: - continue - self._last_discovered_number[el] = 0 - - self._rm._registry.addAttrToPipeDamageTable('discovered', False) # noqa: FBT003, SLF001 - self._rm._registry.addAttrToDistNodeDamageTable('discovered', False) # noqa: FBT003, SLF001 - - def updateDiscovery(self, time): # noqa: C901, N802, D102 - if time < self._rm.restoration_start_time: - print('Time is less than init time') # noqa: T201 - - else: - # if self.method == 'old': - # time_since_dispatch_activity = time - self._rm.restoration_start_time - # discovered_ratios = self._rules.getDiscoveredPrecentage(time_since_dispatch_activity) - # discovered_damage_numbers = self._getDamageNumbers(discovered_ratios) - # self._updateDamagesNumbers(discovered_damage_numbers) - - if ( - self.settings['pipe_damage_discovery_model']['method'] - == 'leak_based' - ): - pipe_leak_criteria = self.settings['pipe_damage_discovery_model'][ - 'leak_amount' - ] - pipe_leak_time_span = self.settings['pipe_damage_discovery_model'][ - 'leak_time' - ] - - pipe_damage_table = self._rm._registry._pipe_damage_table # noqa: SLF001 - not_discovered_pipe_damage_table = pipe_damage_table[ - pipe_damage_table['discovered'] == False # noqa: E712 - ] - to_be_checked_node_list = list( - not_discovered_pipe_damage_table.index - ) - breaks_not_discovered_pipe_damage_table = pipe_damage_table[ - (pipe_damage_table['discovered'] == False) # noqa: E712 - & (pipe_damage_table['damage_type'] == 'break') - ] - not_discovered_break_node_B = ( # noqa: N806 - self._rm._registry._pipe_break_history.loc[ # noqa: SLF001 - breaks_not_discovered_pipe_damage_table.index, 'Node_B' - ] - ) - not_dicovered_node_B_list = not_discovered_break_node_B.to_list() # noqa: N806 - to_be_checked_node_list.extend(not_dicovered_node_B_list) - # break_pair = zip(breaks_not_discovered_pipe_damage_table, not_discovered_break_node_B) - # not_discovered_pipe_damage_name_list = list(not_discovered_pipe_damage_table.index) - # breaks_not_discovered_pipe_damage_table - # all_nodes_name_list = set(self._rm._registry.result.columns) - available_nodes = set( - self._rm._registry.result.node['demand'].columns # noqa: SLF001 - ) - to_be_checked_node_list = set(to_be_checked_node_list) - shared_nodes_name_list = ( - to_be_checked_node_list.union(available_nodes) - - (available_nodes - to_be_checked_node_list) - - (to_be_checked_node_list - available_nodes) - ) - if len(shared_nodes_name_list) > 0: - leaking_nodes_result = self._rm._registry.result.node['demand'][ # noqa: SLF001 - list(shared_nodes_name_list) - ] - - leaking_nodes_result = leaking_nodes_result.loc[ - (leaking_nodes_result.index > (time - pipe_leak_time_span)) - ] - discovered_bool = leaking_nodes_result >= pipe_leak_criteria - discovered_bool_temp = discovered_bool.any() - discovered_bool_temp = discovered_bool_temp[ - discovered_bool_temp == True # noqa: E712 - ] - to_be_discoverd = discovered_bool_temp.index.to_list() - - # time1 = leaking_nodes_result.index[1:] - # time2 = leaking_nodes_result.index[0:-1] - # time_dif = (pd.Series(time1) - pd.Series(time2)) - # leaking_nodes_result = leaking_nodes_result.drop(leaking_nodes_result.index[-1]) - - # leaking_nodes_result.index = time_dif.to_numpy() - # leaking_nodes_result = leaking_nodes_result.apply(lambda x: x.values * x.index) - # summed_water_loss = leaking_nodes_result.sum() - # to_be_discoverd = summed_water_loss[summed_water_loss > 3600*2*0.2] - discovery_list = set() - # to_be_discoverd = list(to_be_discoverd.index) - for discovery_candidate in to_be_discoverd: - if discovery_candidate in not_dicovered_node_B_list: - candidate_break_A = not_discovered_break_node_B[ # noqa: N806 - not_discovered_break_node_B == discovery_candidate - ].index[0] - discovery_list.add(candidate_break_A) - else: - discovery_list.add(discovery_candidate) - # discovery_list = list(discovery_list) - pipe_damage_table.loc[discovery_list, 'discovered'] = True - - if ( - self.settings['node_damage_discovery_model']['method'] - == 'leak_based' - ): - node_leak_criteria = self.settings['node_damage_discovery_model'][ - 'leak_amount' - ] - node_leak_time_span = self.settings['node_damage_discovery_model'][ - 'leak_time' - ] - - nodal_damage_table = self._rm._registry._node_damage_table # noqa: SLF001 - not_discovered_nodal_damage_table = nodal_damage_table[ - nodal_damage_table['discovered'] == False # noqa: E712 - ] - if 'virtual_of' in not_discovered_nodal_damage_table.columns: - to_be_checked_node_list = list( - not_discovered_nodal_damage_table['virtual_of'] - ) - else: - to_be_checked_node_list = list( - not_discovered_nodal_damage_table.index - ) - available_leak_nodes = set( - self._rm._registry.result.node['leak'].columns # noqa: SLF001 - ) - to_be_checked_node_list = set(to_be_checked_node_list) - shared_nodes_name_list = ( - to_be_checked_node_list.union(available_leak_nodes) - - (available_leak_nodes - to_be_checked_node_list) - - (to_be_checked_node_list - available_leak_nodes) - ) - if len(shared_nodes_name_list) > 0: - shared_nodes_name_list = list(shared_nodes_name_list) - leaking_nodes_result = self._rm._registry.result.node['leak'][ # noqa: SLF001 - shared_nodes_name_list - ] - leaking_nodes_result = leaking_nodes_result.sort_index() - - if 'virtual_of' in not_discovered_nodal_damage_table.columns: - leaking_number_of_damages = ( - not_discovered_nodal_damage_table.groupby('virtual_of')[ - 'Number_of_damages' - ].sum() - ) - else: - leaking_number_of_damages = ( - not_discovered_nodal_damage_table.loc[ - shared_nodes_name_list, 'Number_of_damages' - ] - ) - - leaking_nodes_result = leaking_nodes_result.loc[ - (leaking_nodes_result.index > (time - node_leak_time_span)) - ] - normalized_summed_water_loss = ( - leaking_nodes_result / leaking_number_of_damages - ) - discovered_bool = ( - normalized_summed_water_loss >= node_leak_criteria - ) - discovered_bool_temp = discovered_bool.any() - discovered_bool_temp = discovered_bool_temp[ - discovered_bool_temp == True # noqa: E712 - ] - discovered_list = discovered_bool_temp.index.to_list() - if 'virtual_of' in not_discovered_nodal_damage_table.columns: - discovered_list = ( - nodal_damage_table[ - nodal_damage_table['virtual_of'].isin( - discovered_list - ) - ] - ).index - - nodal_damage_table.loc[discovered_list, 'discovered'] = True - # else: - - time_since_dispatch_activity = time - self._rm.restoration_start_time - discovered_ratios = self._rules.getDiscoveredPrecentage( - time_since_dispatch_activity - ) - discovered_damage_numbers = self._getDamageNumbers(discovered_ratios) - self._updateDamagesNumbers(discovered_damage_numbers) - - # else: - # raise ValueError('Unknown method: '+repr(self.method)) - - def _getDamageNumbers(self, discovered_ratios): # noqa: N802 - num_damaged_entity = {} - - for el in discovered_ratios: - if discovered_ratios[el] - 1 > 0: - if discovered_ratios[el] - 1.000001 > 0: - raise ValueError( - 'ratio is bigger than 1: ' - + str(discovered_ratios[el]) - + ' in element = ' - + el - ) - else: # noqa: RET506 - discovered_ratios[el] = 1 - temp = len(self._rm._registry.getDamageData(el)) # noqa: SLF001 - num_damaged_entity[el] = int(np.round(temp * discovered_ratios[el])) - return num_damaged_entity - - def _updateDamagesNumbers(self, discovered_numbers): # noqa: N802 - for el in discovered_numbers: - if self._last_discovered_number[el] > discovered_numbers[el]: - raise ValueError( - 'Discovered number is less than what it used to be in element ' - + el - ) - elif self._last_discovered_number[el] < discovered_numbers[el]: # noqa: RET506 - refined_damaged_table = self._rm._registry.getDamageData(el) # noqa: SLF001 - if len(refined_damaged_table) < discovered_numbers[el]: - raise ValueError( - 'discovered number is bigger than all damages in element' - + el - ) - - discovered_damage_table = refined_damaged_table[ - refined_damaged_table['discovered'] == True # noqa: E712 - ] - if discovered_numbers[el] <= len(discovered_damage_table): - continue - undiscovered_damage_table = refined_damaged_table[ - refined_damaged_table['discovered'] == False # noqa: E712 - ] - - # ============================================================================= - # used_number = [] - # i = 0 - # while i < (discovered_numbers[el] - self._last_discovered_number[el]): - # picked_number = random.randint(0,len(undiscovered_damage_table)-1) - # if picked_number not in used_number: - # used_number.append(picked_number) - # i += 1 - # else: - # pass - # ============================================================================= - if len(undiscovered_damage_table) > 0: - used_number = random.sample( - range(len(undiscovered_damage_table)), - discovered_numbers[el] - len(discovered_damage_table), - ) - else: - used_number = [] - for i in used_number: - temp_index = undiscovered_damage_table.index[i] - self._rm._registry.updateElementDamageTable( # noqa: SLF001 - el, - 'discovered', - temp_index, - True, # noqa: FBT003 - icheck=True, - ) - - if el == 'PIPE': - refined_damaged_table = self._rm._registry.getDamageData(el) # noqa: SLF001 - discovered_damage_table = refined_damaged_table[ - refined_damaged_table['discovered'] == True # noqa: E712 - ] - self._last_discovered_number[el] = discovered_numbers[el] - - -class Priority: # noqa: D101 - def __init__(self, restoration): - self._data = {} - self._rm = restoration - - def addData(self, agent_type, priority, order): # noqa: N802, D102 - if agent_type not in self._data: - self._data[agent_type] = pd.Series(index=[priority], data=[order]) - else: - temp = self._data[agent_type] - if priority in temp.index: - raise ValueError( - 'Prority redefined. type: ' - + agent_type - + ' & priority: ' - + str(priority) - ) - self._data[agent_type].loc[priority] = order - - def getPriority(self, agent_type, priority): # noqa: N802, D102 - if agent_type not in self._data: - raise ValueError( - 'The agent type(' - + repr(agent_type) - + ') is not defined in the prioity:' - + repr(priority) - ) - - temp = self._data[agent_type] - - if priority not in temp.index: - raise ValueError( - 'prioirty not in priority data. Agent_type: ' - + agent_type - + ' & PriorityL ' - + priority - ) - - return temp.loc[priority] - - def getHydSigDamageGroups(self): # noqa: N802, D102 - damage_group_list = set() - for crew_type in self._data: - whole_priority_list = self._data[crew_type] - primary_priority_list = whole_priority_list.loc[1] - secondary_priority_list = whole_priority_list.loc[2] - i = 0 - for cur_second_priority in secondary_priority_list: - if cur_second_priority.upper() == 'HYDSIG': - cur_damage_group = primary_priority_list[i][1] - damage_group_list.add(cur_damage_group) - i += 1 # noqa: SIM113 - return damage_group_list - - def sortDamageTable( # noqa: C901, N802, D102 - self, - wn, - entity_data, - entity, - agent_type, - target_priority_index, - order_index, - target_priority=None, - ): - all_priority_data = self._data[agent_type] - target_priority_list = all_priority_data.loc[target_priority_index] - - if len(target_priority_list) == 0: - return entity_data - - name_sugest = 'Priority_' + str(target_priority_index) + '_dist' - - if target_priority == None: # noqa: E711 - target_priority = target_priority_list[order_index] - - if target_priority == None: # noqa: E711 - return entity_data - - elif target_priority in self._rm.proximity_points: # noqa: RET505 - Proximity_list = self._rm.proximity_points[target_priority] # noqa: N806 - node_name_list = list(entity_data.index) - for node_name in node_name_list: - # Sina: you can enhance the run time speed with having x, y coordinates in the damage table and not producing and dropping them each time - node_name_vir = get_node_name(node_name, entity_data) - coord = wn.get_node(node_name_vir).coordinates - entity_data.loc[node_name, 'X_COORD'] = coord[0] - entity_data.loc[node_name, 'Y_COORD'] = coord[1] - counter = 1 - columns_to_drop = [] - for x, y in Proximity_list: - name_sug_c = name_sugest + '_' + str(counter) - columns_to_drop.append(name_sug_c) - entity_data[name_sug_c] = ( - (entity_data['X_COORD'] - x) ** 2 - + (entity_data['Y_COORD'] - y) ** 2 - ) ** 0.5 - counter += 1 - dist_only_entity_table = entity_data[columns_to_drop] - min_dist_entity_table = dist_only_entity_table.min(axis=1) - entity_data.loc[:, name_sugest] = min_dist_entity_table - entity_data.sort_values(by=name_sugest, ascending=True, inplace=True) # noqa: PD002 - columns_to_drop.append(name_sugest) - columns_to_drop.append('X_COORD') - columns_to_drop.append('Y_COORD') - entity_data.drop(columns=columns_to_drop, inplace=True) # noqa: PD002 - - # Sina: It does nothing. When there are less damage location within - # the priority definition for the crew type, this works fine, but - # when there are more damage location within the priority definition, - # it does not guarantee that only the closet damage locations to the - # crew-type agents are matched to jobs - elif target_priority.upper() == 'CLOSEST': - pass - elif target_priority.upper() == 'HYDSIGLASTFLOW': - element_type = self._rm.entity[entity] - if element_type != 'PIPE': - entity_data = self.sortDamageTable( - entity_data, - entity, - agent_type, - target_priority_index, - order_index, - target_priority='CLOSEST', - ) - else: - all_time_index = self._rm._registry.result.link[ # noqa: SLF001 - 'flowrate' - ].index[: self._rm.restoration_start_time + 1] - pipe_name_list = entity_data.loc[:, 'Orginal_element'] - last_valid_time = [ - cur_time - for cur_time in all_time_index - if cur_time not in self._rm._registry.result.maximum_trial_time # noqa: SLF001 - ] - last_valid_time.sort() - if len(last_valid_time) == 0: - last_valid_time = self._rm.restoration_start_time - else: - last_valid_time = last_valid_time[-1] - - name_sugest = 'Priority_' + str(target_priority_index) + '_dist' - flow_rate = ( - self._rm._registry.result.link['flowrate'] # noqa: SLF001 - .loc[last_valid_time, pipe_name_list] - .abs() - ) - entity_data.loc[:, name_sugest] = flow_rate.to_list() - entity_data.sort_values(name_sugest, ascending=False, inplace=True) # noqa: PD002 - entity_data.drop(columns=name_sugest, inplace=True) # noqa: PD002 - - elif ( - target_priority in self._rm.proximity_points - and target_priority != 'WaterSource2' - ): - all_node_table = self._rm._registry.all_node_table # noqa: SLF001 - Proximity_list = self._rm.proximity_points[target_priority] # noqa: N806 - node_name_list = list(entity_data.index) - for node_name in node_name_list: - # Sina: you can enhance the run time speed with having x, y coordinates in the damage table and not producing and dropping them each time - node_name_vir = get_node_name(node_name, entity_data) - coord = wn.get_node(node_name_vir).coordinates - entity_data.loc[node_name, 'X_COORD'] = coord[0] - entity_data.loc[node_name, 'Y_COORD'] = coord[1] - counter = 1 - columns_to_drop = [] - - g = nx.MultiDiGraph() - - for name, node in wn.nodes(): - g.add_node(name) - nx.set_node_attributes( - g, name='pos', values={name: node.coordinates} - ) - nx.set_node_attributes(g, name='type', values={name: node.node_type}) - - for name, link in wn.links(): - start_node = link.start_node_name - end_node = link.end_node_name - g.add_edge(start_node, end_node, key=name) - nx.set_edge_attributes( - g, - name='type', - values={(start_node, end_node, name): link.link_type}, - ) - - try: - length = link.length - d = link.diameter - roughness = link.roughness - cost = ( - length / np.power(d, 4.8655) / np.power(roughness, 1.852) - + 1 / d - ) - except: # noqa: E722 - cost = 0.00001 - - weight = cost - - nx.set_edge_attributes( - g, name='weight', values={(start_node, end_node, name): weight} - ) - - g = g.to_undirected() - - for x, y in Proximity_list: - point_length_vector = np.square( - all_node_table['X_COORD'] - x - ) + np.square(all_node_table['Y_COORD'] - y) - point_length_vector = np.sqrt(point_length_vector) - closest_node_name = point_length_vector.idxmin() - - # print("closest_node_name= "+str(closest_node_name)) - - orginal_pipe_name_list = entity_data['Orginal_element'] - damaged_pipe_node_list = [ - self._rm._registry.undamaged_link_node_list[link_node_names] # noqa: SLF001 - for link_node_names in orginal_pipe_name_list - ] - try: - shortest_path_length = [ - min( - nx.shortest_path_length( - g, closest_node_name, pipe_nodes_name[0], 'weight' - ), - nx.shortest_path_length( - g, closest_node_name, pipe_nodes_name[1], 'weight' - ), - ) - for pipe_nodes_name in damaged_pipe_node_list - ] - except nx.NetworkXNoPath: - shortest_path_length = [] - for pipe_nodes_name in damaged_pipe_node_list: - start_node_name = pipe_nodes_name[0] - end_node_name = pipe_nodes_name[1] - - try: - closest_path_from_start = nx.shortest_path_length( - g, closest_node_name, start_node_name, 'weight' - ) - except nx.NetworkXNoPath: - closest_path_from_start = 10000000000000.0 - - try: - closest_path_from_end = nx.shortest_path_length( - g, closest_node_name, end_node_name, 'weight' - ) - except nx.NetworkXNoPath: - closest_path_from_end = 10000000000000.0 - - cur_shortest_path_length = min( - closest_path_from_start, closest_path_from_end - ) - shortest_path_length.append(cur_shortest_path_length) - # print(shortest_path_length) - - name_sug_c = name_sugest + '_' + str(counter) - columns_to_drop.append(name_sug_c) - entity_data[name_sug_c] = shortest_path_length - counter += 1 - dist_only_entity_table = entity_data[columns_to_drop] - min_dist_entity_table = dist_only_entity_table.min(axis=1) - entity_data.loc[:, name_sugest] = min_dist_entity_table - entity_data.sort_values(by=name_sugest, ascending=True, inplace=True) # noqa: PD002 - columns_to_drop.append(name_sugest) - columns_to_drop.append('X_COORD') - columns_to_drop.append('Y_COORD') - entity_data.drop(columns=columns_to_drop, inplace=True) # noqa: PD002 - # print(entity_data) - # print("+++++++++++++++++++++++++++++++++++++++") - - # Sina: It does nothing. When there are less damage location within - # the priority definition for the crew type, this works fine, but - # when there are more damage location within the priority definition, - # it does not guarantee that only the closet damage locations to the - # crew-type agents are matched to jobs - - elif target_priority.upper() == 'HYDSIG': - element_type = self._rm.entity[entity] - if element_type != 'PIPE': - entity_data = self.sortDamageTable( - entity_data, - entity, - agent_type, - target_priority_index, - order_index, - target_priority='CLOSEST', - ) - else: - name_sugest = 'Priority_' + str(target_priority_index) + '_dist' - hyd_sig = self._rm._registry.hydraulic_significance[ # noqa: SLF001 - entity_data['Orginal_element'] - ] - - entity_data.loc[:, name_sugest] = hyd_sig.to_list() - entity_data.sort_values(name_sugest, ascending=False, inplace=True) # noqa: PD002 - entity_data.drop(columns=name_sugest, inplace=True) # noqa: PD002 - - # If element type is not leakable, it does nothing. IF nodes are not - # Checked (i.e. check is not at the sequence before the current action) - # the leak data is real time leak for the damage location. - elif target_priority.upper() == 'MOSTLEAKATCHECK': - # real_node_name_list = [] - node_name_list = list(entity_data.index) - name_sugest = ( - 'Priority_' + str(target_priority_index) + '_leak_sina' - ) # added Sina so the possibility of a conflict of name is minimized - # for node_name in node_name_list: - # node_name_vir = get_node_name(node_name, entity_data) - # real_node_name_list.append(node_name_vir) - element_type = self._rm.entity[entity] - leak_data = self._rm._registry.getMostLeakAtCheck( # noqa: SLF001 - node_name_list, element_type - ) - if leak_data is not None: - entity_data.loc[node_name_list, name_sugest] = leak_data - entity_data.sort_values(by=name_sugest, ascending=True, inplace=True) # noqa: PD002 - entity_data.drop(columns=[name_sugest], inplace=True) # noqa: PD002 - else: - entity_data = self.sortDamageTable( - entity_data, - entity, - agent_type, - target_priority_index, - order_index, - target_priority='CLOSEST', - ) - else: - raise ValueError( - 'Unrcognized Secondary Primary: ' + repr(target_priority) - ) - - return entity_data - - def isAgentTypeInPriorityData(self, agent_type): # noqa: N802, D102 - return agent_type in self._data - - -class Jobs: # noqa: D101 - def __init__(self, restoration): - self._rm = restoration - self._job_list = pd.DataFrame( - columns=['agent_type', 'entity', 'action', 'time_argument'] - ) - self._effect_defualts = {} # pd.DataFrame(columns=['effect_definition_name', 'method_name','argument','value']) - self._effect_data = {} - self._time_overwrite = {} - self._final_method = {} - self._once = {} - - def addEffect(self, effect_name, method_name, def_data): # noqa: N802, D102 - if effect_name not in self._effect_data: - self._effect_data[effect_name] = None - - if self._effect_data[effect_name] != None: # noqa: E711 - if method_name in self._effect_data[effect_name]: - raise ValueError( - 'Dupplicate method_name is given. Effect name: ' - + str(effect_name) - + ', ' - + str(method_name) - ) - - if self._effect_data[effect_name] == None: # noqa: E711 - temp = {} - temp[method_name] = def_data - self._effect_data[effect_name] = temp - else: - self._effect_data[effect_name][method_name] = def_data - - def setJob(self, jobs_definition): # noqa: N802, D102 - self._job_list = pd.DataFrame.from_records(jobs_definition) - - def _filter(self, agent_type, entity, action): - temp = self._job_list - temp = temp[ - ( - temp[['agent_type', 'entity', 'action']] - == [agent_type, entity, action] - ).all(1) - ] - temp_length = len(temp) - if temp_length > 1: - raise ValueError('We have more than one job description') # noqa: EM101, TRY003 - elif temp_length == 0: # noqa: RET506 - raise ValueError( - 'We have Zero one job description for agent type= ' - + repr(agent_type) - + ', entity= ' - + repr(entity) - + ', action= ' - + repr(action) - ) - return temp - - def getAJobEstimate( # noqa: N802, D102 - self, - orginal_element, - agent_type, - entity, - action, - method_name, - number, - ): - temp = self._filter(agent_type, entity, action) - time_arg = temp['time_argument'].iloc[0] - operation_name = temp['effect'].iloc[0] - overwrite_key = (operation_name, method_name, orginal_element) - if overwrite_key in self._time_overwrite: - overwrite_data = self._time_overwrite[overwrite_key] - if 'FIXED_TIME_OVERWRITE' in overwrite_data: - time_arg = overwrite_data['FIXED_TIME_OVERWRITE'] - else: - raise ValueError('Unknown Time Data') # noqa: EM101, TRY003 - time = int(time_arg) - # try: - # time_arg = int(time_arg): - # time = time_arg - # except: - # raise ValueError('Unknow time argument: '+str(type(time_arg))) - - once_flag = False - if operation_name in self._once: - if method_name in self._once[operation_name]: - once_flag = True - - if once_flag == False: # noqa: E712 - time = int(time * number) - - # IMPORTANT/sina - if (method_name == 2 or method_name == 1) and action == 'reroute': # noqa: PLR1714, PLR2004 - pass - - return time - - def getMeanJobTime(self, agent_type, entity, action): # noqa: N802, D102 - temp = self._filter(agent_type, entity, action) - time_arg = temp['time_argument'].iloc[0] - if type(time_arg) == int: # noqa: E721 - time = time_arg - else: - raise ValueError('Unknow time argument: ' + str(type(time_arg))) - return time - - def getAllEffectByJobData( # noqa: N802, D102 - self, - agent_type, - action, - entity, - iWithout_data=True, # noqa: FBT002, ARG002, N803 - iOnlyData=False, # noqa: FBT002, N803 - ): - temp = self._filter(agent_type, entity, action) - all_effect_name = temp['effect'].iloc[0] # noqa: F841 - - if iOnlyData == True: # noqa: E712 - return - - def addEffectDefaultValue(self, input_dict): # noqa: N802, D102 - _key = ( - input_dict['effect_definition_name'], - input_dict['method_name'], - input_dict['argument'], - ) - - if _key in self._effect_defualts: - raise ValueError( - 'Duplicate effects definition: {0}, {1}, {2}'.format( # noqa: EM103, UP030 - repr(input_dict['effect_definition_name']), - repr(input_dict['method_name']), - repr(input_dict['argument']), - ) - ) - - self._effect_defualts[_key] = input_dict[ - 'value' - ] # self._effect_defualts.append(temp_s, ignore_index=True) - - def getEffectsList(self, effect_definition_name, method_name): # noqa: N802, D102 - if effect_definition_name == None: # noqa: E711 - return [] - - if effect_definition_name == 'CHECK': - return [{'EFFECT': 'CHECK'}] - all_methods = self._effect_data[effect_definition_name] - effects_list = all_methods[method_name] - return effects_list # noqa: RET504 - - def getEffectDefinition(self, effect_definition_name, iWithout_data=True): # noqa: FBT002, N802, N803, D102 - all_methods = self._effect_data[effect_definition_name] - - if iWithout_data == True and 'DATA' in all_methods: # noqa: E712 - all_methods = copy.deepcopy(all_methods) - all_methods.pop('DATA') - - return all_methods - - def getEffectDefinitionName(self, agent_type, action, entity): # noqa: N802, D102 - temp = self._filter(agent_type, entity, action) - effects_definition_name = temp['effect'].iloc[0] - return effects_definition_name # noqa: RET504 - - def chooseMethodForCurrentJob(self, node_name, effects_definition_name, entity): # noqa: N802, D102 - returned_method = None - if effects_definition_name == None: # noqa: E711 - return None - elif ( # noqa: RET505 - effects_definition_name == 'CHECK' # noqa: PLR1714 - or effects_definition_name == 'FASTCHECK' - or effects_definition_name == 'SKIP' - ): - return effects_definition_name - else: - effects_definition = self.getEffectDefinition( - effects_definition_name - ) # self._effect_data[effects_definition_name] - for method_name, effect_list in effects_definition.items(): # noqa: B007, PERF102 - prob_applicability = self.iEffectApplicableByProbability( - effects_definition_name, method_name, node_name, entity - ) - condition_applicability = self.iEffectApplicableByOtherConditions( - effects_definition_name, method_name, node_name, entity - ) - if prob_applicability and condition_applicability: - returned_method = method_name - break - - if returned_method == None: # noqa: E711 - try: # noqa: SIM105 - returned_method = self._final_method[effects_definition_name] - except: # noqa: S110, E722 - pass - return returned_method - - def _getProbability(self, method, iCondition, element_type): # noqa: ARG002, N802, N803 - if iCondition == True: # noqa: E712 - if 'METHOD_PROBABILITY' in method: # noqa: SIM401 - probability = method['METHOD_PROBABILITY'] - else: - probability = 1 # noqa: F841 - # else: - # if 'METHOD_PROBABILITY' in method: - - def _iConditionHolds(self, val1, con, val2): # noqa: C901, N802 - if con == 'BG': - if val1 > val2: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - elif con == 'BG-EQ': - if val1 >= val2: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - elif con == 'LT': - if val1 < val2: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - elif con == 'LT-IF': - if val1 <= val2: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - elif con == 'EQ': - if val1 == val2: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - else: - raise ValueError('Unrecognized condition: ' + repr(con)) - - def getDefualtValue(self, effects_definition_name, method_name, argument): # noqa: N802, D102 - _default = self._effect_defualts - value = _default.get((effects_definition_name, method_name, argument), None) - - return value # noqa: RET504 - - def iEffectApplicableByOtherConditions( # noqa: N802, D102 - self, - effects_definition_name, - method_name, - damaged_node_name, - entity, - ): - element_type = self._rm.entity[entity] - effects_definition = self.getEffectDefinition(effects_definition_name) - if element_type == 'DISTNODE': - for single_effect in effects_definition[method_name]: - if 'PIDR' in single_effect: - condition = single_effect['PIDR'] - _con = condition[0] - _con_val = condition[1] - _PIDR_type = self.getDefualtValue( # noqa: N806 - effects_definition_name, method_name, 'PIDR_TYPE' - ) - if _PIDR_type == None or _PIDR_type == 'ASSIGNED_DEMAND': # noqa: E711, PLR1714 - old_demand = self._rm._registry._node_damage_table.loc[ # noqa: SLF001 - damaged_node_name, 'Demand1' - ] - new_demand = self._rm._registry._node_damage_table.loc[ # noqa: SLF001 - damaged_node_name, 'Demand2' - ] - else: - raise ValueError('unrecognized Setting: ' + _PIDR_type) - - _PIDR = new_demand / old_demand # noqa: N806 - - iHold = self._iConditionHolds(_PIDR, _con, _con_val) # noqa: N806 - - return iHold # noqa: RET504 - - return True - - def iEffectApplicableByProbability( # noqa: N802, D102 - self, - effects_definition_name, - method_name, - damaged_node_name, - entity, - ): - _prob = 0 - temp = self.getDefualtValue( - effects_definition_name, method_name, 'METHOD_PROBABILITY' - ) - if temp != None: # noqa: E711 - _prob = temp - try: - self._check_probability(_prob) - except Exception as e: # noqa: BLE001 - print( # noqa: T201 - 'in Method bsaed Probability of method ' - + str(method_name) - + ', and definition_name ' - + str(effects_definition_name) - + ', :' - + str(_prob) - ) - raise ValueError(e) # noqa: B904 - - # ============================================================================= - # if 'DEFAULT' in self._effect_data[effects_definition_name]: - # data = self._effect_data[effects_definition_name]['DEFAULT'] - # if 'METHOD_PROBABILITY' in data: - # if method_name in data['METHOD_PROBABILITY']: - # _prob=data['METHOD_PROBABILITY'][method_name] - # try: - # _check_probability(_prob) - # except Exception as e: - # print('in Method bsaed Probability of method ' +method_name+ ', and definition_name '+effects_definition_name) - # raise ValueError(e) - # ============================================================================= - - if 'DATA' in self._effect_data[effects_definition_name]: - data = self._effect_data[effects_definition_name]['DATA'] - if 'METHOD_PROBABILITY' in data.columns: - element_name = self._rm._registry.getOrginalElement( # noqa: SLF001 - damaged_node_name, self._rm.entity[entity] - ) - - # temp =data[(data[['ELEMENT_NAME','METHOD_NAME']]==[element_name, method_name]).all(1)] - element_data = data[data['ELEMENT_NAME'] == element_name] - if len(element_data) == 0: - pass - else: - element_method_data = element_data[ - element_data['METHOD_NAME'] == method_name - ] - if len(element_method_data) == 0: - _prob = 0 - elif len(element_method_data) == 1: - _prob = element_method_data['METHOD_PROBABILITY'].iloc[0] - else: - raise ValueError( - 'Number of probability found for element ' - + element_name - + ', : ' - + str(len(temp)) - ) - try: - self._check_probability(_prob) - except Exception as e: # noqa: BLE001 - print( # noqa: T201 - 'in LIST of method ' - + method_name - + ', and definition_name ' - + effects_definition_name - ) - raise ValueError(e) # noqa: B904 - - _rand = random.random() - # if effects_definition_name == 'MJTRreroute': - # print(str(method_name) + ' - ' + repr(_prob)) - logger.debug(_prob) - if _rand < _prob: # noqa: SIM103 - return True - return False - - def _check_probability(self, _prob): - mes = None # noqa: F841 - _prob = float(_prob) - if _prob < 0: - raise ValueError('probability cannot be less than 0.') # noqa: EM101, TRY003 - elif _prob > 1: # noqa: RET506 - res = False # noqa: F841 - raise ValueError('probability cannot be more than 1.') # noqa: EM101, TRY003 - - -# ============================================================================= -# class Effects(): -# def __init__(self, restoration_model): -# #self._data_table = pd.DataFrame(columns=['effect', 'method_name', 'data_index']) -# -# -# -# -# -# #self._data_table.loc[effect_name, 'method'] = method -# #self._data_table.loc[effect_name, 'effect'] = effect -# #self._data_table.loc[effect_name, 'connection'] = connection -# #self._data_table.loc[effect_name, 'connection_value'] = connection_value -# #self._data_table.loc[effect_name, 'CV'] = cv -# ============================================================================= diff --git a/modules/systemPerformance/REWET/REWET/restoration/io.py b/modules/systemPerformance/REWET/REWET/restoration/io.py deleted file mode 100644 index ce6e932da..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/io.py +++ /dev/null @@ -1,1271 +0,0 @@ -"""Created on Wed Dec 19 19:10:35 2020 - -@author: snaeimi -""" # noqa: INP001, D400 - -import logging -from collections import OrderedDict -from pathlib import Path - -import pandas as pd - -logger = logging.getLogger(__name__) - - -# the following function is borrowed from WNTR -def _split_line(line): - _vc = line.split(';', 1) - _cmnt = None - _vals = None - if len(_vc) == 0: - pass - elif len(_vc) == 1: - _vals = _vc[0].split() - elif _vc[0] == '': - _cmnt = _vc[1] - else: - _vals = _vc[0].split() - _cmnt = _vc[1] - return _vals, _cmnt - - -class RestorationIO: # noqa: D101 - def __init__(self, restoration_model, definition_file_name): - """Needs a file that contains: - - Parameters - ---------- - restoratio_model : Restoration object - restoration model to be defined by files - definition_file : str - path for tegh definition file. - - Returns - ------- - None. - - """ # noqa: D400, DOC202, RUF100 - # some of the following lines have been adopted from WNTR - self.rm = restoration_model - self.crew_data = {} - - expected_sections = [ - '[FILES]', - '[ENTITIES]', - '[JOBS]', - '[AGENTS]', - '[GROUPS]', - '[PRIORITIES]', - '[SHIFTS]', - '[SEQUENCES]', - '[DEFINE]', - '[POINTS]', - ] - - self.config_file_comment = [] - self.edata = [] - - self.sections = OrderedDict() - for sec in expected_sections: - self.sections[sec] = [] - - section = None - lnum = 0 - edata = {'fname': definition_file_name} - # Sprint(definition_file_name) - config_file_path = Path(definition_file_name) - - if config_file_path.is_absolute(): - pass - else: - config_file_path = config_file_path.resolve() - - self.config_file_dir = config_file_path.parent - - with open(definition_file_name, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - edata['lnum'] = lnum - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.startswith('['): # noqa: RET507 - vals = line.split() - sec = vals[0].upper() - edata['sec'] = sec - if sec in expected_sections: - section = sec - continue - else: # noqa: RET507 - raise RuntimeError( - '%(fname)s:%(lnum)d: Invalid section "%(sec)s"' % edata - ) - elif section is None and line.startswith(';'): - self.config_file_comment.append(line[1:]) - continue - elif section is None: - raise RuntimeError( - '%(fname)s:%(lnum)d: Non-comment outside of valid section!' - % edata - ) - # We have text, and we are in a section - self.sections[section].append((lnum, line)) - - # Parse each of the sections - self._read_files() - self._read_shifts() - self._read_entities() - self._read_agents() - self._read_groups() - self._read_sequences() - self._read_points() - self._read_priorities() - self._read_jobs() - self._read_define() - # self._read_config() - - def _read_files(self): - edata = OrderedDict() - self.file_name = [] - self._file_data = {} - self._file_handle_address = {} - for lnum, line in self.sections['[FILES]']: - edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 2: # noqa: PLR2004 - edata['key'] = words[0] - raise RuntimeError( - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' - % edata - ) - file_handle = words[0] - file_address = words[1] - - self._file_handle_address[file_handle] = file_address - - for file_handle, file_address in self._file_handle_address.items(): - self._file_data[file_handle] = self._read_each_file(file_address) - self.rm._files = self._file_data # noqa: SLF001 - - def _read_each_file(self, file_address, method=0): - lnum = 0 - iTitle = True # noqa: N806 - data_temp = None - if method == 0: - try: - raise # noqa: PLE0704 - with open(file_address, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.startswith(';'): # noqa: RET507 - # comment - continue - else: - lnum += 1 - vals = line.split() - if iTitle == True: # noqa: E712 - iTitle = False # noqa: N806 - data_temp = pd.DataFrame(columns=vals) - else: - data_temp.loc[lnum - 2] = vals - except: # noqa: E722 - data_temp = self._read_each_file(file_address, method=1) - elif method == 1: - file_address = self.config_file_dir / file_address - data_temp = pd.read_csv(file_address) - else: - raise ValueError('Uknown method: ' + str(method)) - return data_temp - - def _read_shifts(self): - # self._shift_data=pd.DataFrame() - # self._file_handle_address = {} - for lnum, line in self.sections['[SHIFTS]']: # noqa: B007 - # edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 3: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' # noqa: EM101 - ) - shift_name = words[0] - shift_begining = int(words[1]) * 3600 - shift_ending = int(words[2]) * 3600 - - self.rm.shifting.addShift(shift_name, shift_begining, shift_ending) - - def _read_entities(self): # noqa: C901 - for lnum, line in self.sections['[ENTITIES]']: - arg1 = None - arg2 = None - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) != 2 and len(words) != 4: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' # noqa: EM101 - ) - entity_name = words[0] - element = words[1].upper() - - if element not in self.rm.ELEMENTS: - raise ValueError('Unknown element line number ' + str(lnum)) - - # if entity_name in self.rm.entity: - # raise ValueError('Entity already defined') - - if len(words) == 4: # noqa: PLR2004 - arg1 = words[2] - arg2 = words[3] - - if ( - element == 'PIPE' # noqa: PLR1714 - and arg1 not in self.rm._registry._pipe_damage_table.columns # noqa: SLF001 - and arg1 != 'FILE' - and arg1 != 'NOT_IN_FILE' - ) and ( - element == 'DISTNODE' - and arg1 not in self.rm._registry._node_damage_table.columns # noqa: SLF001 - ): - raise ValueError( - 'Argument 1(' - + arg1 - + ') is not recognized in line number: ' - + str(lnum) - ) - - if arg1 == None: # noqa: E711 - self.rm.entity[entity_name] = element - ent_rule = [('ALL', None, None)] - - if entity_name not in self.rm.entity_rule: - self.rm.entity_rule[entity_name] = ent_rule - else: - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - self.rm._registry.addAttrToElementDamageTable( # noqa: SLF001 - element, - entity_name, - True, # noqa: FBT003 - ) - - elif arg1 == 'FILE' or arg1 == 'NOT_IN_FILE': # noqa: PLR1714 - name_list = self.rm._files[arg2]['ElementID'].unique().tolist() # noqa: SLF001 - ent_rule = [(arg1, None, name_list)] - self.rm.entity[entity_name] = element - - if entity_name not in self.rm.entity_rule: - self.rm.entity_rule[entity_name] = ent_rule - self.rm._registry.addAttrToElementDamageTable( # noqa: SLF001 - element, - entity_name, - True, # noqa: FBT003 - ) - else: - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - else: - if ':' in arg2: - split_arg = arg2.split(':') - - if len(split_arg) != 2: # noqa: PLR2004 - raise ValueError( - 'There must be two parts: PART1:PART2. Now there are ' - + repr( - len(split_arg) - + ' parts. Line number is ' - + repr(lnum) - ) - ) - if split_arg[0] == '': - raise ValueError( - 'The first part is Empty in line ' + repr(lnum) - ) - if split_arg[1] == '': - raise ValueError( - 'The second part is Empty in line ' + repr(lnum) - ) - else: - raise ValueError( - 'There must be two parts as a condition, separated with ":". Example: PART1:PART2 \nPart1 can be one of the following: EQ, BG, LT, BG-EQ, and LT-EQ. Line number: ' - + repr(lnum) - ) - - rest_of_args = arg2.split(':') - arg2 = rest_of_args[0] - arg3 = rest_of_args[1] - - try: - temp_arg3 = float(arg3) - except: # noqa: E722 - temp_arg3 = str(arg3) - - arg3 = temp_arg3 - ent_rule = [(arg1, arg2, arg3)] - if entity_name not in self.rm.entity: - self.rm.entity[entity_name] = element - self.rm.entity_rule[entity_name] = ent_rule - self.rm._registry.addAttrToElementDamageTable( # noqa: SLF001 - element, - entity_name, - True, # noqa: FBT003 - ) - else: - if self.rm.entity[entity_name] != element: - raise ValueError( - 'Element must not change in an added condition. Line ' - + str(lnum) - ) - self.rm.entity_rule[entity_name].append(ent_rule[0]) - - # ============================================================================= - # if element == 'PIPE': - # #candidate = self.getDamageData(element) - # #candidate.index.tolist() - # ent_rule = [element,'ALL'] - # #self.rm.entity[entity_name] = element - # self.rm.entity_rule[entity_name] = ent_rule - # self.rm._registry.addAttrToPipeDamageTable(entity_name, True) - # elif element == 'DISTNODE': - # ent_rule = [element,'ALL'] - # #self.rm.entity[entity_name] - # self.rm.entity_rule[entity_name] = ent_rule - # self.rm._registry.AttrToDistNodeDamageTable(entity_name, True) - # else: - # raise ValueError('Element type is not recognized') - # ============================================================================= - - def _read_sequences(self): - for lnum, line in self.sections['[SEQUENCES]']: # noqa: B007 - words, comments = _split_line(line) - if words is not None and len(words) > 0: - # if len(words) != 2 or len(words)!=4: - # raise RuntimeError('%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' % edata) - element = words[0].upper() - seq = [] - for arg in words[1:]: - seq.append(arg) # noqa: PERF402 - if element in self.rm.sequence: - raise ValueError('Element already in sequences') # noqa: EM101, TRY003 - self.rm.sequence[element] = seq - for el in self.rm.sequence: - if el in self.rm.ELEMENTS: - for action in self.rm.sequence[el]: - self.rm._registry.addAttrToElementDamageTable(el, action, None) # noqa: SLF001 - - def _read_agents(self): - agent_file_handle = {} - group_names = {} - group_column = {} - - for lnum, line in self.sections['[AGENTS]']: # noqa: B007 - # edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - _group_name = None - _group_column = None - - if len(words) < 3: # noqa: PLR2004 - raise RuntimeError( # noqa: TRY003 - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' # noqa: EM101 - ) - agent_type = words[0] - if words[1].upper() == 'FILE': - agent_file_handle[words[0]] = words[2] - else: - raise ValueError('Unknown key') # noqa: EM101, TRY003 - if len(words) >= 4: # noqa: PLR2004 - group_data = words[3] - _group_name = group_data.split(':')[0] - _group_column = group_data.split(':')[1] - - group_names[agent_type] = _group_name - group_column[agent_type] = _group_column - - for agent_type, file_handle in agent_file_handle.items(): - data = self._file_data[file_handle] - - # print(file_handle) - # print(self._file_data[file_handle]) - - agent_number = data['Number'] - j = 0 - for lnum, line in data.iterrows(): # noqa: B007 - # try: - num = int(agent_number[j]) - # except : - # print('exception') - # pass - _r = range(num) - - for i in _r: - agent_name = agent_type + str(j) + str(i) - predefinitions = line.to_dict() - definitions = {} - definitions['cur_x'] = predefinitions['Curr.-X-Coord'] - definitions['cur_y'] = predefinitions['Curr.-Y-Coord'] - definitions['base_x'] = predefinitions['Home-X-Coord'] - definitions['base_y'] = predefinitions['Home-Y-Coord'] - definitions['shift_name'] = predefinitions['Shift'] - - group_name_temp = None - if group_names[agent_type] != None: # noqa: E711 - definitions['group'] = predefinitions[ - group_column[agent_type] - ] - group_name_temp = group_names[agent_type] - else: - group_name_temp = 'default' - definitions['group'] = 'Default' - - definitions['group_name'] = group_name_temp - self.rm.agents.addAgent(agent_name, agent_type, definitions) - j += 1 # noqa: SIM113 - - def _read_groups(self): - for lnum, line in self.sections['[GROUPS]']: - words, comments = _split_line(line) - - if words is not None and len(words) > 0: - if len(words) != 6: # noqa: PLR2004 - raise ValueError( - 'error in line: ' + str(lnum) + ': ' + repr(len(words)) - ) - group_name = words[0] - element_type = words[1] - argument = words[2] - file_handler = words[3] - element_col_ID = words[4] # noqa: N806 - pipe_col_ID = words[5] # noqa: N806 - - if element_type not in self.rm.ELEMENTS: - raise ValueError( - 'Unknown element type: ' - + repr(element_type) - + ', in line: ' - + repr(lnum) - ) - if argument != 'FILE': - raise ValueError( - 'the Only acceptable argument is FILE. Line: ' + repr(lnum) - ) - - data = self.rm._files[file_handler] # noqa: SLF001 - - if pipe_col_ID not in data: - raise ValueError( - repr(pipe_col_ID) - + 'not in file handle=' - + repr(file_handler) - ) - - if element_col_ID not in data: - raise ValueError( - repr(element_col_ID) - + 'not in file handle=' - + repr(file_handler) - ) - - group_list = data[pipe_col_ID] - group_list.index = data[element_col_ID] - - if element_type not in self.rm.group: - raise ValueError( - 'This error must never happen: ' + repr(element_type) - ) - - if group_name in self.rm.group[element_type]: - raise ValueError( - 'The Group is already identified: ' - + repr(group_name) - + ' in line: ' - + repr(lnum) - ) - - self.rm.group[element_type][group_name] = group_list - - def _read_points(self): # noqa: C901 - for lnum, line in self.sections['[POINTS]']: - words, comments = _split_line(line) - - if words is None or len(words) < 1: # Empty Line - continue - - if not len(words) >= 2: # Syntax Error # noqa: PLR2004 - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "Each Point Group must have at least one name and one point coordinate operated by a ':'" - + '\n' - + "Example= 'PointGroupName X1:Y1 [X2:Y2 ...]'" - ) - - group_name = words[0] - current_group_point_list = [] - - if group_name.upper() in self.rm.reserved_priority_names: - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + 'Group name ' - + "'" - + group_name - + "'" - + ' is ambiguous. ' - + "'" - + group_name - + ' is a reserved priority' - ) - - for word in words[1:]: - if ':' not in word: - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "'" - + word - + "'" - + " is not an acceptable point coordinate. It must be point coordinate separated by a ':'" - + '\n' - + "Example= 'X1:Y1'" - ) - - x_y_coord = word.split(':') - if len(x_y_coord) > 2: # noqa: PLR2004 - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "Multiple divider (':') in " - + "'" - + word - + "'" - + "It must be point coordinate separated by a ':'" - + '\n' - + "Example= 'X1:Y1'" - ) - - x_coord = x_y_coord[0] - y_coord = x_y_coord[1] - - try: - x_coord = float(x_coord) - except: # noqa: E722 - raise ValueError( # noqa: B904 - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "'" - + x_coord - + "'" - + ' in ' - "'" + word + "'" + ' is not a number' - ) - - try: - y_coord = float(y_coord) - except: # noqa: E722 - raise ValueError( # noqa: B904 - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "'" - + y_coord - + "'" - + ' in ' - "'" + word + "'" + ' is not a number' - ) - - current_group_point_list.append((x_coord, y_coord)) - # print(group_name) - # print(words[1:]) - if ( - group_name in self.rm.proximity_points - ): # To Support multiple line assignment of the same group - self.rm.proximity_points[group_name].extend(current_group_point_list) - else: - self.rm.proximity_points[group_name] = current_group_point_list - - def _read_priorities(self): # noqa: C901 - agent_type_list = self.rm.agents.getAllAgentTypes() - for lnum, line in self.sections['[PRIORITIES]']: - words, comments = _split_line(line) - - if words is None or len(words) < 1: - continue - - if not len(words) >= 3: # noqa: PLR2004 - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + 'Inadequate parameters to define priority. There must be at least three parameters, ' - + repr(len(words)) - + ' is given.' - + '\n' - + "Example= 'CREW TYPE PriorityType[1 or 2], Action:DamageGroup" - ) - - agent_type = words[0] - - if agent_type not in agent_type_list: - raise ValueError( - 'Logical error in line: ' - + str(lnum) - + '\n' - + 'Crew type ' - + "'" - + agent_type - + "'" - + ' is not defined in the crew section.' - ) - - try: - priority_type = int(words[1]) - except: # noqa: E722 - try: - priority_type = int(float(words[1])) - except: # noqa: E722 - raise ValueError( # noqa: B904 - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "'" - + priority_type - + "'" - + ' is not an acceptable priority type. Priority type must be either 1 or 2 to define the first or secondary priority consecutively.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1 or 2], Action:DamageGroup" - ) - - if priority_type not in [1, 2]: - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "'" - + priority_type - + "'" - + ' is not an acceptable priority type. Priority type must be either 1 or 2 to define the first or secondary priority consecutively.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1 or 2], Action:DamageGroup" - ) - - arg = [] - for word in words[2:]: - if priority_type == 1: - if word.find(':') == -1: - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "The divider (':') is lacking. The primary priority " - + "'" - + word - + "'" - + ' is not an acceptable Primary Priority. A Priority Priority is a consisted of an Action:DamageGroup.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1], Action:DamageGroup" - ) - split_temp = word.split(':') - - if len(split_temp) > 2: # noqa: PLR2004 - raise ValueError( - 'Syntax error in line: ' - + str(lnum) - + '\n' - + "More than one divider (':') In the Primary Priority. The primary priority " - + "'" - + word - + "'" - + ' is not an acceptable Primary Priority. A Priority Priority is a consisted of an Action:DamageGroup.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1], Action:DamageGroup" - ) - - action = split_temp[0] - damage_group = split_temp[1] - - if damage_group not in self.rm.entity: - raise ValueError( - 'Logical error in line: ' - + str(lnum) - + '\n' - + 'DamageGroup ' - + "'" - + damage_group - + "'" - + ' is not an defined. A Priority Priority is a consisted of an Action:DamageGroup.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1], Action:DamageGroup" - ) - - if action not in self.rm.sequence[self.rm.entity[damage_group]]: - raise ValueError( - 'Logical error in line: ' - + str(lnum) - + '\n' - + 'Action ' - + "'" - + action - + "'" - + ' is not an defined in Action Sequence. A Priority Priority is a consisted of an Action:DamageGroup.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[1], Action:DamageGroup" - ) - - arg.append((action, damage_group)) - - elif priority_type == 2: # noqa: PLR2004 - if ( - word not in self.rm.proximity_points - and word not in self.rm.reserved_priority_names - ): - raise ValueError( - 'Logical error in line: ' - + str(lnum) - + '\n' - + 'Secondary Priority ' - + "'" - + word - + "'" - + ' is not defined as a Point Group and is not a Reserved Secondary Priority.' - + '\n' - + "Example= 'CREW TYPE Prioritytype[2] ['Point Group' or 'Reserved Secondary Priority']" - ) - arg.append(word) - else: - raise ValueError('Uknown Priority type: ' + repr(priority_type)) - - self.rm.priority.addData(agent_type, priority_type, arg) - - for crew_type in self.rm.priority._data: # noqa: SLF001 - priority_list = self.rm.priority._data[crew_type] # noqa: SLF001 - primary_priority_order_list = priority_list[1] - secondary_priority_order_list = priority_list[2] - if len(primary_priority_order_list) != len( - secondary_priority_order_list - ): - raise ValueError( - 'Logical error. The number of Primary Priority and Secondary Primary does not match for Crew Type: ' - + repr(crew_type) - ) - - not_defined = [] - for agent_type in agent_type_list: - if not self.rm.priority.isAgentTypeInPriorityData(agent_type): - not_defined.append(agent_type) # noqa: PERF401 - - if len(not_defined) > 0: - raise ValueError( - 'Logical error. The following agent types are not defined in the priority sections:\n' - + repr(not_defined) - ) - - def _read_jobs(self): - jobs_definition = [] - for lnum, line in self.sections['[JOBS]']: - cur_job_definition = {} - words, comments = _split_line(line) - - if words is not None and len(words) > 0: - if not len(words) >= 3: # noqa: PLR2004 - raise ValueError( - 'Not enough arguments. error in line: ' + str(lnum) - ) - agent_type = words[0] - - action_entity = words[1] - if not action_entity.find(':') != -1: - raise ValueError( - 'There must be an action and entity separated by : in line ' - + str(lnum) - ) - split_temp = action_entity.split(':') - action = split_temp[0] - entity = split_temp[1] - - definer_arg = words[2] - if not definer_arg.find(':') != -1: - raise ValueError( - 'There must be an Time Definer and Argument separated by : in line ' - + str(lnum) - ) - split_temp = definer_arg.split(':') - definer = split_temp[0] - argument = split_temp[1] - - if definer.upper() == 'FIXED': - try: - argument = int(argument) - except: # noqa: E722 - print('exeption handled in _read_jobs') # noqa: T201 - else: - raise ValueError('Definer is not recognized: ' + definer) - - effect = None - if len(words) >= 4: # noqa: PLR2004 - effect = words[3] - - cur_job_definition = { - 'agent_type': agent_type, - 'entity': entity, - 'action': action, - 'time_argument': argument, - 'effect': effect, - } - jobs_definition.append(cur_job_definition) - self.rm.jobs.setJob(jobs_definition) - - def _read_define(self): # noqa: C901, PLR0912 - job = {} # noqa: F841 - used_jobs = self.rm.jobs._job_list.effect.unique().tolist() # noqa: SLF001 - if None in used_jobs: - used_jobs.remove(None) - - # for key in used_effect: - # job[key]=[] - for lnum, line in self.sections['[DEFINE]']: - words, comments = _split_line(line) - if words is not None and len(words) > 0: - # if not len(words) >= 3: - # raise ValueError('Not enough arguments. error in line: ' + str(lnum)) - job_name = words[0] - if job_name not in used_jobs: - raise ValueError( - 'Effect name not recognized in line ' - + str(lnum) - + ' : ' - + job_name - ) - try: - method_name = float(words[1]) - except: # noqa: E722 - method_name = words[1] - - res_list = [] - flag = False - - if method_name == 'FILE': - file_data = self._read_file_effect(words[2:], job_name) - self.rm.jobs.addEffect(job_name, 'DATA', file_data) - continue - - method_data_list = words[2:] - for method_data in method_data_list: - res = {} - definition = method_data.split(':') - - i = 0 - if len(definition) % 2 != 1: - raise ValueError('Error in line ' + str(lnum)) - - main_arg = None - - while i < len(definition): - arg = definition[i].upper() - if i == 0: - main_arg = arg - i += 1 - res['EFFECT'] = main_arg - continue - val = definition[i + 1].upper() - - if main_arg == 'RECONNECT': - if arg == 'PIPESIZE': - if 'PIPESIZEFACTOR' in res: - raise ValueError( # noqa: TRY003 - 'Either pipe size or pipe size factor can be defined' # noqa: EM101 - ) - res['PIPESIZE'] = float(val) - - elif arg == 'PIPESIZEFACTOR': - if 'PIPESIZE' in res: - raise ValueError( # noqa: TRY003 - 'Either pipe size or pipe size factor can be defined' # noqa: EM101 - ) - val = float(val) - if val > 1 or val < 0: - raise ValueError( - 'Pipe Size Factor must be bigger than 0 and less than or eqal to 1: ' - + str(val) - ) - res['PIPESIZEFACTOR'] = float(val) - elif arg == 'CV': - if val == 'TRUE' or val == '1': # noqa: PLR1714 - val = True - elif val == 'FALSE' or val == '0': # noqa: PLR1714 - val = False - else: - raise ValueError( - 'Unrecognized value for CV in line ' - + str(lnum) - + ': ' - + val - + ( - 'Value for CV must be either True or False' - ) - ) - res['CV'] = val - elif arg == 'PIPELENGTH': - try: - val == float(val) # noqa: B015 - except Exception as e: - print( # noqa: T201 - 'The value for PIPELENGTH must be a number' - ) - raise e # noqa: TRY201 - res['PIPELENGTH'] = val - elif arg == 'PIPEFRICTION': - try: - val == float(val) # noqa: B015 - except Exception as e: - print( # noqa: T201 - 'The value for PIPEFRICTION must be a number' - ) - raise e # noqa: TRY201 - res['PIPEFRICTION'] = val - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - elif main_arg == 'ADD_RESERVOIR': - if arg == 'PUMP': - res['PUMP'] = float(val) - - elif arg == 'CV': - if val == 'TRUE' or val == '1': # noqa: PLR1714 - val = True - elif val == 'FALSE' or val == '0': # noqa: PLR1714 - val = False - else: - raise ValueError( - 'Unrecognized value for CV in line ' - + str(lnum) - + ': ' - + val - + ( - 'Value for CV must be either True or False' - ) - ) - res['CV'] = val - elif arg == 'ADDEDELEVATION': - val = float(val) - res['ADDEDELEVATION'] = float(val) - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - elif main_arg == 'REMOVE_LEAK': - if arg == 'LEAKFACTOR': - val = float(val) - if val > 1 or val <= 0: - raise ValueError( - 'Leak factor must be bigger than 0 and less than or eqal to 1: ' - + str(val) - ) - res['LEAKFACTOR'] = val - else: - raise ValueError( - 'Unrecognized argument: ' - + arg - + ', in effect: ' - + main_arg - ) - - elif main_arg == 'COL_CLOSE_PIPE': - raise ValueError( # noqa: TRY003 - 'REPAIR at this stage does not accept any argument' # noqa: EM101 - ) - - elif main_arg == 'ISOLATE_DN': - if arg == 'PIDR': # Post Incident Demand Ratio - if ( - val[0] != '(' - or val[-1] != ')' - or val.find(',') == -1 - ): - ValueError( # noqa: PLW0133 - 'After PIDR the format must be like (CONDIION,VALUE)' - ) - - val = val.strip('(').strip(')') - val_split = val.split(',') - _con = val_split[0].upper() - _con_val = float(val_split[1]) - - if not ( - _con == 'BG' # noqa: PLR1714 - or _con == 'EQ' - or _con == 'LT' - or _con == 'BG-EQ' - or _con == 'LT-EQ' - ): - raise ValueError( - 'Condition is not recognized:' + str(_con) - ) - - if _con_val < 0: - raise ValueError( - 'PIDR condition value cannot be less than zero-->' - + repr(_con_val) - ) - - res['PIDR'] = (_con, _con_val) - - elif main_arg == 'REPAIR': - raise ValueError( # noqa: TRY003 - 'REPAIR at this stage does not accept any argument' # noqa: EM101 - ) - - elif method_name.upper() == 'DEFAULT': - try: # noqa: SIM105 - arg = int(arg) - except: # noqa: S110, E722 - pass - - if main_arg == 'METHOD_PROBABILITY': - val = float(val) - - if val < 0: - raise ValueError( - 'Probability cannot be less than zero. ' # noqa: ISC003 - + ' In line ' - + lnum - + ' probability: ' - + val - ) - elif val > 1: # noqa: RET506 - raise ValueError( - 'Probability cannot be bigger than 1. ' # noqa: ISC003 - + ' In line ' - + lnum - + ' probability: ' - + val - ) - temp = { - 'effect_definition_name': job_name, - 'method_name': arg, - 'argument': main_arg, - 'value': val, - } - self.rm.jobs.addEffectDefaultValue(temp) - # temp={'effect_definition_name':effect_name, 'method_name':arg,'argument':'METHOD_PROBABILITY','value':val} - elif main_arg == 'FINALLY': - if val.upper() == 'NULL': - val = None - else: - val = None - print( # noqa: T201 - 'WARNING: At default line in FINAL section, the third argument is not NULL: ' - + str(val) - + 'The value is ignored antywhere' - ) - self.rm.jobs._final_method[job_name] = arg # noqa: SLF001 - elif main_arg == 'ONLYONCE': - try: # noqa: SIM105 - val = float(val) - except: # noqa: S110, E722 - pass - - if job_name in self.rm.jobs._once: # noqa: SLF001 - self.rm.jobs._once[job_name].append(val) # noqa: SLF001 - else: - self.rm.jobs._once[job_name] = [val] # noqa: SLF001 - else: - raise ValueError( - 'Unrecognized argument in line ' - + str(lnum) - + ': ' - + arg - ) - - flag = True - else: - raise ValueError( - 'Unrecognized argument in line ' - + str(lnum) - + ': ' - + arg - ) - - i += 2 - res_list.append(res) - if flag == False: # noqa: E712 - self.rm.jobs.addEffect(job_name, method_name, res_list) - - # for self.rm.effects.pruneData() - - def _read_file_effect(self, file_info, effect_name): - res = {} - - file_handle = file_info[0] - file_data = file_info[1:] - - data = self.rm._files[file_handle] # noqa: SLF001 - - # columns_to_remove = data.columns.tolist() - aliases = {} - - for pair in file_data: - if not pair.find(':'): - raise ValueError('Error in file info. Not Pair: ' + pair) - _arg, val = pair.split(':') - arg = _arg.upper() - - if arg in res: - raise ValueError('Argument already added: ' + _arg) - - if val not in data.columns: - raise ValueError('Value not in file: ' + val) - if ( - arg == 'ELEMENT_NAME' # noqa: PLR1714 - or arg == 'METHOD_NAME' - or arg == 'METHOD_PROBABILITY' - ): - aliases[arg] = val - res[arg] = data[val].to_dict() - - elif arg == 'FIXED_TIME_OVERWRITE': - time_overwrite_data = data[val].to_list() - # self.rm.jobs._job_list[self.rm.jobs._job_list['effect']==effect_name] - temp_list_for_effect_name = [effect_name] * data[val].size - _key = list( - zip( - temp_list_for_effect_name, - data[aliases['METHOD_NAME']], - data[aliases['ELEMENT_NAME']], - ) - ) - - time_overwrite_data = [ - {'FIXED_TIME_OVERWRITE': int(time_overwrite_data[i] * 3600)} - for i in range(len(time_overwrite_data)) - ] - self.rm.jobs._time_overwrite.update( # noqa: SLF001 - pd.Series(index=_key, data=time_overwrite_data).to_dict() - ) - - else: - raise ValueError('Unrecognized argument in pair: ' + _arg) - res = pd.DataFrame(res) - # print(res) - return res # noqa: RET504 - - def _read_config(self): - """Reads config files which contains general specification of - configurations - - Raises - ------ - RuntimeError - DESCRIPTION. - - Returns - ------- - None. - - """ # noqa: D205, D400, D401, DOC202, RUF100 - edata = OrderedDict() - self._crew_file_name = [] - self._crew_file_type = [] - for lnum, line in self.sections['[FILES]']: - edata['lnum'] = lnum - words, comments = _split_line(line) - if words is not None and len(words) > 0: - if len(words) < 2: # noqa: PLR2004 - edata['key'] = words[0] - raise RuntimeError( - '%(fname)s:%(lnum)-6d %(sec)13s no value provided for %(key)s' - % edata - ) - key = words[0].upper() - - if key == 'DEMAND_NODES': - self._demand_Node_file_name = words[1] - self._read_demand_nodes() - if key == 'CREW': - self._crew_file_type.append(words[1]) - self._crew_file_name.append(words[2]) - self._read_crew() - - def _read_demand_nodes(self): - titles = [] # noqa: F841 - ntitle = 0 - lnum = 0 - dtemp = [] - with open(self._demand_Node_file_name, encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - words = line.split() - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.upper().startswith('NODEID'): # noqa: RET507 - title = words.copy() - ntitle = len( - words - ) # we need this to confirm that every line has data for every title(column) - continue - elif nwords != ntitle: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d: Number of data does not match number of titles' # noqa: EM101 - ) - elif nwords == ntitle: - dtemp.append(words) - else: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d:This error must nnever happen' # noqa: EM101 - ) - self.demand_node = pd.DataFrame(dtemp, columns=title) - - def _read_crew(self): - titles = [] # noqa: F841 - ntitle = 0 - lnum = 0 - dtemp = [] - with open(self._crew_file_name[-1], encoding='utf-8') as f: # noqa: PTH123 - for line in f: - lnum += 1 - line = line.strip() # noqa: PLW2901 - nwords = len(line.split()) - words = line.split() - if len(line) == 0 or nwords == 0: - # Blank line - continue - elif line.upper().startswith('DISTYARDID'): # noqa: RET507 - title = words.copy() - ntitle = len( - words - ) # we need this to confirm that every line has data for every title(column) - continue - elif nwords != ntitle: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d: Number of data does not match number of titles' # noqa: EM101 - ) - elif nwords == ntitle: - dtemp.append(words) - else: - raise ValueError( # noqa: TRY003 - '%{fname}s:%(lnum)d:This error must nnever happen' # noqa: EM101 - ) - self.crew_data[self._crew_file_type[-1]] = pd.DataFrame( - dtemp, columns=title - ) diff --git a/modules/systemPerformance/REWET/REWET/restoration/model.py b/modules/systemPerformance/REWET/REWET/restoration/model.py deleted file mode 100644 index 3f92bf261..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/model.py +++ /dev/null @@ -1,1892 +0,0 @@ -"""Created on Fri Dec 25 05:09:25 2020 - -@author: snaeimi -""" # noqa: INP001, D400 - -import logging -import random -from collections import OrderedDict - -import numpy as np -import pandas as pd - -# import warnings -import restoration.io as rio -from repair import Repair -from restoration import base -from restoration.base import get_node_name - -logger = logging.getLogger(__name__) - - -class Restoration: # noqa: D101 - def __init__(self, conifg_file_name, registry, damage): - self.ELEMENTS = ['PIPE', 'DISTNODE', 'GNODE', 'TANK', 'PUMP', 'RESERVOIR'] - self._CONDITIONS = ['EQ', 'BG', 'LT', 'BG-EQ', 'LT-EQ', 'NOTEQ'] - self.reserved_priority_names = [ - 'CLOSEST', - 'MOSTLEAKATCHECK', - 'HYDSIG', - 'HYDSIGLASTFLOW', - ] - self._hard_event_table = pd.DataFrame(columns=['Requester', 'New', 'Detail']) - self._reminder_time_hard_event = {} - self.shifting = base.Shifting() - self.jobs = base.Jobs(self) - self.agents = base.Agents( - registry, self.shifting, self.jobs, registry.restoration_log_book - ) - self.proximity_points = {} - self.priority = base.Priority(self) - self.repair = Repair(registry) - self.eq_time = None - self.restoration_start_time = None - self.earthquake = None - self.if_initiated = False - self.sequence = {} - self.entity = {} - self.entity_rule = {} - self.group = {} - self.pump_restoration = pd.DataFrame() - self._damage = damage - # self.temp =[] - - for el in self.ELEMENTS: - self.group[el] = OrderedDict() - - self._registry = registry - self.dispatch = base.Dispatch(self, registry.settings, method='new') - - rio.RestorationIO(self, conifg_file_name) - retoration_data = {} - retoration_data['sequence'] = self.sequence - retoration_data['entity'] = self.entity - retoration_data['group'] = self.group - registry.retoration_data = retoration_data - - self.ApplyOverrides() - - def ApplyOverrides(self): # noqa: N802, D102 - overrides = self._registry.settings.overrides - - if 'POINTS' in overrides: - points_overrides = overrides['POINTS'] - for point_group_name in points_overrides: - if point_group_name not in self.proximity_points: - logger.warning( - 'CAUTION!' # noqa: ISC003, G003 - + '\n' - + 'Override Point Group ' - + repr(point_group_name) - + ' is not a defined point group in the restoration plan.' - ) - self.proximity_points[point_group_name] = points_overrides[ - point_group_name - ] - - def perform_action(self, wn, stop_time): # noqa: C901, D102 - logger.debug(stop_time) - - # checks if the restoration is started - if self.eq_time == None or self.restoration_start_time == None: # noqa: E711 - raise ValueError('restoration is not initiated') # noqa: EM101, TRY003 - - # checks if the stop time is a hard event - if not self._isHardEvent(stop_time): - raise RuntimeError('stop time is not a hard event') # noqa: EM101, TRY003 - - # gets the latest damage revealed and reported to the damage board registry - self.dispatch.updateDiscovery(stop_time) - - if self._isHardEvent(stop_time, 'pump'): - pump_list = ( - self.pump_restoration[ - self.pump_restoration['Restore_time'] == stop_time - ] - )['Pump_ID'].tolist() - - # logger.warning(pump_list) - self.repair.restorePumps(pump_list, wn) - - if self._isHardEvent(stop_time, 'tank'): - tank_list = ( - self.tank_restoration[ - self.tank_restoration['Restore_time'] == stop_time - ] - )['Tank_ID'].tolist() - - # logger.warning(tank_list) - self.repair.restoreTanks(tank_list, wn) - - if self._isHardEvent(stop_time, 'agent'): - # logger.debug('INSIDE RELEASE') - released_agents = self.getHardEventDetails(stop_time, 'agent') - - logger.warning('-----------------') - - for r_agent in released_agents: - agent_type = self.agents._agents.loc[r_agent, 'type'] # noqa: SLF001 - action = self.agents._agents.loc[r_agent, 'data'].cur_job_action # noqa: SLF001 - entity = self.agents._agents.loc[r_agent, 'data'].cur_job_entity # noqa: SLF001 - effect_definition_name = self.agents._agents.loc[ # noqa: SLF001 - r_agent, 'data' - ].cur_job_effect_definition_name - method_name = self.agents._agents.loc[ # noqa: SLF001 - r_agent, 'data' - ].cur_job_method_name - damaged_node_name = self.agents._agents.loc[ # noqa: SLF001 - r_agent, 'data' - ].cur_job_location - iOngoing = self.agents._agents.loc[r_agent, 'data'].cur_job_ongoing # noqa: SLF001, N806 - element_type = self.entity[entity] - - effects_list = self.jobs.getEffectsList( - effect_definition_name, method_name - ) - - if iOngoing == False: # noqa: E712 - # This must be before apply effect because if not, bypass pipe will not be removed/Sina - _damage_data = self._registry.getDamageData( - element_type, iCopy=False - ) - if ( - self.entity[entity] == 'PIPE' - or self.entity[entity] == 'DISTNODE' - ): - orginal_name = _damage_data.loc[ - damaged_node_name, 'Orginal_element' - ] - - collective_damage_data = _damage_data[ - _damage_data['Orginal_element'] == orginal_name - ] - collective_damage_data = collective_damage_data[ - collective_damage_data[action] == 'Collective' - ] - collective_damage_data_name_list = ( - collective_damage_data.index.to_list() - ) - if len(collective_damage_data_name_list) > 0: - next_action = self.getNextSequence(element_type, action) - if next_action != None: # noqa: E711 - self._registry.setDamageDataByRowAndColumn( - element_type, - collective_damage_data_name_list, - next_action, - False, # noqa: FBT003 - ) - self._registry.setDamageDataByRowAndColumn( - element_type, - collective_damage_data_name_list, - 'discovered', - True, # noqa: FBT003 - ) - - self._registry.updateElementDamageTable( - element_type, - action, - damaged_node_name, - True, # noqa: FBT003 - ) - for single_effect in effects_list: - self.applyEffect( - damaged_node_name, - single_effect, - element_type, - wn, - action, - stop_time, - ) - - next_action = self.getNextSequence(element_type, action) - - if next_action != None: # noqa: E711 - if ( - type(_damage_data.loc[damaged_node_name, next_action]) # noqa: E721 - == str - ): - pass - elif np.isnan( - _damage_data.loc[damaged_node_name, next_action] - ): - self._registry.updateElementDamageTable( - element_type, - next_action, - damaged_node_name, - False, # noqa: FBT003 - icheck=True, - ) - else: - self._registry.assignAgenttoLongJob( - damaged_node_name, action, entity, None - ) # potential bug... When there is a long job available but not a suitable agent to take care of the job, the job will be forgotten - - self.agents.releaseAgent(r_agent) - - # checks for shift change and if the stop time is a shift change, changes the shift and update agent data accordingly - self.updateShifiting(stop_time) - self.updateAvailability(stop_time) - - # gets list of ready agents, (on shift and idle) - ready_agent = self.agents.getReadyAgents() - - ready_agent_types = ready_agent['type'].unique() - - # for each agent type, we get the priority data (entity and action), refine damage data from entity that are waiting for action (action = False) - for agent_type in ready_agent_types: - typed_ready_agent = ready_agent[ready_agent['type'] == agent_type] - typed_ready_agent._is_copy = None # noqa: SLF001 - - if not len(typed_ready_agent) > 0: - continue - - agent_prime_priority_list = self.priority.getPriority(agent_type, 1) - agent_group_tag_list, agent_group_name = ( - self.agents.getAgentGroupTagList(typed_ready_agent) - ) - - non_tagged_typed_ready_agent = typed_ready_agent.copy() - non_tagged_typed_ready_agent._is_copy = None # noqa: SLF001 - for agent_group_tag in agent_group_tag_list: - typed_ready_agent = non_tagged_typed_ready_agent[ - non_tagged_typed_ready_agent['group'] == agent_group_tag - ] - typed_ready_agent._is_copy = None # noqa: SLF001 - order_counter = -1 - for prime_priority in agent_prime_priority_list: - order_counter += 1 - action = list(prime_priority)[0] # noqa: RUF015 - entity = list(prime_priority)[1] - damage_data = self._registry.getDamageData(self.entity[entity]) - entity_data = self.refineEntityDamageTable( - damage_data, - agent_group_name, - agent_group_tag, - self.entity[entity], - ) - if len(entity_data) == 0: - continue - entity_data = entity_data[(entity_data['discovered'] == True)] # noqa: E712 - entity_data = entity_data[(entity_data[entity] == True)] # noqa: E712 - entity_data = entity_data[(entity_data[action] == False)] # noqa: E712 - - logger.warning( - 'action=' # noqa: G003 - + action - + ', entity=' - + entity - + ', len(entity_data)=' - + repr(len(entity_data)) - + ', OC= ' - + repr(order_counter) - ) - for previous_action in self.sequence[self.entity[entity]]: - if previous_action == action: - break - entity_data = entity_data[ - (entity_data[previous_action] != False) # noqa: E712 - ] - - vacant_job_list = self._registry.getVacantOnGoingJobs( - action, entity - ) - - if len(vacant_job_list) > 0 and len(typed_ready_agent) > 0: - self.assignVacantJob( - vacant_job_list, - typed_ready_agent, - entity_data, - agent_type, - action, - entity, - stop_time, - order_counter, - wn, - ) - - res = self.perform_action_helper( - typed_ready_agent, - entity_data, - agent_type, - action, - entity, - stop_time, - order_counter, - wn, - ) - - if res == 'break': - break - elif res == 'continue': # noqa: RET508 - continue - - new_events = self.getNewEventsTime(reset=True) - self._registry.restoration_log_book.updateAgentLogBook( - self.agents._agents, # noqa: SLF001 - stop_time, - ) - self._registry.restoration_log_book.updateAgentHistory( - self.agents._agents, # noqa: SLF001 - stop_time, - ) - - return new_events - - def perform_action_helper( # noqa: C901, D102 - self, - typed_ready_agent, - entity_data, - agent_type, - action, - entity, - stop_time, - order_counter, - wn, - flag=False, # noqa: FBT002 - ): - ignore_list = [] - if len(entity_data) == 0: - if flag == True: # noqa: E712 - raise RuntimeError( # noqa: TRY003 - 'Ongoing and zero-length emtity data does must never appended together.' # noqa: EM101 - ) - return 'continue' - entity_data = self.priority.sortDamageTable( - wn, entity_data, entity, agent_type, 2, order_counter - ) # sort according to the possible secondary priority - - for node_name, damage_data in entity_data.iterrows(): # noqa: RET503 - if not len(typed_ready_agent) > 0: - break - - # if damage_data[action]!=False or node_name in ignore_list: - if ( - node_name in ignore_list - ): # if this condition is not here there will be a problem regarding same pipe damages/Sina - continue - - number_of_damages = damage_data['Number_of_damages'] - - # mean_time_of_job = self.jobs.getMeanJobTime(agent_type, entity, action) - # if not typed_ready_agent['data'].iloc[0].isOnShift(stop_time + mean_time_of_job + 900): - # logger.debug('BREAK due to TIME at '+str(stop_time)) - # break - - distnace_agent_entity = pd.Series( - index=typed_ready_agent.index.tolist(), - data=typed_ready_agent.index.tolist(), - ) - node_name_vir = get_node_name(node_name, entity_data) - coord = wn.get_node(node_name_vir).coordinates - - distnace_agent_entity.apply( - lambda x: typed_ready_agent.loc[x, 'data'].getDistanceFromCoordinate( - coord # noqa: B023 - ) - ) - - # --------------------------------- - # for agent_name, d_agent in typed_ready_agent.iterrows(): - # distnace_agent_entity.loc[agent_name] = d_agent['data'].getDistanceFromCoordinate(coord) - # --------------------------------- - - distnace_agent_entity.sort_values(ascending=True, inplace=True) # noqa: PD002 - if self.entity[entity] == 'PIPE': - orginal_element = entity_data.loc[node_name, 'Orginal_element'] - else: - orginal_element = node_name - # ----------------------------------------------------------- - while len(distnace_agent_entity) > 0: - choosed_agent_name = distnace_agent_entity.index[0] - - if flag == False: # noqa: E712 - i_assigned, description, job_gross_time, collective = ( - self.agents.assignsJobToAgent( - choosed_agent_name, - node_name, - entity, - action, - stop_time, - wn, - None, - number_of_damages, - orginal_element, - ) - ) - else: - reminded_time = self._registry.getLongJobRemindedTime( - node_name, action, entity - ) - i_assigned, description, job_gross_time, collective = ( - self.agents.assignsJobToAgent( - choosed_agent_name, - node_name, - entity, - action, - stop_time, - wn, - reminded_time, - None, - None, - ) - ) - collective = None # Collective already assigned/Sina - if i_assigned == False and description == 'ShortOfTime': # noqa: E712 - distnace_agent_entity.pop(distnace_agent_entity.index[0]) - break - - elif i_assigned == False and description == 'FASTCHECK': # noqa: RET508, E712 - self._registry.updateElementDamageTable( - self.entity[entity], action, node_name, 'NA', icheck=True - ) - next_action = self.getNextSequence(self.entity[entity], action) - if next_action != None: # noqa: E711 - self._registry.updateElementDamageTable( - self.entity[entity], - next_action, - node_name, - False, # noqa: FBT003 - icheck=True, - ) - break - - elif i_assigned == False and description == 'SKIP': # noqa: E712 - break - - elif i_assigned == True: # noqa: E712 - if collective != None: # noqa: E711 - orginal_element = entity_data.loc[ - node_name, 'Orginal_element' - ] - entity_same_element_damage_index = ( - entity_data[ - entity_data['Orginal_element'] == orginal_element - ] - ).index.to_list() - - same_element_damage_data = self._registry.getDamageData( - self.entity[entity], iCopy=False - ) - same_element_damage_data = same_element_damage_data[ - same_element_damage_data['Orginal_element'] - == orginal_element - ] - - same_element_damage_index = ( - same_element_damage_data.index.to_list() - ) - - same_element_damage_index.remove(node_name) - entity_same_element_damage_index.remove(node_name) - - ignore_list.extend(same_element_damage_index) - - _damage_data = self._registry.getDamageData( - self.entity[entity], iCopy=False - ) - - if ( - _damage_data.loc[same_element_damage_index, action] - == 'Collective' - ).any(): - same_element_damage_index.append(node_name) - raise ValueError('Hell to the naw' + repr(node_name)) - - _damage_data.loc[same_element_damage_index, action] = ( - collective # For times later - ) - - entity_data.loc[entity_same_element_damage_index, action] = ( - 'Collective' - ) - - self._registry.setDamageDataByRowAndColumn( - self.entity[entity], - same_element_damage_index, - action, - 'Collective', - ) - # tt=self._registry.getDamageData(self.entity[entity], iCopy=False) - - self._registry.updateElementDamageTable( - self.entity[entity], - action, - node_name, - 'On_Going', - icheck=not flag, - ) - typed_ready_agent.drop(choosed_agent_name, inplace=True) # noqa: PD002 - job_end_time = self.agents.getJobEndTime(choosed_agent_name) - - if job_end_time != None and description == 'INSIDE_SHIFT': # noqa: E711 - modfied_end_time = self._addHardEvent( - job_end_time, 'agent', choosed_agent_name, stop_time - ) - self._registry.restoration_log_book.addEndTimegentActionToLogBook( - choosed_agent_name, stop_time, modfied_end_time - ) - - if ( - self._registry.isThereSuchOngoingLongJob( # noqa: E712 - node_name, action, entity - ) - == True - ): - arival_time = self.agents.getJobArivalTime( - choosed_agent_name - ) - self._registry.deductLongJobTime( - node_name, action, entity, job_end_time - arival_time - ) - self._registry.removeLongJob(node_name, action, entity) - - break - - elif description == 'OUTSIDE_SHIFT': # noqa: RET508 - # logger.warning('cur_time= '+repr(stop_time)+', end_time= '+repr(stop_time+job_gross_time)) - if not self._registry.isThereSuchOngoingLongJob( - node_name, action, entity - ): - self._registry.addLongJob( - node_name, - action, - entity, - job_gross_time, - choosed_agent_name, - ) - else: - self._registry.assignAgenttoLongJob( - node_name, action, entity, choosed_agent_name - ) - - end_shift_time = self.agents._agents.loc[ # noqa: SLF001 - choosed_agent_name, 'data' - ].getAgentShiftEndTime(stop_time) - - arival_time = self.agents.getJobArivalTime( - choosed_agent_name - ) - self._registry.deductLongJobTime( - node_name, action, entity, end_shift_time - arival_time - ) - modfied_end_time = self._addHardEvent( - end_shift_time, 'agent', choosed_agent_name, stop_time - ) - self._registry.restoration_log_book.addEndTimegentActionToLogBook( - choosed_agent_name, stop_time, modfied_end_time - ) - - break - elif job_end_time == None: # noqa: E711 - raise ValueError('Job is not assigned to the agent') # noqa: EM101, TRY003 - else: - raise ValueError('Unknown description: ' + description) - else: - raise RuntimeError('i_assigned not boolean') # noqa: EM101, TRY003 - - # ----------------------------------------------------------- - # self._registry.updatePipeDamageTableTimeSeries(stop_time) - - def assignVacantJob( # noqa: N802, D102 - self, - vacant_job_list, - typed_ready_agent, - entity_data, - agent_type, - action, - entity, - stop_time, - order_counter, - wn, - ): - if not len(typed_ready_agent) > 0: - raise RuntimeError( # noqa: TRY003 - # JVM: Not sure what we're saying here. - 'This should not happen. We have a condition before in perform action' # noqa: EM101 - ) - if not len(vacant_job_list) > 0: - return - damage_data = self._registry.getDamageData(self.entity[entity]) - entity_data = pd.DataFrame( - columns=damage_data.columns, index=vacant_job_list - ) - - entity_data = entity_data.apply(lambda x: damage_data.loc[x.name], axis=1) - self.perform_action_helper( - typed_ready_agent, - entity_data, - agent_type, - action, - entity, - stop_time, - order_counter, - wn, - flag=True, - ) - - def applyEffect( # noqa: C901, N802, D102, PLR0912, PLR0915 - self, - damage_node_name, - single_effect_data, - element_type, - wn, - action, - stop_time, - ): - effect_type = single_effect_data['EFFECT'] - damage_data = self._registry.getDamageData(element_type, iCopy=False) - node_damage_data = damage_data.loc[damage_node_name] - damage_type = None - - if element_type == 'PIPE': - damage_type = damage_data.loc[damage_node_name, 'damage_type'] - - if effect_type == 'CHECK': - if element_type == 'DISTNODE': - result = self._registry.result.node - # damage_table = self._registry.getDamageData('DISTNODE', iCopy=False) - real_node_name = get_node_name(damage_node_name, damage_data) - if real_node_name in result['leak'].columns: - leak_demand = result['leak'].loc[stop_time, real_node_name] - else: - leak_demand = 0 - real_demand = result['demand'].loc[stop_time, real_node_name] - total_demand = leak_demand + real_demand - - node = wn.get_node(real_node_name) - pattern_list = node.demand_timeseries_list.pattern_list() - default_pattern = wn.options.hydraulic.pattern - node_pattern_name = None - if pattern_list[0] != None: # noqa: E711 - node_pattern_name = pattern_list[0].name - elif pattern_list[0] == None and default_pattern != None: # noqa: E711 - node_pattern_name = str(default_pattern) - - if node_pattern_name == None: # noqa: E711 - multiplier = 1 - else: - cur_pattern = wn.get_pattern(node_pattern_name) - multiplier = cur_pattern.at(stop_time) - - base_demand = node.base_demand - required_demand = multiplier * base_demand - if 'virtual_of' in damage_data.columns: - vir_nodal_damage_list = damage_data[ - damage_data['virtual_of'] == real_node_name - ] - vir_nodal_damage_list = vir_nodal_damage_list.index - if ( - damage_data.loc[vir_nodal_damage_list, 'Demand1'] - .isna() - .any() - ): - self._registry.addNodalDemandChange( - vir_nodal_damage_list, required_demand, total_demand - ) # Sina: maybe make it optional - else: - self._registry.addNodalDemandChange( - damage_node_name, required_demand, total_demand - ) - - elif element_type == 'PIPE': - leak_sum = 0 - - pipe_damage_table = self._registry._pipe_damage_table # noqa: SLF001 - pipe_break_history = self._registry._pipe_break_history # noqa: SLF001 - damage_type = pipe_damage_table.loc[damage_node_name, 'damage_type'] - available_node_results = ( - self._registry.result.node['demand'].loc[stop_time].dropna() - ) - available_node_results = available_node_results.index - if damage_type == 'break': - if damage_node_name in pipe_damage_table.index: - break_node_B = pipe_break_history.loc[ # noqa: N806 - damage_node_name, 'Node_B' - ] - if break_node_B in available_node_results: - leak_beark_node_B = self._registry.result.node[ # noqa: N806 - 'demand' - ].loc[stop_time, break_node_B] - else: - leak_beark_node_B = 0 # noqa: N806 - leak_sum += leak_beark_node_B - else: - break_node_A = ( # noqa: N806 - pipe_break_history[ - pipe_break_history['Node_B'] == damage_node_name - ] - ).iloc[0]['Node_A'] - if break_node_A in available_node_results: - leak_beark_node_A = self._registry.result.node[ # noqa: N806 - 'demand' - ].loc[stop_time, break_node_A] - else: - leak_beark_node_A = 0 # noqa: N806 - leak_sum += leak_beark_node_A - - if damage_node_name in available_node_results: - leak_damaged_node = self._registry.result.node['demand'].loc[ - stop_time, damage_node_name - ] - leak_sum += leak_damaged_node - - self._registry._pipe_damage_table.loc[ # noqa: SLF001 - damage_node_name, 'LeakAtCheck' - ] = leak_sum - - elif effect_type == 'RECONNECT': - self._registry.addRestorationDataOnPipe( - damage_node_name, stop_time, 'RECONNECT' - ) - middle_pipe_size = None - cv = False - _length = None - _friction = None - if 'PIPESIZE' in single_effect_data: - middle_pipe_size = single_effect_data['PIPESIZE'] - elif 'PIPESIZEFACTOR' in single_effect_data: - attached_pipe_name = node_damage_data.attached_element - attached_pipe = wn.get_link(attached_pipe_name) - attached_pipe_diameter = attached_pipe.diameter - - middle_pipe_size = attached_pipe_diameter * ( - single_effect_data['PIPESIZEFACTOR'] ** 0.5 - ) - - elif 'CV' in single_effect_data: # this has a problem /Sina - cv = single_effect_data['CV'] - elif 'PIPELENGTH' in single_effect_data: - _length = single_effect_data['PIPELENGTH'] - elif 'PIPEFRICTION' in single_effect_data: - _friction = single_effect_data['PIPEFRICTION'] - - self.repair.bypassPipe( - damage_node_name, - middle_pipe_size, - damage_type, - wn, - length=_length, - friction=_friction, - ) - - elif effect_type == 'ADD_RESERVOIR': - pump = None - middle_pipe_size = None - cv = False - if 'PIPESIZE' in single_effect_data: - middle_pipe_size = single_effect_data['PIPESIZE'] - elif 'CV' in single_effect_data: - cv = single_effect_data['CV'] # noqa: F841 - elif 'PUMP' in single_effect_data: - pump = {} - pump['POWER'] = single_effect_data['PUMP'] - - self.repair.addReservoir( - damage_node_name, damage_type, 'PUMP', pump, wn - ) - elif 'ADDEDELEVATION' in single_effect_data: - reservoir = {} - reservoir['ADDEDELEVATION'] = single_effect_data['ADDEDELEVATION'] - - self.repair.addReservoir( - damage_node_name, damage_type, 'ADDEDELEVATION', reservoir, wn - ) - else: - raise ValueError( - 'Unknown parameter. Damaged Node: ' + repr(damage_node_name) - ) - - elif effect_type == 'REMOVE_LEAK': - factor = None - if 'LEAKFACTOR' in single_effect_data: - factor = single_effect_data['LEAKFACTOR'] - self.repair.removeLeak(damage_node_name, damage_type, wn, factor) - else: - self.repair.removeLeak(damage_node_name, damage_type, wn) - - elif effect_type == 'ISOLATE_DN': - if 'FACTOR' in single_effect_data: # noqa: SIM401 - factor = single_effect_data['FACTOR'] - else: - factor = 1 - real_node_name = damage_node_name - damage_table = self._registry.getDamageData('DISTNODE', iCopy=True) - if 'virtual_of' in damage_table.columns: - real_node_name = get_node_name(damage_node_name, damage_table) - - if self._registry.settings['damage_node_model'] == 'Predefined_demand': - self.repair.removeDemand(real_node_name, factor, wn) - elif ( - self._registry.settings['damage_node_model'] - == 'equal_diameter_emitter' - or self._registry.settings['damage_node_model'] - == 'equal_diameter_reservoir' - ): - self.repair.removeDemand(real_node_name, factor, wn) - self.repair.removeExplicitNodalLeak(real_node_name, factor, wn) - else: - raise ValueError('Unknown nodal damage method') # noqa: EM101, TRY003 - - elif effect_type == 'REPAIR': - if element_type == 'PIPE': - self._registry.addRestorationDataOnPipe( - damage_node_name, stop_time, 'REPAIR' - ) - self.repair.removePipeRepair(damage_node_name, wn, action) - self.repair.repairPipe(damage_node_name, damage_type, wn) - elif element_type == 'DISTNODE': - if self._registry.settings['Virtual_node'] == True: # noqa: E712 - real_node_name = get_node_name( - damage_node_name, - self._registry._node_damage_table, # noqa: SLF001 - ) - virtual_node_table = self._registry._node_damage_table[ # noqa: SLF001 - self._registry._node_damage_table['Orginal_element'] # noqa: SLF001 - == real_node_name - ] - temp = virtual_node_table[action] == True # noqa: E712 - if temp.all(): - self.repairDistNode(real_node_name, wn) - - else: - repaired_number = temp.sum() - total_number = virtual_node_table['Number_of_damages'].sum() - if self._registry.isVirtualNodeDamaged(damage_node_name): - self._registry.setVirtualNodeRepaired(damage_node_name) - if ( - self._registry.settings['damage_node_model'] - == 'Predefined_demand' - ): - self.repair.modifyDISTNodeDemandLinearMode( - damage_node_name, - real_node_name, - wn, - repaired_number, - total_number, - ) - elif ( - self._registry.settings['damage_node_model'] - == 'equal_diameter_emitter' - ): - self.repair.modifyDISTNodeExplicitLeakEmitter( - damage_node_name, - real_node_name, - wn, - repaired_number, - total_number, - ) - elif ( - self._registry.settings['damage_node_model'] - == 'equal_diameter_reservoir' - ): - self.repair.modifyDISTNodeExplicitLeakReservoir( - damage_node_name, - real_node_name, - wn, - repaired_number, - total_number, - ) - else: - self.repairDistNode(real_node_name, wn) - - else: - raise ValueError('Unknown effect_type: ' + repr(effect_type)) - - def repairDistNode(self, damage_node_name, wn): # noqa: N802, D102 - self.repair.removeNodeTemporaryRepair(damage_node_name, wn) - - def updateShifiting(self, time): # noqa: N802 - """Updates shifting with the new time given - - Parameters - ---------- - time : int - the current time. - - Returns - ------- - None. - - """ # noqa: D400, D401, DOC202, RUF100 - if type(time) != int and type(time) != float: # noqa: E721 - raise ValueError('Time must be integer not ' + str(type(time))) - time = int(time) - if time < 0: - raise ValueError('Time must be bigger than zero') # noqa: EM101, TRY003 - next_shift_time = self.shifting.getNextShiftTime(time) - # logger.debug('next shitt time = ' + str(next_shift_time)) - self._addHardEvent(int(next_shift_time), 'shift') - - if 'shift' in self._hard_event_table['Requester'].loc[time]: - self.agents.setChangeShift(time, working_check=True) - - def updateAvailability(self, time): # noqa: N802, D102 - # SINA DELETET IT [URGENT] - # ============================================================================= - # import pickle - # - # with open("av_data.pkl","rb") as f: - # av_data = pickle.load(f) - # try: - # av_data_time = av_data[time] - # except: - # av_last_time = 0 - # time_list = list(av_data.keys()) - # time_list.append(time) - # time_list.sort() - # - # time_list = pd.Series(data = time_list) - # time_index = time_list.searchsorted(time) - # av_last_time = time_list.iloc[time_index-1] - # - # av_data_time = av_data[av_last_time] - # - # self.agents._agents.loc[av_data_time.index, 'available'] = av_data_time.to_list() - # #for agent_type in agent_type_list: - # return - # ============================================================================= - agent_type_list = self.agents._agents['type'].unique() # noqa: SLF001 - availible_agent_table = self.agents._agents[ # noqa: SLF001 - self.agents._agents['available'].eq(True) # noqa: FBT003, SLF001 - ] - for agent_type in agent_type_list: - if time == self.eq_time: - av_r = self.agents.getDefaultAvailabilityRatio(agent_type) - elif time > self.eq_time: - av_r = self.agents.getAvailabilityRatio( - agent_type, time - self.eq_time - ) - av_r = min(av_r, 1) - - available_typed_table = availible_agent_table[ - availible_agent_table['type'].eq(agent_type) - ] - availible_number = len(available_typed_table) - all_number = len( - self.agents._agents[self.agents._agents['type'].eq(agent_type)] # noqa: SLF001 - ) - new_availible_number = np.round(av_r * all_number) - availible_number - - if new_availible_number < 0: - new_index_list = random.sample( - available_typed_table.index.to_list(), - int(abs(new_availible_number)), - ) - self.agents._agents.loc[new_index_list, 'available'] = False # noqa: SLF001 - elif new_availible_number > 0: - not_available_typed_table = self.agents._agents[ # noqa: SLF001 - (self.agents._agents['type'] == agent_type) # noqa: SLF001 - & (self.agents._agents['available'] == False) # noqa: SLF001, E712 - ] - new_index_list = random.sample( - not_available_typed_table.index.to_list(), - int(new_availible_number), - ) - self.agents._agents.loc[new_index_list, 'available'] = True # noqa: SLF001 - - def initializeActiveAgents(self, time): # noqa: N802, D102 - for name, data in self.agents._agents.iterrows(): # noqa: B007, SLF001 - agent = data['data'] - if agent.isOnShift(time): - data['active'] = True - # data['ready'] = True - - def initializeReadyAgents(self): # noqa: N802, D102 - active_agents_name_list = self.agents._agents[ # noqa: SLF001 - self.agents._agents['active'].eq(True) # noqa: FBT003, SLF001 - ].index - self.agents._agents.loc[active_agents_name_list, 'ready'] = True # noqa: SLF001 - # for name, data in self.agents._agents.iterrows(): - # f data['active'] == True: - # data['ready'] = True - - # def initializeAvailableAgents(self): - # ready_agents_name_list = self.agents._agents['ready'].eq(True).index - # self.agents._agents.loc[ready_agents_name_list, 'available'] = True - - def initializeEntities(self, WaterNetwork): # noqa: N802, N803, D102 - for entity, val in self.entity_rule.items(): - element_type = self.entity[entity] - if element_type not in self.ELEMENTS: - raise ValueError('Unknown Element type') # noqa: EM101, TRY003 - - if val[0][0] == 'ALL': - self._registry.setDamageData(element_type, entity, True) # noqa: FBT003 - else: - res = [] - node_res = [] - - for line in val: - attribute = line[0] - condition = line[1] - condition_value = line[2] - - temp, temp_node = self._getRefinedElementList( - WaterNetwork, - attribute, - condition, - condition_value, - element_type, - WaterNetwork, - ) - - res.append(temp) - node_res.append(temp_node) - - union_list = self._unionOfAll(res) - - node_res = self._unionOfAll(node_res) - - self._registry.setDamageDataByList( - element_type, - node_res, - entity, - True, # noqa: FBT003 - iCheck=True, - ) - - self._registry.setDamageDataByList( - element_type, - union_list, - entity, - True, # noqa: FBT003 - ) - - def removeRecordsWithoutEntities(self, element_type): # noqa: N802, D102 - entity_list = [] - for entity in self.entity: - if self.entity[entity] == element_type: - entity_list.append(entity) # noqa: PERF401 - - damage_table = self._registry.getDamageData(element_type, iCopy=False) - if len(entity_list) > 0: - entities_damaged_table = damage_table[entity_list] - - not_asigned_damaged_table = entities_damaged_table[ - entities_damaged_table.isna().any(1) - ].index.tolist() - else: - not_asigned_damaged_table = damage_table.index.to_list() - damage_table.drop(not_asigned_damaged_table, inplace=True) # noqa: PD002 - - def initializeGroups(self): # noqa: N802, D102 - for el in self.ELEMENTS: - group_name_list = [] - - if el in self.group: - element_groups_data = self.group[el] - if len(element_groups_data) < 1: - temp = self._registry.getListAllElementOrginalName(el).unique() - element_groups_data['default'] = pd.Series( - index=temp, data='Default' - ) - - for group_name in element_groups_data: - self._registry.addAttrToElementDamageTable( - el, group_name, np.nan - ) - group_name_list.append(group_name) - group_data = element_groups_data[group_name] - - group_location_name_list = ( - self._registry.getDamagedLocationListByOriginalElementList_2( - el, group_data - ) - ) - group_cat_list = group_data.reindex(group_location_name_list) - - self._registry.setDamageDataByRowAndColumn( - el, - group_location_name_list.index.tolist(), - group_name, - group_cat_list.tolist(), - ) - - temp = self._registry.getDamageData(el) - - temp = temp[group_name_list] - - temp_list = [] - for col_name, col in temp.iteritems(): # noqa: B007 - not_na = col.notna() - not_na = not_na[not_na == False] # noqa: E712 - - temp_list.append(not_na.index.tolist()) - - temp_list = self._unionOfAll(temp_list) - if len(temp_list) > 0: - print( # noqa: T201 - 'In element: ' - + repr(el) - + ', the following damaged locations does not have a assigned group and will not be affected in the course of restoration:\n' - + repr(temp_list) - ) - logger.warning( - 'In element: ' # noqa: G003 - + repr(el) - + ', the following damaged locations does not have a assigned group and will not be affected in the course of restoration:\n' - + repr(temp_list) - ) - - def initializeGroups_old(self): # noqa: N802, D102 - for el in self.ELEMENTS: - group_name_list = [] - - if el in self.group: - element_groups_data = self.group[el] - if len(element_groups_data) < 1: - temp = self._registry.getListAllElementOrginalName(el).unique() - element_groups_data['default'] = pd.Series( - index=temp, data='Default' - ) - - for group_name in element_groups_data: - self._registry.addAttrToElementDamageTable( - el, group_name, np.nan - ) - group_name_list.append(group_name) - group_data = element_groups_data[group_name] - - group_location_name_list = ( - self._registry.getDamagedLocationListByOriginalElementList( - el, group_data - ) - ) - for ( - damage_location, - element_name, - ) in group_location_name_list.iteritems(): - group_cat = group_data.loc[element_name] - self._registry.setDamageDataByRowAndColumn( - el, damage_location, group_name, group_cat - ) - - temp = self._registry.getDamageData(el) - - temp = temp[group_name_list] - - temp_list = [] - for col_name, col in temp.iteritems(): # noqa: B007 - not_na = col.notna() - not_na = not_na[not_na == False] # noqa: E712 - - temp_list.append(not_na.index.tolist()) - - temp_list = self._unionOfAll(temp_list) - if len(temp_list) > 0: - print( # noqa: T201 - 'In element: ' - + repr(el) - + ', the following damaged locations does not have a assigned group and will not be affected in the course of restoration:\n' - + repr(temp_list) - ) - logger.warning( - 'In element: ' # noqa: G003 - + repr(el) - + ', the following damaged locations does not have a assigned group and will not be affected in the course of restoration:\n' - + repr(temp_list) - ) - - def initializeNumberOfDamages(self): # noqa: N802, D102 - for element_type in self.ELEMENTS: - if ( - 'Number_of_damages' - not in ( - self._registry.getDamageData(element_type, iCopy=False) - ).columns - ): - self._registry.addAttrToElementDamageTable( - element_type, 'Number_of_damages', 1 - ) - - def _unionOfAll(self, in_list): # noqa: N802 - num_of_lists = len(in_list) - - if len(in_list) == 0: - return in_list - - if len(in_list) == 1: - if type(in_list[0]) == list: # noqa: E721 - return in_list[0] - else: # noqa: RET505 - raise ValueError('Something is wrong here') # noqa: EM101, TRY003 - - first_list = in_list[0] - second_list = in_list[1] - union_list = [] - - for item in first_list: - if item in second_list: - union_list.append(item) # noqa: PERF401 - - if num_of_lists == 2: # noqa: PLR2004 - return union_list - else: # noqa: RET505 - in_list.pop(0) - in_list[0] = union_list - return self._unionOfAll(in_list) - - def _getRefinedElementList( # noqa: N802 - self, - WaterNetwork, # noqa: N803 - attribute, - condition, - condition_value, - element_type, - wn, - ): - res = [] - node_res = [] - - if element_type == 'PIPE': - res = self._getRefinedPipeList( - WaterNetwork, attribute, condition, condition_value - ) - - elif element_type == 'PUMP': - res = self._getRefinedPumpList( - WaterNetwork, attribute, condition, condition_value - ) - - elif element_type in ['DISTNODE', 'GNODE', 'TANK', 'PUMP', 'RESERVOIR']: - res, node_res = self._getRefinedNodeElementList( - WaterNetwork, attribute, condition, condition_value, element_type, wn - ) - else: - raise ValueError('Unknown Element Type:' + str(element_type)) - - return res, node_res - - def refineEntityDamageTable( # noqa: N802, D102 - self, - damaged_table, - group_name, - agent_group_tag, - element_type, - ): - ret = [] - # logger.warning('Sina') - if group_name == None: # noqa: E711 - ret = damaged_table - # logger.warning('1') - - elif group_name in damaged_table.columns: - # logger.warning('2') - # logger.warning(group_name) - # logger.warning(agent_group_tag) - # logger.warning(damaged_table[damaged_table[group_name]==agent_group_tag]) - # agent_type = damaged_table['type'].iloc[0] - ret = damaged_table[damaged_table[group_name] == agent_group_tag] - if len(ret) == 0: - logger.warning( - 'Empty damage table in element type=' # noqa: G003 - + repr(element_type) - + 'group name=' - + repr(group_name) - + ', group_tag=' - + repr(agent_group_tag) - ) - else: - ret = pd.DataFrame(columns=damaged_table.columns) - - return ret - - def _refine_table(self, table, attribute, condition, condition_value): # noqa: C901 - refined_table = None - - if type(condition_value) == str: # noqa: E721 - if condition == 'EQ': - refined_table = table[table[attribute] == condition_value] - elif condition == 'NOTEQ': - refined_table = table[table[attribute] != condition_value] - else: - raise ValueError('Undefined condition: ' + repr(condition)) - elif type(condition_value) == int or type(condition_value) == float: # noqa: E721 - if condition == 'EQ': - refined_table = table[table[attribute] == condition_value] - elif condition == 'BG-EQ': - refined_table = table[table[attribute] >= condition_value] - elif condition == 'LT-EQ': - refined_table = table[table[attribute] <= condition_value] - elif condition == 'BG': - refined_table = table[table[attribute] > condition_value] - elif condition == 'LT': - refined_table = table[table[attribute] < condition_value] - elif condition == 'NOTEQ': - refined_table = table[table[attribute] != condition_value] - else: - raise ValueError('Undefined condition: ' + repr(condition)) - else: - raise ValueError('Undefined data type: ' + repr(type(condition_value))) - - return refined_table - - def _getRefinedNodeElementList( # noqa: C901, N802 - self, - WaterNetwork, # noqa: ARG002, N803 - attribute, - condition, - condition_value, - element_type, - wn, - ): - res = [] - node_res = [] - - if attribute == 'FILE' or attribute == 'NOT_IN_FILE': # noqa: PLR1714 - node_damage_list = self._registry.getDamageData(element_type) - - for org_file_name in condition_value: - # not_included = set(org_file_name) - set(wn.node_name_list) - if org_file_name not in node_damage_list.index: - # Sina out it back. Suppressed for ruining in cluster - continue - - if 'virtual_of' in node_damage_list.columns: - node_name_list = node_damage_list.index - temp_damage_table = node_damage_list.set_index( - 'Virtual_node', drop=False - ) - temp_damage_table['random_sina_index'] = node_name_list.tolist() - temp = temp_damage_table.loc[org_file_name] - temp.index = temp['random_sina_index'] - temp = temp.drop('random_sina_index', axis=1) - else: - if type(org_file_name) == str: # noqa: E721 - org_file_name = [org_file_name] # noqa: PLW2901 - temp = node_damage_list.loc[org_file_name] - - ichosen = False - - if len(temp) >= 1: - res.extend(temp.index.tolist()) - ichosen = True - - if ichosen == False: # noqa: E712 - if org_file_name in wn.node_name_list: - ichosen = True - node_res.append(org_file_name) - if ichosen == False: # noqa: E712 - raise ValueError( - 'Element with ID: ' - + repr(org_file_name) - + ' is not either a element: ' - + repr(element_type) - + ' or a node.' - ) - - if attribute == 'NOT_IN_FILE': - index_list = node_damage_list.index.tolist() - for in_file in res: - index_list.remove(in_file) - - res = index_list - - # res.extend(node_res) - - elif attribute in self._registry.getDamageData(element_type).columns: - temp = self._registry.getDamageData(element_type) - - refined_table = self._refine_table( - temp, attribute, condition, condition_value - ) - refined_table = refined_table.index - res = refined_table.to_list() - else: - raise ValueError('Unknown Entity Condition: ' + condition) - - return res, node_res - - def _getRefinedPumpList( # noqa: N802 - self, - WaterNetwork, # noqa: ARG002, N803 - attribute, - condition, - condition_value, - ): - element_res = [] - - if attribute == 'FILE' or condition == 'NOT_IN_FILE': - pump_damage_list = self._registry.getDamageData('PUMP') - - for org_file_name in condition_value: - temp = pump_damage_list[ - pump_damage_list['element_name'] == org_file_name - ] - - if len(temp) == 1: - element_res.append(temp.element_name[0]) - elif len(temp) > 1: - raise ValueError('Something wrong here') # noqa: EM101, TRY003 - - if attribute == 'NOT_IN_FILE': - index_list = pump_damage_list.element_name.tolist() - for in_file in element_res: - index_list.remove(in_file) - - element_res = index_list - - elif attribute in self._registry.getDamageData('PUMP').columns: - temp = self._registry._pump_damage_table # noqa: SLF001 - - refined_table = self._refine_table( - temp, attribute, condition, condition_value - ) - - refined_table = refined_table.index - element_res = refined_table.to_list() - else: - raise ValueError('Unknown Entity Condition: ' + attribute) - - res = [] - pump_name_list = pump_damage_list['element_name'].tolist() - - for element_name in element_res: - if element_name in pump_name_list: - temp = pump_damage_list[ - pump_damage_list['element_name'] == element_name - ].index[0] - - res.append(temp) - return res - - def _getRefinedPipeList( # noqa: C901, N802 - self, - WaterNetwork, # noqa: N803 - attribute, - condition, - condition_value, - ): - res = [] - - # if condition in self._CONDITIONS: - if attribute.upper() == 'DIAMETER': - # for pipe_name in WaterNetwork.pipe_name_list: - for damage_name, line in self._registry.getDamageData('PIPE').iterrows(): - if attribute.upper() == 'DIAMETER': - # orginal_element = line['Orginal_element'] - attached_elements = line['attached_element'] - - pipe = WaterNetwork.get_link(attached_elements) - pipe_value = pipe.diameter - else: - raise ValueError('Undefined attribute ' + attribute) - - if condition == 'EQ': - if pipe_value == condition_value: - res.append(damage_name) - elif condition == 'BG': - if pipe_value > condition_value: - res.append(damage_name) - elif condition == 'LT': - if pipe_value < condition_value: - res.append(damage_name) - elif condition == 'BG-EQ': - if pipe_value >= condition_value: - res.append(damage_name) - elif condition == 'LT-EQ': - if pipe_value <= condition_value: - res.append(damage_name) - - elif attribute == 'FILE' or attribute == 'NOT_IN_FILE': # noqa: PLR1714 - pipe_damage_list = self._registry.getDamageData('PIPE') - for org_file_name in condition_value: - temp = pipe_damage_list[ - pipe_damage_list['Orginal_element'] == org_file_name - ] - - if len(temp) == 1: - res.append(temp.index[0]) - elif len(temp) > 1: - res.extend(temp.index.to_list()) - - if attribute == 'NOT_IN_FILE': - index_list = pipe_damage_list.index.tolist() - for in_file in res: - i = 0 - - while i in range(len(index_list)): - if index_list[i] == in_file: - index_list.pop(i) - i += 1 - - res = index_list - - elif attribute in self._registry.getDamageData('PIPE').columns: - temp = self._registry.getDamageData('PIPE') - - refined_table = self._refine_table( - temp, attribute, condition, condition_value - ) - - refined_table = refined_table.index - res = refined_table.to_list() - else: - raise ValueError('Unknown Entity Condition: ' + condition) - - return res - - def _getReminderTime(self, name): # noqa: N802 - return self._reminder_time_hard_event[name] - - def _saveReminderTime(self, time, name): # noqa: N802 - if name not in self._reminder_time_hard_event: - self._reminder_time_hard_event[name] = int(time) - else: - self._reminder_time_hard_event[name] += int(time) - - def _addHardEvent(self, next_time, requester, detail=None, current_time=None): # noqa: N802 - """Adds a hard event - - Parameters - ---------- - time : int - Time of hard event. - requester : str - Requeter type - - Returns - ------- - None. - - """ # noqa: D400, D401 - time = int(next_time) - next_time = int(next_time) - if type(next_time) != int and type(next_time) != float: # noqa: E721 - raise ValueError('time must be int, not ' + str(type(next_time))) - if detail != None and current_time == None: # noqa: E711 - raise ValueError('When detail is provided, current time cannot be None') # noqa: EM101, TRY003 - - minimum_time_devision = int(self._registry.settings['simulation_time_step']) - if current_time != None: # noqa: E711 - if next_time < current_time: - raise ValueError('Time is smaller than current time') # noqa: EM101, TRY003 - if detail == None: # noqa: E711 - raise ValueError( # noqa: TRY003 - 'When current time is provided, detail cannot be None' # noqa: EM101 - ) - if minimum_time_devision < 0: - raise ValueError('Minimum time division cannot be negative') # noqa: EM101, TRY003 - - name = requester + '-' + detail - - time = next_time - current_time - - _b = np.round(time / minimum_time_devision) - - if abs(_b) < 0.01: # noqa: PLR2004 - _b = 1 - - new_time = _b * minimum_time_devision - reminder = time - new_time - self._saveReminderTime(reminder, name) - next_time = current_time + new_time - - if next_time not in self._hard_event_table.index: - self._hard_event_table.loc[next_time] = [ - [ - requester, - ], - True, - [ - detail, - ], - ] - elif ( - requester in self._hard_event_table.loc[next_time, 'Requester'] - and detail == None # noqa: E711 - ): - pass - else: - self._hard_event_table.loc[next_time, 'Requester'].append(requester) - self._hard_event_table.loc[next_time, 'New'] = True - self._hard_event_table.loc[next_time, 'Detail'].append(detail) - - return next_time - - def _isHardEvent(self, time, requester=None): # noqa: N802 - if requester == None: # noqa: E711 - return time in self._hard_event_table.index - else: # noqa: RET505 - if time in self._hard_event_table.index: - req = self._hard_event_table.loc[time, 'Requester'] - if requester in req: - return True - return False - - def getHardEventDetails(self, time, by=None): # noqa: N802, D102 - if by == None: # noqa: E711 - return self._hard_event_table.loc[time, 'Detail'] - elif by not in self._hard_event_table.loc[time, 'Requester']: # noqa: RET505 - return [] - else: - res = [] - requester_list = self._hard_event_table.loc[time, 'Requester'] - detail_list = self._hard_event_table.loc[time, 'Detail'] - i = 0 - for requester in requester_list: - if requester == by: - res.append(detail_list[i]) - i += 1 # noqa: SIM113 - return res - - def getNewEventsTime(self, reset=False): # noqa: FBT002, N802, D102 - new_event_table = self._hard_event_table[ - self._hard_event_table['New'] == True # noqa: E712 - ] - new_event_table = new_event_table.sort_index() - - if reset == True: # noqa: E712 - for ind, val in new_event_table.iterrows(): # noqa: B007 - self._hard_event_table.loc[ind, 'New'] = False - - return list(new_event_table.index) - - def unmarkNewEvents(self): # noqa: N802, D102 - self._hard_event_table['new'][self._hard_event_table['New'] == True] = False # noqa: E712 - - def getAllSequences(self, element_type): # noqa: N802, D102 - return self.sequence[element_type] - - def getNextSequence(self, element_type, cur_seq): # noqa: N802, D102 - seq_list = self.sequence[element_type] - if cur_seq not in seq_list: - raise ValueError('Sequence was not in sequence list: ' + str(cur_seq)) - i = 0 - for seq in seq_list: - if cur_seq == seq: - break - i += 1 - if not i + 1 < len(seq_list): - return None - else: # noqa: RET505 - return seq_list[i + 1] - - def initialize(self, wn, stop_time, delay=0, earthquake=None): # noqa: C901, D102 - self.if_initiated = True - self.eq_time = stop_time - if delay < 0: - raise ValueError('delay value is less than 0: ' + str(delay)) - self.delay = delay - - if stop_time < 0: - raise ValueError('Stop time is less than 0') # noqa: EM101, TRY003 - - # refined_pump = self.pump_restoration[self.pump_restoration['Restore_time']>=stop_time] - if not self.pump_restoration.empty: - self.pump_restoration['Restore_time'] = ( - self.pump_restoration['Restore_time'] + stop_time - ) - - if not self.tank_restoration.empty: - self.tank_restoration['Restore_time'] = ( - self.tank_restoration['Restore_time'] + stop_time - ) - - for ( - ind, # noqa: B007 - row, - ) in self.pump_restoration.items(): # noqa: PERF102 - self._addHardEvent(row['Restore_time'], 'pump') - - if type(self.tank_restoration) != pd.core.series.Series: # noqa: E721 - raise # noqa: PLE0704 - for ( - ind, # noqa: B007 - row, - ) in self.tank_restoration.items(): # noqa: PERF102 - self._addHardEvent(row['Restore_time'], 'tank') - - self.restoration_start_time = stop_time + delay - - self._addHardEvent(self.restoration_start_time, 'start') - self.initializeActiveAgents(stop_time) - self.initializeReadyAgents() - - for node_name in wn.node_name_list: - self._registry.addGeneralNodeDamageToRegistry(node_name) - - for tank_name in wn.tank_name_list: - self._registry.addTankDamageToRegistry(tank_name) - - for pump_name in wn.pump_name_list: - self._registry.addPumpDamageToRegistry(pump_name, wn.get_link(pump_name)) - - for reservoir_name in wn.reservoir_name_list: - self._registry.addReservoirDamageToRegistry(reservoir_name) - - self.initializeEntities(wn) - self.removeRecordsWithoutEntities('TANK') - self.removeRecordsWithoutEntities('RESERVOIR') - self.removeRecordsWithoutEntities('PUMP') - self.removeRecordsWithoutEntities('GNODE') - - for el in self.ELEMENTS: - self._registry.setDamageData(el, 'discovered', False) # noqa: FBT003 - self.initializeGroups() - self.initializeNumberOfDamages() - - for seq_key, seq_list in self.sequence.items(): - self._registry.setDamageData(seq_key, seq_list[0], False) # noqa: FBT003 - - if self.delay == 0: - event_time_list = self.perform_action(wn, stop_time) - else: - event_time_list = self.getNewEventsTime(reset=True) - - if earthquake != None: # noqa: E711 - self.earthquake = earthquake - - event_time_list = event_time_list[1:] - return event_time_list # noqa: RET504 - - def iRestorationStopTime(self): # noqa: N802, D102 - if self.if_initiated == False: # noqa: E712 - return False - logger.debug('Func: node functionality') - pipe_damage_end = self.iAllPipeLastActionDone() - node_damage_end = self.iAllNodeLastActionDone() - pump_damage_end = self.iAllPumpLastActionDone() - GNODE_damage_end = self.iAllGNodeLastActionDone() # noqa: N806 - tank_damage_end = self.iAllTankLastActionDone() - reservoir_damage_end = self.iAllReservoirLastActionDone() - - logger.debug('pipe: ' + repr(pipe_damage_end)) # noqa: G003 - logger.debug('node: ' + repr(node_damage_end)) # noqa: G003 - logger.debug('pump: ' + repr(pump_damage_end)) # noqa: G003 - logger.debug('GNODE: ' + repr(GNODE_damage_end)) # noqa: G003 - logger.debug('tank: ' + repr(tank_damage_end)) # noqa: G003 - logger.debug('reservoir: ' + repr(reservoir_damage_end)) # noqa: G003 - - if ( # noqa: SIM103 - pipe_damage_end - and node_damage_end - and pump_damage_end - and GNODE_damage_end - and tank_damage_end - and reservoir_damage_end - ): - return True - else: # noqa: RET505 - return False - - def iAllPipeLastActionDone(self): # noqa: N802, D102 - print() # noqa: T201 - if 'PIPE' in self.sequence: - if len(self._registry._pipe_damage_table) == 0: # noqa: SLF001 - return True - - pipe_action = self.sequence['PIPE'][-1] - pipe_last_action_values = self._registry._pipe_damage_table[pipe_action] # noqa: SLF001 - if_pipe_last_action_true = ( - pipe_last_action_values - == True | (pipe_last_action_values == 'Collective') - ).all() - if if_pipe_last_action_true: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - else: - return True - - def iAllNodeLastActionDone(self): # noqa: N802, D102 - if 'DISTNODE' in self.sequence: - if len(self._registry._node_damage_table) == 0: # noqa: SLF001 - return True - - node_action = self.sequence['DISTNODE'][-1] - node_last_action_values = self._registry._node_damage_table[node_action] # noqa: SLF001 - if_node_last_action_true = ( - node_last_action_values - == True | (node_last_action_values == 'Collective') - ).all() - - if if_node_last_action_true == True: # noqa: SIM103, E712 - return True - else: # noqa: RET505 - return False - else: - return True - - def iAllPumpLastActionDone(self): # noqa: N802, D102 - if 'PUMP' in self.sequence: - if len(self._registry._pump_damage_table) == 0: # noqa: SLF001 - return True - - pump_action = self.sequence['PUMP'][-1] - pump_last_action_values = self._registry._pump_damage_table[pump_action] # noqa: SLF001 - - if len(self._registry._pump_damage_table) == 0: # noqa: SLF001 - return True - - if_pump_last_action_true = (pump_last_action_values == True).all() # noqa: E712 - - if if_pump_last_action_true == True: # noqa: SIM103, E712 - return True - else: # noqa: RET505 - return False - else: - return True - - def iAllGNodeLastActionDone(self): # noqa: N802, D102 - if 'GNODE' in self.sequence: - if len(self._registry._gnode_damage_table) == 0: # noqa: SLF001 - return True - - gnode_action = self.sequence['GNODE'][-1] - gnode_last_action_values = self._registry._gnode_damage_table[ # noqa: SLF001 - gnode_action - ] - if_gnode_last_action_true = (gnode_last_action_values == True).all() # noqa: E712 - - if if_gnode_last_action_true == True: # noqa: SIM103, E712 - return True - else: # noqa: RET505 - return False - else: - return True - - def iAllTankLastActionDone(self): # noqa: N802, D102 - if 'TANK' in self.sequence: - if len(self._registry._tank_damage_table) == 0: # noqa: SLF001 - return True - - tank_action = self.sequence['TANK'][-1] - tank_last_action_values = self._registry._tank_damage_table[tank_action] # noqa: SLF001 - if_tank_last_action_true = (tank_last_action_values == True).all() # noqa: E712 - - if if_tank_last_action_true == True: # noqa: SIM103, E712 - return True - else: # noqa: RET505 - return False - else: - return True - - def iAllReservoirLastActionDone(self): # noqa: N802, D102 - if 'RESERVOIR' in self.sequence: - if len(self._registry._reservoir_damage_table) == 0: # noqa: SLF001 - return True - - reservoir_action = self.sequence['RESERVOIR'][-1] - reservoir_last_action_values = self._registry._reservoir_damage_table[ # noqa: SLF001 - reservoir_action - ] - if_reservoir_last_action_true = ( - reservoir_last_action_values == True # noqa: E712 - ).all() - - if if_reservoir_last_action_true == True: # noqa: SIM103, E712 - return True - else: # noqa: RET505 - return False - else: - return True - - def getHydSigPipeList(self): # noqa: N802, D102 - damage_group_list = self.priority.getHydSigDamageGroups() - pipe_damage_group_list = [ - cur_damage_group - for cur_damage_group in damage_group_list - if self.entity[cur_damage_group] == 'PIPE' - ] - return pipe_damage_group_list # noqa: RET504 diff --git a/modules/systemPerformance/REWET/REWET/restoration/registry.py b/modules/systemPerformance/REWET/REWET/restoration/registry.py deleted file mode 100644 index 38037c5b8..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/registry.py +++ /dev/null @@ -1,1489 +0,0 @@ -"""Created on Sat Dec 26 03:22:21 2020 - -@author: snaeimi -""" # noqa: INP001, D400 - -import logging -from collections import OrderedDict - -import numpy as np -import pandas as pd -from restoration.restorationlog import RestorationLog - -logger = logging.getLogger(__name__) - - -class Registry: # noqa: D101 - def __init__(self, WaterNetwork, settings, demand_node_name_list, scenario_name): # noqa: N803 - self._registry_version = 0.15 - self.wn = WaterNetwork - self.settings = settings - self.demand_node_name_list = demand_node_name_list - self.scenario_name = scenario_name - # self.EQCoordinates = (6398403.298, 1899243.660) - # self.proximity_points = {'WaterSource':[(6435903.606431,1893248.592426),(6441950.711447,1897369.022871), - # (6424377.955317,1929513.408731),(6467146.075381,1816296.452238), - # (6483259.266246,1803209.907606),(6436359.6420960,1905761.7390040), - # (6492204.110122,1758379.158018),(6464169.549436,1738989.098520), - # (6504097.778564,1875687.031985),(6414434.124,1929805.346), - # (6412947.370,1936851.950)]} - self._pipe_break_node_coupling = {} # for broken points that each has two nodes - self._break_point_attached_to_mainPipe = [] # for broken points to show which node is attached to the main point. For easier and faster coding in removals of damage - # self._occupancy = pd.Series() # for agent occupency - # self._pipe_RepairAgentNameRegistry=[] # MAYBE NOT NEEDED for agent occupency - self._tank_damage_table = pd.DataFrame(columns=['damage_type']) - self._reservoir_damage_table = pd.DataFrame(columns=['damage_type']) - self._pump_damage_table = pd.DataFrame( - columns=['damage_type', 'element_name', 'start_node', 'end_node'] - ) - self._gnode_damage_table = pd.DataFrame(columns=['damage_type']) - self._pipe_damage_table = pd.DataFrame( - columns=[ - 'damage_type', - 'damage_sub_type', - 'Orginal_element', - 'attached_element', - 'number', - 'LeakAtCheck', - ] - ) - self._pipe_data = pd.DataFrame(columns=['diameter']) - self._node_damage_table = pd.DataFrame( - columns=['Demand1', 'Demand2', 'Number_of_damages'] - ) - self._pipe_break_history = pd.DataFrame( - columns=['Pipe_A', 'Pipe_B', 'Orginal_pipe', 'Node_A', 'Node_B'] - ) - self._pipe_leak_history = pd.DataFrame( - columns=['Pipe_A', 'Pipe_B', 'Orginal_pipe', 'Node_name'] - ) - self._long_task_data = pd.DataFrame( - columns=['Node_name', 'Action', 'Entity', 'Time', 'cur_agent_name'] - ) - self.all_node_table = pd.DataFrame( - columns=['X_COORD', 'Y_COORD'], dtype=float - ) - self.pre_event_demand_met = pd.DataFrame(dtype=float) - self.hydraulic_significance = pd.Series(dtype=float) - self.if_first_event_occured = 0 - self.restoration_log_book = RestorationLog(settings) - self.explicit_leak_node = {} - self.demand_node_name_list = [] - self.all_node_name_list = WaterNetwork.node_name_list.copy() - # self.demand_node_users = pd.Series() - # self.minimum_time_devision = 60*60 - self.nodal_equavalant_diameter = None - self.original_pipe_data = {} - self.result = None - self.active_pipe_damages = OrderedDict() - self.active_nodal_damages = OrderedDict() - self.active_collectives = pd.DataFrame(columns=['action', 'Orginal_pipe']) - self.virtual_node_data = OrderedDict() - self._nodal_data = OrderedDict() - self.result = None - self.result_dump_file_list = [] - self.Pipe_Damage_restoration_report = [] - self.undamaged_link_node_list = {} - - for name, pipe in WaterNetwork.pipes(): - self._pipe_data.loc[name] = [pipe.diameter] - - for node_name, node in WaterNetwork.junctions(): - if node.demand_timeseries_list[0].base_value > 0.00000008: # noqa: PLR2004 - self.demand_node_name_list.append(node_name) - - # for demand_node_name in self.demand_node_name_list: - # self.demand_node_users.loc[demand_node_name]=1 - - for node_name, node in WaterNetwork.nodes(): - self.all_node_table.loc[node_name, 'X_COORD'] = node.coordinates[0] - self.all_node_table.loc[node_name, 'Y_COORD'] = node.coordinates[1] - - for link_name, link in WaterNetwork.links(): - self.undamaged_link_node_list[link_name] = ( - link.start_node_name, - link.end_node_name, - ) - - # self._restoration_table = pd.DataFrame(columns = ['node_name','function', 'element_name', 'element_type', 'in_function_index']) - self._restoration_table = pd.DataFrame( - columns=['node_name', 'function', 'record_index'] - ) - self._record_registry = [] - - self._pipe_damage_table_time_series = OrderedDict() - self._node_damage_table_time_series = OrderedDict() - self._tank_level_time_series = OrderedDict() - self._restoration_reservoir_name_time_series = OrderedDict() - self.ED_history = pd.Series(dtype='O') # Equavalant Damage Diameter - - for pipe_name, pipe in WaterNetwork.pipes(): - self.original_pipe_data[pipe_name] = { - 'diameter': pipe.diameter, - 'length': pipe.length, - 'start_node_name': pipe.start_node_name, - 'end_node_name': pipe.end_node_name, - 'roughness': pipe.roughness, - } - - # ============================================================================= - # def addElementToRestorationRegistry(self, damaged_node_name, function_name, element_name, elemenet_type, in_function_index): - # data = self.__restoration_table - # selected_data = data[(data[['node_name', 'element_name', 'element_type']]==[damaged_node_name,element_name,elemenet_type]).all(1))] - # - # if len(selected_data)>1: - # raise ValueError('There are data in restroation regustry. Damaged node name: '+damaged_node_name) - # - # - # temp = pd.Series(data=[damaged_node_name, function_name, element_name, elemenet_type, in_function_index], index=['node_name','function', 'element_name', 'element_type', 'in_function_index']) - # self._restoration_table = self._restoration_table.append(temp, ignore_index=True) - # ============================================================================= - - def addRestorationDataOnPipe(self, damage_node_name, time, state): # noqa: N802, D102 - if self.settings['dmg_rst_data_save'] == True: # noqa: E712 - orginal_pipe_name = self._pipe_damage_table.loc[ - damage_node_name, 'Orginal_element' - ] - time = time / 3600 - temp_row = { - 'time': time, - 'pipe_name': orginal_pipe_name, - 'last_state': state, - } - self.Pipe_Damage_restoration_report.append(temp_row) - - def addEquavalantDamageHistory( # noqa: N802, D102 - self, - node_name, - new_node_name, - new_pipe_name, - equavalant_pipe_diameter, - number_of_damages, - ): - if node_name in self.ED_history: - raise ValueError('Node_damage already in history') # noqa: EM101, TRY003 - - self.ED_history.loc[node_name] = { - 'new_node_name': new_node_name, - 'new_pipe_name': new_pipe_name, - 'equavalant_pipe_diameter': equavalant_pipe_diameter, - 'initial_number_of_damage': number_of_damages, - 'current_number_of_damage': number_of_damages, - } - - def getEquavalantDamageHistory(self, node_name): # noqa: N802, D102 - temp = self.ED_history[node_name] - - if type(temp) != dict: # noqa: E721 - raise ValueError('probably two damages with the same name: ' + node_name) - - return temp - - def removeEquavalantDamageHistory(self, node_name): # noqa: N802, D102 - self.ED_history.drop(node_name, inplace=True) # noqa: PD002 - - def isThereSuchOngoingLongJob(self, damaged_node_name, action, entity): # noqa: N802, D102 - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity']] == [ - damaged_node_name, - action, - entity, - ] - temp = data[temp.all(1)] - - if len(temp) > 1: - raise ValueError('More job than 1 in long jobs') # noqa: EM101, TRY003 - elif len(temp) == 1: # noqa: RET506 - if abs(temp['Time'].iloc[0]) < 0.01: # noqa: PLR2004 - raise ValueError('Something Wrong') # noqa: EM101, TRY003 - else: # noqa: RET506 - return True - else: - return False - - def addLongJob( # noqa: N802, D102 - self, - damaged_node_name, - action, - entity, - job_gross_time, - agent_name, - ): - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity', 'Time', 'cur_agent_name']] == [ - damaged_node_name, - action, - entity, - job_gross_time, - agent_name, - ] - - if temp.all(1).any(): - raise ValueError( - 'There are currently data on: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - # elif temp['cur_agent_name'].iloc[0]!=None: - # raise ValueError('There is one agent: '+temp['cur_agent_name'].iloc[0]+' assigned to long job: '+damaged_node_name+','+action+','+entity) - - temp = pd.Series( - index=['Node_name', 'Action', 'Entity', 'Time', 'cur_agent_name'], - data=[damaged_node_name, action, entity, job_gross_time, agent_name], - ) - self._long_task_data = data.append(temp, ignore_index=True) - - def assignAgenttoLongJob( # noqa: N802, D102 - self, - damaged_node_name, - action, - entity, - choosed_agent_name, - ): - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity']] == [ - damaged_node_name, - action, - entity, - ] - temp = data[temp.all(1)] - - if len(temp) != 1: - raise ValueError( - 'There must be one record: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - - ind = temp.index[0] - if ( - self._long_task_data.loc[ind, 'cur_agent_name'] != None # noqa: E711 - and choosed_agent_name != None # noqa: E711 - ): - raise ValueError( - 'Already someone is here ' - + repr(self._long_task_data.loc[ind, 'cur_agent_name']) - ) - - self._long_task_data.loc[ind, 'cur_agent_name'] = choosed_agent_name - - def deductLongJobTime(self, damaged_node_name, action, entity, deduced_time): # noqa: N802, D102 - deduced_time = int(deduced_time) - - if deduced_time < 0: - raise ValueError( - 'deductig time must not be less than zero: ' + repr(deduced_time) - ) - - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity']] == [ - damaged_node_name, - action, - entity, - ] - - temp = data[temp.all(1)] - - if len(temp) == 0: - raise ValueError( - 'There is no long task defined for: ' - + damaged_node_name - + ', ' - + action - + ', ' - + entity - ) - elif len(temp) > 1: # noqa: RET506 - raise ValueError( - 'There are MORE THAN ONE long task defined for: ' - + damaged_node_name - + ', ' - + action - + ', ' - + entity - ) - - ind = temp.index[0] - - if (self._long_task_data.loc[ind, 'Time'] - deduced_time) < 0: - logger.warning( - damaged_node_name # noqa: G003 - + ', ' - + action - + ', ' - + entity - + ', ' - + str(self._long_task_data.loc[ind, 'Time']) - + ', ' - + str(deduced_time) - + ', ' - + str(self._long_task_data.loc[ind, 'Time'] - deduced_time) - ) - raise ValueError('Zero reminded time for long task') # noqa: EM101, TRY003 - - self._long_task_data.loc[ind, 'Time'] -= deduced_time - - def getLongJobRemindedTime(self, damaged_node_name, action, entity): # noqa: N802, D102 - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity']] == [ - damaged_node_name, - action, - entity, - ] - - temp = data[temp.all(1)] - - if len(temp) == 0: - raise ValueError( - 'There is no long task defined for: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - elif len(temp) > 1: # noqa: RET506 - raise ValueError( - 'There are MORE THAN ONE long task defined for: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - - return temp['Time'].iloc[0] - - def getVacantOnGoingJobs(self, action, entity): # noqa: N802, D102 - res = [] - data = self._long_task_data - temp = data[['Action', 'Entity']] == [action, entity] - - temp = data[temp.all(1)] - - for ind, data in temp.iterrows(): # noqa: B007 - if data['cur_agent_name'] == None: # noqa: E711 - res.append(data['Node_name']) - - return res - - def getdamagedNodesOfPipes(self, damage_type): # noqa: N802, D102 - if damage_type != 'break' and damage_type != 'leak': # noqa: PLR1714 - raise ValueError('The damage for pipe is either break or leak.') # noqa: EM101, TRY003 - - if damage_type == 'break': # noqa: RET503 - return self._pipe_break_history[['Node_A', 'Node_B']] - - elif damage_type == 'leak': # noqa: RET505 - return self._pipe_leak_history['Node_name'] - - def removeLongJob(self, damaged_node_name, action, entity): # noqa: N802, D102 - data = self._long_task_data - temp = data[['Node_name', 'Action', 'Entity']] == [ - damaged_node_name, - action, - entity, - ] - - temp = data[temp.all(1)] - - if len(temp) == 0: - raise ValueError( - 'There is no long task defined for: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - elif len(temp) > 1: # noqa: RET506 - raise ValueError( - 'There are MORE THAN ONE long task defined for: ' - + damaged_node_name - + ',' - + action - + ',' - + entity - ) - - ind = temp.index[0] - - self._long_task_data.drop(ind, inplace=True) # noqa: PD002 - - def addFunctionDataToRestorationRegistry( # noqa: N802, D102 - self, - damaged_node_name, - history, - function_name, - ): - data = self._restoration_table - selected_data = data[ - ( - data[['node_name', 'function']] == [damaged_node_name, function_name] - ).all(1) - ] - if len(selected_data) > 0: - raise ValueError( - 'There are data in restroation registry. Damaged node name: ' - + damaged_node_name - + ' ' - + ' ' - + function_name - ) - - self._record_registry.append(history) - latest_index = len(self._record_registry) - 1 - - temp = pd.Series( - data=[damaged_node_name, function_name, latest_index], - index=['node_name', 'function', 'record_index'], - ) - self._restoration_table = self._restoration_table.append( - temp, ignore_index=True - ) - - def addNodalDamage(self, nodal_damage, new_pipe_name_list): # noqa: N802, D102 - if self.settings['Virtual_node'] == True: # noqa: E712 - for ind, val in nodal_damage.items(): - val = int(val) # noqa: PLW2901 - virtual_node_name_list = [] - for i in range(val): - new_virtual_node_name = ind + '_vir_' + str(i) - self._node_damage_table.loc[ - new_virtual_node_name, 'Number_of_damages' - ] = 1 - self._node_damage_table.loc[ - new_virtual_node_name, 'virtual_of' - ] = ind - self._node_damage_table.loc[ - new_virtual_node_name, 'Orginal_element' - ] = ind - self.virtual_node_data[new_virtual_node_name] = { - 'is_damaged': True - } - self.virtual_node_data[new_virtual_node_name][ - 'new_pipe_name' - ] = new_pipe_name_list[ind] - virtual_node_name_list.append(new_virtual_node_name) - self._nodal_data[ind] = new_pipe_name_list[ind] - else: - for ind, val in nodal_damage.items(): - self._node_damage_table.loc[ind, 'Number_of_damages'] = val - self._node_damage_table.loc[ - new_virtual_node_name, 'Orginal_element' - ] = ind - self._nodal_data[ind] = { - 'real_node_name': ind, - 'number_of_damages': val, - } - - def isVirtualNodeDamaged(self, virtual_node_name): # noqa: N802, D102 - return self.virtual_node_data[virtual_node_name]['is_damaged'] - - def setVirtualNodeRepaired(self, virtual_node_name): # noqa: N802, D102 - self.virtual_node_data[virtual_node_name]['is_damaged'] = False - - def addNodalDemandChange(self, node_name, demand1, demand2): # noqa: N802, D102 - # if self.settings['Virtual_node'] == False: - if type(node_name) == str: # noqa: E721 - if node_name not in self._node_damage_table.index: - raise ValueError(repr(node_name) + ' is not in the node table') - self._node_damage_table.loc[node_name, 'Demand1'] = demand1 - self._node_damage_table.loc[node_name, 'Demand2'] = demand2 - # else: - # node_name_vir = get_node_name(node_name, self._node_damage_table) - # self._node_damage_table.loc[node_name_vir, 'Demand1'] = demand1 - # self._node_damage_table.loc[node_name_vir, 'Demand2'] = demand2 - - def addPipeDamageToRegistry(self, node_name, data): # noqa: N802 - """Adds damage to pipe registry - - Parameters - ---------- - node_name : string - Damaged node Name. - data : Dict - Data about Damage. - - Returns - ------- - None. - - """ # noqa: D400, D401, DOC202, RUF100 - # self._pipe_node_damage_status[name] = data - - leaking_pipe_with_pipeA_orginal_pipe = self._pipe_leak_history[ # noqa: N806 - self._pipe_leak_history.loc[:, 'Pipe_A'] == data['orginal_pipe'] - ] - breaking_pipe_with_pipeA_orginal_pipe = self._pipe_break_history[ # noqa: N806 - self._pipe_break_history.loc[:, 'Pipe_A'] == data['orginal_pipe'] - ] - - i_leak_not_zero_length = len(leaking_pipe_with_pipeA_orginal_pipe) > 0 - i_break_not_zero_length = len(breaking_pipe_with_pipeA_orginal_pipe) > 0 - - if i_leak_not_zero_length and i_break_not_zero_length: - raise ValueError( # noqa: TRY003 - 'There are more than 1 damage with original pipe name in pipe A. it does not make sense' # noqa: EM101 - ) - if i_leak_not_zero_length: - temp_node_name = leaking_pipe_with_pipeA_orginal_pipe.index[0] - self._pipe_leak_history.loc[temp_node_name, 'Pipe_A'] = data['pipe_B'] - elif i_break_not_zero_length: - temp_node_name = breaking_pipe_with_pipeA_orginal_pipe.index[0] - self._pipe_break_history.loc[temp_node_name, 'Pipe_A'] = data['pipe_B'] - - if data['damage_type'] == 'leak': - self._pipe_damage_table.loc[node_name, 'damage_type'] = data[ - 'damage_type' - ] - self._pipe_damage_table.loc[node_name, 'damage_sub_type'] = data[ - 'damage_subtype' - ] - self._pipe_damage_table.loc[node_name, 'Orginal_element'] = data[ - 'orginal_pipe' - ] - self._pipe_damage_table.loc[node_name, 'attached_element'] = data[ - 'pipe_A' - ] - self._pipe_damage_table.loc[node_name, 'number'] = data['number'] - - self._pipe_leak_history.loc[node_name, 'Pipe_A'] = data['pipe_A'] - self._pipe_leak_history.loc[node_name, 'Pipe_B'] = data['pipe_B'] - self._pipe_leak_history.loc[node_name, 'Orginal_pipe'] = data[ - 'orginal_pipe' - ] - self._pipe_leak_history.loc[node_name, 'Node_name'] = node_name - - elif data['damage_type'] == 'break': - self._pipe_damage_table.loc[node_name, 'damage_type'] = data[ - 'damage_type' - ] - self._pipe_damage_table.loc[node_name, 'Orginal_element'] = data[ - 'orginal_pipe' - ] - self._pipe_damage_table.loc[node_name, 'attached_element'] = data[ - 'pipe_A' - ] - self._pipe_damage_table.loc[node_name, 'number'] = data['number'] - - self._pipe_break_history.loc[node_name, 'Pipe_A'] = data['pipe_A'] - self._pipe_break_history.loc[node_name, 'Pipe_B'] = data['pipe_B'] - self._pipe_break_history.loc[node_name, 'Orginal_pipe'] = data[ - 'orginal_pipe' - ] - self._pipe_break_history.loc[node_name, 'Node_A'] = data['node_A'] - self._pipe_break_history.loc[node_name, 'Node_B'] = data['node_B'] - - else: - raise ValueError('Undefined damage type') # noqa: EM101, TRY003 - - def addGeneralNodeDamageToRegistry(self, node_name, data=None): # noqa: ARG002, N802, D102 - self._gnode_damage_table.loc[node_name, 'damage_type'] = None - - def addTankDamageToRegistry(self, node_name, data=None): # noqa: ARG002, N802, D102 - self._tank_damage_table.loc[node_name, 'damage_type'] = None - - def addPumpDamageToRegistry(self, pump_name, data): # noqa: N802, D102 - node_name = data.start_node.name - self._pump_damage_table.loc[node_name, 'damage_type'] = None - self._pump_damage_table.loc[node_name, 'element_name'] = pump_name - self._pump_damage_table.loc[node_name, 'start_node'] = data.start_node.name - self._pump_damage_table.loc[node_name, 'end_node'] = data.end_node.name - - def addReservoirDamageToRegistry(self, node_name, data=None): # noqa: ARG002, N802, D102 - self._reservoir_damage_table.loc[node_name, 'damage_type'] = None - - # def assignAgentToDamage(self, element, node_name, choosed_agent_name): - - def getListAllElementOrginalName(self, element_type): # noqa: N802, D102 - original_element_list = None - if element_type == 'PIPE': - original_element_list = self._pipe_damage_table['Orginal_element'] - - elif element_type == 'PUMP': - original_element_list = self._pump_damage_table['element_name'] - - elif ( - element_type == 'DISTNODE' # noqa: PLR1714 - or element_type == 'GNODE' - or element_type == 'TANK' - or element_type == 'RESERVOIR' - ): - temp = self.getDamageData(element_type, iCopy=False) - if 'virtual_of' in temp.columns: - original_element_list = pd.Series( - temp['virtual_of'], index=temp.index - ) - else: - original_element_list = pd.Series(temp.index, index=temp.index) - - else: - raise ValueError('Unkown recognized element type: ' + repr(element_type)) - - return original_element_list - - def getDamagedLocationListByOriginalElementList( # noqa: N802, D102 - self, - element_type, - orginal_element_list, - iCheck=False, # noqa: FBT002, N803 - ): - res = pd.Series() - - if element_type == 'PIPE': - original_element_list = self._pipe_damage_table['Orginal_element'] - - elif element_type == 'PUMP': - original_element_list = self._pump_damage_table['element_name'] - - elif ( - element_type == 'DISTNODE' # noqa: PLR1714 - or element_type == 'GNODE' - or element_type == 'TANK' - or element_type == 'RESERVOIR' - ): - temp = self.getDamageData(element_type) - original_element_list = pd.Series(temp.index, index=temp.index) - - else: - raise ValueError('Unkown recognized element type: ' + repr(element_type)) - - for element_name, group_tag in orginal_element_list.iteritems(): # noqa: B007 - temp = original_element_list[original_element_list == element_name] - - # if len(temp)!=1: - if len(temp) != 0: - res = res.append(temp) - # elif len(temp)>1: - # raise ValueError('Something wrong here') - elif iCheck: - raise ValueError( - 'The element: ' - + repr(element_name) - + ' does not exist in element type: ' - + repr(element_type) - ) - - return res - - def getDamagedLocationListByOriginalElementList_2( # noqa: N802, D102 - self, - element_type, - orginal_element_list, - iCheck=False, # noqa: FBT002, N803 - ): - if element_type == 'PIPE': - all_original_element_list = self._pipe_damage_table['Orginal_element'] - - elif element_type == 'PUMP': - all_original_element_list = self._pump_damage_table['element_name'] - - elif ( - element_type == 'DISTNODE' # noqa: PLR1714 - or element_type == 'GNODE' - or element_type == 'TANK' - or element_type == 'RESERVOIR' - ): - temp = self.getDamageData(element_type, iCopy=False) - if 'virtual_of' in temp: - all_original_element_list = temp['virtual_of'] - else: - all_original_element_list = pd.Series(temp.index, index=temp.index) - - else: - raise ValueError('Unkown recognized element type: ' + repr(element_type)) - temp_bool = all_original_element_list.isin(orginal_element_list.index) - res = all_original_element_list[temp_bool] - if iCheck == True: # noqa: E712 - if len(res.index) < len(orginal_element_list): - not_available_list = set(orginal_element_list) - set(res.index) - raise ValueError( - 'The element: ' - + repr(not_available_list) - + ' does not exist in element type: ' - + repr(element_type) - ) - - return res - - def getOriginalPipenodes(self, orginal_pipe_name): # noqa: N802, D102 - return self.original_pipe_data[orginal_pipe_name] - - def getLeakData(self, leaking_node_name): # noqa: N802, D102 - pipe_A = self._pipe_leak_history.loc[leaking_node_name, 'Pipe_A'] # noqa: N806 - pipe_B = self._pipe_leak_history.loc[leaking_node_name, 'Pipe_B'] # noqa: N806 - orginal_pipe = self._pipe_leak_history.loc[leaking_node_name, 'Orginal_pipe'] - - return pipe_A, pipe_B, orginal_pipe - - def getCertainLeakData(self, damage_node_name, wn): # noqa: C901, N802, D102 - pipe_name_list = [] - - result_pipe_A = None # noqa: N806 - result_pipe_B = None # noqa: N806 - - orginal_pipe = self._pipe_leak_history.loc[damage_node_name, 'Orginal_pipe'] - refined_data = self._pipe_leak_history[ - self._pipe_leak_history['Orginal_pipe'] == orginal_pipe - ] - - for damage_point_name, data in refined_data.iterrows(): # noqa: B007 - pipe_A = data['Pipe_A'] # noqa: N806 - pipe_B = data['Pipe_B'] # noqa: N806 - - if pipe_A not in pipe_name_list: - pipe_name_list.append(pipe_A) - if pipe_B not in pipe_name_list: - pipe_name_list.append(pipe_B) - - # orginal_pipe = self._pipe_break_history.loc[damage_node_name, 'Orginal_pipe'] - refined_data = self._pipe_break_history[ - self._pipe_break_history['Orginal_pipe'] == orginal_pipe - ] - - for damage_point_name, data in refined_data.iterrows(): # noqa: B007 - pipe_A = data['Pipe_A'] # noqa: N806 - pipe_B = data['Pipe_B'] # noqa: N806 - - if pipe_A not in pipe_name_list: - pipe_name_list.append(pipe_A) - if pipe_B not in pipe_name_list: - pipe_name_list.append(pipe_B) - - for pipe_name in pipe_name_list: - try: - pipe = wn.get_link(pipe_name) - except: # noqa: S112, E722 - continue - - if damage_node_name == pipe.start_node_name: - result_pipe_B = pipe_name # noqa: N806 - elif damage_node_name == pipe.end_node_name: - result_pipe_A = pipe_name # noqa: N806 - - if result_pipe_A != None and result_pipe_B != None: # noqa: E711 - return result_pipe_A, result_pipe_B - raise RuntimeError( - 'There must be a pair of pipes for ' + repr(damage_node_name) - ) - - def getBreakData(self, breaking_node_name): # noqa: N802, D102 - pipe_A = self._pipe_break_history.loc[breaking_node_name, 'Pipe_A'] # noqa: N806 - pipe_B = self._pipe_break_history.loc[breaking_node_name, 'Pipe_B'] # noqa: N806 - orginal_pipe = self._pipe_break_history.loc[ - breaking_node_name, 'Orginal_pipe' - ] - node_A = self._pipe_break_history.loc[breaking_node_name, 'Node_A'] # noqa: N806 - node_B = self._pipe_break_history.loc[breaking_node_name, 'Node_B'] # noqa: N806 - - return pipe_A, pipe_B, orginal_pipe, node_A, node_B - - def getCertainBreakData(self, damage_node_name, wn): # noqa: C901, N802, D102 - pipe_name_list = [] - - result_pipe_A = None # noqa: N806 - result_pipe_B = None # noqa: N806 - - node_A = self._pipe_break_history.loc[damage_node_name, 'Node_A'] # noqa: N806 - node_B = self._pipe_break_history.loc[damage_node_name, 'Node_B'] # noqa: N806 - - orginal_pipe = self._pipe_break_history.loc[damage_node_name, 'Orginal_pipe'] - - refined_data = self._pipe_leak_history[ - self._pipe_leak_history['Orginal_pipe'] == orginal_pipe - ] - - for damage_point_name, data in refined_data.iterrows(): # noqa: B007 - pipe_A = data['Pipe_A'] # noqa: N806 - pipe_B = data['Pipe_B'] # noqa: N806 - - if pipe_A not in pipe_name_list: - pipe_name_list.append(pipe_A) - if pipe_B not in pipe_name_list: - pipe_name_list.append(pipe_B) - - # orginal_pipe = self._pipe_break_history.loc[damage_node_name, 'Orginal_pipe'] - refined_data = self._pipe_break_history[ - self._pipe_break_history['Orginal_pipe'] == orginal_pipe - ] - - for damage_point_name, data in refined_data.iterrows(): # noqa: B007 - pipe_A = data['Pipe_A'] # noqa: N806 - pipe_B = data['Pipe_B'] # noqa: N806 - - if pipe_A not in pipe_name_list: - pipe_name_list.append(pipe_A) - if pipe_B not in pipe_name_list: - pipe_name_list.append(pipe_B) - - for pipe_name in pipe_name_list: - try: - pipe = wn.get_link(pipe_name) - except: # noqa: S112, E722 - continue - - if node_B == pipe.start_node_name: - result_pipe_B = pipe_name # noqa: N806 - elif node_A == pipe.end_node_name: - result_pipe_A = pipe_name # noqa: N806 - - if result_pipe_A != None and result_pipe_B != None: # noqa: E711 - return result_pipe_A, result_pipe_B, node_A, node_B - raise RuntimeError( - 'There must be a pair of pipes for ' + repr(damage_node_name) - ) - - def getPipeDamageAttribute(self, attribute_name, damage_node_name=None): # noqa: N802, D102 - if attribute_name not in self._pipe_damage_table.columns: - raise ValueError('Attribute not in damage table: ' + str(attribute_name)) - - if damage_node_name == None: # noqa: E711 - return self._pipe_damage_table[attribute_name] - else: # noqa: RET505 - return self._pipe_damage_table.loc[damage_node_name, attribute_name] - - def getDamageData(self, element_type, iCopy=True): # noqa: FBT002, C901, N802, N803, D102 - if element_type.upper() == 'PIPE': - if iCopy: - res = self._pipe_damage_table.copy() - else: - res = self._pipe_damage_table - elif element_type.upper() == 'DISTNODE': - if iCopy: - res = self._node_damage_table.copy() - else: - res = self._node_damage_table - - elif element_type.upper() == 'GNODE': - if iCopy: - res = self._gnode_damage_table.copy() - else: - res = self._gnode_damage_table - - elif element_type.upper() == 'TANK': - if iCopy: - res = self._tank_damage_table.copy() - else: - res = self._tank_damage_table - - elif element_type.upper() == 'PUMP': - if iCopy: - res = self._pump_damage_table.copy() - else: - res = self._pump_damage_table - - elif element_type.upper() == 'RESERVOIR': - if iCopy: - res = self._reservoir_damage_table.copy() - else: - res = self._reservoir_damage_table - - else: - raise ValueError('Unknown element type: ' + element_type) - return res - - def getOrginalElement(self, damaged_node_name, element_type): # noqa: N802, D102 - element_damage_data = self.getDamageData(element_type, iCopy=False) - return element_damage_data.loc[damaged_node_name, 'Orginal_element'] - - def getPipeData(self, attr, name=None): # noqa: N802, D102 - if name != None: # noqa: E711 - return self._pipe_data[attr].loc[name] - else: # noqa: RET505 - return self._pipe_data[attr] - - def setDamageData(self, element, col, value): # noqa: N802, D102 - if element.upper() == 'PIPE': - if col not in self._pipe_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - self._pipe_damage_table[col] = value - elif element.upper() == 'DISTNODE': - if col not in self._node_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - self._node_damage_table[col] = value - elif element.upper() == 'GNODE': - self._gnode_damage_table[col] = value - elif element.upper() == 'TANK': - self._tank_damage_table[col] = value - elif element.upper() == 'PUMP': - self._pump_damage_table[col] = value - elif element.upper() == 'RESERVOIR': - self._reservoir_damage_table[col] = value - else: - raise ValueError('Element is not defined: ' + element) - - def setDamageDataByRowAndColumn(self, element, index, col, value, iCheck=False): # noqa: FBT002, N802, N803, D102 - # if element.upper() == 'PIPE': - damage_table = self.getDamageData(element, iCopy=False) - if col not in damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - if type(index) == list or ( # noqa: E721 - (index in damage_table.index and col in damage_table.columns) - or iCheck == True # noqa: E712 - ): - damage_table.loc[index, col] = value - else: - raise ValueError(index) - - def setDamageDataByList(self, element, index_list, col, value, iCheck=False): # noqa: FBT002, C901, N802, N803, D102 - if type(index_list) != list: # noqa: E721 - raise ValueError('index_list is not data type list') # noqa: EM101, TRY003 - - if element.upper() == 'PIPE': - if col not in self._pipe_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for damage_node_name in index_list: - if ( - damage_node_name in self._pipe_damage_table.index - or iCheck == True # noqa: E712 - ): - self._pipe_damage_table.loc[damage_node_name, col] = value - else: - raise ValueError(damage_node_name) - - elif element.upper() == 'DISTNODE': - if col not in self._node_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for damage_node_name in index_list: - if ( - damage_node_name in self._node_damage_table.index - or iCheck == True # noqa: E712 - ): - self._node_damage_table.loc[damage_node_name, col] = value - else: - raise ValueError(damage_node_name) - - elif element.upper() == 'GNODE': - if col not in self._gnode_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for gnode_name in index_list: - if gnode_name in self._gnode_damage_table.index or iCheck == True: # noqa: E712 - self._gnode_damage_table.loc[gnode_name, col] = value - else: - raise ValueError(gnode_name) - - elif element.upper() == 'TANK': - if col not in self._tank_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for _tank_damage_table in index_list: - if ( - _tank_damage_table in self._tank_damage_table.index - or iCheck == True # noqa: E712 - ): - self._tank_damage_table.loc[_tank_damage_table, col] = value - else: - raise ValueError(_tank_damage_table) - - elif element.upper() == 'PUMP': - if col not in self._pump_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for _pump_damage_table in index_list: - if ( - _pump_damage_table in self._pump_damage_table.index - or iCheck == True # noqa: E712 - ): - self._pump_damage_table.loc[_pump_damage_table, col] = value - else: - raise ValueError(_pump_damage_table) - - elif element.upper() == 'RESERVOIR': - if col not in self._reservoir_damage_table.columns: - raise ValueError('Columns is not in damage table: ' + col) - - for _reservoir_damage_table in index_list: - if ( - _reservoir_damage_table in self._reservoir_damage_table.index - or iCheck == True # noqa: E712 - ): - self._reservoir_damage_table.loc[ - _reservoir_damage_table, col - ] = value - else: - raise ValueError(_reservoir_damage_table) - else: - raise ValueError('Element is not defined: ' + element) - - def updatePipeDamageTableTimeSeries(self, time): # noqa: N802, D102 - if time in self._pipe_damage_table_time_series: - raise ValueError('Time exist in pipe damage table time history') # noqa: EM101, TRY003 - - self._pipe_damage_table_time_series[time] = self._pipe_damage_table.copy() - - def updateNodeDamageTableTimeSeries(self, time): # noqa: N802, D102 - if time in self._node_damage_table_time_series: - raise ValueError('Time exist in node damage table time history') # noqa: EM101, TRY003 - - self._node_damage_table_time_series[time] = self._node_damage_table.copy() - - def updateTankTimeSeries(self, wn, time): # noqa: N802, D102 - if time in self._tank_level_time_series: - raise ValueError('Time exist in tank damage table time history') # noqa: EM101, TRY003 - - tank_name_list = wn.tank_name_list - tank_level_res = pd.Series(index=tank_name_list) - - for tank_name in wn.tank_name_list: - node = wn.get_node(tank_name) - net_water_level = node.level - node.min_level - if net_water_level < 0.001: # noqa: PLR2004 - raise ValueError( - 'Net Water Level in tank cannot be less than zero:' - + repr(tank_name) - + ' ' - + repr(net_water_level) - ) - tank_level_res.loc[tank_name] = net_water_level - - self._tank_level_time_series[time] = tank_level_res - - def updateRestorationIncomeWaterTimeSeries(self, wn, time): # noqa: ARG002, N802, D102 - if time in self._restoration_reservoir_name_time_series: - raise ValueError( # noqa: TRY003 - 'Time exist in restoration reservoir damage table time history' # noqa: EM101 - ) - res = [] - for list_of_restoration in self._record_registry: - for key, value in list_of_restoration.items(): - if key == 'ADDED_RESERVOIR': - res.append(value) - - self._restoration_reservoir_name_time_series[time] = res - - def updateElementDamageTable(self, element, attr, index, value, icheck=False): # noqa: FBT002, C901, N802, D102 - if element == 'PIPE': - if icheck == True: # noqa: E712 - if self._pipe_damage_table[attr].loc[index] == value: - raise ValueError('the value is already set') # noqa: EM101, TRY003 - - self._pipe_damage_table.loc[index, attr] = value - - elif element == 'DISTNODE': - if icheck == True: # noqa: E712 - if self._node_damage_table[attr].loc[index] == value: - raise ValueError( - 'the value is already set in element: ' - + element - + ', attr: ' - + attr - + ', index: ' - + index - + ', value: ' - + value - ) - - self._node_damage_table.loc[index, attr] = value - - elif element == 'GNODE': - if icheck == True: # noqa: E712 - if self._gnode_damage_table[attr].loc[index] == value: - raise ValueError( - 'the value is already set in element: ' - + element - + ', attr: ' - + attr - + ', index: ' - + index - + ', value: ' - + value - ) - - self._gnode_damage_table.loc[index, attr] = value - - elif element == 'TANK': - if icheck == True: # noqa: E712 - if self._tank_damage_table[attr].loc[index] == value: - raise ValueError( - 'the value is already set in element: ' - + element - + ', attr: ' - + attr - + ', index: ' - + index - + ', value: ' - + value - ) - - self._tank_damage_table.loc[index, attr] = value - - elif element == 'PUMP': - if icheck == True: # noqa: E712 - if self._pump_damage_table[attr].loc[index] == value: - raise ValueError( - 'the value is already set in element: ' - + element - + ', attr: ' - + attr - + ', index: ' - + index - + ', value: ' - + value - ) - - self._pump_damage_table.loc[index, attr] = value - - elif element == 'RESERVOIR': - if icheck == True: # noqa: E712 - if self._reservoir_damage_table[attr].loc[index] == value: - raise ValueError( - 'the value is already set in element: ' - + element - + ', attr: ' - + attr - + ', index: ' - + index - + ', value: ' - + value - ) - - self._reservoir_damage_table.loc[index, attr] = value - - else: - raise ValueError('Unknown element: ' + element) - - def addAttrToElementDamageTable(self, element, attr, def_data): # noqa: N802, D102 - if element == 'PIPE': - self.addAttrToPipeDamageTable(attr, def_data) - elif element == 'DISTNODE': - self.addAttrToDistNodeDamageTable(attr, def_data) - elif element == 'GNODE': - self.addAttrToGeneralNodeDamageTable(attr, def_data) - elif element == 'TANK': - self.addAttrToTankDamageTable(attr, def_data) - elif element == 'PUMP': - self.addAttrToPumpDamageTable(attr, def_data) - elif element == 'RESERVOIR': - self.addAttrToReservoirDamageTable(attr, def_data) - - else: - raise ValueError('Undefined element: ' + element) - - def addAttrToPipeDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._pipe_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._pipe_damage_table[attr] = np.nan - else: - self._pipe_damage_table[attr] = def_data - - def addAttrToDistNodeDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._node_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._node_damage_table[attr] = np.nan - else: - self._node_damage_table[attr] = def_data - - def addAttrToGeneralNodeDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._gnode_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._gnode_damage_table[attr] = np.nan - else: - self._gnode_damage_table[attr] = def_data - - def addAttrToTankDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._tank_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._tank_damage_table[attr] = np.nan - else: - self._tank_damage_table[attr] = def_data - - def addAttrToPumpDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._pump_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._pump_damage_table[attr] = np.nan - else: - self._pump_damage_table[attr] = def_data - - def addAttrToReservoirDamageTable(self, attr, def_data): # noqa: N802, D102 - if attr in self._reservoir_damage_table.columns: - raise ValueError('attribute already in the damage table') # noqa: EM101, TRY003 - - if def_data == None: # noqa: E711 - self._reservoir_damage_table[attr] = np.nan - else: - self._reservoir_damage_table[attr] = def_data - - def iOccupied(self, node_name): # noqa: N802 - """Checks if the node is occuoied - - Parameters - ---------- - node_name : string - Node ID. - - Returns - ------- - bool - result. - - """ # noqa: D400, D401 - return node_name in self._occupancy.index - - def _getDamagedPipesRegistry(self): # noqa: N802 - """Gets the whole damage registry. Not safe to be used outside the class. - - Returns - ------- - Pandas.Series - damage locations by node name. - - """ # noqa: D401 - return self._pipe_node_damage_status - - def getNumberofDamagedNodes(self): # noqa: N802 - """Gets numbers of Damaged locations. Counts two for broken pipes - - Returns - ------- - Int - Number of damaged locations by node name. - - """ # noqa: D400, D401 - return len(self._pipe_node_damage_status) - - def occupyNode(self, node_name, occupier_name): # noqa: N802 - """Put adds node and its occupier in occupency list - - Parameters - ---------- - node_name : string - Node ID. - occupier_name : string - occupier's name'. - - Raises - ------ - ValueError - If occupier is reused, meaning that occupier is busy somewhere else. - - Returns - ------- - None. - - """ # noqa: D400, DOC202, RUF100 - if occupier_name in self._occupancy: - # if not iNodeCoupled(node_name): - raise ValueError( # noqa: TRY003 - 'Occupier name already in the list. Forget to remove another occupancy or double adding?' # noqa: EM101 - ) - self._occupancy = self._occupancy.append( - pd.Series(data=occupier_name, index=[node_name]) - ) - - def removeOccupancy(self, occupier_name): # noqa: N802 - """Removes occupency in the node by occupier's name. - - Parameters - ---------- - occupier_name : string - Occupier's name that is evacuating the node(s). - - Raises - ------ - ValueError - If the occupier's is not in occupency's name. - - Returns - ------- - None. - - """ # noqa: D401, DOC202, RUF100 - temp = self._occupancy[self._occupancy == occupier_name] - - if len(temp) == 0: - raise ValueError('there is no node occupied with this occupier name') # noqa: EM101, TRY003 - - ind = temp.index.tolist() - self._occupancy = self._occupancy.drop(ind) - - def whoOccupiesIn(self, node_name): # noqa: N802 - """Gets name of the occupier - - Parameters - ---------- - node_name : string - node ID. - - Returns - ------- - string - Occupier's name. - - """ # noqa: D400, D401 - return self._occupancy[node_name] - - def whereIsOccupiedByName(self, occupier_name): # noqa: N802 - """Gets node(s) occupied by occupier - - Parameters - ---------- - occupier_name : string - occupier's name. - - Raises - ------ - ValueError - if occupier is not occupying any node. - - Returns - ------- - str or series - node(s) ID. - - """ # noqa: D400, D401, DOC202, RUF100 - temp = self._occupancy[self._occupancy == occupier_name] - if len(temp) == 0: - raise ValueError('there is no occupancy with this name') # noqa: EM101, TRY003 - - def getListofFreeRepairAgents(self): # noqa: N802 - """MAYBE NOT NEEDED Gets a list of free agents. Not needed anymore. - - Returns - ------- - Free_RepairAgents : TYPE - DESCRIPTION. - - """ - working_RepairAgents = set(self._occupancy.tolist()) # noqa: N806 - RepairAgentsNameList = self._pipe_RepairAgentNameRegistry # noqa: N806 - Free_RepairAgents = [ # noqa: N806 - name for name in RepairAgentsNameList if name not in working_RepairAgents - ] - return Free_RepairAgents # noqa: RET504 - - def coupleTwoBreakNodes(self, break_point_1_name, break_point_2_name): # noqa: N802 - """Couples two nodes in registry for the time which we have a break. - PLEASE NOTE THAT THE FIRST NODE MUST BE THE ONE CONNECTED TO THE - MAIN(ORIGINAL) PIPE THAT IS BROKEN NOW. - - Parameters - ---------- - break_point_1_name : STR - First broken node(connected to the original node) - break_point_2_name : STR - Second node. - - Returns - ------- - None. - - """ # noqa: D205, DOC202, RUF100 - self._pipe_break_node_coupling[break_point_1_name] = break_point_2_name - self._pipe_break_node_coupling[break_point_2_name] = break_point_1_name - self._break_point_attached_to_mainPipe.append(break_point_1_name) - - def getCoupledBreakNode(self, break_point_name): # noqa: N802 - """Gets the coupled node given the first coupled node, and checks if the - given coupled node is connected to the main pipe. - - Parameters - ---------- - break_point_name : str - Node name - - Returns - ------- - out1 : str - the other coupled node name - is_breakPoint_1_attacjedToMainPipe : bool - If the given (first node) is the one connected to the main(original) - pipe - - """ # noqa: D205, D401 - out1 = self._pipe_break_node_coupling[break_point_name] - is_breakPoint_1_attacjedToMainPipe = ( # noqa: N806 - break_point_name in self._break_point_attached_to_mainPipe - ) - return out1, is_breakPoint_1_attacjedToMainPipe - - def iNodeCoupled(self, node_name): # noqa: N802, D102 - return node_name in self._pipe_break_node_coupling - - def iDamagedPipeReminded(self): # noqa: N802, D102 - damaged_nodes = self._pipe_node_damage_status.index - if len(damaged_nodes) == 0: - return False - is_reminded = False - for node_name in iter(damaged_nodes): - if node_name not in self._occupancy.index: - is_reminded = True - return is_reminded # noqa: RET504 - return is_reminded - - def getOtherCoupledBreakPoint(self, node_name): # noqa: N802, D102 - return self._pipe_break_node_coupling[node_name] - - def removeCoupledBreakNodes(self, break_point_name): # noqa: N802 - """Removes the coupled - - Parameters - ---------- - break_point_name : str - Name of either one of a couple break points. - - Returns - ------- - first : str - Name of first node(coonected to the mnain pipe). - second : str - Name of second node(connected to the pipe created after break) - - """ # noqa: D400, D401 - other_coupled_break_point = self._pipe_break_node_coupling.pop( - break_point_name - ) - self._pipe_break_node_coupling.pop(other_coupled_break_point) - # self._break_node_coupling.pop(break_point_name) - - i_in_list = break_point_name in self._break_point_attached_to_mainPipe - if i_in_list: - self._break_point_attached_to_mainPipe.remove(break_point_name) - first = break_point_name - second = other_coupled_break_point - else: - first = other_coupled_break_point - second = break_point_name - return first, second - - def recordPipeDamageTable(self, stop_time): # noqa: N802, D102 - if self.settings['result_details'] == 'minimal': - return None - if stop_time in self._pipe_damage_table_history: - return ValueError('Time exists in pipe damage hostry: ' + str(stop_time)) - self._pipe_damage_table_history['stop_time'] = ( # noqa: RET503 - self._pipe_damage_table_history - ) - - def getMostLeakAtCheck(self, real_node_name_list, element_type): # noqa: N802, D102 - if element_type == 'DISTNODE': - total_demand = self._node_damage_table.loc[ - real_node_name_list, 'Demand2' - ] - total_demand.loc[total_demand[total_demand.isna()].index] = 0 - return total_demand - elif element_type == 'PIPE': # noqa: RET505 - leak = self._pipe_damage_table.loc[real_node_name_list, 'LeakAtCheck'] - leak.loc[leak[leak.isna()].index] = 0 - return leak - else: - return None diff --git a/modules/systemPerformance/REWET/REWET/restoration/restorationlog.py b/modules/systemPerformance/REWET/REWET/restoration/restorationlog.py deleted file mode 100644 index 5098acb3a..000000000 --- a/modules/systemPerformance/REWET/REWET/restoration/restorationlog.py +++ /dev/null @@ -1,178 +0,0 @@ -"""Created on Sun Jan 31 21:54:19 2021 - -@author: snaeimi -""" # noqa: INP001, D400 - -from collections import OrderedDict - -import pandas as pd - - -class RestorationLog: # noqa: D101 - def __init__(self, settings): - self.settings = settings - self._agent_state_log_book = pd.DataFrame( - columns=[ - 'Time', - 'Name', - 'Type', - 'Lable', - 'Action', - 'EFN', - 'MN', - 'Location', - 'X', - 'Y', - ] - ) - self._agent_action_log_book = pd.DataFrame( - columns=[ - 'Agent', - 'Node', - 'Entity', - 'Action', - 'Time', - 'End_time', - 'Travel_time', - 'effect_definition_name', - 'method_name', - 'iFinished', - ] - ) - self.crew_history = OrderedDict() - - def updateAgentHistory(self, agent_table, time): # noqa: N802, D102 - if self.settings['record_restoration_agent_logs'] == False: # noqa: E712 - return - - self.crew_history[time] = agent_table.copy() - - def updateAgentLogBook(self, agent_table, time): # noqa: N802, D102 - if self.settings['record_restoration_agent_logs'] == False: # noqa: E712 - return - - for agent_name, line in agent_table.iterrows(): # noqa: B007 - temp = None - if line['active'] == True and line['ready'] == False: # noqa: E712 - data = line['data'] - _x = data.current_location.coord.x - _y = data.current_location.coord.y - _name = data.name - _type = data.agent_type - _lable = data.cur_job_entity - _action = data.cur_job_action - _EFN = data.cur_job_effect_definition_name # noqa: N806 - _MN = data.cur_job_method_name # noqa: N806 - _loc = data.cur_job_location - - temp = pd.Series( - data=[ - int(time), - _name, - _type, - _lable, - _action, - _EFN, - _MN, - _loc, - _x, - _y, - ], - index=[ - 'Time', - 'Name', - 'Type', - 'Lable', - 'Action', - 'EFN', - 'MN', - 'Location', - 'X', - 'Y', - ], - ) - - # if temp != None: - self._agent_state_log_book = self._agent_state_log_book.append( - temp, ignore_index=True - ) - - def addAgentActionToLogBook( # noqa: N802, D102 - self, - agent_name, - node_name, - entity, - action, - time, - end_time, - travel_time, - effect_definition_name, - method_name, - iFinished=True, # noqa: FBT002, N803 - ): - if self.settings['record_restoration_agent_logs'] == False: # noqa: E712 - return - - temp = pd.Series( - data=[ - agent_name, - node_name, - entity, - action, - time, - end_time, - travel_time, - effect_definition_name, - method_name, - iFinished, - ], - index=[ - 'Agent', - 'Node', - 'Entity', - 'Action', - 'Time', - 'End_time', - 'Travel_time', - 'effect_definition_name', - 'method_name', - 'iFinished', - ], - ) - self._agent_action_log_book = self._agent_action_log_book.append( - temp, ignore_index=True - ) - - def addEndTimegentActionToLogBook(self, agent_name, time, modified_end_time): # noqa: N802, D102 - if self.settings['record_restoration_agent_logs'] == False: # noqa: E712 - return - - temp = self._agent_action_log_book[['Agent', 'Time']] == [agent_name, time] - temp = self._agent_action_log_book[temp.all(1)] - - if len(temp) > 1: - raise ValueError( # noqa: TRY003 - 'There are too many agents record with the same time and name' # noqa: EM101 - ) - - elif len(temp) == 0: # noqa: RET506 - raise ValueError( # noqa: TRY003 - 'There is not agent agent record with this time and name' # noqa: EM101 - ) - - ind = temp.index - - self._agent_action_log_book.loc[ind, 'Modified_end_time'] = modified_end_time - - -# ============================================================================= -# def getAgentActioLogBookat(self, time, end_time=True): -# res=None -# -# if end_time==True: -# res=self._agent_action_log_book[self._agent_action_log_book['Modified_end_time']==time] -# else: -# res=self._agent_action_log_book[self._agent_action_log_book['Time']==time] -# -# return res -# ============================================================================= diff --git a/modules/systemPerformance/REWET/REWET/timeline.py b/modules/systemPerformance/REWET/REWET/timeline.py deleted file mode 100644 index fa1a875ab..000000000 --- a/modules/systemPerformance/REWET/REWET/timeline.py +++ /dev/null @@ -1,374 +0,0 @@ -"""Created on Sat Dec 26 02:00:40 2020 - -@author: snaeimi -""" # noqa: D400 - -import logging - -import numpy # noqa: ICN001 -import pandas as pd - -logger = logging.getLogger(__name__) - -EVENT_TYPE = ['dmg', 'rpr', 'rst'] # event types are defined here - - -class Timeline: # noqa: D101 - # ============================================================================= - # This class has many functions that can make a lot of exceptions. - # We need to modify their codes, so their usage be safe and bug-free. - # ============================================================================= - - def __init__(self, simulation_end_time, restoration, registry): - if simulation_end_time < 0: - raise ValueError('simulation end time must be zero or bigger than zero') # noqa: EM101, TRY003 - self._current_time = 0 - self._event_time_register = pd.DataFrame( - dtype='bool' - ) # create event at time 0 with No event marked as True - # print(type(self._event_time_register)) - self._event_time_register.loc[0, EVENT_TYPE] = [ - False for i in range(len(EVENT_TYPE)) - ] # create event at time 0 with No event marked as True - self._event_time_register.loc[simulation_end_time, EVENT_TYPE] = [ - False for i in range(len(EVENT_TYPE)) - ] # create event at time simulation end time with No event marked as True - self.restoration = restoration - self._simulation_end_time = simulation_end_time - self._ending_Event_ignore_time = ( - 0 # in seconds - events in less than this value is ignored - ) - self._iFirst_time_zero = True - self._current_time_indexOfIndex = 0 - self.registry = registry - - def iContinue(self): # noqa: N802, D102 - if ( - self._current_time == 0 and self._iFirst_time_zero == True # noqa: E712 - ): # So that the other condition happens - self._iFirst_time_zero = False - - else: - self._current_time = self.getNextTime() - self._current_time_indexOfIndex += 1 - if abs(self._simulation_end_time - self._current_time) <= abs( - self._ending_Event_ignore_time - ): - print('End_Time_Reached') # noqa: T201 - return False - - simulation_minimum_time = self.restoration._registry.settings[ # noqa: SLF001 - 'minimum_simulation_time' - ] - minimum_simulation_time_satisfied = ( - self._current_time >= simulation_minimum_time - ) - consider_last_sequence_termination = self.registry.settings.process[ - 'last_sequence_termination' - ] - consider_node_demand_temination = self.registry.settings.process[ - 'node_demand_temination' - ] - - if minimum_simulation_time_satisfied == True: # noqa: E712 - if consider_last_sequence_termination == True: # noqa: E712 - if self.restoration.iRestorationStopTime(): - print('Last_sequence_termination') # noqa: T201 - return False - - if consider_node_demand_temination == True: # noqa: E712 - if self.iFunctionalityRequirementReached(): - print('FunctionalityRequirementReached') # noqa: T201 - return False - - return True - - def getNextTime(self): # noqa: N802, D102 - if ( - not self._event_time_register.index.is_monotonic_increasing - ): # for just in case if the index of event time register is not sorted - self._event_time_register.sort_index() - - if ( - self._event_time_register.index[self._current_time_indexOfIndex] - != self._current_time - ): - raise RuntimeError( # noqa: TRY003 - 'A possible violation of time in timeline event variables and/or event time registry' # noqa: EM101 - ) - next_time = self._event_time_register.index[ - self._current_time_indexOfIndex + 1 - ] - return next_time # noqa: RET504 - - def getCurrentStopTime(self): # noqa: N802, D102 - return int(self._current_time) - - def iCurrentTimeRepairEvent(self): # noqa: N802, D102 - return self._event_time_register['rpr'].loc[self._current_time] - - def iCurenttimeRestorationEvent(self): # noqa: N802, D102 - print('current_time is= ' + str(self._current_time)) # noqa: T201 - print(self._event_time_register['rst'].loc[self._current_time]) # noqa: T201 - return self._event_time_register['rst'].loc[self._current_time] - - def iCurrentTimeDamageEvent(self): # noqa: N802, D102 - return self._event_time_register['dmg'].loc[self._current_time] - - def addEventTime(self, event_distinct_time, event_type='dmg'): # noqa: N802 - """This function is a low-level function to add event type in an already- - existing event_time in event_time_register. FOR NOW THE DISTINCT TIMES - CAN BE A LIST OR A LIST. MAYBE IN THE FUTURE WE CAN DECIDE WEATHER IT - SHOULD BE LEFT THE WAY IT IS OR IT SHOULD BE MODIFIED IN A SINGLE - VARIABLE OR LIST VARIABLE. - - Parameters - ---------- - event_distinct_time : numpy.float64 or int or float or list - This variable is either a list or a seriest of data to represent - time of an specified event - - event_type : str, optional - Evenet type. FOR CURRENT VERSSION AN EVENT COULD BE EIOTHER - dmg(damage) or rpr(repair). The default is 'dmg'. - - Raises - ------ - ValueError - If the input variable for distinct time or the type of event is not - recognizabe, a Valueerrorr exception is raised - Also if the damage typeis not recognized - - Returns - ------- - None. - - """ # noqa: D205, D401, D404, DOC202, RUF100 - if type(event_distinct_time) != pd.core.series.Series: # noqa: E721 - if ( - type(event_distinct_time) == numpy.float64 # noqa: E721 - or type(event_distinct_time) == int # noqa: E721 - or type(event_distinct_time) == float # noqa: E721 - or type(event_distinct_time) == list # noqa: E721 - ): - event_distinct_time = pd.Series( - data=event_distinct_time, dtype='int64' - ) - else: - print(type(event_distinct_time)) # noqa: T201 - raise ValueError('event_distinct_time must be pandas.Series type') # noqa: EM101, TRY003 - - if event_type not in EVENT_TYPE: - raise ValueError('unrecognized value for event_type') # noqa: EM101, TRY003 - - # check for duplicate in time index. if there is duplicate, we will only change the true and false value in the DataFrame - temp_to_pop = [] - logger.debug('event distinct time ' + repr(event_distinct_time)) # noqa: G003 - - for i, i_time in event_distinct_time.items(): # noqa: B007, PERF102 - if i_time in self._event_time_register.index: - self._event_time_register.loc[i_time, event_type] = True - self.checkAndAmendTime() - temp_to_pop.append(i_time) - logger.debug('temp_to_pop' + repr(temp_to_pop)) # noqa: G003 - - for i_time in temp_to_pop: - ind = event_distinct_time[event_distinct_time == i_time].index[0] - event_distinct_time.pop(ind) - - if len(event_distinct_time) != 0: - for i, i_time in event_distinct_time.items(): # noqa: PERF102 - self._event_time_register.loc[i_time, EVENT_TYPE] = [ - False for i in range(len(EVENT_TYPE)) - ] - self._event_time_register.loc[i_time, event_type] = True - self._event_time_register = self._event_time_register.sort_index() - self.checkAndAmendTime() - - def iEventTypeAt(self, begin_time, event_type): # noqa: N802 - """Checks if an event type is in event registry at the time of begin_time - ---------- - begin_time : int - beginning time - event_type : str - damage type - - Returns - ------- - bool - rResult if such data exist or not - - """ # noqa: D205, D400, D401 - if begin_time not in self._event_time_register.index: - return False - if self._event_time_register[event_type].loc[begin_time]: # noqa: SIM103 - return True - else: # noqa: RET505 - return False - - def checkAndAmendTime(self): # noqa: N802 - """Checks if the time of event is higher than the sim time.Also checks - if the the ending event has any thing event(nothings must be true). - - Parameters - ---------- - None. - - Returns - ------- - None. - - """ # noqa: D205, D401, DOC202, RUF100 - first_length = len(self._event_time_register.index) - self._event_time_register = self._event_time_register[ - self._event_time_register.index <= self._simulation_end_time - ] - if first_length > len(self._event_time_register): - print( # noqa: T201 - 'here was ' - + repr(first_length - len(self._event_time_register)) - + 'amended' - ) - - # Sina: I removed the following code at the time for immigration to - # Pandas 1.5.2. Not only it is not efficient piece of code, but also - # this not required. The end time event is already made when the event - # table is created. - # if self._event_time_register[self._event_time_register.index==self._simulation_end_time].empty==True: - # self._event_time_register=self._event_time_register.append(pd.DataFrame(data = False , index = [self._simulation_end_time], columns = EVENT_TYPE)) - - def iFunctionalityRequirementReached(self): # noqa: C901, N802, D102 - logger.debug('Func: node functionality') - ratio_criteria = self.registry.settings.process[ - 'node_demand_termination_ratio' - ] - time_window = self.registry.settings.process.settings[ - 'node_demand_termination_time' - ] - stop_time = self.getCurrentStopTime() - if self.registry.if_first_event_occured == False: # noqa: RET503, E712 - return False - - elif self.registry.if_first_event_occured == True: # noqa: RET505, E712 - if self.registry.result == None: # noqa: E711 - return False - - # for checking if we have still any leak in the system, since we - # cannot measure the effect of exessive leak in the LDN - if stop_time in self.registry.result.node['leak'].index: - return False - - last_pre_event_time = self.registry.pre_event_demand_met.index.max() - pre_event_demand = self.registry.pre_event_demand_met[ - self.registry.pre_event_demand_met.index - <= (last_pre_event_time - time_window) - ] - demand_met = self.registry.result.node['demand'] - begining_time_window = stop_time - time_window - demand_met = demand_met.loc[demand_met.index > begining_time_window] - - """ - calculating required demand for each demand node - """ - - # demand_ratio = self.registry.settings['demand_ratio'] - time_index = demand_met.index - req_node_demand = {} - default_pattern = self.registry.wn.options.hydraulic.pattern - # node_pattern_list = pd.Series(index=self.registry.demand_node_name_list, dtype=str) - - # req_node_demand = req_node_demand.transpose() - - demand_nodes_list = [ - self.registry.wn.get_node(node_name) - for node_name in self.registry.demand_node_name_list - ] - - if default_pattern is not None: - node_pattern_list = [ - (node.name, node.demand_timeseries_list.pattern_list()[0]) - if node.demand_timeseries_list.pattern_list()[0] != None # noqa: E711 - else (node.name, default_pattern) - for node in demand_nodes_list - ] - else: - node_pattern_list = [ - (node.name, node.demand_timeseries_list.pattern_list()[0]) - for node in demand_nodes_list - if node.demand_timeseries_list.pattern_list()[0] != None # noqa: E711 - ] - - base_demand_list = [node.base_demand for node in demand_nodes_list] - one_time_base_demand = dict( - zip(self.registry.demand_node_name_list, base_demand_list) - ) - req_node_demand = pd.DataFrame.from_dict( - [one_time_base_demand] * len(time_index) - ) - req_node_demand.index = time_index - - req_node_demand = pd.DataFrame.from_dict(req_node_demand) - - # node_pattern_list = node_pattern_list.dropna() - if len(node_pattern_list) > 0: - node_pattern_list = pd.Series( - index=[ - node_pattern_iter[0] - for node_pattern_iter in node_pattern_list - ], - data=[ - node_pattern_iter[1] - for node_pattern_iter in node_pattern_list - ], - ) - patterns_list = node_pattern_list.unique() - multiplier = pd.DataFrame( - index=time_index, columns=list(patterns_list) - ) - - for pattern_name in patterns_list: - cur_pattern = self.registry.wn.get_pattern(pattern_name) - time_index = time_index.unique() - cur_patern_time = [ - cur_pattern.at(time) for time in iter(time_index) - ] - multiplier.loc[:, pattern_name] = cur_patern_time - - for node_name, pattern_name in node_pattern_list.items(): - cur_node_req_demand = ( - multiplier[pattern_name] - * self.registry.wn.get_node(node_name) - .demand_timeseries_list[0] - .base_value - ) - cur_node_req_demand.name = node_name - cur_node_req_demand = pd.DataFrame( - cur_node_req_demand - ).transpose() - req_node_demand = pd.concat( - [req_node_demand, cur_node_req_demand] - ) - - # print(req_node_demand) - # raise - # req_node_demand = req_node_demand.transpose() - req_node_demand = req_node_demand.filter( - self.registry.demand_node_name_list - ) - req_node_demand = req_node_demand.filter(pre_event_demand.columns) - demand_met = demand_met.filter(self.registry.demand_node_name_list) - demand_met = demand_met.filter(pre_event_demand.columns) - demand_met = demand_met.dropna(axis=1) - - pre_event_demand = demand_met.filter(self.registry.demand_node_name_list) - - if len(demand_met.columns) < len(pre_event_demand.columns): - return False - - ratio = demand_met.mean() / pre_event_demand.mean() - mean_of_ratio_satisfied = (ratio >= ratio_criteria).sum() / len(ratio) - logger.debug('ratio that is= ' + repr(mean_of_ratio_satisfied)) # noqa: G003 - if (ratio >= ratio_criteria).all(): # noqa: SIM103 - return True - else: # noqa: RET505 - return False diff --git a/modules/systemPerformance/REWET/REWET_Wrapper.py b/modules/systemPerformance/REWET/REWET_Wrapper.py index 9285f2021..2e7e5a7f9 100644 --- a/modules/systemPerformance/REWET/REWET_Wrapper.py +++ b/modules/systemPerformance/REWET/REWET_Wrapper.py @@ -56,9 +56,9 @@ this_dir = Path(os.path.dirname(os.path.abspath(__file__))).resolve() # noqa: PTH100, PTH120 # TODO (SINA): Import REWET instead and check these -sys.path.insert(0, str(this_dir / 'REWET')) -from initial import Starter # noqa: E402 -from Result_Project import Project_Result # noqa: E402 +# sys.path.insert(0, str(this_dir / 'REWET')) +from rewet.initial import Starter # noqa: E402 +from rewet.result import Result # noqa: E402 PAR_CERITERIA = 2 @@ -604,7 +604,7 @@ def create_path(path): REWET_starter = Starter() REWET_starter.run(settings_json_file_path) - p = Project_Result( + p = Result( Path(rewet_input_data['settings']['result_directory']) / 'project.prj' )