diff --git a/src/pyaedt/workflows/project/DCIR_with_Ptree.py b/src/pyaedt/workflows/project/DCIR_with_Ptree.py new file mode 100644 index 00000000000..2144b5484ee --- /dev/null +++ b/src/pyaedt/workflows/project/DCIR_with_Ptree.py @@ -0,0 +1,816 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +#Author:Hehe +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +import tkinter as tk +from tkinter import ttk, messagebox, filedialog +import os +import json +import csv +import subprocess +import xml.etree.ElementTree as ET +from pyedb import Edb +import core_logic # Import the core logic module + +AEDT_VERSION = "2025.1" +NG_MODE = False + +class PyAEDTGUI: + def __init__(self, root): + self.root = root + self.root.title("Py_DC_" + AEDT_VERSION) + + # Initialize EDB object as None + self.edb = None + + # Bind window close event + self.root.protocol("WM_DELETE_WINDOW", self.on_closing) + + # Main frame + self.main_frame = ttk.Frame(self.root, padding="10") + self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) + + # EDB file path + ttk.Label(self.main_frame, text="EDB File Path:").grid(row=0, column=0, sticky=tk.W) + self.edb_path_var = tk.StringVar(value=r"D:\PycharmProjects\Pyaedt_scripts\example\ANSYS_HSD_V1.aedb") + ttk.Entry(self.main_frame, textvariable=self.edb_path_var, width=40).grid(row=0, column=1, sticky=(tk.W, tk.E)) + ttk.Button(self.main_frame, text="Browse", command=self.browse_edb).grid(row=0, column=2) + + # PowerTree parameters (horizontal layout) + power_tree_frame = ttk.Frame(self.main_frame) + power_tree_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E)) + + ttk.Label(power_tree_frame, text="VRM RefDes:").grid(row=0, column=0, sticky=tk.W) + self.vrm_refdes_var = tk.StringVar(value="PQ77") + ttk.Entry(power_tree_frame, textvariable=self.vrm_refdes_var, width=10).grid(row=0, column=1, sticky=tk.W) + + ttk.Label(power_tree_frame, text="Sink RefDes:").grid(row=0, column=2, sticky=tk.W) + self.sink_refdes_list_var = tk.StringVar(value="U*,CN*") + ttk.Entry(power_tree_frame, textvariable=self.sink_refdes_list_var, width=20).grid(row=0, column=3, sticky=tk.W) + + ttk.Label(power_tree_frame, text="Target Nets:").grid(row=0, column=4, sticky=tk.W) + self.target_power_nets_var = tk.StringVar(value="") + ttk.Entry(power_tree_frame, textvariable=self.target_power_nets_var, width=20).grid(row=0, column=5, sticky=tk.W) + + ttk.Label(power_tree_frame, text="Ground Nets:").grid(row=0, column=6, sticky=tk.W) + self.ground_nets_var = tk.StringVar(value="GND") + ttk.Entry(power_tree_frame, textvariable=self.ground_nets_var, width=10).grid(row=0, column=7, sticky=tk.W) + + # Intermediate Component Prefixes input + ttk.Label(power_tree_frame, text="Intermediate Components:").grid(row=0, column=8, sticky=tk.W) + self.intermediate_prefixes_var = tk.StringVar(value="PL,L,PJ,PQ") + ttk.Entry(power_tree_frame, textvariable=self.intermediate_prefixes_var, width=15).grid(row=0, column=9, sticky=tk.W) + + # PowerTree buttons and output + ttk.Button(self.main_frame, text="Plot PowerTree", command=self.plot_power_tree).grid(row=2, column=1, pady=5) + ttk.Button(self.main_frame, text="Apply PowerTree", command=self.apply_power_tree).grid(row=2, column=2, pady=5) + + ttk.Label(self.main_frame, text="PowerTree Paths:").grid(row=3, column=0, sticky=tk.W) + self.powertree_text = tk.Text(self.main_frame, height=10, width=50) + self.powertree_text.grid(row=3, column=1, columnspan=2, sticky=(tk.W, tk.E)) + + # Voltage Source and Current Sources (horizontal layout) + sources_frame = ttk.Frame(self.main_frame) + sources_frame.grid(row=4, column=0, columnspan=3, sticky=(tk.W, tk.E)) + + # Voltage Sources (using tabs for multiple VRMs) + self.voltage_frame = ttk.LabelFrame(sources_frame, text="Voltage Sources by VRM", padding="5") + self.voltage_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=5) + + # Configure vertical tab style + style = ttk.Style() + style.configure("Vertical.TNotebook", tabposition="w") + + # Use vertical tabs + self.voltage_notebook = ttk.Notebook(self.voltage_frame, style="Vertical.TNotebook") + self.voltage_notebook.grid(row=0, column=0, columnspan=5) + + # Store VRM data: {vrm_name: {"name": "", "refdes": "", "magnitude": "", "pos_net": "", "neg_net": ""}} + self.vrm_configs = {} + # Store Entry widget references + self.vrm_entries = {} + + # Current Sources + self.current_frame = ttk.LabelFrame(sources_frame, text="Current Sources by Power Net", padding="5") + self.current_frame.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=5) + + # Use vertical tabs + self.current_notebook = ttk.Notebook(self.current_frame, style="Vertical.TNotebook") + self.current_notebook.grid(row=0, column=0, columnspan=5) + + self.power_net_sinks = {} # {power_net: [{"refdes": "", "magnitude": ""}, ...]} + self.tab_treeviews = {} # Store Treeview references + self.update_current_notebook() + + # Magnitude textbox and Apply button + ttk.Label(self.current_frame, text="Magnitude (A):").grid(row=2, column=0, pady=5) + self.magnitude_var = tk.StringVar(value="10") + ttk.Entry(self.current_frame, textvariable=self.magnitude_var, width=10).grid(row=2, column=1, pady=5) + ttk.Button(self.current_frame, text="Apply", command=self.apply_magnitude_to_all_sinks).grid(row=2, column=2, pady=5) + + # Other buttons + ttk.Button(self.current_frame, text="Add Net", command=self.add_power_net).grid(row=1, column=0, pady=5) + ttk.Button(self.current_frame, text="Add Sink", command=self.add_sink_to_net).grid(row=1, column=1, pady=5) + ttk.Button(self.current_frame, text="Remove Sink", command=self.remove_sink_from_net).grid(row=1, column=2, pady=5) + ttk.Button(self.current_frame, text="Remove Net", command=self.remove_power_net).grid(row=1, column=3, pady=5) + + # Intermediate components display + self.intermediate_frame = ttk.LabelFrame(sources_frame, text="Intermediate Components by Part Name", padding="5") + self.intermediate_frame.grid(row=0, column=2, sticky=(tk.W, tk.E), padx=5) + + # Use vertical tabs + self.intermediate_notebook = ttk.Notebook(self.intermediate_frame, style="Vertical.TNotebook") + self.intermediate_notebook.grid(row=0, column=0, sticky=(tk.W, tk.E)) + + # Scrollbar (if needed) + scrollbar = ttk.Scrollbar(self.intermediate_frame, orient=tk.VERTICAL) + scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S)) + + # R_value textbox and Apply button + self.rvalue_frame = ttk.LabelFrame(self.intermediate_frame, text="Set R_value", padding="5") + self.rvalue_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=5) + + ttk.Label(self.rvalue_frame, text="R_value (mOhm):").grid(row=0, column=0, padx=5) + self.rvalue_var = tk.StringVar(value="1") + ttk.Entry(self.rvalue_frame, textvariable=self.rvalue_var, width=10).grid(row=0, column=1, padx=5) + ttk.Button(self.rvalue_frame, text="Apply", command=self.apply_rvalue_to_all_components).grid(row=0, column=2, padx=5) + + # Plating Thickness settings + self.plating_frame = ttk.LabelFrame(sources_frame, text="Padstack Plating Thickness", padding="5") + self.plating_frame.grid(row=0, column=3, sticky=(tk.W, tk.E), padx=5) + + ttk.Label(self.plating_frame, text="Thickness:").grid(row=0, column=0) + self.plating_thickness_var = tk.StringVar(value="25") + ttk.Entry(self.plating_frame, textvariable=self.plating_thickness_var, width=10).grid(row=0, column=1) + + # Unit selection dropdown + self.plating_unit_var = tk.StringVar(value="um") + ttk.Combobox(self.plating_frame, textvariable=self.plating_unit_var, values=("um", "mil", "mm"), width=5, state="readonly").grid(row=0, column=2) + + ttk.Label(self.plating_frame, text="(e.g., 25 um = 0.025e-3 m)").grid(row=1, column=0, columnspan=3) + + # Stackup editor + ttk.Label(self.main_frame, text="Stackup:").grid(row=5, column=0, sticky=tk.W) + self.stackup_frame = ttk.LabelFrame(self.main_frame, text="Layers", padding="5") + self.stackup_frame.grid(row=5, column=1, sticky=(tk.W, tk.E)) + + # Checkbutton for stackup inclusion + self.generate_stackup_var = tk.BooleanVar(value=False) + ttk.Checkbutton(self.stackup_frame, text="Include Stackup in Config", variable=self.generate_stackup_var).grid(row=0, column=0, columnspan=4, sticky=tk.W) + + self.stackup_tree = ttk.Treeview(self.stackup_frame, columns=("Name", "Type", "Material", "Fill Material", "Thickness"), show="headings") + self.stackup_tree.heading("Name", text="Name") + self.stackup_tree.heading("Type", text="Type") + self.stackup_tree.heading("Material", text="Material") + self.stackup_tree.heading("Fill Material", text="Fill Material") + self.stackup_tree.heading("Thickness", text="Thickness") + self.stackup_tree.grid(row=1, column=0, columnspan=4) + + ttk.Button(self.stackup_frame, text="Add Layer", command=self.add_layer).grid(row=2, column=0, pady=5) + ttk.Button(self.stackup_frame, text="Delete Layer", command=self.delete_layer).grid(row=2, column=1, pady=5) + ttk.Button(self.stackup_frame, text="Load CSV", command=self.load_csv).grid(row=2, column=2, pady=5) + ttk.Button(self.stackup_frame, text="Load XML", command=self.load_xml).grid(row=2, column=3, pady=5) + + # Siwave Setup and Cutout Operations + setup_operations_frame = ttk.Frame(self.main_frame) + setup_operations_frame.grid(row=6, column=0, columnspan=3, sticky=(tk.W, tk.E)) + + # Setups configuration + self.setup_frame = ttk.LabelFrame(setup_operations_frame, text="SIwave Setup", padding="5") + self.setup_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=5) + + ttk.Label(self.setup_frame, text="Name:").grid(row=0, column=0) + self.setup_name_var = tk.StringVar(value="siwave_1") + ttk.Entry(self.setup_frame, textvariable=self.setup_name_var).grid(row=0, column=1) + + ttk.Label(self.setup_frame, text="DC Slider:").grid(row=1, column=0) + self.dc_slider_var = tk.StringVar(value="1") + ttk.Entry(self.setup_frame, textvariable=self.dc_slider_var).grid(row=1, column=1) + + ttk.Label(self.setup_frame, text="Export Thermal:").grid(row=2, column=0) + self.export_thermal_var = tk.BooleanVar(value=True) + ttk.Checkbutton(self.setup_frame, variable=self.export_thermal_var).grid(row=2, column=1) + + # Operations configuration + self.operations_frame = ttk.LabelFrame(setup_operations_frame, text="Cutout Operations", padding="5") + self.operations_frame.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=5) + + ttk.Label(self.operations_frame, text="Signal List:").grid(row=0, column=0) + self.signal_list_var = tk.StringVar(value="1V0") + ttk.Entry(self.operations_frame, textvariable=self.signal_list_var, width=30).grid(row=0, column=1) + + ttk.Label(self.operations_frame, text="Ref List:").grid(row=1, column=0) + self.ref_list_var = tk.StringVar(value="GND") + ttk.Entry(self.operations_frame, textvariable=self.ref_list_var, width=30).grid(row=1, column=1) + + ttk.Label(self.operations_frame, text="Extent Type:").grid(row=2, column=0) + self.extent_type_var = tk.StringVar(value="ConvexHull") + ttk.Entry(self.operations_frame, textvariable=self.extent_type_var, width=30).grid(row=2, column=1) + + ttk.Label(self.operations_frame, text="Expansion:").grid(row=3, column=0) + self.expansion_size_var = tk.StringVar(value="20mm") + ttk.Entry(self.operations_frame, textvariable=self.expansion_size_var, width=30).grid(row=3, column=1) + + # Generated script path + ttk.Label(self.main_frame, text="Generated Script:").grid(row=7, column=0, sticky=tk.W) + self.script_path_var = tk.StringVar(value="Not generated yet") + ttk.Entry(self.main_frame, textvariable=self.script_path_var, width=40).grid(row=7, column=1, sticky=(tk.W, tk.E)) + ttk.Button(self.main_frame, text="Browse", command=self.browse_script).grid(row=7, column=2) + ttk.Button(self.main_frame, text="Generate Script", command=self.generate_script).grid(row=7, column=3, padx=5) + + # Run button + ttk.Button(self.main_frame, text="Run Script", command=self.run_script).grid(row=8, column=1, pady=5) + + # Store latest PowerTree paths + self.latest_paths = [] + + def update_voltage_notebook(self): + """Update Voltage Source tabs""" + for tab in self.voltage_notebook.tabs(): + self.voltage_notebook.forget(tab) + self.vrm_entries.clear() + for vrm_name, config in self.vrm_configs.items(): + frame = ttk.Frame(self.voltage_notebook) + self.voltage_notebook.add(frame, text=vrm_name) + ttk.Label(frame, text="Name:").grid(row=0, column=0, sticky=tk.W) + name_var = tk.StringVar(value=config["name"]) + ttk.Entry(frame, textvariable=name_var, width=10).grid(row=0, column=1, sticky=tk.W) + ttk.Label(frame, text="Ref Des:").grid(row=1, column=0, sticky=tk.W) + refdes_var = tk.StringVar(value=config["refdes"]) + ttk.Entry(frame, textvariable=refdes_var, width=10).grid(row=1, column=1, sticky=tk.W) + ttk.Label(frame, text="Mag (V):").grid(row=2, column=0, sticky=tk.W) + magnitude_var = tk.StringVar(value=config["magnitude"]) + ttk.Entry(frame, textvariable=magnitude_var, width=10).grid(row=2, column=1, sticky=tk.W) + ttk.Label(frame, text="Pos Net:").grid(row=3, column=0, sticky=tk.W) + pos_net_var = tk.StringVar(value=config["pos_net"]) + ttk.Entry(frame, textvariable=pos_net_var, width=10).grid(row=3, column=1, sticky=tk.W) + ttk.Label(frame, text="Neg Net:").grid(row=4, column=0, sticky=tk.W) + neg_net_var = tk.StringVar(value=config["neg_net"]) + ttk.Entry(frame, textvariable=neg_net_var, width=10).grid(row=4, column=1, sticky=tk.W) + self.vrm_entries[vrm_name] = { + "name": name_var, + "refdes": refdes_var, + "magnitude": magnitude_var, + "pos_net": pos_net_var, + "neg_net": neg_net_var + } + + def on_closing(self): + """Clean up resources on window close""" + self.close_edb() + self.root.destroy() + + def open_edb(self): + """Open EDB object, create new if not initialized""" + if self.edb is None: + edb_path = self.edb_path_var.get() + print(f"Attempting to initialize Edb with path: {edb_path}") + self.edb = Edb(edb_path, edbversion="2025.1") + if self.edb is None: + raise RuntimeError(f"Failed to initialize Edb object with path: {edb_path}") + try: + test_instances = self.edb.components.instances + if test_instances is None: + raise RuntimeError("edb.components.instances is None, EDB data may not be loaded correctly.") + print("Edb initialization verified with components.instances.") + except AttributeError as e: + raise RuntimeError(f"Edb object initialization failed: {str(e)}") + return self.edb + + def close_edb(self): + """Close EDB object and clean up""" + if self.edb is not None: + try: + self.edb.close_edb() + print("Edb closed successfully.") + except Exception as e: + print(f"Failed to close Edb: {str(e)}") + finally: + self.edb = None + + def browse_edb(self): + folder = filedialog.askdirectory(title="Select EDB Folder") + if folder: + if self.edb_path_var.get() != folder: + self.close_edb() + self.edb_path_var.set(folder) + + def browse_script(self): + script_file = filedialog.askopenfilename(title="Select Python Script", filetypes=[("Python files", "*.py")]) + if script_file: + self.script_path_var.set(script_file) + + def add_layer(self): + layer_window = tk.Toplevel(self.root) + layer_window.title("Add Layer") + ttk.Label(layer_window, text="Name:").grid(row=0, column=0) + name_var = tk.StringVar() + ttk.Entry(layer_window, textvariable=name_var).grid(row=0, column=1) + ttk.Label(layer_window, text="Type:").grid(row=1, column=0) + type_var = tk.StringVar(value="signal") + ttk.Combobox(layer_window, textvariable=type_var, values=["signal", "dielectric"]).grid(row=1, column=1) + ttk.Label(layer_window, text="Material:").grid(row=2, column=0) + material_var = tk.StringVar(value="copper") + ttk.Entry(layer_window, textvariable=material_var).grid(row=2, column=1) + ttk.Label(layer_window, text="Fill Material:").grid(row=3, column=0) + fill_material_var = tk.StringVar() + ttk.Entry(layer_window, textvariable=fill_material_var).grid(row=3, column=1) + ttk.Label(layer_window, text="Thickness:").grid(row=4, column=0) + thickness_var = tk.StringVar(value="0.035mm") + ttk.Entry(layer_window, textvariable=thickness_var).grid(row=4, column=1) + def save_layer(): + self.stackup_tree.insert("", tk.END, values=(name_var.get(), type_var.get(), material_var.get(), fill_material_var.get(), thickness_var.get())) + layer_window.destroy() + ttk.Button(layer_window, text="Save", command=save_layer).grid(row=5, column=1, pady=5) + + def delete_layer(self): + selected = self.stackup_tree.selection() + if selected: + self.stackup_tree.delete(selected) + + def load_csv(self): + csv_file = filedialog.askopenfilename(title="Select CSV File", filetypes=[("CSV files", "*.csv")]) + if csv_file: + with open(csv_file, newline='') as f: + reader = csv.DictReader(f) + expected_headers = {"Name", "Type", "Material", "Fill Material", "Thickness"} + if not expected_headers.issubset(reader.fieldnames): + messagebox.showerror("Error", "CSV must contain headers: Name, Type, Material, Fill Material, Thickness") + return + self.stackup_tree.delete(*self.stackup_tree.get_children()) + for row in reader: + self.stackup_tree.insert("", tk.END, values=(row["Name"], row["Type"], row["Material"], row["Fill Material"], row["Thickness"])) + + def load_xml(self): + xml_file = filedialog.askopenfilename(title="Select XML File", filetypes=[("XML files", "*.xml")]) + if xml_file: + try: + tree = ET.parse(xml_file) + root = tree.getroot() + namespace = {"ns0": "http://www.ansys.com/control"} + stackup = root.find(".//ns0:Stackup", namespace) or root.find(".//Stackup") + if stackup is None: + messagebox.showerror("Error", "Invalid XML: Stackup section not found") + return + self.stackup_tree.delete(*self.stackup_tree.get_children()) + self.materials_data = [] + self.stackup_xml_path = xml_file + self.stackup_from_xml = True + materials = stackup.find("Materials", namespace) or stackup.find("Materials") + if materials is not None: + for mat in materials.findall("Material", namespace) or materials.findall("Material"): + name = mat.get("Name") + permittivity = mat.find("Permittivity/Double", namespace) or mat.find("Permittivity/Double") + loss_tangent = mat.find("DielectricLossTangent/Double", namespace) or mat.find("DielectricLossTangent/Double") + conductivity = mat.find("Conductivity/Double", namespace) or mat.find("Conductivity/Double") + mat_dict = {"name": name} + if permittivity is not None: + mat_dict["permittivity"] = float(permittivity.text) + if loss_tangent is not None: + mat_dict["dielectric_loss_tangent"] = float(loss_tangent.text) + if conductivity is not None: + mat_dict["conductivity"] = float(conductivity.text) + self.materials_data.append(mat_dict) + layers = stackup.find("Layers", namespace) or stackup.find("Layers") + if layers is not None: + length_unit = layers.get("LengthUnit", "mil") + unit_to_mm = {"mil": 0.0254, "mm": 1.0, "um": 0.001} + conversion_factor = unit_to_mm.get(length_unit, 0.0254) + for layer in layers.findall("Layer", namespace) or layers.findall("Layer"): + layer_type = layer.get("Type") + if layer_type in ["conductor", "dielectric"]: + name = layer.get("Name") + material = layer.get("Material") + fill_material = layer.get("FillMaterial", "") + thickness = float(layer.get("Thickness", 0)) + thickness_mm = thickness * conversion_factor + self.stackup_tree.insert("", tk.END, values=(name, layer_type, material, fill_material, f"{thickness_mm}mm")) + messagebox.showinfo("Success", "XML loaded successfully!") + except ET.ParseError: + messagebox.showerror("Error", "Invalid XML file format") + except Exception as e: + messagebox.showerror("Error", f"Failed to load XML: {str(e)}") + + def add_power_net(self): + net_window = tk.Toplevel(self.root) + net_window.title("Add Power Net") + ttk.Label(net_window, text="Power Net:").grid(row=0, column=0) + net_var = tk.StringVar() + ttk.Entry(net_window, textvariable=net_var).grid(row=0, column=1) + def save_net(): + power_net = net_var.get().strip() + if power_net and power_net not in self.power_net_sinks: + self.power_net_sinks[power_net] = [] + self.update_current_notebook() + net_window.destroy() + ttk.Button(net_window, text="Save", command=save_net).grid(row=1, column=1, pady=5) + + def add_sink_to_net(self): + net_window = tk.Toplevel(self.root) + net_window.title("Add Sink to Power Net") + ttk.Label(net_window, text="Power Net:").grid(row=0, column=0) + net_var = tk.StringVar() + ttk.Combobox(net_window, textvariable=net_var, values=list(self.power_net_sinks.keys())).grid(row=0, column=1) + ttk.Label(net_window, text="Ref Designator:").grid(row=1, column=0) + refdes_var = tk.StringVar() + ttk.Entry(net_window, textvariable=refdes_var).grid(row=1, column=1) + ttk.Label(net_window, text="Magnitude (A):").grid(row=2, column=0) + magnitude_var = tk.StringVar(value="10") + ttk.Entry(net_window, textvariable=magnitude_var).grid(row=2, column=1) + def save_sink(): + power_net = net_var.get() + if power_net in self.power_net_sinks: + self.power_net_sinks[power_net].append({"refdes": refdes_var.get(), "magnitude": magnitude_var.get()}) + self.update_current_notebook() + net_window.destroy() + ttk.Button(net_window, text="Save", command=save_sink).grid(row=3, column=1, pady=5) + + def remove_sink_from_net(self): + try: + current_tab = self.current_notebook.tab(self.current_notebook.select(), "text") + if not current_tab: + messagebox.showwarning("Warning", "No network selected.") + return + if current_tab not in self.power_net_sinks: + messagebox.showerror("Error", f"Network {current_tab} not found in power_net_sinks.") + return + treeview = self.tab_treeviews.get(current_tab) + if not treeview: + messagebox.showerror("Error", f"Treeview for network {current_tab} not found.") + return + selection = treeview.selection() + if not selection: + messagebox.showwarning("Warning", "No sink selected to remove.") + return + selected_index = treeview.index(selection[0]) + self.power_net_sinks[current_tab].pop(selected_index) + self.update_current_notebook() + messagebox.showinfo("Success", "Sink removed successfully.") + except Exception as e: + messagebox.showerror("Error", f"Failed to remove sink: {str(e)}") + + def remove_power_net(self): + try: + current_tab = self.current_notebook.tab(self.current_notebook.select(), "text") + if not current_tab: + messagebox.showwarning("Warning", "No network selected to remove.") + return + if current_tab in self.power_net_sinks: + del self.power_net_sinks[current_tab] + self.update_current_notebook() + messagebox.showinfo("Success", f"Network {current_tab} removed successfully.") + else: + messagebox.showerror("Error", f"Network {current_tab} not found in power_net_sinks.") + except Exception as e: + messagebox.showerror("Error", f"Failed to remove network: {str(e)}") + + def update_current_notebook(self): + for tab in self.current_notebook.tabs(): + self.current_notebook.forget(tab) + self.tab_treeviews = {} + for power_net, sinks in self.power_net_sinks.items(): + if not sinks: + continue + frame = ttk.Frame(self.current_notebook) + self.current_notebook.add(frame, text=power_net) + treeview_name = f"{power_net.lower()}_treeview" + tree = ttk.Treeview(frame, name=treeview_name, columns=("RefDes", "Magnitude"), show="headings", height=5) + tree.heading("RefDes", text="Ref Designator") + tree.heading("Magnitude", text="Magnitude (A)") + tree.column("RefDes", width=100) + tree.column("Magnitude", width=100) + tree.grid(row=0, column=0, sticky=(tk.W, tk.E)) + tree.bind("", lambda event, t=tree: self.edit_magnitude(event, t)) + for sink in sinks: + tree.insert("", tk.END, values=(sink["refdes"], sink["magnitude"])) + self.tab_treeviews[power_net] = tree + tabs = [self.current_notebook.tab(tab, "text") for tab in self.current_notebook.tabs()] + print(f"Notebook tabs updated with: {tabs}") + + def apply_magnitude_to_all_sinks(self): + try: + new_magnitude = float(self.magnitude_var.get()) + if new_magnitude < 0: + raise ValueError("Magnitude must be non-negative") + for power_net, sinks in self.power_net_sinks.items(): + for sink in sinks: + sink["magnitude"] = str(new_magnitude) + self.update_current_notebook() + messagebox.showinfo("Success", f"All sinks' magnitude set to {new_magnitude} A.") + except ValueError as e: + messagebox.showerror("Error", f"Invalid Magnitude value: {str(e)}") + except Exception as e: + messagebox.showerror("Error", f"Failed to apply magnitude: {str(e)}") + + def edit_magnitude(self, event, tree): + item = tree.identify_row(event.y) + column = tree.identify_column(event.x) + if not item or column != "#2": + return + current_magnitude = tree.set(item, "Magnitude") + bbox = tree.bbox(item, column) + if not bbox: + return + entry = ttk.Entry(tree, width=10) + entry.insert(0, current_magnitude) + entry.place(x=bbox[0], y=bbox[1], width=bbox[2], height=bbox[3]) + def save_edit(event=None): + try: + new_value = float(entry.get()) + if new_value < 0: + raise ValueError("Magnitude must be non-negative") + refdes = tree.set(item, "RefDes") + power_net = self.current_notebook.tab(self.current_notebook.select(), "text") + for sink in self.power_net_sinks[power_net]: + if sink["refdes"] == refdes: + sink["magnitude"] = str(new_value) + tree.set(item, "Magnitude", str(new_value)) + except ValueError as e: + messagebox.showerror("Error", f"Invalid input: {str(e)}") + finally: + entry.destroy() + entry.bind("", save_edit) + entry.bind("", save_edit) + entry.focus_set() + + def generate_config(self): + cfg = {"sources": []} + for vrm_name, config in self.vrm_configs.items(): + entries = self.vrm_entries[vrm_name] + cfg["sources"].append({ + "name": entries["name"].get(), + "reference_designator": entries["refdes"].get(), + "type": "voltage", + "magnitude": float(entries["magnitude"].get()), + "positive_terminal": {"net": entries["pos_net"].get()}, + "negative_terminal": {"net": entries["neg_net"].get()} + }) + first_neg_net = list(self.vrm_configs.values())[0]["neg_net"] if self.vrm_configs else "GND" + for power_net, sinks in self.power_net_sinks.items(): + for sink in sinks: + cfg["sources"].append({ + "name": f"{sink['refdes']}_{power_net}", + "reference_designator": sink['refdes'], + "type": "current", + "magnitude": float(sink["magnitude"]), + "positive_terminal": {"net": power_net}, + "negative_terminal": {"net": first_neg_net} + }) + stackup_from_xml = getattr(self, "stackup_from_xml", False) + if not stackup_from_xml and self.generate_stackup_var.get(): + cfg["stackup"] = {"layers": []} + for item in self.stackup_tree.get_children(): + values = self.stackup_tree.item(item, "values") + cfg["stackup"]["layers"].append({ + "name": values[0], + "type": values[1], + "material": values[2], + "fill_material": values[3], + "thickness": values[4] + }) + cfg["setups"] = [{ + "name": self.setup_name_var.get(), + "type": "siwave_dc", + "dc_slider_position": int(self.dc_slider_var.get()), + }] + cfg["operations"] = { + "cutout": { + "signal_list": self.signal_list_var.get().split(","), + "reference_list": self.ref_list_var.get().split(","), + "extent_type": self.extent_type_var.get(), + "expansion_size": self.expansion_size_var.get() + } + } + return cfg + + def run_script(self): + script_path = self.script_path_var.get() + if not os.path.isfile(script_path): + messagebox.showerror("Error", "Invalid script path! Please generate or select a valid script.") + return + try: + try: + username = os.getlogin() + except OSError: + username = os.environ.get("USERNAME") + if not username: + raise RuntimeError("Unable to determine the current username.") + virtual_env_python = os.path.join(r"C:\Users", username, r"AppData\Roaming\.pyaedt_env\3_10\Scripts\python.exe") + if not os.path.isfile(virtual_env_python): + messagebox.showerror("Error", f"Python interpreter not found at: {virtual_env_python}\nPlease ensure the virtual environment exists on this machine.") + return + env = os.environ.copy() + env["PATH"] = r"C:\Program Files\AnsysEM\AnsysEM25.1\Win64;" + env.get("PATH", "") + result = subprocess.run([virtual_env_python, script_path], check=True, capture_output=True, text=True, env=env) + messagebox.showinfo("Success", f"Script {script_path} executed successfully!\nOutput:\n{result.stdout}") + except subprocess.CalledProcessError as e: + error_message = f"Script execution failed:\nCommand: {' '.join(e.cmd)}\nExit Code: {e.returncode}\nStandard Output:\n{e.stdout}\nStandard Error:\n{e.stderr}" + messagebox.showerror("Error", error_message) + except Exception as e: + messagebox.showerror("Error", f"Unexpected error:\n{str(e)}") + + def set_plating_thickness(self, plating_thickness_m): + """Set Plating Thickness for all Padstacks.""" + script_content = f""" +# Define Plating Thickness (in meters) +plating_thickness_m = {plating_thickness_m} + +# Set Plating Thickness for all Padstacks (only if hole_properties is not empty and hole diameter is not zero) +for padstack in list(edbapp.padstacks.definitions): + edb_padstack = edbapp.padstacks.definitions[padstack] + if edb_padstack.hole_properties and len(edb_padstack.hole_properties) > 0: # 检查 hole_properties 是否为空 + hole_diameter = float(edb_padstack.hole_properties[0]) # 孔径 + if hole_diameter > 0: # 确保孔径不为 0 + edb_padstack.hole_plating_thickness = plating_thickness_m + else: + print(f"Skipping padstack {{padstack}} due to zero hole diameter.") + else: + print(f"Skipping padstack {{padstack}} due to empty hole properties.") +""" + return script_content + + def plot_power_tree(self): + try: + success, result = core_logic.plot_power_tree( + self, + edb_path=self.edb_path_var.get(), + vrm_refdes=self.vrm_refdes_var.get(), + sink_refdes_patterns=self.sink_refdes_list_var.get(), + target_power_nets=self.target_power_nets_var.get(), + ground_nets=self.ground_nets_var.get(), + intermediate_prefixes=self.intermediate_prefixes_var.get() + ) + if success: + self.powertree_text.delete("1.0", tk.END) + for path in result: + self.powertree_text.insert(tk.END, f"{path}\n") + messagebox.showinfo("Success", "PowerTree paths for all VRMs generated successfully!") + else: + messagebox.showerror("Error", result) + except Exception as e: + messagebox.showerror("Error", f"Failed to plot PowerTree: {str(e)}") + finally: + self.close_edb() + + def apply_power_tree(self): + try: + success, message = core_logic.apply_power_tree( + self, + powertree_content=self.powertree_text.get("1.0", tk.END).strip(), + vrm_refdes=self.vrm_refdes_var.get(), + ground_nets=self.ground_nets_var.get() + ) + if success: + self.update_voltage_notebook() + self.update_current_notebook() + for tab in self.intermediate_notebook.tabs(): + self.intermediate_notebook.forget(tab) + for part_name, components in getattr(self, 'intermediate_components', {}).items(): + display_part_name = part_name + if len(part_name) > 10: + display_part_name = f"{part_name[:5]}...{part_name[-5:]}" + frame = ttk.Frame(self.intermediate_notebook) + self.intermediate_notebook.add(frame, text=display_part_name) + tree = ttk.Treeview(frame, columns=("RefDes", "Net_Pins", "R_value"), show="headings", height=5) + tree.heading("RefDes", text="RefDes") + tree.heading("Net_Pins", text="Net (Pins)") + tree.heading("R_value", text="R_value (mOhm)") + tree.column("RefDes", width=80) + tree.column("Net_Pins", width=250) + tree.column("R_value", width=80) + tree.grid(row=0, column=0, sticky=(tk.W, tk.E)) + power_nets = set() + if hasattr(self, 'latest_paths'): + for path in self.latest_paths: + for i in range(1, len(path) - 1, 2): + if i < len(path): + power_nets.add(path[i]) + for comp in components: + net_to_pins = {} + for pin, net in comp["pins"]: + if net in power_nets: + if net not in net_to_pins: + net_to_pins[net] = [] + net_to_pins[net].append(pin) + net_pins_info = ",".join(f"{net} ({','.join(pins)})" for net, pins in net_to_pins.items()) if net_to_pins else "" + r_value_mohm = float(comp["r_value"]) * 1000 + tree.insert("", tk.END, values=(comp["refdes"], net_pins_info, r_value_mohm)) + tree.bind("", lambda event, t=tree, pn=part_name: self.edit_r_value(event, t, pn)) + messagebox.showinfo("Success", message) + else: + messagebox.showerror("Error", message) + except Exception as e: + messagebox.showerror("Error", f"Failed to apply PowerTree: {str(e)}") + finally: + if not hasattr(self, 'latest_paths'): + self.close_edb() + + def generate_script(self): + try: + cfg = self.generate_config() + success, script_path, message = core_logic.generate_script( + self, + cfg=cfg, + edb_path=self.edb_path_var.get(), + vrm_configs=self.vrm_configs, + plating_thickness=self.plating_thickness_var.get(), + plating_unit=self.plating_unit_var.get(), + stackup_xml_path=getattr(self, "stackup_xml_path", None) + ) + if success: + self.script_path_var.set(script_path) + messagebox.showinfo("Success", message) + else: + messagebox.showerror("Error", message) + except Exception as e: + messagebox.showerror("Error", f"Failed to generate script: {str(e)}") + finally: + self.close_edb() + + def edit_r_value(self, event, tree, part_name): + item = tree.identify_row(event.y) + column = tree.identify_column(event.x) + if not item or column != "#3": + return + current_r_value_mohm = tree.set(item, "R_value") + bbox = tree.bbox(item, column) + if not bbox: + return + entry = ttk.Entry(tree, width=10) + entry.insert(0, current_r_value_mohm) + entry.place(x=bbox[0], y=bbox[1], width=bbox[2], height=bbox[3]) + def save_edit(event=None): + try: + new_value_mohm = float(entry.get()) + if new_value_mohm < 0: + raise ValueError("R_value must be non-negative") + new_value_ohm = new_value_mohm / 1000 + refdes = tree.set(item, "RefDes") + for comp in self.intermediate_components[part_name]: + if comp["refdes"] == refdes: + comp["r_value"] = str(new_value_ohm) + break + tree.set(item, "R_value", str(new_value_mohm)) + except ValueError as e: + messagebox.showerror("Error", f"Invalid input: {str(e)}") + finally: + entry.destroy() + entry.bind("", save_edit) + entry.bind("", save_edit) + entry.focus_set() + + def apply_rvalue_to_all_components(self): + try: + new_rvalue_mohm = float(self.rvalue_var.get()) + if new_rvalue_mohm < 0: + raise ValueError("R_value must be non-negative") + new_rvalue_ohm = new_rvalue_mohm / 1000 + for tab_id in self.intermediate_notebook.tabs(): + part_name = self.intermediate_notebook.tab(tab_id, "text") + for pn in self.intermediate_components.keys(): + if len(pn) > 10 and part_name == f"{pn[:5]}...{pn[-5:]}": + part_name = pn + break + frame = self.intermediate_notebook.nametowidget(tab_id) + tree = None + for child in frame.winfo_children(): + if isinstance(child, ttk.Treeview): + tree = child + break + if not tree: + continue + for item in tree.get_children(): + refdes = tree.item(item, "values")[0] + net_pins = tree.item(item, "values")[1] + tree.item(item, values=(refdes, net_pins, new_rvalue_mohm)) + for comp in self.intermediate_components[part_name]: + comp["r_value"] = str(new_rvalue_ohm) + print(f"All intermediate components' R_value set to {new_rvalue_mohm} mOhm ({new_rvalue_ohm} Ohm)") + messagebox.showinfo("Success", f"All components' R_value set to {new_rvalue_mohm} mOhm.") + except ValueError as e: + messagebox.showerror("Error", f"Invalid R_value: {str(e)}") + except Exception as e: + messagebox.showerror("Error", f"Failed to apply R_value: {str(e)}") + +if __name__ == "__main__": + root = tk.Tk() + app = PyAEDTGUI(root) + root.mainloop() \ No newline at end of file diff --git a/src/pyaedt/workflows/project/core_logic.py b/src/pyaedt/workflows/project/core_logic.py new file mode 100644 index 00000000000..8dc365a55e0 --- /dev/null +++ b/src/pyaedt/workflows/project/core_logic.py @@ -0,0 +1,3 @@ +# Pyarmor 9.1.3 (trial), 000000, non-profits, 2025-04-23T11:16:53.203621 +from pyarmor_runtime_000000 import __pyarmor__ +__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\xb7H\x00\x00\x12\t\x04\x00\x0b\xa4Q\xce\x96\x9c\xa2\xf0\x96,j-jYu\x0e\x00\x00\x00\x00\x00\x00\x00\x00i)\x0b\x01\xf2\t2\xdera}|a\x89\xc9q\x083\xdaf\x91.E,\x1b\xee\x8b\x81\x97qL\x93\xb0I\x0c\x8e\xcfe\xe6\x1dh\x85\xd1\x99\x016\xae\xf1\x0c\x80\xfd\x98\xbb\x80\xb0r\xf6*\xc1Y\x0c+\xe7\xbbD\xd6\xc0\xc3\xb7\xf5|\x19\x8b\x99\x97g\xbc\xd6\xda9\xa4\xdb\xe14)\x99vK\xaa\xd0\xc3\x15>\x9a\xb9\x93\xeei\xaaK\xe5\x14\xc5\\\xa2\xeaGbsH\xf7\xcdT<\x10\x08j\x0e\xc9\x1du\x1ed\xfd,\x98\xee\x80\xba:\xe0.E\xdc=\x0c\'\xdfP-\xe1\xef\x97\xcd<@\xcf\xa1\x1b\x17\x04\xb3\\x?\x8a\x1d\xf9\xa2\xe8\xd2x\xf3\xa2\xdf@\x94\xc1&\xf9S\xa3/\x1e\xd3\x89\x01Z\xc7z\xbdZ\x19B\xea\xd7\x15\x83&X\x10B[\xef\x97\xfb\x0e\xa0P\xbdI\xd7\xe7\xf9\xe1E\xb01\xa6A\xbf\xdb{\xe8\xae\xa5Y\xbc"h\x94 \x9d\xaah0\xb0cG\xe8\xa4,{\xd7\x86LX{\x94\xd5\xb3\x0f\xe3;\xf6\xf1\xc2\x985^`\xab\xe14\xe7U\xd7\xf6T\xb7Q~\x8a8\x99\xb8\x13\xaa_\x9c\xa9\xe6\xd4\xa0\xe1\x9d(\xc6\xe9"\xc0k\x072\x86\x8e\xc3\xe6\xa0,\xb3{e\xbb\x98\xf9\xcd|Z\xe4,y9t\r\xbf\x1d\xfc\xce/,\xe7W\xbe\x14\xc8\xe5\xcb/}\xba\x8b\x00\xde\xb0\x02\x91\xfa\x99\xa8,\r1\xb9v\xdfS\xd58vT\x9e=8;\xa1\xdb\xdb\xfe\xa1Z\xce0\x15\x8a\x02t\x07\xb1x\xe6\x05\xa1\x0f\xf8s\xa1V\xb5V3\xcf\x83\xb5\xd2\xb6\x8f\x8a\x86\xef\xf1\xce\x13Sx\x0b\xb9j\xe0\xf7<\x07\xb5\x10\x8e\xb0\x9f\xa2\x8d\xbc\x9b\xa4\xb9\xdc\xa9\xfd10\xb0q\x1e)\xb6\xe8\xd0\xfc\x8c\xb6\xa9\x0e\x9b5\xd3E3\xd8\x1c\xef\xb5\xc1(\'$fg\xde\xc3D\x84\xf49\xb0\x16"}N\x0c\xf2\xbc$\xbfl- m+\xd0(\x0b\xdbq(\xef\xcf\x04k\x1eb\x06[\r\xc0?\x15\xb7\x16\x18Go\xbb`\xde\xdd"_7^\xec\x00\xd8\xf2\x98\x81I\x18W\xe7\\\x98\xc2\xd2w\xcf\x96\xfd\x04Mh\xe2\xb1V\x88\xc5\x91\x06\xf1\xd4_&Em\xd2d\xe5\x1a\x03\xfd\x8f\xa3\xeaj\xfe5P\xe2\xbd]\x84\xf3\xce\x9bj\xf4\xec\xfdm\x15\xc6\xe8\x08]\xc4^&S\xf7\xc51\x1cA\xa7\x93\xe6\x05\xfb\xbb\xf8\x16\x1b\xf4P\xc8d}_\x13\xda\xa8\xe3b!\xe4f\x16;\xf7\x14\xd1\x14H\xbc\xce\x18\x93W\x13\xc8\x8a\xf9\xc7\xa5\xe5m\xf6\xfe\xdcp\x1b\xfd=a\xae\xd6\\\xd1J\x7f\x11\xe2\xa6\xebj\x9b\x99\xb1\xe4(\x1bU\xe6/Q\x19\xc6\x14\x11\xbb\xceN\x04\xa6\x9d\xe5\x99\t\xf9\xc4\xda\xa90\x02\xe3\x14\xd21\x81\xc0\xf0\x9bs\xe4\xc6\xb2\xc2C\xeb-T\xb2\x98\xcd8G\xb1\xd6s0&\x9e?i\xd7\x9f\xba"S\xe2KV\x85*O\xea\xe9=\x05\x0c(\xcdB\x8f8\x12\x17P\xfe\r2\xd8\xee\xc7\xf9\xd5\xfec\x90-"\xc7j\xbd\xed\xd0\xb7n\xa0\x11\xb4]!Z\xdf\xde\x11\x13\xb4*J3\x8d{\xfem\x0b\xd9>\xfc5\x9f\xe9]b\xd3\xd2\'\x82\xd7\xa9E\xa1\xe5\xe8\xae\xe7\x19w\xf6Z&\x0b\xc5\xa4\xe7\xcfcih\xc6\xff\xe5\xb7\x1en\xac]V-\xb8\x0c]s\x88\xe3\xc3\x00\xd5\xee\xf0\xc8\x87,\x9e\xc1\xc3\xae\x0c7-\x07^\xed\x966\x15B \xc72\xbd\x83\xcf\x07\xba\x8b\xa0\xb1#g\xcc17>\xfbO\xca\xcb&e\x01\xbd-m\x97\xe8[\xf2c\x83^\xf8\xd9\xc4_\xfeB\x8e\x83\xdc\xb6%\xaa\x9c)\x8e\x02hcR\xd9\xcb\x81\xbf\x9c\x91\xb8\xef\xa6Q\xf8Z\x93K\x1b\xb1\xfb\xbd\xb8\x7fTS\xc9\xe2>\x80)\x01\xa5\xef\xd3\xa5\xfd\xe3\x05FV\x1e\xb9ks\xf9\xc3|}h\x02\x83h\xdf\x16\x82]=}\xcb^g\x88\xc3\xb2\xad\x95(\x02X\x99Epp\x16\xb8\x9e-\xe4\xf0\xe4\xff\xb2BH0i\xe6J7R\xa1\xa4\xf4\x91\x89\\\xb4I\xdb\xc8\xf6\x9d\xb5\xae\xd6\xde\xd0\xbf\x9c\xcbq\xf6D\xd5\xeeYm*\x980|\xb5%\xb0\xeb\x9a3\x15\x19u\xa0\xcfT=\xc6\x16o\xb3!\xc0\xaf\xfd\x17\xac\xa2\x04\xa6\xeb\xaew\x08\x02\xdb\xdd\r\xf8\x0fg\xb6\x95$!\x98R\x135\x82[y>UM\x0f7\x80\xf3\x98\'!\xaf\x81\x8a\xdf\x19\xf6"z\x9bc\xd2^A\x1b\xcb\x07\xb8\x0c\x81\x1f\x8f\x1f\x97f\x0e\xc5q\xe9c,\x9b\xacoup3\x18\t\xbcFP\xa4$>\x1273\xc1\xa0,\xdb,M\\\xe3\xab\xeax\xc0\xb4#\x1d\xde\xba\xca\x8a\xf2x0\xd8C\xda\xa3@2\x841U\x0e\x12\xb3\x90\xb0\xae\xd7\x8f\xa6;g\xbe\x1b\xbe\xdf\xa3Ao=\xea\x8bi\xd4V\x10j7A\x80\x02?\x04\xa8\xcc\xe6\xa0\x8f\xe1\xf7qu\xb42\xee\x8f9H\xe7 5\xde\x1c\xb9\x98\xfe.E)\xea\xe8\xab\x92W\xff\xb0\x01?e\n\x91\x91~\x89|\x89\xcf8a4! \x92\xdc[l\xfb\xcd\xc0\x99b\xcf\xc4\x7fY>\\8w\xb3\x90\xe4\xa6i3;\xf2R\r\xd3\x10J{\xf8=\xd9rKa\xe6\xb1\xac\xb3\xdf\x84)\xceCJ\x1c\x16\xf7\x15\x80\xb9\xe4\x06\x9c\xd0#<\x9a\xfc\x95\n\xec\x0f\xa8\x9d\xb51$S\x17\xfb\xf1\xa7G\xf8\xb7\xc4\x98\xbbi\xf7{\x0e\x89\x87Q\xf7A3B;H\xc6kB\xd7\x7f7\x8b\x06\x8f\x95\xb2g`\xc3m\xa5\xc7(oo\xd6\xe7\xd5\xdf7\xbb\xeeK\xe1\x8aN\x82\xb8\xf4\x83\x18\x82m\x96@\x9b\x00C\xda\xab\xd4\xa6h\xc9\xfc/\xb4b\xc0\x97\x01,CLo\x05w\n\t\x89o\xf5\xc2\x86M\xf6\xf8\xcf\xb6x\x93\xc9\x82\xb6\x14\xd4\xf4\xe0\x89*[* \xd3\xb2\r\x98\xeehY\x87\xcf\x98\xaaY2\xf7\t\xd2]\xf9\xf8\x1a\x1c\x03\xa6\x08~\x96*\x1b\xc7\x91\xa0\x95\r`NGg\x937x\xb7C\xbe\x05\x8b@\x01]-\xba\xe1% \x9dq\xb3y\x1f\xac\xa3\x0c3y\x99\xa1\xafF(\x06\x01\x11\xa0r\x00`\xb0PE[\xfd\xc9.\xfb\xcf\x9b\xd9\xac\x7f\xd2\xce\xfc\x8a\xabi\x1f\x7f\xfd\xcd\x9c4\xfdRE9\x07b\xeb#s9\x89\x88e\xcc\xf4\x89O\xfd\xcc\x12j\xfc\xfd\x88\xa5M\x00\xbd\x1f\xb3\xfcSQY\xa7\xf0\xe2J\xf1#=\xa6\xf8T\xa4\x90_\xe4\x04\t2\xf0\x19vK@g\xb8\xdb\x88\xab\x01\xc5q\xec\xf5\x96\xa3\xc9j\xe8\x86\'q\x07\xfeD)f\xed\xac\x8aeZ\x99\x18\xb1\x16\x83\x19\xedB\xff\xc2\xcf@\xaexo\xa3&\x05\xe1\xae\xdc\xee\xd6\xfb\xa9\x9e\xb0\xa4\x1e\xf5\xa6\\\xff\xdf\x0fp\x13\x1f%\x8f\xc2+\xf7\xa7\x0c\xe1\x0b\xe9\x03Yt\xe2\xac\x84^\xa8O7nR\xa7*\xd2\x0b6\xc6\x98\x80\x81\x0fF!\xec\xbar\n.\xaf\xb7\xdcV\x13\x8a\xe4\xf0\x0e\x01\x9cEMH\x9e\x95\xb3\x0c\xec\x9e\xda^a\x10\x89\xa0\xd8\xf5\x93]\xe1\x82\x93\x93\x90\xcd\xceH\xb1K\xa7\xb9xz\x8c\xae\x91\x9b\xe4W\xdc\x94D\xd4dE&?\x8cy^\xda\xdf\xed/\x1d\xc2Au\x0cu\x95.t\xb7\xdc\xbe\x93p@\xff\xd6\xb6\x05B$B\xae\xd1\x0c\xaf S=\xcf\xd2!\x16%^$\'u\xb0\xad.\x054\x17kxX\xe8\xe1\xd9t\xd0M\x937\x07\tRb\xb4$\rD\xe0a\x00\xc6\xbcL\xd3\xe3H\xcc\x94\'\xd1-\xf9\xac(\xd0*9y\xc8\xbb&\xc9\xf4\xb3.\xf1a\x9aB \x9c#\x03\xa9QX"\xcd\xdc*j\xe3\x99\xcb\xba\x10\xddT\xfc\xa3M*\x9f\x0bv]\x18\xfe\xe6\xb9\x8d\xe4j\xf7\xab\xec\x17\xce\x89\xa5?\x1d\xf9\xaaq\ne\x8c\xacA\xe4-\xf7ME\xc2\xdf#/\x85\xbf@\x17\x7f\x8c\'\xa7\xf3\x9et\xeb?\x1b\xf1F\xc1\x8c\x9c\x005~}!\xbd:\xb8\x99\xca\xf4\x93\xf0\xd0\x83\x16\x02\x8fp\x98\xb6\xbd\xe2\xbf\xaa\xacz\x02\xa7\x8e\xdb\x0cC\xd2\xecI*\x9d\xc1\xea\xb7(o\x06]\t\xc3\xc3\x808h\xfdb\xef\xd1\x08\xd2\xc4\xd5\xe0\x13\x17U\x84\xcf\xbf\x19\xa1b\x19\xf0c{l\xaf\\\xfc\xbc\x9e\xa1\x87\xd7\x08\xb1\xbb\xf9i\x0f\xbf\x11\x06\xc9\xa9\xcc(\xd1\\$\xd9W\xbf\xd3I\xe83\xdf[^\xb2><\x04]r\x84\xcf\xc9S\xec\xbaH\xa7\x852\xf1\xc8_\x13+4\x9c\xe6g\xe1P\x06\xb1\xee\x94RR\x96f\xc5A\x82;2J+\xdd\xbf\xee[\xc0\xee\x05\xba\xbe=\x93jV0\x03%\xd0ZS)\xaa\x14\xd1\xcd\xb0\xdet\xca\xa1<7\xb1\xaa\xfa\xa5\xff\xe2\x0c-\xc6GDf\xaaV1\xdceNUC\x8c:\xe6w\x1c\x9dqzn!6\xb9v-\x1e\xe6\x07\x86\xd2(\x15\xed\xdd\x96\xfa\xb4\x95\xc8u\xba\x99\xf2F\x90\xd4s-h\xdf\x14\x17X\xf0\x80=5\xb8\x05\x0e\xe4m\xdb\x81\x13\xae/-G(\xb6\x93\xa7V\x06;\xb5;\x01A&<\xa0\x8a\xde$\x94\xf46\x87\xb3\xc2\x0eM\xee\x04;a\x90\xa9\x8c\xa8\x17\xba>f[\xb9\xb5Y\xa1N\xbf\xe4i\xa1\xb0O"x\xaa\xf4t/&kV\x8a\x03\x8e\xbd\xdc\x7fD3U`Jf\xe7\xee\xd5\xb7\xee\xa3\xb9\x93\'\xc2\x8f\xabJ@\xf2Bk\x8e\xb9\x17\x19\xd8\xfb7\xf2\xd4X\xabv\tM\xc4M\x1coU+h\xe1\xc5\xcf{n\x9b-\x9f|\x8a\xd0n0\xde\xea\x01#\x92\t\xe7\xb6\xee!\xcf\xe1{Dc\x1b(3\x08*\xfa\xc0\xd0\xbc\x80)6\xa9\xbd\xfb0`\x8e\x05H?E\xdb\xa5\xac\xb9\x7fS\xcd\xbbWx\x83\x94\xe7\xc7\xab\xf0Q\x11\xd7\x15\x8e(\xbaP\x90z\xa2A\x05\xa4\x82\xeaD\xd6\t\xa7\xec\x89\xb2z{4\x9f/\xe1\x0b,l\xf7\x87\xbbv}\xa1\xfc\xce\x91\x8f\x1d\xcdT\x81\x14\xa8\xc1J\x7fl/\x8f\xaeB\xf7\xa0\xd9\xc9\x9c\xbc8\x00C\x87\xad\r\xdb+\x85xr\xed\xd2\x11\xdb\xfa\xfe\x95X.\x9d\xb9\xae\xdf\n9\xf9x:\xe34\x91\xe5)\x07\xb8\x04\x00\x9a\xe3C\x00\xb7\tm\xf0*\xc1\xecN\xc7\xde5v8\x8c\xd5\xcbHz\xefy\xe6\xd4\x8b\xaa\xcd\xbd\x121X\x15z\xa2F6d3P\x17\xa5{\xbd\x84\x9e#\xf4D\x05\x07I\xa3\xec\x10\x86\xc1\x14\x97\x19Pb\xf7\xf8U\x15\xe6\tJ\xf2aSEMd\x1f\x0ct\xc4\x93{\x19\x07\xf2\xa5A\x1f,L\x1a\x9d\x9b\x83.=z/\xec\xca\x0eg\t\x0f\xb4oT\x13\x8f\x88\xbbP\xc1\x14\x8b\x19\x80\x9az\xf5\xe2:\x89\xe0\x17\'G?c\xd6\xa6\x95 \xdcb\xff\xe4\xee\xeb$\xef\xb0n$`D\x95Gl\x92&\x7fmK.\xa5\xc1f\xc8\xb2\x00c\x9eb\xb2\xf6D\xad\x1b\xac\x0f\x95\xd3\x19\xc9\t\xb3V\xc1ww\xb5ks\xd9qw\xc5\xe6\x90\xc8^\x94?\x91\x1bl\xa6\xc4\xd2U\x9f\xb4\xdb\xd8~\x84N0\xd7\xd8\xa8}Og/XO.(\r\xa5\xfee\x0b\x19\x95\x9bj\x98\xd6`e\x98\xc5{]\x93\x8a\xfdGd,\xcd\xbb\x9an\x92\x80#\xbb\xed\x8ad\xc2\xbe\r\xc4G\xfc\xa8\xd6\r\x89=8\xf5y\'\xdb\\\x1c\xaa^9\xc1\xe6\x88^j\xfb9\xd1\xed\xb8j\xb5\x8f\x88\x15K\xc9\x7f\xf8nV2\x9d_\xc7\xb9\xfb\x83\x85\x05\x90\xda\xc9*\xd2%Wt\x94#(\xb4H\x17\x0f\xdeQh\x81(\xcb\xdd\x1d\x99\x8esP*a1x\r\xb7\x8c\x1f*)SOoWS\xddK\xa8\xa2i\xe3#%]1WY\xf2\xb3c\x98G\x1e\xffIj\x9c\xca\x08\xed\xa3\xd2\x8dW\xd3\xaa%\xe0\x80\xc3<\xb1\xa7n*\xb10\xf5\xe5\xa7Ku\xe8\x83.Y \x00\xd4\xa4_%\xc5j\xed=\xcc\x8fS1\xcd\xff\xcff1\xc9\xf8R\xfa\x81\xa4\xb1\xd1`\xf4\xd1I7\x1a\x97\x8c\x99\x87C\t\x0c\tAa\x95\x91\x88\x1b\xdd^\xfe\x94\xc4\x1cF\x16\xbd+\xee\xeb\xcf\xa0\x07\xe9(2\x88~,-f\xe0A\x07\x95N<\x83\xe5\xbdU\xd8\x9d\xde\x82\'\x1bA\x97\x86u\x19\x87\xf9\xea(\xda\x8e\xeaf\x96\x82\x8f\xed\x93\r\xa4bO\xf8r\xc6\xdc\xacO\x1c\t\xfb\'\xa7\xebw\x84\x84\x82\xf4:\xe0\x81O\x8e|\xa4\x19\xf6\xbf\xe3\xf5n\xa6\xfd19\x9e\xfb\xf2\xcbpN\x08\xb9V\x17\xa0+\xb7\x17\x02\x06\xd7\xd4O\xb7\x82\xeb\xd69\xd5\xc3\xf1(A^\xf2\xbf\x9f\x1c\x0cJ\x06/&\x95\x93\x01\x12K.O\xd2\xb9\xf4;\x05\x0c\xb4"_\xef\xaa\x1c\xd3\xcdD\x97P\xe3\xd3\x15z\xa1\xc7\xea\x1b\xfcT\xcbT~\'\xbe%\xba@^\x81\x8e\x81o\x0b\x0b\x1e-d\xe6\x83\x85\xbaT\xa6\xf2\xdf\xd9\xcbO\xf0\x04H\x89R\xdb\x1a\xd3\xff\x7f\x7f\xdb\x99\xc2\x9d=1P\xa4\xeaC\xdf\xad\xd6\xa1{9sl\xda\xdc\xaa\x16\x11C\xe4?\xac\xe2\x86o\x914\xa2\xc5\xf4B\xf0\x92\xb8\xc88\xa9#K@\xfa\xfb\xb2A[\x05\x01b\x9e\xc3R~s|\xd2\xc7\x17\xce\xb1\x0b \x024\xff\x87#\x14\x945\xcb\xd5\x0f\xfb\xdb\xbe\xcd\x16^\xef\xd3\xaa\x9c\x80\xe0z\xf3E2l\x1fLW\\9\x91\x1a\x1f\x8e\rj\xe5~\x1c>}M\x8d9\xbf\xb6n3.\x1d3\xe3\x05\xba\xd7Z\xe6 \xb7G/\xbe\xc7\x10\x9cV|1\xbf\xde\xcb\xc2\xfcZ\xa0\xec\xaf\x8f\x89Z+6\xae\xb2\xce\x97\x9d<\xe0\xb4\xee\x8eW\xe4\x0f\x95H\xe2c-GS\xed\xd7Z\x8d\xd3\xab(^\xd4Qz\xb8\x81\xc5f\xa9Et\x9cU\xed3<\xbdpVJ\x9f$\xa6?\x18\xfc\x11\xd8\x0e\xcb\xe3\x11\x95\t\x1c\xa2\'\xa5\x8d \x9d\x81}\xa8v0\n\xb0\x98B@gsq\xd6K\xb1\xfcB\xbd<\xd1A\xf6xlC$<\x86T\xee\xd6\xa2\x13PHq\xee\xb3\xb1E\xc3\xce\xdb\xfcP[\x9ay\x0e\xe2MK^;\x00\xa8\x1d\x7f\xeb\xdcTm\xfc\xe4\x16\x9fm +\xc9qL\xf0e\xbc*\xd6\xce\x8a\'\xc34#\xef\xeb\xfe\xfd,|\xd7X.\x14L\x91\xdf\x89\xd8T\xf5\x89@B ai\xdc\xba\xd1\xf1\xac\xee%\x9f\x19\x0f\x1f_\xe9\x9f\x91y\xca\xf8\x9f\xc9\x8c\x89\x9b\xf9\x89\xd5\n2\x0b&2\xd5([\x80\x85o\xe8=\xb6\x93+Z`M\x96\x1fM\xcePM\xe3\x03\x80\xf4\xaa\x9fx\x12\xfeI\xe3\xf4\xef\xe5\xc1ye=\x93\xda8\xc1\xa3`A\x90\t\xf3a$\x07\xa1\x88~\xa8\x94\x84%l\x10\xa8\xe0hW(\xf7\x11n\xd0\'\x82\x80\x94\xf5\xb5y\x9c\x94\xd8\xab\xdc\x9e\xe0\xae+&wy\xf7\x8f ]\xa5m^\xf1\x9fy\xc2\xdb\xff\xa2\x13\xb4\xa1u\r\xdc\xc3-e"\xa0\xa8\x0f\x11E\x9an\xac\xc4R\x9b\xb2K\x8a\x8cO\xb2\xbf\xd2m;\xb3\xa97\xec\x93*b\xb64\x89jv\x1c\xcaL\'Qa\xf0\xbb\xc6\xa8q\nr\xedNi\xb7\x83\xafO\x88\x8a\xd9\xa2\xce_\xc2\xdf\\\x05\xaaUF+\\"YdX\xc9+J\xf9_\xdfN[\xf4\x91*U\xdbw\xae\xaa\xd1\xbc\xaa\xbf\xd23\xa0\xd5\xe5D%=\xf1\xcea\tFK\x0c!Z\x80\xf7B\x94x\x9d75\xea\x98\x07\x99\xb0|\x84\x8a\xe1sl[\xf6o\x80\xe1\xd1jR\x92\xbc:\xa0x\x06R\xbc\xceN\xb0\x97\xb9\xd2\x04t\xe4\xd2\xe4X\xb6\x1a\x99\\!\x1f\xebAFR\x80g\x8c\xd2\x7fcl\x14\xec\x17\x9d}!\xc3\x7fM\x80\xc1k\xc2\xde:\x01\xb8Cr\x1c.+{\xdf\xd56o{\xd5u\xd3\x9aW\x9f\x9c\xfcU\xbe5\xa1\t\xa6,\xad\x85\x86\x88<\xa1LlKM{\x9d\x16\xdd\xa2\x07/-m\x80pb\xb4YjA\xf8)\t\xfe7\r\xa19;\xba\x1b\x8f\xb0_\xbfs*q\x0f\xe4s\x1a\x90a\xf6\x91\xd3\xf7%\xe4\x9d\x17\xa1\x0f\x8e\xe1\xed\'+:)\x04;\xd4\xbd\xd0\xb2a\xdf\xf3\xd1\xf9x\xab`\xef(a2\xbb\xa3\xa2\xa7\x87\x08\xf7V\xee8.\xfe&\xae5~aH=\x0f\x9f\x10*\x17\x99\x0b\x9c\x8dp\xd5\xe7\xd6\xb5&\xe3\xfb\xa9[5D]\xa8L\xfb\xf8\x06\xd0`7\x1a\x90\x05\x93\xbe\xa4~\xd1\x12\x7f\x96\xdcN\r\xf3\x1f\x08|Y.\xec\xf3l^>F\xcb\x8f`\x0f\x91CDIV\xe7~q\'\xc48\xb6\x90!\xa6L\t\xf8NX\xf2\xff\xe3QJd\x81j\xc8\x9b\xd2P\xf7\xad\x9bK\x8c\x96\xb1\x8c\x01r\x08%h<44sG\x03\x02_\x92\x97\x19\xfd`\x06\xf0\xe1\x0e1\x8b\xb3a\xb6k\x08F\x9d\x03`\xdb\xf7\xea6\x82\xd2\xc9\xcd\xb1\t\x82\xf9\x9b\xd6K\x12HP-\x15\xb2\xb0r\xb9\x91\xe8\xb5\xa9\xec{\xd9\x8b\xed\xe6\x10\xacmq\xb9\x06\xc2\x0fgt\xe1\xa8\xd9\xbb\xcfO\xee\r\x02X\xdan\x00<\xfb\x1d\n\xbf\x93\x1d\xfb\xbb\xab\xf4\x7fF\xc4#\x13\xb0\xff\x16\xa3\x9d\xbf\x0fK\\\x04x\xba\x9e\xb5\xdc\')o\xe4\xa0lr\x9e\xe7\xb9\x05\xccN\x99:c\xf6\x07\xbc\x04\x8fe\x13\xde\x1b_X\xdb\xd8\xf2}\x16!\xe4^7#~,\xd1\xf7\x85C\x06z\xa43|\xabp\x11W\xf3\xa6X\xb9Q\x9d\xa84E\xa19,\xd4\n\x06\xaf\x8er\xa5c\x7f\x03\x9aMo0b\xc9y\xdd\x19\xc7D\xf7\x90\xf2&\x8eI\x81\xfboF\xaf)\xc3\xf8\x07\xb8\x19j\x17\x93\xcd\x0e\xc8I\xa0\xb4\x9f\xd6\x17\x7f\x900e\x97\xb3\xfb]\xfe\xa8\tk\x000\xcb9\xd5\xcf^\x13j\x92\x97\x8a(\xa7&\x81@\xb8\xc3\xbc\x93G\xa1\xe3K\xeb\x19\xba\xfe\xab|\x12\xe6f{hE\x9c\xda\x19\xbe\x98\xfe\xed\xda\x8a\xe0hb\xad\x9c\xd6\xe2\xbb\xe8\x86\xae\xf8\x12P1\x9b\x8eDW*4\xbe\x98\x1a.8\xf0`Q\xcd\x07\xff\x00\xc2\xb2\xb2\x0e\x96\x9e\x00EZ\xae>\xf9\xc4\xb39\x98\xde/7\xb8\x93\r\x97\x1d\xb4\x9b\xb0\x1a\x16\xc4\xa9\r\xb2\xc7D\xb3.\xf9?\x95\x97\xb8\xebP\x99\xa3\xa7\xcb\xc4&\x16L\x80\xb4)\xc5\x8f\xb5\x82\x87\xccQ\xd3\xf5(\xd9\xb8\x9781U>u@C\x80\x1e "\x8ey\xe9\xd8\x95\x95\x1d\x1d\xfd\x1fC\xf5\xe0\x93\xb6_\xa7\xc57\xeb,F`\xcdz\xb3\xc6h\x044F#\x86\xde\xb7\xaa\xa6L9\x11\x0e\xe4\xd4?\xff\xa8\x89+T\xe2\x8a\xb1o\x98\r\xe1*\xb5\\\xc6\xc5\xe4\xfb\xb9\x91n*F}r$\xd2\x13Hlo=t\xff\xd9!\xd9\xb6\x19\x7f\x9b\xfc\x9cti\xb4\n\xf4[&\xb41\xc1\x99\xb5\x82\xf6S\x8e\x01i\xd9\xc9\xa4\x82\xbe\xa7\x96N#\x95,\x11}\x89|\x12N\x99gjV\xe2\xdf8/\xe1\xe1Gs\x8d,\x9c~\x01\x0b\xd5\x89\xaf\xe5\xf6\x9a$\xee\xfb6]\x0e\xa7\x182\\\xa0 o\xa3I\x9b\x10F\xbf\x96\r\xed\xf3\x90\xab\x86l\x9d\xa6\x16\tl\xae1A{\x84I\x80\xa4\x82\x93\xfa\x04\x9c\xa8`\x959f{$\x13\'\xbf\xb7!+\x0bL.\xe9\xed?\xe2*\xf0\xe0\xb8^\xaa\x07?\x08\x9dZ\xf6\x04\x1c\xa9\x8e\xb8\x08\xb9\x80\xc7\x06\xd5Tn\xe2\xec\x07\xfd\xa1\n\xda\xbaL\xf0\xf5A\x1fA:G7k3\x9c\xb5\xb2\x96\xe2\xf4\xb5,\xecB\xe9\xd7t\xdb\x16\x16\x85\xe0\xa3(\x04f\xf6\xa8\xdf\xbfL\x9b7\x84a=\xd7\xd3=[\xf5Jp\xaf5Y\x985p\x0c\xc4oP\xa0bL\xe6\xadJW\xa5K\xde\x8d\x82\xf452\xc4#\x9915\x82ey\x11\xd1\xb7b\x91\x8e\xa7\x94\xc2\xd7\x152\xb4A\xc4j\xbd\xde\xa6\x1e\x01b2m\xb7\xe6\xea^\xebk\x93\xa7W\xfd\xbdv1\xc9o\xfey:\xc4E\xd1\xe5\xc8\xf5\r;.\n\xf4t\xca>\xd7\x04\x9e\xfd\x95\xbdNY\\\xa7\xfe\x0f\x93\xa2\xc1\x8c\xa1T3\x00\xddv\x03\xabg\x80//|\xe5\xbc\x8e\xa8\xe1\xfc%\x9b"\xe9\x00\xee\x04\xe8\x80\x8f\x05\xf7\xae\x96\x81SF\xe1\t\x13e~\x9al\x88\x8c\xc8\xda\x08\xf8\x95i\xf8\x04R\xa3\xf6\t\x14bF\x86Q\x1c\xda\xfd\x8eP\xb6\x85\x17\x0f\x99(\x02\xf5\xa0\xbex\xcb \t\xd7\xd3\xe8\x06\x98_N\xa9LU\xca\xae\xe4\xf1\x98koc\x84>\x0e:\x9a\xc8\xfd\x82\xaa\xeaS\x98\xcc\x1a\xcd6\xd0\xa5\xea\xe6j|\xe1\xa4@7\x17m\x12\xea\xbfs\x16D\x12p^\xec6\xc4O=\x8f\x8a(\xb8\x11\xd7!\xba\xe1u\xce\x94\x13[\xaa\xe2k\xf7\x05\x17\xf0\xc3u\xa3=R<\x1ez\x0c\xda\xeb\xbf+R\x19\xc0\x9b\x8e\x98`\xaa\xeb\xc7\xde\xdaR\xd2\xa6\x10&:m\xb1.\xde\x08(\xf2k\x14\xeai\xb7y\xba_\x8a\x1b\x9fr\xd58B\x19p\x1e3\x00Y*x\xeb\xf4\xf2\x1b\xf1e\x86u\x1a\xb4\x9f\xa8i\xda!\x97\xcb\xb8\x8d\x05\x9c\xa7\xc1\x90\xd7\x19\xc5:\x05\x19 !\xa6\xd6f=?\xb69\xd4L\x88\x9d\x12\x7f\xea\x1b\xa3S\xacF\xe10\xc1\xb1\x8a1\x01\xf7(t\xff\xa3[\xe3\x8e\x1d\xfe\xc6{\xf4\xceY4\xa1C\x12\x1c\xd0\x0cv%\xe54}\xad\xb5]\xafuf\xdeZ\x17(\x97\xed\xb0{\x0e\xbf\xf6K\xbc]\xd9,\x1a8\xf9\x85%v\xd2\xa0\xe0-P\x01\xe6\xa4\xecV\xf7\x0f\\\x00\x9c\x99\rp`\xff\x92"\xcf\xc4\x82\x84[\xf6\xb1s\xa2\xad\xe1C\xdbR5\x93\xceU\x07\x19\xad\x00\xd3\x90s\xd6B\xba\xd6Wk%\xfe\xc7 \x1ce\xae\xf5-\x91d0;\x8d\xc2w\xbey\x96N\xaf\xf6\xf5\xbb\xb2h\x82?\xbc\xc8\xdeU\xc8\xff\xbbp\xc5\xd3R\x08c(P\x80]\xab\x8f\x99\xd1\x88\xb6;\x90Yn~\x08\xa0\xf6DD\x964\xf3-\xf0\xa1L\xb8j\xd5\xa7F\x9d\xcd8:\xa6*\xc5\xf9\t\x1fm\x0fIF\t\x1a}\x87?B/\x90\xf3t\x1c5\x97\xdb\x81\x83.)\x05\xdb\xedB\xed\xdd\xf9-5\xe4\xbc\x93\xd2\xe1{\x11uy\x04\xdf\x81Pf\xe7\x08x\x99\xb5\xb1)\xd1\x97\x0c\xf7qT\xd2\xcb\x07\\\xf4#\x16\xe0\xdc\x81<\x17\xc6/\xbeW`\xc3g\x84t\x9a:\xc3\x9b\x10\xb5(toK\x14\xef\xeb\x98\xdd\xf1\xceH$4\xf2\xe6d\x8a\x11m\x9c\x95\x8a\xc3]qT\x7f\x16|\x16\xb5\xac\x9e\xea:\x99\xc3\x98\'3\xc5\xe5e\xe2pq\x1f\x80\xe6\xdel\x04\x98\x96\xf5\x8bd.q\x8eF\x7f\x19V\xf8\x02\x10\x0cr\x8b\r6\xf3\xfd\xb5\x91\xad\x80(R\xc66\xf1\x83\x8e\xdf\x88Qg\x8b\xbejw\x8f6\x99\xfc\xf5\x12\xfb\xbbx\xd9\xe7\x1e\xa97rA\xd7\\\xff\xb3>jG\x84\xfd\xf4\xe0\xc2g\xd2\x91\xb3\xb3t\xeaZ\x16\x06\xaf\xbbIO\xa7\xc0\xd5Y\xca\xc79\x19\xc3\x10\x0e\x81\x95\x8a\xd4B\xb7F\xdcU\x9eo\x993\x1a\x0e(\x93\xc3<\xb1\x02\x1b\x98\xb9P@\xba\x1f\x97\x80\x03\x9b\xa5\xf3\xc0>\xaf\xf6\xb9\x8e\x04\xcf\xcc\x9b\xdf\x84\xec\xb6\x96\xac\x84\xe0\xf2$\x19\xbd-\x9a\xd2&\x8b\x99\xdc\xf50i\n\xf3\n\xe1e\xebn\x1d\x8f}\x1bN\\\x05\xd9\x17\x8a\x05b\'EM\x97G\xcas\xdd`&\x04\x16e\xf8\xf2\x84\xbe\x9a\xab\x06R\x122Lp\xa8\xf9\x1c(2\xdf\x0b\xcf\x0cj\xb3M\xd0\\\xe5w\xea\x1b\x87\x16\xd9w\x84\xd6\xf0\xfe\x0f\xaa\x86\xf1[\xd5-@7\x9cGh\xa4\xd0\xca\xd6\xbda\x8d\xa00\xebSE\xa5=gS2<\x1c\x92\xa8o\xdfY7\x98\xe9\xe4\x8f1\x07P\xb5D6\x9c\xceg\x9f\x8f#*\xa5\xfa\x83\xe5,u\x0f\xef\xa1\xf92\x9f8\x91\xb5!{\xc8\xb7\xc8\x81\xe7\x0b\xc6\x91\xe1NvC\x00z{F\xbcY\xd6#V\xee\xa2\xe0x\x96%\xab\xb3>\xb8\x9c"\xbe\x86\x17p\xa4a%\x92t\r\xf0o\x82|\xea\x10\xf8\xbe\xd9\xa2\xa5P\xa9z(\xc4\xa8\x98\xcf\xe8\xfc\xee\x9c\xf4\x80\xd8\xf0\\4\xa1\x01\xbf\x8a_\xeb<\n\xb5\xc7a\xb4d\xb9\xc4\xa7\x12>\xda5\xd5\xeau\xfcC\x00\x82\x9c\xb7\xc90e\x1d\xd7/\xb8\x17P\xeagT\\/\xfbi\xc7\xf9y\x7fR\xee\xc0\xbea\x7fZ^\xa8\xb1\xb0\xe0\xaebl\x86.a\xf6\xf4JI\x8b\x81\x9f\xa1\x1d\x98\x14pv\xfa\xb8\x8d\xc5 \xce\x07g\xf5Y\xd6(!\x12\x14\x9f\x1c\xf0\x08\xd5\xab\xf6D0\x0fO\x8e\x84\xa4\xe2\x0b\x94\x93a&\x03\xa5\xc1$W\xc9z\xaedI\xcf\x05h#r\xb3/\xe9\xcb$p\xc4!\xca\xa7\xdb\x8c \x1bX\xbe\x0f\xab\xf3\xe2\x92\x9ba\xfb\xd0\x82\xdcNx7\x9e\x13\r\x8ah\x84q\xc4\x15\xf5\x94 \xd9\xcb@\xf95Z\x9f\x9b6\xf3\x16\xcf\xa4\x8a\xd9@\x90\x1c\x960\xc3\x0e\x8b\xac\xb3N\xf3f\x84J6\xfc\xa7\xc8T\xc8\xc5\x96\xe3\x08\xe2\x92H\x14\x15CR\x7fO\xc1\xc4\x82\x8d\x7ft\xf7\xefBy\xa8\x9clBno\xf3\xaf |\xf1\xf4"\x01 \xff#\xb3\xc9s\xb1\xbb\xa4\xd1>\x80\xc3\t\xbe\xc1\x13\xd7,\x1cx\xc1K+x8>M\xa8\x81j\xf4\xbc\x8e\x88\x89\xc9V\xf6C\x18\xed\xe8\xf0\x13=2;\x8e\xd5\xf4\x08\x1e\xda\x9d\xe2$\xd9\xebc\xb5\xdf\xe9\x86{\xd8\xf5\x8b\x9e\xb6\xe8\x1a\xc7\x95\xff,l\xc1]\xd87\xc5\x7f\x17,\xf9\x08(\xdbaZU\x84\xa4\x90k\xda\xd00\xf4\x12k\x8e\xdb\x86\xe6\x7f\xb8\xf4a\xb0\xbb\x0c\x92(\x7f\xea\xaf\xa4\x9b\x8d\xb7\xa1"\xf8zw\xaa\x9b$\x1a \x04\xa76\xa6\x1a\x17$\x0f\xf9\x03\x8e\xb5f\x93\x1a\x80\x17\xbd]\xb2 \xf0\x140\xcd\x98(S\xb6\x83\xcfi\xde!\x99`\xa3\x0b\x157\xebx\xc9\x1dE\xe6\xf9fW\x8e\x1c\x8c\xa1:\x19T\xba2\x19(\xf4v\xb8\x02A-l\x08\x92^\xc7\x17$\xe1\x03~\x85\x02\xd3\xb7uK\r\x04X\xd4\xb0\xc5\xc9Q\xdd\x9c&\xea\x7fO\xfd\xd3\x92\x18\x1eVa\x00)\xe5\x8e\xf8\x98\xdfJ\xc1\xc0\xb0p\x9a\xbc\xcaP\xdb\x15\x87r\xe6j#\xb89\'\xc8\xc9\xbc\xa8\xdf\x99\xcaC\n\x16~,\xcd9\x8e\xaa\x00\x97\xef<"3\x96\xc5T\x92\x12\x87hPT7Q\xf5N\xed)R\x15P\x0b\x86v\xd2\x10{\xf5\xf5o\x87]\x8f\xb0w\x90\xb0\xcf\xad\x9d\xb1?\xc7[\x04[\xb2\xb9V\x07zN5z\xd3nd\x06\xbd\xdc\xc1\xaf^\x9b\x16\x00u\xadO\xaa\xc3\x1ev\xb1\xf6;\n\t\xf1%\xc9\xfaij\xd7?RC\xfa\xa1\xee!d9\x92\x86/"\x84\xec\xb7\x99\xbf\xd3v\xbe\xf5g\xeca$\xff\x83\xb4\xd3\xe2n\x1b\xab\x977\x91\xa4g\xd9;|\nE\xd7\xf8\x9aa\x87\x16\xf0\x8e\x83\x8bA\x00\xed\x15\xbf\xdaSN\x92\xfdE\xdc`\xcf%\x83\xedDv/\xb8rPt\nQ\xbcp\xd2\xa2\x87:\x1dD\x1f\xf3`0:4<\x0e\x9e\xa1&\xd17/\x91\xaa\\(\x80\xa5\xbc\x8f\xcc\x8fX\x10\xcc\xa3A\x95\x1c~3\xe4\xce\x1a\x17\xebW\xfd\x91\xdb9\x8f> \x16\xa5^.$@\xd6\x00\xe2\xa2\xac\xc1H\xc8\x0c\xe8\x95\xfd\xf2^\x11\x7f\x9c\xce\xc3W8\xadEV\xe5K\x0c\xe6\x07\xff\x8cF\x08\x06{\x92\x97`\x97wg0\xd9\x04(\xcc=\\\xe5A\xeb\x96\xa5bB7\xf4\xf2\x02\x8a\x1e\xadi\xe4\x96\xabK\x16M[\x8b\xe6i\x88\xbd\xc8\x973\x89\x97N$\xcb\xd3H_|\xa8T),\xb1\x9b\rSm\x8c\x97r=7\xdb\xf9\xea6\xdd\x9e\xdeK\x1bZ\x11r^\xd2%G\xf9\xad\xccx\x1d\x8c\xe1\xd4\xa2\xe3\x81h\x1d\xbb\xb8\t!\x03z\xe7\xc7ri,\xe4\xca\x1av\'4\xf2\xf9|\x1bKI\xd5Q\xab\xc1\x80\x92\xc1\x1e\xaaN\xf6\x7f\x84\xd5,\x03\x8cv\xa4\x96\x9a\xf9\xb3o\xcaJ\xb8knE\x9ee\x9a)\xf2Ve\xe1J\'W\xa7\xf75\x91\xf1\xbb\xcb\xc1\xa4\x95\x1b/\xd8\xdd\t\xf4ats\xe2E\xd7\xc2#`\xe92"\x11\xcdv\xd6\xfd\xba]\xad\xe3\xcej\x03\xb7\xa73\x06TD\x9f_Lk\xe6\xa9\xccv\xed\x02\xb07GzH\xaeBl^\xce\x02\xeb\x0e\xaf\x92\xf3\xe9\x9a\xc2\xe7~\xf5\xc0B\x1f\x98r\x19`\x10\xc5i\xe5\xb8\xe9\xc3\xe1\x1f\xd6\xf1\x92\xf2\x01\x97T\xe1a\x1b\xcf)p\xeb\xf4P\x81t\t6q$D\xae\x81\xc3\xda\x0bb\x049\xf8BEH\xcd\x94\xaf8\xf9\xd0y[\xf1=\nK\xe9\xb7t\xfd\xdd\x0fh\xef\x14\xba\xbf\x8fu\xf0\x14XA\xf6\xd7\x9f\xfdo\xb1\xab,\xd9<\x13\xe8>N\xdd\xc3\x03d\xdf\x97\x00\xe0\xc9\xf3m\xe6\xa0\xaf\xa2\x00\xb4\xcbt\xc4d\xb2\x10\x9b\xddH\xd8\x9fU\xa8Yj\xab\x8b\x9d\x97=?\xd7\xbe\xfc\xda"I\x890\x0cIp9mb\x14V\xd3|\x80\xc9\x13\\\x8c\xcc\x99\x06\xe5G\xfbS\xf0\xb51\x16@\xf1\x91\xce\xae\xf7\xb0\x03\xa1\xec\x0b\xa8\x8c\x7f\xd4\x06\x14\x82\xec\xc0\xbf\x0f"\xe0\x8c\xce\xd5\xae\x80\x91!\xd6hv\xa8\xb3a\xf31\x93i\x18H\xd0\xcb\xc41z>\xd3P$\xe9e1\xd7\xd9\x02\xc3\xd5S\xe7X\x11\xe5\x81\x03\x01\x8dg\xcb\xb6\xac\x06\x1f\x9e\xf3\x8b+\xd9\x06q\xady\xe3f\xdd\xbfOw\x81)\xd0\x9e]\\\xf8U\xf8\xd6m\xbe\xee\xe8[\x8b\x16\xd8T\'L\x94q\x11\x81b\xd5\xc4]W\xb6Z\xee\xc3\x10\x8b\xa3\x18\x02\xd6\xf7\x83\xa6\xeb\xe4+\x02\x06\x08\xb5\xa7\x02\x1fku\x80Q\xec\x10\xbc\x92n-4\x88\x81\x1a9\xb5\x9e\x83\x8b?\x08\x1e}\x1b\x17\x96D(\xbd\x153\xe4\xb2\xe3\n\x13\x9d"\x8d\xd2\xb6\x15dr\xe6\\\x01\xac\xdc\xc7g\x9b\xec+\xec1\xe9\\CX\xb6\xd4\xf3Iq\x05\xfc\x8c\xc8\xf4\x84w?\xe7\xf5\x8ftu\xf8f\xe5Qm:\x9dz\xfe\xd0\xbf\xac\xe0\xb5\x87\xa6\x00\xaf\xeb\x996\x0c\x84<\x92#\xfdW\x15B\xa9\xe9\x18Z\x7fH\xc3\xf5\x1a\xcf#\x10\xa8\xca\xba\rY\xf2\x89\xbb\x04\xc1I[\xaf)+:\xe0\x8dn\xed\x07\xfe\xea\x13O\xb7\x189\x06\x1a\xa1\x19\xd7\x8d\x10\x9e\x86\x1a\x8158\xbay\x99:\x83\x12I\xffd\xbc\x01~3\x1d\x17vI\ta!g\xcb\xac5\n\x96y\xe7\x96\xe7\xb0\xea\xf8\xb9S\xf5et\xba\\\xac\xd8\x85m\xf1\xa4KU\t\xd4D\xa5)\xba\xfcx4\xf5\xad\x96)\x890?\t\xad\xc0V\xc0\xd2Fb\xe7\x08\xbe\xf0\xfe`{\xadeB>\xe1L\xe5\x0fI\xdd\xaaS\xeb\xd1\xfb\x83\x8e\x8a\x84\xd8\xbe\xcd\xdc\x16\xbcf\xbf.\xae\xaf\xba\xaa\xf3\x86U\xdd\x06\xad\xc5\x8cB I:\x19G\xeez\xad\x0c1t\x1bIF}H\x85\xda\xb9\xbe$3\xf8O\x8f\xc61\xc7q\x9er\xca,;2\xb7\xd8aL\xfc\xf1\x11\xdf#\x91^\xecx\x08\xf6\x0c\xef\xe43\xe0\x9d\x97[u_\xe6\xcf\xf5\x1b3Q&X\x95r\xe9b\xb9R\xf6\xb7\x9e\xa9\x0f\xbck\xd2c \xc5\x1c\xeek\xd4\xd9\xc5\xa5\xb9\x86\x82[P\xdaiP\xb2\xee\xf7\x15\x835\xb7\x96\xcb-a\xe5p\x85\xfc\x9aRX\xb2C(+\x87\xd4 \xf5\xe6,e\x9dF\n\xef#R\xdc\xca\xb9\xe4\'\xe2\xa8\x82J\xce$c\xbc\xb2\x95\xb0\x0fv^\x1f\xb6\xe6\xf6V\x1eY-F\xf0\x10\xe6\x9d:V\x07\xb8\xc5\x08\xe3\x87\xfcI3\xa0\xb0\xe8\x84+\xca{x\xb7<\x86\x01\x02\x1a\xb5\xe9"\x1e\xdd4o\xc5j\'F\x0e\xa8Z/U\x9b\x03\x13\xa8\x8a~\xaf\xfa\xf4\xa2`\xc4V\xffl\x088<\xadU\x1cT\xde\x80\xb3g\xc4=?\x06k\x07G}2\xbb\x07\r\xec5^Iyx\xc5m\x9a\xbdV\x0cj\x1f\xa2\x96\x08\x1c\xd2\xb7\xcfnE\t\xc6R\n\xc5`\x8b\x9c\xd7\xe4\xe4\xde\xe9\x8f\x15m\xd7\xd6\xb2k/\xa0\x8eHO\xec\xa8{\xb7\xb4\xba!Y\x11_\x8b\x01\x0f\xda\xed\xc4\x0br6\xc87\xb7\x7fx]=\x0f\xc3^v\xe3@\xa6\xfd\xf0\xfc\xa2J\x8f\x143}f)?>\xfb\xbe)\xa4\x99\xe2\xf0R;\xaa\xa04\x06\x82}\xc78\xafA\\\xed\x96U\xd6\xbf\xa1yol\xa6\x08\n)\xf30O~T#\xd3\x8dA\x17\x1d\x08V\x84\xa7\xec\x9e\x15}\xc8YuE\x16\xcdI\xda!N\x07m%\xcf\x03\x9bU\xa8\xd0\xf6\tL>\xcbhk\xaf\xc1`\xad\xb8\xa9-\xb1\xc5\xf2\xd7\xea\x15\x81\xb9r\xf3p\x92\xf0\x82\x13\xb6l\xa1n;\xa1t\x9b\x1d\xac<\x11\xc1\xba\x96H \x044\xe9\xa3\x00\xd0?q$/\x9c\x90\xb6\xde\xb7\x80\x83\x03\x92\xe6B\x9e\x88\x8b\x11\xc1$\x8aa\x1a\xd3:d\n\x0c\xa4Ci{\x0fM\x96\xb6D\x14@\xc7\x17\xac\xfe\x86\x07\x12>\xcc\xab\x8e\x9f\xef\x19C*\x11J\x80\xc5\x7f\xdd\xa2\xc7\xf0\xc3\xc2Q\xfa\tl\xa1C;\x12 \x93\xb7\x9e\xf9J\xb4\xa3\xe5\\\xc2\xff\x0c\x05m\x81\xbf\x81\xeb\xa8!b\xa4\x13\xf8[\xe4\xd1\xbe\x9dr\xe4\xd2\xd1\xf20\x91\xcb#\xdc\xe2\xd1\x127\x93\xbaC\x1e*B\'2f\x9b\x0b\x01\xae7\x1c\x18\xef\nh\xf8vp\x9a\xdc\x04\xc2\xfeK\xcek\x8b\x80#\x92i\xc5B\xda\xff\x9fL\x13\xa7\xa6\x95\x98\xf0\x02%Q\x99\x8b\xdc\x0c\x01\xa5\t;I\x97T1\x18\x82\x9b\xde\x9f\xd4"!Z\xdd\xedp\x86\x01F\x92s\xc0m~\xb7!\xe6\xef\t\xb3\\\xd9k\x94A\xd8\xff\x02\x8dn\x1aK\xaa}\xeb\xf0\xd1\xff\xb5\x86\x98"R;x^V\xc1\x94+\xb2\xf0\xc1P\xc69/T\xf5\xa4h\xd0\\\xcd-\xd4\x93m\xfa\x8cb(j\x86\xaf\x82\xc1\xf9H\xfcM?y\xdcq\xd1d\x9f\x1bEz\x82\xc34\x7f\x8f!\x9d[\xe3w\x05\x158\xa9\xb9\xefF\x02]\xa1\x9b\x1c\xbc\x91(\xe9\xd3\xc1z\xc44\xad\x99\x01jra\xc5\x8e\xe8\xab1gM\x1e\xc2\xf4\x8d\x1bG\xcc\x9f>H3\x8e-ce\xa3\x9b }\x1eV\x9a\xdd?>\x9a\x9f\xfb\xf7)S\x0c]\xa9\x87\x1eJ\xa2\xb9\x02\x8d\x84\x16tz\x11\xe0\x86v1\xaf\x82~\xea\xea\x11an#BS\x84\x9c\xda\xbe\xc1\xb6u\x02\xf0\xee\xaf\x0f\xaaP8\x0fo\x89\x19\x86\x9d\x82\xfb\xb9\x8fF\xa2(_v{4\xacI\xbb\x86\xd7\x17\xd42G\xa3\x87\xff\xaf\x0cb)\xa9\xe7\x16\x0f\xee\xe4\xae8\x02\x96\xe2;\xd3&PL\x01K\xa9\xbb\x02\xa0F?\xaf\x08\x1a\xd272\x81\xa4\xf8\n\xfa\x9d\xa0!e\xb4\xdc\xad\x87\x19Z .\x84\xcb\xe0y\x07\nN\xe0\xcb\x1eF\x8d\xb5nD\x1cB\xf4\x89\xc7\x8c`\xc3\xb8\x9f!q\xa04\xce2\x0bN\x08\\R\xcd\x12\xfbq\x89\x14_$v\xf9\xbe\xc7E\xa9\xe9B$&\xea\xb623\xcaV\x10\xa8\r\xd4\xebj\x11KQ\xfa\xf4!3\xefyp\x0b\n\x98\x8c\xb16\r\\\x95N\xe9\x9b\xd7\x8a\xa8\x9es\x08v\x8c\xf2`\x05\xeaz\xc7\x1c\x16\xe6\xd5\\\xbb\xd3A{\xc9\xfe\xfe*\xfe\xba\x1c\x86\xe2\xb0k4)\x02\x9eg\xc2&\xa7\x19b\xf2$Q\x84u|\x81B\xc2\x1d\xa5y\xb1\x1d\xd1\x1d\x81W%\x84\xeb\tT\xd7m\xed\xaaZ\xa7\xf9X\xe7=C",d\xddS\xa2-1qa\x87\xc1\xaf#!\xc9\'Q\x1c\x8a\xa2\x911\x002$\x11\xb6\x8eS\xa0\x9e-4\x1fK]Ug\x86V\x02\xde\xc2\xda`^k\x8dfS\xd2\xb7\xda\xb21\x86\xac\x91\xbc\xbc:\xc3=\x00G\xc2\x1e\xd4\x18n\x03i\x8f\x1d\xf4\xa7\xa2AC~Hl\xc0\x12k\xb5\x96\x97]\r~\xd7\xea\xe1\xfbE\xb9\xcdsRF\xf6\x8e\xd0\x83{\xfc\xe2\xbf\xf1\xf55\xe25\x05k\x8cI\xb1\xeau=c\x0c\x8f\xf8XE8X,\x87\xc6,\xf4\xca\x85\xee\x94\x9c\x00@Ry\\\x06\xea}\xa9V\r\xed\xde\xde#\x03e\xd4\xb2\xf7\xedr\xbf\xc9\xdeK\x9c\xa89\x9ce\x06B~\x9a\x1fr\x96h\x0fy`\xe6B.\x07\x86\x8e2\xb8\xf2\xb38\xaa\xef\xad^\x98\x06U\xf5\ty\xb1(w\n\x8a\xfc\xd7\xbez\x13\xd1f\xfc\xde?\xf0bxV\x1f:\xcd\xb3qy\x83k\xb8\xcd]/\xea\x8f\xb6+\x92\x8cW\x14\xd9\xea:\xcejHK\xc3"\xe4q\xa7Y\xef+\xd3i@\xb9\x91g\xf2R\xf3J\x94\x89\xfdo\xafv\xbbq\x9c\x9e\x1d\xe9\xb3\x9e\x078\x1d\xf2\xaa\xdd\x19V\tj\xa2+l\xa2\x12=+\xe0?\x11\xc6\t4\x96<\xa3~\'B\xdc\\\x96\x1d\xb8\x1d;e\xb0C\x8e\xdf6\xb2\xef\x83\x9d\x17\xd0i[*\x82\xdcu+\xc5\xac\xe1Q\xd7Z\x0bU\x05R}\xfc\x93{v\x85{\x7f(\xda\xa7D8\x884\xd6\xb1\xf7=\xeeir\x97Ke\xc6\xd5\x98_\xa3H\xc8(1.A\r\xb3-\x05\x04\x92tky\xbfk\x0e\x90\xebVH\xbf\xabb\x98s\xa66\x0f\xf2/\xc7R\xb3\x01Z\x14\xe9\x12\x8d\xd2BPw\xa8\xce\x1c \x12\xb6\xa5\x8d3C\x84\xb1\x9a\xd6\xc9\xdf\xea-\xfd\xd4_\xe3C\x060\x90\xb8\x1b\x0en\xc4\xc6\xcc\xf1\x7f\xe2\xd0\xbe\xfc\x1000\xc3_\xf8\xb1\x9d\xb4B\x1fp\x84\x9c\x92\x92G\x9f\xbc\xa92C\x197\x16\xc7\x9d\x1fx\xa0\xb1U\xffnr[\xed\xfeJ\x8fo\x91A\xf6\x9f`\xd3NAii\xdfv $\xa58\t\xfe\x06\xe0,\xa4\xad\x84t\x94!\x80\xfe\x90\xfa\xa0o@\x98\x06LG\xfeT\xd2ya\xcb\x19Sf\xb9\xf6\xfc\xf1\xe4kp\xc8\x92z\xadhK\x19\xd7\x95\xe5\xc4:\xb2t\xb7\xe0\x12\x81\xf1\x1bE:\x939\xd2\x17\x8dp\xa6\xc7&/\x10\xba\xf7\x80\x12\xe2\xf8\x91\xb1V\x06i\x1b`\xe7\xcc\xc8\x9eJ\x14\xb5o\xa4\xa9\x8a\xe8\x00\xbf?m\xe40\xde9\xe0M9\x06\x9b>\xcfeY\xd6\x18\x17\xeb\xbb\x19g\xf3%\x18~|#l\xdc4\x92\xdd\xe7\xea\xc9\x04\x1a\x00\xb8\x1eM%\xa7R\xb4\xcae\xcd\r\xf0\x884\x90\x1d\xd4G\xbb<\xdd\xee\'o\x0b*Z\xe0\x85\xfe\xf5\xadm\x1ah\x82[\xa9+H\xfe\xb1\xb7\xeb\xd9\xe8\x82\xb8c\x07\xe2\xf2\xe0\x9f\xf6~Z^E\xcfTo\xf1\xa0G\x85\xa3\x13\xc9\t\x16\xa6X\x14\xf8\x03\xea\xa7\x19\x0b\x82\xb3UEk+dI1]\x896\xbf\x7f\x91\x99\xfe\xc9\x12\x81\x03D\x9da\xb1\xaa\x1aNcL~@H\xf2\xa2\x0b5~n\x16\x0f\xef\xef\xbd\xe7b\x92\xd3z|\x91\xb9\xd0\xb3\x83\xfb;\xd9\xb4\xcc\xcd\xd5\x04\xcc\x18\xc4\x08N\xf08v\x9fM\xb3\xb9A{\x88\n\x14;\xf4\xac\xc7\xd0\xa7\xb3\xd9\\\xb1\x92X\x10\xf6\xbc\x0e\xf6\xb9L\xcd\x82;%\x07o\xbb\xa9\xf2\xed;k\xd9\xa6L\x10W\xae\xa8\x13\xa1\x1d>\xd9\x15/\xfe\xe7\xa9\x9be\xb1b\x8f\x0f\x96-\x8cJ\x7f\x1b5\x16\xe0\x16\xdci\xa3\x94\x8bl=\xe5\t\x8c\x0e\xa4t\xfe\xb7Y\x90\xfbv\xd1\x84\xbf)\xe5\xb1<\xd1\xff\xd4R\x11\xd0>3X4\xba\x8bJm\x1c\r`_\xc4\xe8\xf8L\xf5)\xaf\x81\xf8\x19L\xdeH\xe3H\xcd\x86\xc8gS@\x11(\x05h\x91\x1f\x94\xbeY\xbc\x9a/\xc1\x98\xea\x10\xf8\xb4\xa4mr\xbe\xbb\xaf\x9d\x04\x12\n\xc7{\xa4^#\xf4!4\xfb\x04\xb6\xaf\xb3j\xcf\xb0E\x15\x83\xa5\xbd\xea<"\xe0\xea\xfc\x8f\xbbB\xa18\xd1\x08j~o\xa4\xd8\xff!e8\xb5EN\x11\xd7\x0c\x8fR\x0b\xdcw4\x99:2q\x9b`\x8fk1\x13\xe7\xa5\x08\xc1\x00Y\x93a\xee7\xa5Y\xdd_\xe9n0h\xa5\x97\xd9#\x98\x02+"P\x93\xb7\x95\xf64r\x81\xc5\x0e!w \x86I\xd0\xd3\xb8\xd0!\x8dE\xaf_\xdb\x0f\xb6\t\xa6"\xf0\xbc\x07\xa4\x0b\x99\xf7\xf3\xe7\xf5\x1a\xc5:]n2\xd0\t^h\xc5\x0cM\x0bZ\xbd="\x12Kd;\x0e1\xa6\x8c\xa6so\x99\xf8\xe2\xf5\x02%rE-\x16\xd5\x91\xd0\xd629\x8f\xdb\xaa\xc6:\xe7M\x97\xde@c\xbb0\x15Y\t\xdd_N\xf0\xfa\xe3|\xe7\xc1\xe0.^\x06\xa5\xc1\xac\\X\xc3K\xb3\xc3\x92@\x91\x86u\xc2\xa6\xee\xd7?\x11\xc4\xfe\xf3\x8e\x15\x12$\x93X\xed+W\xfd\xfb\xe7C\xb2:\x93\xfc\x9b;\xd2\x14o\xb5H\xa83\xf3\x8dd\xd3\xa3*\xa6\xee\xc50\xaf\xc6\xbdB\xf2z\x84\x91\x0f\xf6\xd9\x19\x99\xd6\x88\xb9\x8e\x1cv\x81\xb5\x02\xc3\xbdb B\xe6\n\x95K*\x85*rTib\x0b}$\xbaz\x8d\xc1\xc1up\xben\xcb\x96\xff\x97\x9f\xde\x01\xfaH{\\y\x92XA\xed\xee\x9d*5\xbb"Z\xb2\xbb\x1d\xc1\xa4\x11y\xaf+\x96*\x8c\xf7\xa0\xf2}\xa1b\x02(z\xd7\x9f\xa5\xb7s\x8f\xfc\x84\x99x\xbc\xd2/I\x1b\x8d-\xb5"\x8b7\xac\xb6\xc6\xef\xb9\x7f\tG\x06Q%z\xba8e\x9a\xdc\xcd\xd23\t\x00\x13\xf5\xda\xc4.Ngz\xcf\xa2\x07\xc1\t\xa3\xd4\x19w\xda\x18]\xed\xa2Y\xa7E\xd7P\xfa\rq\xffX\xc9\x18\x16\xea\xfb\xa5\xb6p\xda\xf8\xda\xa0\xd5\xea\x16?\x85\xcaB}\xd4\xb7\x12\xf62\x9dH*\xdd?(\r@v\xba\xdd\xa5\x13\x80\x15\x80\x8e=\xcd\xf7@}Z\xbc\x17\x97\xbch~\xc5\x0f\xf8\xf0\xc1S\xd7N\xc5\xb3\x9c\xcc\x14l\xf4\xa2\xabb\x7f\x16\x9e\xd0\xe4\x1a1\xd5\xef8a\xc4(\x99\x047\xec\xe4Scg\xbc\xc4\xe7\xdfg[MB\xac\xf5CC\xa2\xae\xd2E\xd6\x9d\xf1\x03\x0e\x14\xb3\xd1@\xc8\xf9g\xf1\x15\n\x8cH$C7\x0b\x9f9j\xeev\xcb-\x14\xa5\xd6&\xfc\xa1\xb2Hrs\x0c\xc7~\xaa\x81\x8b\xb3Cv\xc3`\x00D%\x90\xe9!\xe8#:\xe3\x10h\x9bf\xea?P\x17\xa5w\xbc\x8dl$\r\xa4\xc5\x97O\x03\xe30\xde\xcc\xee\xeb"\x96D\xbfSz\x9dvs\xca\x836fV\x82[Q\xe9\xdf\xae|\x07e\xbcK\x93\xc1\x0e`"\x14W\x93\x95:\x07\xb3\xb1@T\xe7u\x86_\x1d\xa8\x9c\xe9/\xe2\xc1\x80\x95\xf7a\xd7\xff\xcf\xb3\xcc\xddl,Wc\x01\xc1hV\xf6RL\xadf\xb4\xaf\x8e\xb6B66\xda\xa2\xd1\xafi\x16,\x02\xabc7\x00\x9c\xd3\xa0\xfe\xa3\xda\xd5\x9d\xeeYz\x14<\xf6\xf3\xfc\x82\xc1fla\x8e\xf1whD5\x8e\xf0]L\x80\x18~\xc9\x86\xee\xfcA/J53\xb7\xad\x1e_M\xae\xeb\xef-\xd86e\xa2\'\xbec"3\x93\xcaZV\xc6\xed\xb0\x04\xaa\xe6>\x1f\xbd&@:1c\xc3\x9a\xe7\xeaG\xed\xf8{]\xab\xa8T\xe8NF\x93\xfc\x88\x1d\x1d/\xac\xb0z\xe5gr\xfd\xcd\xcb\x12\xa1\x01j\xcft\xdf/\xba&\xb5t\xd1\xb2\x91H\xc5@\xbf\x92[\xef\x11\xd8*\xae7\x8c\xe8I\x86z\xf2\x8c\xc7\xa6\xd1YR"JV\x12\xed\x1a\x1f+\x870\x126\x07\xb8\x9aIj<\xbf\xa0\xdc\xc0\xc1f\xea\xa7\xe5\xb6I\x16\xf1!\xe4\x1b.@U\x8a\x80\x91xs\x06\xbd\xa6n\xd8cw\xb8\x06\x89\xf1\x19\xacjth\xdd\xa2\x08Y\xd1%!\xcf\x01\x84.\xbbNrFh:P\x1d\x0f\x8a\x96\x0b\x11Z\xfaN\x88@\x9c\xbb+rT\xbf-F\xaf\xa9\xcc\x88\x08M\xa7\x91?*\xf2Aj\x9af\x8d\xf3\x08\xfd\xda\xb9N02\xe6\xfe\x1e\x05\xfb\x8bS\xfb\xa8\xb0\xc8P\xf0\x8f\xb4\xfe8\xec\x10\x87\xe0G?\xaf\xf1h\xfcW{\xe3\xfa\xde\xa3L\xcb\x1fFv\x8c\xe4\xdaE\x04\x90%VI\x14\xefz$C\x162:H\xf7\xd1\xa6\xb7k\x93x\xa2"\x98\xb5\x13\x11\t\x04\x80Y\x97l\xa5\x8f\x88\x80/\x1e04\x7f\xa4b\xbd\xc7\xbag\xbe\xb3\xce\xc4`\xd8\xc2Y\xfa\x1dw\xaaS\xfea\x160\x80\xb4\xb3%\x81\xcc\x07\xab\xb8\xf7\xeb\xfe\x9c\x06\x0e\xf9<\xa5\\\xa9\xff\xb6\xae\xa0\xa2\x8f\x9b\xd0\x83\x8f=\xdaG\x057j\x97ZE\xf3\xb5\x0c\xd9\xdbW\xc6\t\xc5S\xca\xfe\xcf\x161\x1e_\x06]\xc72O~\xa9\xc3\xde\xdf\xad\x99\x0cr\xb2\x82}\xac\xa01S\x98_\xa0@h\xd1U\x9e\xed<\x96\xb7d\xf7\xd5\x13djq\xf1\x9e\xa3\xf4-\xdc\x01\x01\xc3\xe5S\x15\n\xa6|j\xe6\xed\xa6\xcf\x88HbF\xdb[\xb3\xc4!\xce1\x87\x17j\x94j\x82\x7f\xf1\xf0\x0e2\xb1@\x05\xbdy\xa0\xa9\x8ch\x80[\x1f;\xfbn\xf2\xb8%\xf7\xc7\xc86\xfc\xd0\x82$\x7f\xa2\xf6X\x97\x94\x12Hv\xa3O\x83B\xf7e%q\xce\xdd\xed\x971\xf6\xc7.0\xc7R\x17|\x10\x00\x04b\xaf,\xf5\xa9)(\xa2\x04\x1ba\xe7P9\x80\x92\x01\xf2\xbb=\xc7}\xc5\xa6\xef^4\xc7\x9e&9\xc7\xc7Y!\x8e\xe80[p\xa5C\xf1\xcb}3\x8b[\x8cw\xe1\x11\xe7[/\xfe\x98\xb0\xbeb\x8eD)Z\x83\xc4\x91\x84\x92F\xdaiP\xbb!\\$\xc6=\x9a_J,\xce\x9e\x83\x13\xb1z\xf7\x8c\xeb*\'\xdf]0\x9f!\xe4\xcf\xees\xc2hJB\x17\x80\xb0J\xed\x88\x84Z\x98n4L\xc3+3T\xa7be\xa8E_5\xde\xfb\xde\xb5\xbf\xba\xe1\xd1\xa1\x8et\x1a\x85\xce:Q-\x13P\n\x9d\x9b<\xacR\xdd\xf2[\xc9W I\xda\xbc_\xe1\xfb2\xc9\x15Xp(y\xa8G\x9b=C\x93V>y%"\xfb\x15w4\xb0k\x11N\x95i\xef\x97\x91\x82\xb0D\xcb[\xd2%\x9fi\x92\x14u\xb6@\xf4e\'\x07\xf6\x9e\x10\xe9\xab\x0f|\xf0\r\xb9Z\xb0\xde,au\xe3\xe1\x8fB,\xb1\xffZ\xf0,\xf7\xb7\xf4~\x18\xf2\x00u$q \xea\xf2J\\\xb5\xb2\x9e\to\xd0\x8b\t~\xb4\xef\xad:|b\xc0\xb8\xdb"\xf4\x9dH\xf4\x81\x8fq\t\x994\x8eT1\x8d\xc2\x01w\x9f\xa4\x17\x0c\xc2\'s#\xf31\xc0\x1fa$\x8c-\xb87C\xd0\xf7K\xedX\xf5>Q\x97\xd1S\xc5\xf2\x99bH\xa4\x8e\xd0\xfd\x15\xe3\xe8\xe7\xae\x1b\x81W\xb4\xa9\xb1\x9axD\xdfF\xac\x06J\xd9\x17\x92\xb2\x11\xd3\x84\xa9Uvk+\x8b|\x93\x8d\x1e\xe5\xa9Q\x80\xdd\xf8\xf9\xc1\x1e\xcfL?\xe6G\x08\xcb/4H\xbc\x1f\x8d\x10Lw\xc2kPXK$[\x08\xf0I\xd2\xb6\xef\xe3l\xb9I\xa2\xda)/\x8b>>\xec\x10om\xf8\xbd\x99g$\t\xed)]\xbe\xa1I\x7f\x1d\x90*\x0e@K"\xac\xd0\xd3Lwt\xdd@\x0b\xaeZ\xfa\x94\x0fU>wP\x82\xb5\xb9\x89\xf1\x02G4\xee\xca\xeed%\x1a\xae\xe7%R\xfe0\x9e\x024\'Jg\xbe*|.\xd4"\x9f\x982\x14\x140\xe0TQ\xa7\x8f\xb6\xb8\xca!\xc7\xd7\xfc~8\x13\x16\x14\xad\x0c\xc1T\x1d\x8b\xe9w\xee\xd1=!\xce\xab\xd0\xc68p\x1f\xcev\'!\xaf\x83\x8bUwAH\x0e\xa4\xff\xf4\x14d\x96+\x10;\x13q\xb2\\\xf12J\x9b\x804\xad\x9c\x7f\xc2\x9f\xb6o\xe2\xc7\'r\xa1\xa2/\xb3pN\xf7\xb3\xdd\xde\x95\xb4\xec-\xdc$\xa6\x1e\xb7\x00\xf5\xcfPUv\xb7/\x13\xc97\x1f\x0c\xe0%\x19u)\x1f\n+\xdf\x04\xf3>N\xe5\xfc\xf3e\x0f\x8f\xb6\xc1b\xb0\xf5\x1e\xfaQ\x8c\xfeT\xf2\x98\x0e\xb2\n\xd1\xad_;\x8dCP\x16\xc2\xc4p\xde\x1e{\x9f\xd9\x9f\x98t\x7f\x9c\x8e\xbe\xc7K7\x90\t\xd99\xeaCb,H^\xeee\xffM\x8d\xb7\n\x1f$-\x83KP\xe0\xfd\xc8\xcd\xaa\xf6\\\xab\xce\xc1g5@\x11`4)\x8aF\xb4g\r\xa5\x873\xf3\xf7_\x9d\xf6\x83\xa4\x016f\xc2\xd7\xce\xc6w9\xb2\x8e\xf2\xb2\x12S\xa5<\xb4$\x1b\t\x99\xdc/\xe5\x92-,\xcc\x996\xd8*\x0c\xb9\'<\x15\xd6>Ph\xd7z\xcc\xe4\xf8j\x89\r\x86\x1a\xea\x04\xb4\x7f~fW\xf4\xde\xad\xf9\xab\xe5\xa53\xebMpC>\xb0\xf8\xa5\xe9\x95{\xb19N\xb4\xab\x9b\\H\x1f\xcc\xb8\x1c=\xfaj\x82+\xac\x84z\x10\xf4\x93\x8f\xce\x1dj\xa4\xce\xaf\x1a0TC\xdau/fiR\xbf\x14\x80\x9c\xca\xa3\x17\x9f\\$\xa4\xe0\xbc*\xd9\x9b?\xe8\x8a\xa0\x16(\xfc\x0c7T\xa5\xfa(z\xd7D\xe6\xde;8Kc/\xd4b/\x9b\x93\xa2\x9f\xc2\x8f\xfd\x96u\x89\xdb\xf2\x9bZ3\xdb\xe3\xcd\xc3?~\xd1\x19 \xeaok\xb8\x97\xe9I\xc2:\xd1\x13-\xb1\x06\x99\xa7\x9e\xa8b\xf5\xdc\x9fL\xcc\x08\xd68\x7fP\xf0\xbd\x7f\xc9}V \xceW\xd0\xbb\x1d\xd9K\xa4\xda*\xc0\x9d\x08h\xe0\xfa\xb1\x84h\x8dV\x98r:\xa1\xf7\xaa\xfd(\xf6\xf5EM`\xd6\xd3\xc5\xf0@\n\x9b\x85\xcd\x8c\xa4l\x95\xd2\x12]Y\r\xda\xb7q\xb4\xf3Le\x1c\xf6\x8f\xb9\xe2 *\xea\x8eI\x15n\x89\xd6\x1aT\xadq\xcf\x98\xa3\x9c\x82|C\xcd\xe9\x12\xd6k;\x14\x9a\xc5\xee0%\x9e\x8f\xb0xY\xd7\x93\xfb~\xc7\xcf\x9a\x8fa&%\xba/Q\xfb\xa0l\xc3\x078`\x97 \x13.\xc9N\xf1m\xc6]\xfd\x10\'H^jj\x15\xf1\xdeJ\x8c\x875H\xac\x87\'\xa3[\x9c2\xca\xfaa2~G\xf2\xe9\xc8\x98\xaf\xe4YQ[\xbb\xce\xd9\xd2\xc1)\x11\xc5a\xdd;\xce\xdc\xd8\x10\xb2\xe3\x15\xc5\xce\xfd\x1e\xb9\x8fA\xd0\xa1.\xc0\x8d\xe8D\xff\x12}b\x98b\xae\xef"\xfc\xbc\x17o/-+\xf5\x88wh\x9f\xf3\xe3\xa5\xac\xc7\xae\x19\xac\xb6\x95\'">\xadH\xed\x16;d\x1e\x0b\xdd\x91\x0f\x01*\xfb\x97\x915hq\x98\x10+0brd\x90\xbc3\r\t\xe4\xfd\x19\x02\xf1N1\xa9$/\x0e>W\xa8qi\xfc\xdf\xc6\xf2\xa6\xb5\x9e(\xbbA\xd0Gr\x9eHi\xaa\xda\xb4r\xb6\xdaN7m\xe7\xb5\xa7\x98~\xf4/\xa1\xfc\xa1,\x8f\xd6]\x13+C\xaa\xde\x8dl\xfd\xe4E\xfb"\xf9\xd0x\xfcB\xf9\x80\x93\x80DV\xd3,\xd3\x85\xb0\xb6J\x8a\x04+\xc1\xbc\xb3\x0e\xb83\xf8\xd4T)\xbe&&\r\x96\x8a\xaeT\x04\x0f\xa8?\xa9\xc3\xef\xf11EP1\xc3\xfcoV\xc4.\x0b\x9e\x1bG\xd8G\x1d&\xc50\xee\xe8\xfb1\xbc\xe8\x1a\xe2\xf4\xa9\xc6i\xddoK\x8bA:\x91\x81\'\xe9\xbc\x16\x83\xb3\x9cGWt\xbd\xb5\x886\x88\x8d5\xf2\xad\xd3\xc3\xe33\x11\xff\xfd\x17\xd4f\xe0!\xc7\xd3\xd5\x1d7\x9bi\x95\x07S\r\xab\xf7T[\x8d*2\t\x86h\xcc\t:\x06\x81$O\xed\x8f\xf6Nw\xf4kO\xde\x85_\x99("@g\x1e:\xf8~\x13k\x12\xbcm\xd6\xae\xdd\xad\r\xd3\xc8`\x92\x8d\xc8H\x1c +\xdc\x9cCd\x01\x92\xbf\xec\xde\xe6\xb12\xf9\'\xa3W\x87\x17\xb9\xc2E\x8f\x8b\x064\xcf\xe9\xaex\x84A\xe7\x06\xad\x9d<\xa1\xb1\xd9\x90r\xdfZ\x0fJ\x15\rCh\xc1\x0f\xf6\xe2K\xe3\xc9\x94a\xea\xeep\xd2\xf0\x97\xfc\x9c\xe4\x10\t\xff\xde\xae\x9c]\x9e\xe6\xcb\x08{\xde:\x86\xadU\xaaI\xf4\xca*)\xceC\xdb\x93\xe3\x7fN\xb7\xfb\xde\xa70\x14\xf8\x03\x07C\xc8z\x82\xee~6U\x01\x8c\xbf4\xb9d\xef\x89\xc6q\x08\x8d\xb4Bf;\xca\x92:\x8e\x18ZA\x86\x1c\x80\xb95\xf2\xc9\xc3\x02\x86\xe9\xe9\xea\x85\xa1\x08\xb04\x91_Hg<\x88`\xb8?\x81\xcc\xe1\xb0S\x1e\xfb\xfb\xff\xb5\xcf\xfb"\x8c\xdd\xb3\x03\xec\xe1.1\xa4\xda\x87\x16g~5@\x9df\x15\x9e\n\x14\x18\xe0\x9b\\vH\xcad\xc5\xe2CsQd\xf3\xb6^\x11e\x13i\x0b\xb3\xc4\x9f\x00\xc3o\x99\x8fU\xff\xf9]\xdf\x83\'\xd6(\xaaR\xb4\xef_\xf9\xdb\xad\x87\xca\xc7\xe7\x98\xcb\x12\xaf\xc4i\xaf\xb6\xa4b\xe6=r}\x1c&I\x9c\xc3\x94\x13\x82\\\x83Nx\xca\x1f\xf2\xa3)?L*\x86m\xb6\xde\xd1c\x93r-\xd0\xa9\xaa[#\xd2\xd9\re\xe0r\xbeU\x8c\x1d\x80\\_\xbbL\x05\xa9w\xce\x10\xd0\x08\xee\xe8B}RrZ\xb9\xb5"7\xb92\x81a\xaf\xbf\x1a\x1a\xeed\xd7\xa1eX\xd8w\xc2\x1a\xd6\xd6q\xd5\xa4y\xff\x14Y\xef&ML\x1a\xc0 \xd9H\xfa\x92\x80.6\xda\t\x82\x07\r\xc6\x17\xef\xa5\xe17\xed\xb3]~\xb3g\xe1l\x983\xe4\x92\x00\xa9\x85OK`69\x18+(B\x7f\x85\xfe\xd8_E\xfdC\x11\xddY~@<\xc6\xd0!\x82\x0b\x8bk\x8b0W\x1eb\xb0\x85\xb3\xf4\tO(\xa5\xf5RN\x8f\x88\x8e"\xd8\xc7\x01Ic\xc2\xb3\x04N3\x8c\x8e\xf5\xae\x12\x0b\xe1\x92\x84X\x98\xe7\x18 6\x9ea\x14\xef\x83\x95e\x94G \x18L\xb5|\xed\xa6\x02P\xe9\x1e\x1f\x04\xc5\x16\xf8\xc3\xbbYrs\xac\x982Ex\xdf\xd9\xe7b\xf5\xe4\xa2\x86\xd8\xb6 \x10\xf6\xec\xa2\xe9\xc8\xc0X3CF\xc5CCQ\xdb\xf1U\x12ZK\xae\xaa\x8cI\xa8\xf42/\x91g?\x05\x9b\x1e\xb2v\xb4_\x04u}0\xa8h\xe4\x19x!\xa2cO\xf8\xb6\xee\xcb\x8e`?\x82\xa2\x13 g\xe9\xd54\x11m\x83\x936\xfcj:\x00\xae\xdb \xdf\xae\x1a9\xff\xb9"\xa2klr\x90\x81\xc4mBG\xabU\xbd%yl\x8dl\xd5\xe5*?\xce\t\x9c\xa5\xa8\xe9\x01\x93\x9f\xca\x95\x8e\n\xd8_Y\x08X\x8eB\xd1\xeb\x1b\x15\xbe]\x8d$\x94\x96\xe8\xf4\x87eh\xd7\n)\\\xdb8w#\xa4\x8d\xab\xaf\xc6\x1a;/]\t\xdd\xddi+4\xc8\xe8%\xc16w\xafu\x9d\x19Q\x91e\xa0\x19\xb3)\xee\xad\x1f\x85s2^a\x07\x99?\xe3\x1c\xd3\xf2\xf2\x8e\x89x\x8f\xb9\xe2\xa8\xf1f\xbe\x13\xd6n\xa2\x93\x0b{\xa8\xa9\'5\x06\xd4\xb0#\x08\xec\x11\xda\xf0\xb0\x13\xfc\xa4\xd6E6\x1a\xc0\xef2<\x7f#\xc4!\xf4[\xc0\xa8\x91\xc4\x0e&\xd9\x99\x8bQ\xaa\x1dH\x0e\xb7>\x0b\x84|\xa0\xbea7C\xcdinN\x82h\xedn^\xdb\x95\xa5\x997Y\x7f\xfc)\xca\xddi\x90\'E~\xa7\x0f,W?\x04Nw&G\x9d\xb2\xae\x94\x03\xa3\x1b!e\xb4\x0bQ\xcb\xbe\x88r\xf7\xbb\xdaM\xd5\x9a\xad\xb8bP\x12\xaf\xcd\xee\xc9\xccJ\xfe\xebC~\xaeq\x83P\x93yR}\xee\xd5\x05"\xa2\x9f\xa5 \xe3\xb6\xea\x965\xfc\xf7\x8b<\xce\xd0n\xe2\xbfI\xfa$n\x12qn=5K\x95q\xc9\x17\xc5\xfc{\x95\xee\xbbT\x9f\x86\\\xe9\x03\x07\xf0\xe3\xddO\xb8x\xb10\x96\x12\xcf\xd1\xbc\xf6\xd0\xa8\xb8O\xc0t\x8c\xa7\x07P\t\xaa\xf6\xcel\xee_\xe3\xfb@Z\xc9J\xc4D\xca\xb5x\xedm\xe2\xf0\xac{\xb964)\xdcI\xa8\x7f1w@8\x9b\xac1\x01\x0cO\xe9\x00\xa0\xe4D(\xca\xf4\x96\x95\x00P\x9d\xd8-\xaaMg\x9bml\xb0`\xf0\x1a\xb4\xa524\x9fK7\xfc\xa9*l\xc3\x16b*\xa4\x1c\xb8\x04\x90\xbe\xa4#\xca\x83.\x13m\xcdxs\x1fu\x00\n\xf8\n\x96D\x1b\xfa6\x83|\x1a\x8f\xd8\x1f\xcag\xf5\x17Tdn-YY\xb8o\xb9d\xb5\xfe\xa0\x19\xc4\x89P\xa5\x87\x93\xc2v\r\xa9>\x9c\xa9\xddR\xa5\xc0\x06J9k\xe6\x96\xbb(\xc7I\xc3^\x8c|`\xe9\xa6\x1b\xa0I>\x9a\x84\xbac\x99\xa5\xbf3\xa3A?-w.\xf8}k\xc2\x07,\xc4\xbe\x9d\xae\xd3\\\xc9\xcbz\xdb\xb0\xca\xda\xd8\xfc\x7f\x02\x16\x10\xadV\x1a\xe6\xbc\x90\x08 J\x15\x8d_\xa2\x83\r\xb70\xfa\xcb\x04\xace(\x80\xbd\xd3\xd4>\x80\xc1\xd0\xdb\xe1>~\xab]!\xacUB\x8b:^\x01\x99\x94\x13\xe2\xb2\xf5,\xe0\x82\xd0\x97F\xbc\n\xed\x1e\xab\x06\xb9\x8e\xc7z\xbe\xe2\x0c\xfc\xca$/\xe7u|\x132\x04\xdba{\xe5JO\xb4d\xf0v\xabz\x8e$\xd9\x9dT\xc0@\x97f:\xd1\xba\x97PT\x80n|V\xb2P>K\xe6(\xd7i&\xa8d\xb8\xb6\xed,~\xa3\xf2\xc1Y\xbc\x82\xf8\xe4\x00\x9e\xd7\xd4\xc8\x96oxx\xd11\xa2\x9f\xd2&\xb8\xcc)U)\x98V\x93\x96\x80\xd7:0\xe3~\'\x0c\xcc\x13\tJ\x05\x18\r\x1f\xd8\xb3\xfd\x8c$\xe5%^\x7f\xe2\x7f\x8a\x11L~P\x8dy\x1d\x91\xf2\xbbM\x10[\x95\xfe\xbb\xd1\xcb\xab\x16C~A\x16\x81\xd3\xd0j\r\xbc_\xc2\xf3,\x1c\xf5^\xefSgs\xf5DOGU\xf3\xf1\xd5\x9e\x9cB]\xba(\xe1\x89\x06\x85\xca\xa9\xf4\x07u\xe2\x00.\x16\x80\xc6\xa6\x12\xbba\xcf\x82\x9c\x17\xa0\xc1a:1\xf6\xfd\x9fp^fb\xe4=\xfb\x89`y\x03\x81\xf2\xd86\xd2$\xe6\xab\xc3\xbb\x16tM\x9c\xd7y\x9a\xcd\x9c\xc3\xc3\x04\xa3\x17\xdf\x15;\xfbz3\xdf\x17\xb9\x82\x1f\xb8\xa6\xe3\xd4\xeac\x14\x0c\x16\xb5TX\xebP\xabn\x8c\x94\xb0\xa3\x10\x14\x82-\xbe\xf8\xd6DJ&t\x9fUg_\xac\xca,HBf\xd5\x97\x13C\x17\xe7l\xbdo7\x0c\x07\xef\xaf\x1d\xd3\xac\x1b\xe4\xdc!\xbe\xf6CA\xf3H@a\xeb\xb4J\xf1\xde\x85\x88\xde\x94\xad\xc8vT~\xd8\xaa\xab\xe4\xa3\xd4\xa5#\xa6\xc2\x07\x94V\xcc\x01\xac\xf6\xae\xff \xd9\xcc\xbf\xa8\xe3\r\xf3\x0eE\xe8\xfd\xa6\x9f\xf4-]\xd85\x86c\x82i\x9e\x1bl\xee\x8fA\xda\xdbs\x02\x89\x90a\xf2\xf66\'\x96\xe9[J\x07G\xb8\xab\xd6\xcb\x01\x18gvo_\x00:R\x9eN\xb3\xbc\xea>\xed\xcdB\x94\xa5>\xc0\xfb\xac\x91\xde1}\xe5\x9fj\x93\x8b\xc4\xd2\x06\xbb\x84\xef\xf5v\xe3\xf0\x1cJ\xc7\x81\x9c\n\xe5\x80\xbe\x9c\xda\x01\x16\xa2UVE\x12\x96\x8d\x8fG\xdb9\x8ck\x98a}[\xb4\xe9sx\x85\x8d\x97\xe5c*y\x1d\xbf",\x9e\xe2;\x82`\xe5n\xa5\xbe\x06\xaa\xe2\xfe@/\n-]ap\xcd\x00\xce\xda\xc1\x00`\xa6\xbd]H\x0b\x8c\x9e\xaau1\x95\xc8\x8c\x0b\xae\xf8\x7f\xbf\xb5y\xcc\xbb\'\xa7.\xfe\xf3\x14\xc0\x1aC\xa8\x1d\xc3<\xa1\x86\x92\xc7\x85\x80\xcd\xf6\xd1Ju\x19\xc0\x19q?\xf1\xd5\x01\xd4\x9c\xcc\xb7\xac\x86?9\x01\x85w\xc4^PO\xf3&\xa8\xd7\xa1"\xee\xee\x9b\x95C\xeb\x897T\x89.\x1c+\xd51\x97\x80*`\x1dR\xf72\xd5c\xf7\xddDY\n\x95\x11\xc0\x93\xdd?\xdd\xd7o\xa1>3 )z\x83\xbd\x8da\xab\x83\x12\xdf\x16\xd5\x06\x0cB>x\x9aX\x17Pl\xdc\xbbc\x06\xba\x80\xe9CJ\x8f\xa4\xad\x98\x9a%\xfbE\xb1\xde\x84\xe7\'m\xbeN?(\xc4r\x95\t\xc3\xff\x9e\xd1ipG\xea\xef\xb9w8\x03\x86\x97\x00\x80\xcb\x03\xfc\xdd(dP\xe6\xf3\x81\xc9T\xd5\x1a\x8br\xd3\x82\x91~\x1ej\x90\x07\x03ZP\xd0Od\xbat\t\xa5~\xf1\xf3\xd2\xba\xfa\xf6M\xe0!m\xfePq\xc4W\xd8\xe6?O\x84\x80\xd4\'-\xe2\xee\xaa\x13\x01\xa9D\xa7\x7f\xbf\x13\xa0X\xcc\x9cJ#\x7f\xfe\xb0+\xf8\xcak\xcd\x15\x82\xd3y?\x939\x87N\x90H\x81\x06=\x02\t\xc8\xafq\xd1\xc0\xee\x84\xdf\x17\r\x9e\xf6\'*i\xfcF\xb4E\x1b\xd7,\xaf\xa0`3T~\xe1\xcd\xf8!~\xa2\x02\xa0y\x87\xdf(\xcd\x92D%\xfc\xdbo\xf1\xee\xbe\x85\x99\xe6\xd4\xe1\xe7\x93\x19\xaf\xdd\xc7.l\x1bY+\x8a5\x1de\xb8\xd8F\xef/G\xbd"\xc9\xb16\x08\x84\xa6\xe1\x9c\xe5\x15A\x90\x13\xf0\x81\x16\xac\x1f\x1a\x93\x92q\x98\xce\x84C\xbd\x05\xe4\x80\xee\':_\x10\xbde\xf7\x80\xd7g\xfb9\x7f\xe9\xb9\xae\x8e\x10;\xbe\t\xc44\x86cl;Z\xc1\x02\xdf\x8a\xba}\xe4\x18K_\x99u\x8a\xa7\xda\x06>6a{d\xef\xc1\xf2 j\x8cO\x89\xbf\x02\xac\x0b\xbeN_\x7f\x00\x87Ts7\xcd3/\xb5\xe3\xc4\xfal\x1e\xde\xc2Q\x199\xdc\xc5\x04\x0b2E\xbc\xf3\xb27%\x03\xdb\x1b\x15\xbd\xb9v\xd7\xf7\xca\xce\xb2\x81\xa5\xda\xf1o\x05`\x02\xd4\xfc\r^\x04\xc6&\xf7as\xa8\xf2\xae*\x16\xdf\x991V\x85\x156V\xd6\x83|\x0e.MAoZ\xbd\xa2 \x18\xf0\xc21\x87\x98nM\x80!\xaa\x96\x0fX]\\\xd61h\x93\x87?i,\xf4O\x03k\xbc\xa4\xa3\xa4\xeeMB\x82\xfb\xa0#_\xb1\x80\xf40\xf9E]_\x7f\xda8f\xc9\xa4\xaa\xcd\x9d\xd5\xddT\xbd\xc7\xd3&m\xd1\xcd\x19q\xc6G\x9cV\x04\xe92q\xe7\xef\xc6\xaa\xd7\xa7\x86^\x85\xd02\xdehX\xa8A6\xaeFF\x8a4xT\xb0\x82\xd8\x0b\xc3E\xa0\'\x86\xb6G\x9d1\x0f \xde\xfd*\xb2\x8c\xb7\x9d\xfa\xf2\xcaE\x82\x1a\xb5=!\xf8\xf3\xb2\x894Y"\xe2\x00JZ\xaf\xa0\r\xbbg\x1c>3_h\x81\xd13]"\x9b\x9b\xa7\xc13L\x04\x80\x17a<=K_\xfd\xe9\x14\xcf\xe1K\xf5\x0e\xd3fG\xf4\xf5D\x03\xe8*\x87>[Z\xed\'\xdc\xfd\xda\xa1*q\xe4\xcc\xfe\xe3\xc8\x84\x06<\xf6{\x1dW\x19C\xa4\xbdb\xdaU\x8e\x82-S\x1a\xe1q\xd4CED\xd6\x13M]h\xb0)\xa6U_j\x0f9\xa0s\xf5m\x9b\xa0|D\xe3\x0f\x92x\x0b\xa3)V\x0b\x95\xd6?\xca\xa2B\r\x01\xf5`\xf7\xf4F3E\x0f\x0f\xca\x7f#\x11\x82\x14\xd9X\xce\xe8\xa2\xac\x1en\xbf\xbe\x85r\xa73>\x91\x9d\xbb\xf8\xa23\xe6\xbc$\xd2\xef\x13\x1b\xb4\'\xf8#\x18f\xdat\xb9\xb8~9\xe3\x02g.n\xd9\xd1\xfbV\xc7|\x99\xddG\x0b\xa7,\xa6\xd2#k?Nw\xf9q\xc2\x9e!R\\\xe5\x9e\xa6Y\xb2\x06\xd2\xa9K\xedw7U\x14k\xfft\x84\x08\xf8\xdc\x98/0\x94&\xf6\xab\xb5\x14\xef\xe9Oa\x17XzI\xad\xf5\xeej\xf8Q\xf0\xd54\xd4\xd2\xde\xb9\x99\xb8\xb9v\x1d\xdc\t#\xc5\x88L\xfc\xefC\x16\x81Np|vC[\x93\xb1\xf0\xd0\xe5e\x058\x13\xdc{\xa7\xfd.\xc1X\xf4\x08\x9b\t\xca\x9e\x9b@\xb8\xf9\xbb\t\xc8\xc6\xb7l \xb9\x88a\xc8b\xe6\xa9_u\xad\xef\x11KP\x99\xc2\x84\xff\xfd\xf1\x9f\xd5-BU\xd3\x87\xf3\xf0?\x1a\xa0<\xa6,\x86\xb8\xbeB[\xe1\xdd\x1e\xc9\xed|\xd9\xaf\xbew#\xd0xe\n\xf8X\xa1\x9b\x91\xc4d\xc9K\xbe\x05\xbf\x8d\xa6\xd4\xd0\x90\x100gyJ\r\xa1\x18\x18\xe4\x91\xc4\x83bc\xb4\x06;\x0c\xb1\x9f\xa3\xf7\xdc\xd5\x16\xbb@?~\xfa\xc3\xe1`\x8d!\xeeq\x00\x85\x0c\xf9\xa2=5\xea\x88\xdd\xc5\x9e\xc0{\x9c\xd5/\x04\xce\xf3\xd1\xf3\xee\xae\xb8|\xf1z\xf0\xf9DvjA\xc4\xa7|D\xcf\xa6\x8d\xb6\xdb\xa8rK\xa2\xd1\xaf\xa5\xf6\x9d\xea\x14S\xc9\\\x1f;q7\xa6\xda\xd1\xec1Zr(B&s\x1ag\xc8T\x88s\xf2\x9d\x97\x1b\xcca\x157\x87J\x8e\xab\r\xf7~\x95\xff\x89\xa0\x1c]"\x15B\xee\x02\xce\xd7\xbdg:i\xa0\xa2\xff\xac\x00\xeb\xbbA\xcb\xae\x02 (\xec\x1e\x9d\xb2I\x16\xbd\xcc\xa1\x87\xad\x7f,\x0f\x02\x84\xc5\xf3P\x98\xa0\x02\xf1\x8f\xb4\xe5\x03\xf3\xd9\xcd!e\xd5\xbf\xcd\x17\xa1]\xe9\x81\xe3}\xb0\x91\x90\x1c\xc5\x00\xe8\xed><\x15CF\x11\x8a7%\x89)&T1\xfc\xbeN\xd3\x13/:\xcd\xd0\xbd\x90\xfc\x0bx\x0c\x8af\x99\x05\x85z\xda\xca\x9a\xdax\x8f\x88l;m5\x8dF\x86\x02\x99\x18z4\xf4\x95\x8f\x8d\xc07\xa2\xd4g>\xc5\x043\x08i\xc3&\x92\xbe\xec$mw\xe6\xc0( G\xd0\xe5?{\xae\xe2\xf5\xcff\xc0yl6\xfa\xde\x10N:\x15\xda+\xf4Q\xb8\x84\xe9:\x15_2\xe4\xdb\xd3\x0f\x82\xe8\xb3\xf8\x0c\xc6\xa5_uY?\xcc\xf3\xe8\xc3\x0f\xd5\xcb\xd0\x97q\xb7\xd84*\xd1\x97+35-c\xe6\xa5\xc6\x8b\x1c\xa5~\x1a\n\xd4$e\xc6\x8ft\xe3\x15\xca7:\xe2\xa0@u\x17-\xe3_\xacA\x17\xd9\x91\x12\xeb.\x13\xb3\xb3\xbd%]\x91\xcf\x1d\x01\xdfB%\x1b\x8c.b\xc5+\xca\x19{\r\'\x15\t\xdd\x18\xba\xa3\xaf\x96\x8e4*\x8f\xd0\xa5Z&\xdf\xda\xd3\xf6^FVj\xb1\xa9/\xb1\t\xbb\xf8\xcb\x84u\xfe\xc9\xe8\xba\xa9\xb6\xd3\x01d\x0c\xc7\xb5\x05\x17\x9eM\xbdHu\x9a\xc0d\xe0\xd8n\xef\xe4sv\x83\xbc}\xe5v\xd7:\xcf^\x1bq\xbc\xe9\xa9\x7f\xae\xf0\xef\xa9\xcd\x8d\xe8\x14\xae\xd1\xd8\xce\x88\xc0|\x12\xc8\x1am(KA\xfdTgh\xb6\x82:\xd9`\x14Xt6\x9cBRN\xa3\x95\x17s1*\xf8@\x8cy\x83\xf9\xc5\x9a\x96\xfc\xea\x0c\xd8fT\x90\x8f\xfa\xa9\xf1U\xdbm\xc9\xb5\xcaIxY\x86\xc3\xa6usn"u\xfd\xf4\xbd\x14!6uz\x00\x92\x94a\xcd\xe3\xec\xd32\x82\xc7\x7f\xd0\x04H/\x7f;R\x04\xaby\xdd\x13\x18\xb3\xa8\xda5\x1d]\x1bxrI\xeen\xe3\x96Al\x07 \xa3\xead\x1f5\x9c0\x0f\xd3\x98\xde<`\xfcA}\xe9*\xbf\x80\x11\x14H\xb6\xa4Jq3\xb9\xcc\xa5z\xf2Zuy\x01\xee\xb4\xaf\n9_\x9e\xbaS\x9f2\x19/tn\x17WO\x96>\x96\xfa"\xb4H\xf6W\r\x16\x82\x8b^\r\xc0\xd6\xb5(\xa7\xcd\\A\xd27\x18t7\xb0g\x99n\xc5Ge\xd2L\xb8\n\xd2\xddh;\xcbV0"\xa1\x7f\xcfr\xcd~O\x83p\xf2>q?8\x1a\x16\xed\x9dy.o\xb2\x9a\xe2\xd2\xb1\xf3|\\\xa5\'\x07\xf5\xe4\x88\xf2\xda\x83\xf8\xe4^\x9b6\n\x06.L8\x15\xa3u\xc65\x97A\xd3\xefH@;\xfbd|Y\r9 ,\xd8\x16\xfd\xb1\x02:1\xd7\xbc\x92\x85\xc0\xdb\t\xd7\x1d{6\x81sQ\x9e\xdcm\xcc\x80Z\xd5\x94\x9c\x07]\xbf\x18|\xbdb\x96\xc5_Xl\xa6\x81\xab\x80\x97\x0f\xac\xb0F\xd40\xc5\xdd,\x84\x02\xe2P\x7f#;H\x17\xdf3\xfew\xfd\x07\xb5f=xe\xc2\x95\x0f\xa4\x83O\x83c\xf5g\xf0J*\x84\x01\x91.\xfa\xf0\xa6\xc1\xa5n\r.n\x8f9\xea\x8b\xdf\xb9\x0e\xc7#\xe3k\xe8\xfb\x80\x0e\x18\xb4\xad\xb9G\xc3;\x8a1\x9e\xe5\x8e\x11\xab\xca\xc0P\x84\x01<\tTl\x8a)\xc1zR3\xc6\xaf:\xb9k\x04\xfd\xd1\x9dG\xaf6m\xd5t\x0cq\xb5\x04 Y\xaf\xc9f\xebv\x92\xe1\xbfHL-\xa6d;\xfa\xee\x9d\xa3\x13\xabxF]\xb7~\x14\xb5\xeci\xff\x9dz\x1e\xceb\x1c\xfdB\x7f6Y\x86\x94X\x16\x00\x86\xc2g\n\x9d+\x05\xf5\xed\x86\x1cgR\xe8Ef\xad\xad\x8axw\xa4\xa0\x1d\x14\xa0\x80\xe5\xde<\xc2\xe6L\xdb\xc5\xe2\x88g\xf1+R\xff\xb8\xa2=\x14\xf4\x1e;\x8a\xe0F@h\xf2eQ\x92N\xe1\xee\xf0# ^\xf1!e\xfd#~U/\x1d+\x91\x02\xb4\x90`m\x93\x9f\xb0\xf6F\x81\xc7\xae7q\x19\xe4J- c\xa6\xc6\x95\xa7\xd0\xd4\x90@\xb0>\xd4\x06\'W\xd1d\xed\xcd\xde\r\xc6I*k\xc0\x00\xbb\x0b\xa3\xaa\r\x9e\xbd7\x13\xa9\x12\xb4\xcdJ={\x11\xb2g\xc4\xbc*\xe1~\xcbYn\xec\xf9\xa8\xd5P\xe4\xc4\xb4c\xd0\x01ai\xdc\xf2H\xd2\xc3\xc1\x9d$G\xd8<\x8a\xf4s\n\x97MC\xe8wZ\x0bu?b\xe7d\xf2\x86\x15\xe3\xb6\xf5\xdc*+\xa8\x84\xed\xc6\xd89\x83\xe6O\xf8\xc9j\xaf\xdfbl\x96\x7f`Z\xae\xcdv\xaf\x9eX3\\\xd4\xa2\xc5:d\xdd3\xcb\x8e\x1c\x95\xae\xa4\xceu\xfc\x03`\xde<\x05\x13N\xa1\xd52F\xc9KOxo\xb6\xbf\x01}a\x88\xca\xe7\xe7\xa7b\x97\x8ay\xb2R\x92;\xa2V\x8c\x9d\xdc\x01JY\x0c\xdc\xdc\xb5\xd8\x82\xbe:\xe1\xb8\x06\xae\xc3d\x1a\x87T\xa8\xcb\xcc\x8f\xa8(n|:\xea`\xb1\xd8\x04{ \x7f\x15Znsw\xf9@L\x86;\xa0[\xd8\xc5\x94\xef\x07\x15\x97\\\xa3\xb2\x88e_\x84E\x90g\x97\xbb\xd7(v\x00\xbb"\xbb]2\xc0Q\x9e\xb1\x1c\x89\xb5\xed\x1f\x0f\x1e\x10j;$ll\x1b\xf8{\xd3~\x97\x85\xe2\x96\x8dM\x07\xfc6v\xa9Zp^\x13\xa0\x00\xebd\x19#\xc9\x7f\xb29\x03\xdb\x16\x9f\rb\xd0\xbe\xd2\xa6l\xde6s\xf4\xc1\x14\xc3.W\xd9\x93"J \xde\x7f\xa2>\xea\xf2Y\r\xfdJ\xf2\xb1\xd6\xd5\x9ce\xff\xc5r\xab\xdc\xd0\xf8|') diff --git a/src/pyaedt/workflows/project/images/large/Ptree.png b/src/pyaedt/workflows/project/images/large/Ptree.png new file mode 100644 index 00000000000..c0cafd4852b Binary files /dev/null and b/src/pyaedt/workflows/project/images/large/Ptree.png differ diff --git a/src/pyaedt/workflows/project/pyarmor_runtime_000000/__init__.py b/src/pyaedt/workflows/project/pyarmor_runtime_000000/__init__.py new file mode 100644 index 00000000000..c57d0150b5b --- /dev/null +++ b/src/pyaedt/workflows/project/pyarmor_runtime_000000/__init__.py @@ -0,0 +1,2 @@ +# Pyarmor 9.1.3 (trial), 000000, 2025-04-23T11:16:53.168246 +from .pyarmor_runtime import __pyarmor__ diff --git a/src/pyaedt/workflows/project/pyarmor_runtime_000000/pyarmor_runtime.pyd b/src/pyaedt/workflows/project/pyarmor_runtime_000000/pyarmor_runtime.pyd new file mode 100644 index 00000000000..3fda92300f5 Binary files /dev/null and b/src/pyaedt/workflows/project/pyarmor_runtime_000000/pyarmor_runtime.pyd differ diff --git a/src/pyaedt/workflows/project/toolkits_catalog.toml b/src/pyaedt/workflows/project/toolkits_catalog.toml index 8a77bd4ac81..67bd49534bc 100644 --- a/src/pyaedt/workflows/project/toolkits_catalog.toml +++ b/src/pyaedt/workflows/project/toolkits_catalog.toml @@ -25,3 +25,10 @@ script = "advanced_fields_calculator.py" icon = "images/large/fields.png" template = "run_pyaedt_toolkit_script" pip = "" + +[PowerTreeDCIR] +name = "PowerTree DCIR" +script = "DCIR_with_Ptree.py" +icon = "images/large/Ptree.png" +template = "run_pyaedt_toolkit_script" +pip = "" \ No newline at end of file