From 4007f74490b116ed51104dcf439b27bfe7bbe31b Mon Sep 17 00:00:00 2001 From: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Date: Tue, 15 Jun 2021 11:23:16 -0700 Subject: [PATCH] USB Cables -- Connect circuits to computers/machines (#59345) * Initial commit * Sprites, finishing work * More ways to detach from circuitboards * Clear TODOs, give bots a button * Fix qdel loop * Designs * It's the bots that have them * Grammar fix * Feedback for connecting to circuit directly * Add USB cable design to basic circuitry * Better naming * Feedback * Fix for new code * COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY * span procs --- code/__DEFINES/dcs/signals.dm | 30 +++- code/__DEFINES/is_helpers.dm | 3 + code/__DEFINES/wiremod.dm | 6 + code/datums/components/shell.dm | 27 ++- code/datums/components/usb_port.dm | 162 ++++++++++++++++++ code/game/machinery/computer/tram_controls.dm | 117 +++++++++++-- .../objects/structures/industrial_lift.dm | 16 +- code/modules/mob/inventory.dm | 2 +- .../research/designs/wiremod_designs.dm | 12 +- code/modules/research/techweb/all_nodes.dm | 1 + code/modules/wiremod/component.dm | 4 +- code/modules/wiremod/integrated_circuit.dm | 21 ++- code/modules/wiremod/shell/bot.dm | 32 +++- code/modules/wiremod/usb_cable.dm | 123 +++++++++++++ icons/obj/wiremod.dmi | Bin 7407 -> 20697 bytes tgstation.dme | 2 + 16 files changed, 532 insertions(+), 26 deletions(-) create mode 100644 code/datums/components/usb_port.dm create mode 100644 code/modules/wiremod/usb_cable.dm diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index d59ce9f34c9..8b3660c2da9 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -93,7 +93,7 @@ #define COMSIG_ATOM_HULK_ATTACK "hulk_attack" ///from base of atom/animal_attack(): (/mob/user) #define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal" -///from base of atom/examine(): (/mob) +///from base of atom/examine(): (/mob, list/examine_text) #define COMSIG_PARENT_EXAMINE "atom_examine" ///from base of atom/get_examine_name(): (/mob, list/overrides) #define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" @@ -1310,5 +1310,33 @@ /// Cancels adding the component to the circuit. #define COMPONENT_CANCEL_ADD_COMPONENT (1<<0) +/// Sent when a [/obj/item/circuit_component] is added to a circuit manually, by putting the item inside directly. +/// Accepts COMPONENT_CANCEL_ADD_COMPONENT. +#define COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY "circuit_add_component_manually" + +/// Sent when a circuit is removed from its shell +#define COMSIG_CIRCUIT_SHELL_REMOVED "circuit_shell_removed" + +/// Sent to [/obj/item/circuit_component] when it is removed from a circuit. (/obj/item/integrated_circuit) +#define COMSIG_CIRCUIT_COMPONENT_REMOVED "circuit_component_removed" + +/// Sent to an atom when a [/obj/item/usb_cable] attempts to connect to something. (/obj/item/usb_cable/usb_cable, /mob/user) +#define COMSIG_ATOM_USB_CABLE_TRY_ATTACH "usb_cable_try_attach" + /// Attaches the USB cable to the atom. If the USB cables moves away, it will disconnect. + #define COMSIG_USB_CABLE_ATTACHED (1<<0) + + /// Attaches the USB cable to a circuit. Producers of this are expected to set the usb_cable's + /// `attached_circuit` variable. + #define COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT (1<<1) + + /// Cancels the attack chain, but without performing any other action. + #define COMSIG_CANCEL_USB_CABLE_ATTACK (1<<2) + +/// Sent from /obj/structure/industrial_lift/tram when its travelling status updates. (travelling) +#define COMSIG_TRAM_SET_TRAVELLING "tram_set_travelling" + +/// Sent from /obj/structure/industrial_lift/tram when it begins to travel. (obj/effect/landmark/tram/from_where, obj/effect/landmark/tram/to_where) +#define COMSIG_TRAM_TRAVEL "tram_travel" + /// Called in /obj/structure/moneybot/add_money(). (to_add) #define COMSIG_MONEYBOT_ADD_MONEY "moneybot_add_money" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 0c8292b9857..b92f3c4d13b 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -2,6 +2,9 @@ #define in_range(source, user) (get_dist(source, user) <= 1 && (get_step(source, 0)?:z) == (get_step(user, 0)?:z)) +/// Within given range, but not counting z-levels +#define IN_GIVEN_RANGE(source, other, given_range) (get_dist(source, other) <= given_range && (get_step(source, 0)?:z) == (get_step(other, 0)?:z)) + #define isatom(A) (isloc(A)) #define isweakref(D) (istype(D, /datum/weakref)) diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index b6e2a70d6b9..752d915fc93 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -92,12 +92,18 @@ /// Whether the shell needs to be anchored for the circuit to be on. #define SHELL_FLAG_REQUIRE_ANCHOR (1<<1) +/// Whether or not the shell has a USB port. +#define SHELL_FLAG_USB_PORT (1<<2) + // Shell capacities. These can be converted to configs very easily later #define SHELL_CAPACITY_SMALL 10 #define SHELL_CAPACITY_MEDIUM 25 #define SHELL_CAPACITY_LARGE 50 #define SHELL_CAPACITY_VERY_LARGE 500 +/// The maximum range a USB cable can be apart from a source +#define USB_CABLE_MAX_RANGE 2 + // Circuit flags /// Creates an input trigger that means the component won't be triggered unless the trigger is pulsed. #define CIRCUIT_FLAG_INPUT_SIGNAL (1<<0) diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index acea9746714..00e08e846a2 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -6,7 +6,7 @@ var/obj/item/integrated_circuit/attached_circuit /// Flags containing what this shell can do - var/shell_flags = 0 + var/shell_flags = NONE /// The capacity of the shell. var/capacity = INFINITY @@ -38,6 +38,7 @@ RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_object_deconstruct) if(shell_flags & SHELL_FLAG_REQUIRE_ANCHOR) RegisterSignal(parent, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, .proc/on_unfasten) + RegisterSignal(parent, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach) /datum/component/shell/UnregisterFromParent() @@ -48,7 +49,8 @@ COMSIG_OBJ_DECONSTRUCT, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, COMSIG_PARENT_EXAMINE, - COMSIG_ATOM_ATTACK_GHOST + COMSIG_ATOM_ATTACK_GHOST, + COMSIG_ATOM_USB_CABLE_TRY_ATTACH, )) QDEL_NULL(attached_circuit) @@ -77,6 +79,8 @@ var/obj/item/stock_parts/cell/cell = attached_circuit.cell examine_text += span_notice("The charge meter reads [cell ? round(cell.percent(), 1) : 0]%.") + if (shell_flags & SHELL_FLAG_USB_PORT) + examine_text += span_notice("There is a USB port on the front.") /** * Called when the shell is wrenched. @@ -163,8 +167,9 @@ SIGNAL_HANDLER remove_circuit() -/datum/component/shell/proc/on_circuit_add_component(datum/source, obj/item/circuit_component/added_comp) +/datum/component/shell/proc/on_circuit_add_component_manually(datum/source, obj/item/circuit_component/added_comp) SIGNAL_HANDLER + return COMPONENT_CANCEL_ADD_COMPONENT /** @@ -180,7 +185,7 @@ for(var/obj/item/circuit_component/to_add as anything in unremovable_circuit_components) to_add.forceMove(attached_circuit) attached_circuit.add_component(to_add) - RegisterSignal(circuitboard, COMSIG_CIRCUIT_ADD_COMPONENT, .proc/on_circuit_add_component) + RegisterSignal(circuitboard, COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY, .proc/on_circuit_add_component_manually) attached_circuit.set_shell(parent) if(shell_flags & SHELL_FLAG_REQUIRE_ANCHOR) @@ -206,3 +211,17 @@ attached_circuit.remove_component(to_remove) to_remove.moveToNullspace() attached_circuit = null + +/datum/component/shell/proc/on_atom_usb_cable_try_attach(atom/source, obj/item/usb_cable/usb_cable, mob/user) + SIGNAL_HANDLER + + if (!(shell_flags & SHELL_FLAG_USB_PORT)) + source.balloon_alert(user, "this shell has no usb ports") + return COMSIG_CANCEL_USB_CABLE_ATTACK + + if (isnull(attached_circuit)) + source.balloon_alert(user, "no circuit inside") + return COMSIG_CANCEL_USB_CABLE_ATTACK + + usb_cable.attached_circuit = attached_circuit + return COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT diff --git a/code/datums/components/usb_port.dm b/code/datums/components/usb_port.dm new file mode 100644 index 00000000000..9131e45f42d --- /dev/null +++ b/code/datums/components/usb_port.dm @@ -0,0 +1,162 @@ +/// Opens up a USB port that can be connected to by circuits, creating registerable circuit components +/datum/component/usb_port + /// The component types to create when something plugs in + var/list/circuit_component_types + + /// The currently connected circuit + var/obj/item/integrated_circuit/attached_circuit + + /// The currently connected USB cable + var/datum/weakref/usb_cable_ref + + /// The components inside the parent + var/list/obj/item/circuit_component/circuit_components + + /// The beam connecting the USB cable to the machine + var/datum/beam/usb_cable_beam + +/datum/component/usb_port/Initialize(list/circuit_component_types) + if (!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + src.circuit_component_types = circuit_component_types + +/datum/component/usb_port/RegisterWithParent() + RegisterSignal(parent, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_moved) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine) + +/datum/component/usb_port/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_ATOM_USB_CABLE_TRY_ATTACH, + COMSIG_MOVABLE_MOVED, + COMSIG_PARENT_EXAMINE, + )) + + unregister_circuit_signals() + +/datum/component/usb_port/Destroy() + QDEL_LAZYLIST(circuit_components) + QDEL_NULL(usb_cable_beam) + + attached_circuit = null + usb_cable_ref = null + + return ..() + +/datum/component/usb_port/proc/unregister_circuit_signals() + if (isnull(attached_circuit)) + return + + UnregisterSignal(attached_circuit, list( + COMSIG_CIRCUIT_SHELL_REMOVED, + COMSIG_PARENT_QDELETING, + )) + + var/shell = attached_circuit.shell + if (!isnull(shell)) + UnregisterSignal(shell, COMSIG_MOVABLE_MOVED) + UnregisterSignal(shell, COMSIG_PARENT_EXAMINE) + +/datum/component/usb_port/proc/create_circuit_components(obj/item/integrated_circuit/circuitboard) + var/created_circuit_components = list() + + for(var/circuit_component_type in circuit_component_types) + var/obj/item/circuit_component/circuit_component = new circuit_component_type(parent) + circuitboard.add_component(circuit_component) + created_circuit_components += circuit_component + RegisterSignal(circuit_component, COMSIG_CIRCUIT_COMPONENT_REMOVED, .proc/on_circuit_component_removed) + + return created_circuit_components + +/datum/component/usb_port/proc/on_examine(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + + if (isnull(attached_circuit)) + examine_text += span_notice("There is a USB port on the front.") + else + examine_text += span_notice("[attached_circuit.shell || attached_circuit] is connected to [parent.p_them()] by a USB port.") + +/datum/component/usb_port/proc/on_examine_shell(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + + examine_text += span_notice("[source.p_they(TRUE)] [source.p_are()] attached to [parent] with a USB cable.") + +/datum/component/usb_port/proc/on_atom_usb_cable_try_attach(datum/source, obj/item/usb_cable/connecting_cable, mob/user) + SIGNAL_HANDLER + + var/atom/atom_parent = parent + + if (!isnull(attached_circuit)) + atom_parent.balloon_alert(user, "usb already connected") + return COMSIG_CANCEL_USB_CABLE_ATTACK + + if (isnull(connecting_cable.attached_circuit)) + connecting_cable.balloon_alert(user, "connect to a shell first") + return COMSIG_CANCEL_USB_CABLE_ATTACK + + if (!IN_GIVEN_RANGE(connecting_cable.attached_circuit, parent, USB_CABLE_MAX_RANGE)) + connecting_cable.balloon_alert(user, "too far away") + return COMSIG_CANCEL_USB_CABLE_ATTACK + + usb_cable_ref = WEAKREF(connecting_cable) + attached_circuit = connecting_cable.attached_circuit + + connecting_cable.forceMove(attached_circuit) + circuit_components = create_circuit_components(attached_circuit) + attached_circuit.interact(user) + + usb_cable_beam = atom_parent.Beam(attached_circuit.shell, "usb_cable_beam", 'icons/obj/wiremod.dmi') + + RegisterSignal(attached_circuit, COMSIG_CIRCUIT_SHELL_REMOVED, .proc/on_circuit_shell_removed) + RegisterSignal(attached_circuit, COMSIG_PARENT_QDELETING, .proc/on_circuit_deleting) + RegisterSignal(attached_circuit.shell, COMSIG_MOVABLE_MOVED, .proc/on_moved) + RegisterSignal(attached_circuit.shell, COMSIG_PARENT_EXAMINE, .proc/on_examine_shell) + + return COMSIG_USB_CABLE_ATTACHED + +/datum/component/usb_port/proc/on_moved() + SIGNAL_HANDLER + + if (isnull(attached_circuit)) + return + + if (IN_GIVEN_RANGE(attached_circuit, parent, USB_CABLE_MAX_RANGE)) + return + + detach() + +/datum/component/usb_port/proc/on_circuit_deleting() + SIGNAL_HANDLER + unregister_circuit_signals() + attached_circuit = null + qdel(usb_cable_ref) + +/datum/component/usb_port/proc/on_circuit_component_removed(datum/source) + SIGNAL_HANDLER + + qdel(source) + detach() + +/datum/component/usb_port/proc/on_circuit_shell_removed() + SIGNAL_HANDLER + + detach() + +/datum/component/usb_port/proc/detach() + var/obj/item/usb_cable/usb_cable = usb_cable_ref?.resolve() + if (isnull(usb_cable)) + return + + unregister_circuit_signals() + + var/atom/atom_parent = parent + usb_cable.forceMove(atom_parent.drop_location()) + usb_cable.balloon_alert_to_viewers("snap") + + QDEL_LAZYLIST(circuit_components) + + attached_circuit = null + usb_cable_ref = null + + QDEL_NULL(usb_cable_beam) diff --git a/code/game/machinery/computer/tram_controls.dm b/code/game/machinery/computer/tram_controls.dm index d73f807ee69..5edb3b9895a 100644 --- a/code/game/machinery/computer/tram_controls.dm +++ b/code/game/machinery/computer/tram_controls.dm @@ -1,5 +1,3 @@ - - /obj/machinery/computer/tram_controls name = "tram controls" desc = "An interface for the tram that lets you tell the tram where to go and hopefully it makes it there. I'm here to describe the controls to you, not to inspire confidence." @@ -12,6 +10,11 @@ var/obj/structure/industrial_lift/tram/tram_part light_color = LIGHT_COLOR_GREEN +/obj/machinery/computer/tram_controls/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + AddComponent(/datum/component/usb_port, list(/obj/item/circuit_component/tram_controls)) + return INITIALIZE_HINT_LATELOAD + /obj/machinery/computer/tram_controls/LateInitialize() . = ..() //find the tram, late so the tram is all... set up so when this is called? i'm seriously stupid and 90% of what i do consists of barely educated guessing :) @@ -73,17 +76,107 @@ /obj/machinery/computer/tram_controls/ui_act(action, params) . = ..() - if(. || tram_part.travelling) - return - var/destination_id = params["destination"] - var/obj/effect/landmark/tram/to_where - for(var/obj/effect/landmark/tram/destination as anything in GLOB.tram_landmarks) - if(destination.destination_id == destination_id) - to_where = destination - break - if(!to_where) + if (.) return + + switch (action) + if ("send") + var/obj/effect/landmark/tram/to_where + for (var/obj/effect/landmark/tram/destination as anything in GLOB.tram_landmarks) + if(destination.destination_id == params["destination"]) + to_where = destination + break + + if (!to_where) + return FALSE + + return try_send_tram(to_where) + +/// Attempts to sends the tram to the given destination +/obj/machinery/computer/tram_controls/proc/try_send_tram(obj/effect/landmark/tram/to_where) + if(tram_part.travelling) + return FALSE if(tram_part.controls_locked || tram_part.travelling) // someone else started - return + return FALSE tram_part.tram_travel(to_where) return TRUE + +/obj/item/circuit_component/tram_controls + display_name = "Tram Controls" + + /// The destination to go + var/datum/port/input/new_destination + + /// The trigger to send the tram + var/datum/port/input/trigger_move + + /// The current location + var/datum/port/output/location + + /// Whether or not the tram is moving + var/datum/port/output/travelling_output + + /// The tram controls computer (/obj/machinery/computer/tram_controls) + var/datum/weakref/computer + +/obj/item/circuit_component/tram_controls/Initialize() + . = ..() + + var/obj/machinery/computer/tram_controls/computer_object = get(src, /obj/machinery/computer/tram_controls) + if (computer_object) + computer = WEAKREF(computer_object) + + RegisterSignal(computer_object.tram_part, COMSIG_TRAM_SET_TRAVELLING, .proc/on_tram_set_travelling) + RegisterSignal(computer_object.tram_part, COMSIG_TRAM_TRAVEL, .proc/on_tram_travel) + + new_destination = add_input_port("Destination", PORT_TYPE_STRING, FALSE) + trigger_move = add_input_port("Send Tram", PORT_TYPE_SIGNAL) + + location = add_output_port("Location", PORT_TYPE_STRING) + travelling_output = add_output_port("Travelling", PORT_TYPE_NUMBER) + +/obj/item/circuit_component/tram_controls/Destroy() + new_destination = null + trigger_move = null + location = null + travelling_output = null + computer = null + return ..() + +/obj/item/circuit_component/tram_controls/input_received(datum/port/input/port) + . = ..() + if (.) + return + + if (!COMPONENT_TRIGGERED_BY(trigger_move, port)) + return + + var/obj/machinery/computer/tram_controls/tram_controls = computer.resolve() + + if (isnull(tram_controls)) + return + + if (!tram_controls.powered()) + return + + var/destination + + for(var/obj/effect/landmark/tram/possible_destination as anything in GLOB.tram_landmarks) + if(possible_destination.name == new_destination.input_value) + destination = possible_destination + break + + if (!destination) + return + + tram_controls.try_send_tram(destination) + +/obj/item/circuit_component/tram_controls/proc/on_tram_set_travelling(datum/source, travelling) + SIGNAL_HANDLER + + travelling_output.set_output(travelling) + +/obj/item/circuit_component/tram_controls/proc/on_tram_travel(datum/source, obj/effect/landmark/tram/from_where, obj/effect/landmark/tram/to_where) + SIGNAL_HANDLER + + location.set_output(to_where.name) diff --git a/code/game/objects/structures/industrial_lift.dm b/code/game/objects/structures/industrial_lift.dm index 9e7bb26536b..410540b712b 100644 --- a/code/game/objects/structures/industrial_lift.dm +++ b/code/game/objects/structures/industrial_lift.dm @@ -208,7 +208,7 @@ GLOBAL_LIST_EMPTY(lifts) bumped_atom.visible_message(span_userdanger("[src] crashes into the field violently!")) for(var/obj/structure/industrial_lift/tram/tram_part as anything in lift_master_datum.lift_platforms) tram_part.travel_distance = 0 - tram_part.travelling = FALSE + tram_part.set_travelling(FALSE) if(prob(15) || locate(/mob/living) in tram_part.lift_load) //always go boom on people on the track explosion(tram_part, devastation_range = rand(0,1), heavy_impact_range = 2, light_impact_range = 3) //50% chance of gib qdel(tram_part) @@ -445,11 +445,18 @@ GLOBAL_DATUM(central_tram, /obj/structure/industrial_lift/tram/central) * even in the worst cast scenario. */ /obj/structure/industrial_lift/tram/proc/find_our_location() - for(var/obj/effect/landmark/tram/our_location as anything in GLOB.tram_landmarks) + for(var/obj/effect/landmark/tram/our_location in GLOB.landmarks_list) if(our_location.destination_id == initial_id) from_where = our_location break +/obj/structure/industrial_lift/tram/proc/set_travelling(travelling) + if (src.travelling == travelling) + return + + src.travelling = travelling + SEND_SIGNAL(src, COMSIG_TRAM_SET_TRAVELLING, travelling) + /obj/structure/industrial_lift/tram/use(mob/user) //dont click the floor dingus we use computers now return @@ -482,7 +489,8 @@ GLOBAL_DATUM(central_tram, /obj/structure/industrial_lift/tram/central) for(var/obj/structure/industrial_lift/tram/other_tram_part as anything in lift_master_datum.lift_platforms) //only thing everyone needs to know is the new location. if(other_tram_part.travelling) //wee woo wee woo there was a double action queued. damn multi tile structs return //we don't care to undo locked controls, though, as that will resolve itself - other_tram_part.travelling = TRUE + SEND_SIGNAL(src, COMSIG_TRAM_TRAVEL, from_where, to_where) + other_tram_part.set_travelling(TRUE) other_tram_part.from_where = to_where lift_master_datum.MoveLiftHorizontal(travel_direction, z) travel_distance-- @@ -499,7 +507,7 @@ GLOBAL_DATUM(central_tram, /obj/structure/industrial_lift/tram/central) /obj/structure/industrial_lift/tram/proc/unlock_controls() visible_message("[src]'s controls are now unlocked.vESg}a@rr=5#42;`HQmDC&4M@uLs=?MY=(}Ph#&LSC zlZz>8kcOT*BJP#S8{S9q*>-Ygk4E%<62CHLNk1aRSDv61pM|E<*5$4WooGJ}eH3~^ z0s9a!Qrp3rQepY%4?A;Oc!KxKG@L_{yhDWSqhJ}*sQMr=$6zU(j@LoWi^H``o78># zg*1NQRVQEVVtMy|zJUZRDgS)+Cw8pEs>i4CFxvCvBY$@e5OHqQp63zwYEuEL%wmX`I0Y2 zpbk2TWIw)_e~W*agjHeY=@L5nUQunh_9bQMEA53mm9#Ea1uH-6XTt);%pw!Z*vy(C z2}&B?ecFOS_3!ma`YPU}DznJBgI?kky|98lWwos55DSZ*`DrL*>TfEF6)$;%lNwHUIApaS z0wdonnLC)9)4U+VLXT5q)JhTX)1;Ubs>@D80@K^1prFvA*@Jm5*8UDR-$(O5QKFA0 z%#wH~tBG~+%j68h_5+FG&s*qnhfQEBnm6n4*)(nv2)fk#IKR&Q)BTb9P4~~Asz3M7 z`*zM)ITMtMK*#YVi|*FWN(>11uPaZjRq~6AF-octNbDFfd`S+}1{vAVaS4BsODA=18PKf(tsn*6$FeVV3NRG~$|pvzf#FQd&wqNG z!ilXZfL3on0}7L-BM9iOypdrT!=9MzUj6*C9O1N-a0LrhS{C=oP`gxtLbNKle7(N7 zM(0!yqEk{($acShzsPzFijYMOl%)MD!S*;gDBCrl$MaU!11OxbySfT>t^- zsQW%ZQzP}+;Y2(kX&FvlR~I$N<+Jztx$i~}+~Nqt{qn3^qB%;_r_4A;iz zPEy)1Uy&Pdq{07)L%*Z9|Eu!JkNi9+ypm$um=&Ur z+!RG2uP8#-Op_Us5YOMS=03ZfcKYceZqdp|F(4PIN8RINK5s<8INROjLgStJI(R?v z|=D)c^WKGYe|_QI!m}lJ@$ZkRa}sG&D5;|Cu-t~vF)eG0RkNP-NfrjIl9o7 zce&TM{mpJ`<0!=U=Xj_E?jms`)R6)EA)C3Iulz15j*+#4)S8B>`me1*q<2M3uupNI z_d55#^Ck#)&X9PJcqKDDvEv&BjTB`HzFta@y~o-m8rfWT8L@LSWg%364DV$CO^kf) zLXa8dq}mm7-ftTZWIFR#Ax=MRJCxLz5GP8)Z5vOTH~veaEPdb_L?l8D2_aB`a)q^+ zxLwFXzuijb(Zw(ZJ|W6A)WBlB8?vrXZmI-EU?p)ukKMiQJ1mOSbs2poO#QpCxa897 z$HIc%!Zl!-!<}y$Ebn>~N&`;WWLuzasXeq-}+EBW82l zKik=G zlwn4Hag*$>*$;zTFLOX$eOAt%FZQ&{3tw7+wb9_${{CsJbn8aZ_+YY*>uZ1Ucn^sa z()62LMNQ3wyse@|5cfMXW0TKSSjV+2f{?+q(Ku@G7}kUrMjnGOLyr$}4&v0=vR-ci zOP%6y0$&RT*6s?#5U+6;Elnm7&E%76hudvZ`{U!|f32<_JUFP}&Pq$0JcsfZKE)Oa3|4(cL>+A}sWY>?MK- z`Ju#)Qj12Sx_7NClgy24vX|0tas37NQl0?5F>Tx*BOt*_k5b6_+xh++3TWekoAY;m z-nqnC+Bhvy#Cp5}HBS-M8`+SxjmxNgwmdde|JR?#dWmB|A2OwO-M~cat82{hi?gVb zU3hV+PsCm%alx0!l~hPU>x%5(#ID%3fPs?Rp|i}Um|OpA;cWVcEP18Tv3dm0G+vUv zK!9?7sluL2!5YjLxITW0D_uM{(_WL<8{D;a0>j*W;m`1oms>rO7aLkvoXs$2>^%}2 z_CdE-gA#(wUD%4_MJoRcOLS8i{j1Je71qT5`ETi;x1cR1N%)wKkr78~q<#iRI;ji~ zsq`s=UmqbEfX@x;zbTLd$llFD?(qut!?rO+fN)O`X;U9l#Qihv>9-rY@=@+!YLLF= z<;)HI#onAdI5UX58uHlnF!n+)=G|we-M_u2gp(UAw;6}Apz}QkIVj}z8~LiI)&s&v z2Fxm!qhXwO>rYcM#7F3XQA-~+IY4X`7i@3xxB&qEiZ{XekGb@eG-@KynN479&%knM z&nYNg>c8%rn26g~Wcl{YgJv@>5_nU6ef>PLbVV|lFQP;t$G_x!Ocpx8slZ!6gM}t1$-FAA9}RN}`?7}@*s$?=fS}DdYQRuIn$B5yLwd+yZlmh= zVU>}A6QUdifpAj_PK;i)Crv?FT)34hHB8(^yS9Q>bSrwaD7l$>ZoIj>%Du~@u72$h zG;s8#YaS7mbo4bbH7(5z-a%>r;du9sh?b5-WT@Fxi1+6q6SC7VHE*8ueeF59=s?W3 z$ja_tEN{>(xs{0QwxX8r9rS=ZzUY|-<*`g`uyY6Z>iQ)%prD?LE&k{ojqNohE84`5 z>ow)h{4F!Eih>c`%R({=BFB?o=)(iPPUNT{#|t(iE{LAC(@jX4f@%kGlQGd+kWd~5 zhQJpvxu38<(nTLKB@4k@vcqT$93u}6CpX15f8kK{-9GBoXm+IZ^KuOahCf_n+3$z+TUTQg0KQBotW7fcC#ml|kdVHrG(YzxX_gZ7~vy^D?NWTQs-<&ULdCzN8$ zTe;(S>W@U|YiFN&#s5Jf9p1EHpj2V@d7hz20Qa{{)J?sGuSQ@`x>Pz*c3xFl@{QT1 zOaCoT&!F|(sm83#HfaFXj))2Za6M8y46mF7_emiuC_v6e`NCZM|4=?^pTx~mBkuXJ z3x|2OaSP?)6P~>lJlhU;=%MkTa&N~7q>i{oxiuC2qo!&)#|mb$#o*hrvd)(;z(Qkt zgGsH^CyBYmcq*`T_7=c?8JXY-R?gPs`UQ4?p7B=?yH5!@KD=$S&_Wd*6(v*j;}^CN zY?5~nYwP0Ol^{}7_du*cU;LH;vU#7N`(ZI$N9uE#be^14AF?WDYLbBF2E!V!?p;Ug z^1#|sWJ16oUYsm(3a1e&Xi`!|KQ2#n*4eRsA;7dKOs@(nw6OAhPT*Ft%RDIJdV;d{ zixI08k~znp*r3^Y0PV4;sn1G=kjw8MNo=pY_7Yj0+Hr@Iemon-=b%vg_~h7>Duj;3 zC>Zp`@9b9+MYiT-F7+9j`-mv+C{+!Z^psokZVsSi0B#LTE>##07KZ7yshqk_`=+K8 z0O$8d5@fOjX%1kL7ZC03htGJp1MG2PfMP*3?N1>T-Ko5%HfmvG3o3e zd3(Gh0FS?xmJ&t3ED3{5nP{CAxwWtK`Skb}2uoaL^u~CUM4)X!EZ4n+a@lUwY;Ir{ z*?`qJ2TaA6Wrs_*!YF^BmPc1EPE4#{^{@|2+#7V$+`mryCgkVNr+7WTV zy1Iq}ilJExTh;yh17mf!w>^*WvNpB$4yP!u*UmZA%Iu8xZ$g!TKY>En+7|0^13Fs+8+AeUK0B~eU14Z zbAsQA3P=%k?SOpK#`q5#`rSS=w7Z{n0@wdZ2j3l)`v@FWGPWiQ_^K;{`Zf#Y2_v># z)JPP0{K5N|NmGsD;Ox&obaXT6g8)DO z`gG16f57#K$zpzWh$cd5&_UZ|7L=5o50EOa>K8nMSOBlGd7SBGY3VC~++1bU_k-3- ztsi{lLntjNGZOpbn-bg?nt17fxYHkDyiX6D=}eY&V9OcE5b0T4Jv6&RrPF)l-n(qS zQvv{W?zCUx%ZS9$4>tUtFZ;|6Iw%MHF2ia)-ah?ng#QPbr6CG8CbJQD!?+138uy>g ztxuO90cFvrE#r1Wo&wRrfRNc{@*Aehe9U07^BZlpt)Sjq?qlI-_;(#X)S^Fg2?Z~O z9$0m2258+yRs!0pv9(oU32A^M3j#(p1d_aWNASxkzjCqKyqj+3Rd1f#A6O1dO8v46 zKp}vOEi1F!n6Yr6MnDHz-rysWm5DUd|}()j^iym_NGhJ z+JSIt;Clx^kC}~_o>KfK_-@V_BE786@(q$gM;(icRy~au5Xgl?=BMA$@m^N8pd_ke z87_byCrit?m?5&RAR~jex4+LLBEqI@V{Lt!T#qJU)9Mk9Fv z>wGQ&lo#OF^)*Ts76k|XMnt)Cg^!TmJ~hzy?EVCXO~RT)fTozhMtuB0MUQWI%8ttl z*SL(C(w5mo(IZY+(@eR^zExf%VSTc^AC6vq*}4(>nI_u8=cskZ(05e{ShWkz8g#bF z^p!Yk3FB(gG-V8cDxCNjUb>VIpek*bv!OPiOg*d!xb1h9=hI~cu4$pEbV3on^)``ZvjDWS9<95#)5IF%AOCxI_v z(<2K-T%?bNVQ*9F3-nZJ2?@0sC!%|21NQAa%jIjwNTDyz>KSky!>{Ad@+^Jcp$3A2 zTCo&iD23=*+wRqwu#a@Pz)~_u7VQPNdnA-VZ%*57CW8kwPaStWKi9^unWsWYtnV7%sjuYW%|#Nod0v}maH)4-)ue7K2we!B zW&IMAX@%AENGTCA`-c2l!pvB42?7l{#8+e1aRH&ug5$55#0D4sG6&0#uSe5!s1WZP zMl^D?gA!>6_9Wu?!@SMgt$)2OdPkO%+QV74)_anpW;$nMaD04)&Us+p`|S!{-+N&R zE!vTbYqN9BL2`?W4F!|~xe^4emyo^;{Y%Pq!$A(JIVBK{U}|iO<*gH)Chez}lpi+# zkh1H&I~AQV{9)>Np{y#iYjtRa^U!_T1_K}vmMl+yLz9Zx-SKzH%h8e_Stp8xF^n0a zziLwo6ES5u%QOEA3f53ojQ%_KgTsw4Bl!iic6)Xr^b15vLq*g6AOfL zcPhexeAXN4-5phBqYQmFg?SZOU0ON}7gttOGibv~6QAY^>3WtR5bT-rxu}{9Wol(K z)y&#j-tyH$u8Es$#z}hMmksxiN99a@u&EdQD{~U(Gn&tN^33-}C}=-QOgUD!r76qv zbMx@jI|{OONR-YF>hPQc6zpT14b=0)x_n+cT8i|jV!6YG^zL63rn5U8nQ`b()joKd zct5!;hT?|^=dkqj^p09aMYsSTU%~6|@^tWF=&WyZYfTLlfa~cSOD|8};&FK8UOE0Z zsU$*$5Qj&%Mk}JKEuIJl->q2$+-v zaz=dgXAhYwdwY9+{5a~w@ZE%3vR%6^^%vrot>biU&*fU^qkKfG%3O{+HtEDj;cjTR zp+4t(+Gf`r22Hw2{1uS#Zy_}u%>%1$yzpHKWta&|&|N~}U8#WY?K`+JM4!pFfjH3G z+WPx3VtRV|MIILoN`OejMZFnFT|k2Na;?4x@RA=lVGIH^VhqvoSn9&t?4Z?K_vzqf z7mHmR37Ho!i8{d&utFW}98>rk#fuDaU=#`W4h{}hbM>E%!NO^rPo*FQeZHYnDaOSP zhgWYvJz}^m7#DKQQT?xkHE z-_96cC%v*8-#_h!;S2HeW68^V0JboYRdD_+K4#`caC(>a_iPN>XwcXDot>S~zwXa? zRQF>Ss%(|-edEvP5GPLz)zA#lU6Ii~0ajK;MTdJF?x((;wvLY9hSK=vyIpd)a|n!w zI#m^{Er+JwO^x&Q_=v`=4JO!1JpHvy^t!CPoQIDuL1%StVgjlLK}=t5aY0Jk#L1r- z&tiEj-+3NIG}{r9otN*SL6ZUB&ZWph<#Qu56Wzg6ju5|BctQZb7#9>2#9?|00QZS+($T&-Y(xPX ze){1Z1?&xEnng~+x9sdpb%IjtYsGWo0O}4frA$&1Ss8i_>_VwYH@xdv!w)FPhCxyc zp(-!w3(tyz&Y#%CEoY35piUQmB|+J%MAu+D{X+5qUxMV>=N}-qW9gj>I69va!ouQo zfWRBJ;}r(52Df`xewW@}u456tt4Ak;SODAdNb?cpe2xWbfOxBuc_PjpuYJeNF(Qvk z=X~NxOf2|z1gf9&?B2w{fX#pRI&{jVNPJ*oO%eP#ulrYQ&blu}2a!1Q-TlSkQeSws zOEE_3^1g+|?=}90Yf#4|VLgvQDbGcNuI5p57UClY86JjPIoPV-64Tds=Se3(?G)NH zl|(O>J*sGK*D)U;OzTOII2Neo@6Ihe_nl95f#C$_3^Cd|gXAe|*d5t9@Zq(miHB?q zxFtK-sJ>iQsKSf$w~b1rd0kvv;&IvB=K>-N(0k4@*^3*|v+Kx0HP14MIQa3A+E4!u z7(<;Eba;)K$ocU|vfmILM`R5u)%PP6CZ4@Zw3NV3MROmj#`Tf`4O1W)z3EQ;6+@ro zz$pl1oAQu|)|f`?JS07wDaq)1DswL#f38-!@kfp6vhOd=vmb3RB)zZFTuwYz&AFcV z6oWj&Wrn3x(K))il`A7LUphXMwL)FzyR-VYCQVePH7kZ>Z^QT8t23Q#qD*}ia__2@XrT2nm=A|X%x-~()vr<0q=^r`jt;>=(785z)AF7W zetFpc-8L~6HGU>#BoTJz+aj>2o(gQG=9JY=N_@~4?q7j{Srb`&6I7gWb4Npo*=k%P@U$+yFTK*MCYiR$d%4im`oR~=m|gpzfV6@{Km*hh_-CQ`W11yl%a<4|F{xqr8{ zTzWsa#)Gz^T$PG=VFs-wm07NSwY59WvKjIP^*2y9Fk9;a0|B3uaMt(70mo>dqWDg0 zZg{S>=hXe^W&jRV=y3GBE*|m=w6`fb6D$<>ch={yKXfwS=b0^N10O#c6ncx>j7XNTML@J;I9mmC|L=E|iAuzRfKA zH9$g9#t#a)|FzdIAH8iIY(%$3MnhwRpuobgZNwX8nc}TC-!~Z8z1yFyE-&Y6mH`20 z4LrS1qLkCo$Y3K5oreyIiZF1Oio>FU;f&Ir@*ZbEvFlxF;&C!j&t=XK~V&kRiJj$o0vBM85*1c>%|m(`mb>YZK|UyMA~Ch?V< z$4KX|nJCz73uJ-AFf@OX<$r2abV*9RJ7;tmW5QEQQO3ImtrX|y=gKC`?6{fz2iyUm zdvh;--)>XyslUJ}_$YG)+X4zuEuOG1RoUQ9dvfFQf)=S1G+B~hH2B5BY`r>^G+}&au)@p^`2nk;xKr3kQOo7AFFR& zFYY8+$QLOs8TNtpJJ;cEbA5e+fvzs$-JklspZQ*A30Ae;qMR;<;5K#|| z$J@dlE9BAU%zCsq9i&a;P!LNxO%1O-33=6o>X~McU^nSYHjM~6#so|vyj9)`u9Qbf ze7Vx{rr(xl@@050fNB(v=qW`3zbQs)|DiW-e6oE>`P_T@%5av11d7$4EE2Y7eASz= zrhobSxfIU6D>wf5yn%uwLw80SN~7uhOC!hMM!GyEwSw@Rv+@*?H1{r1%kd7CmdR{j zRpz1RX8i^o?&5u72>zGV>^^X?{I!8!q!W8?zE7ZU?#kJy9_jS2?Y=_-RH+#SbpHZ- z=rBFM3xD1zAOu(~P!H}`Eu){G#Er1&oG=w%3PC&T_JzpqtqDXRAE>8ag?SaUoJHdR^8Pq98aiZ??cz4R<_QqPsmrK@Jw<(%#ZDkTRRu*gE z#K!(7a?fA8qsJ?LOYF+Lwk0p2B1+}QRqe*v@kFzcKOw@4<3yV_SemCM=vS$9v9i1} z-_HmXln?+jUrJ%Ok5EONv}SKZ+S_O?L++2mC2|W2&>&a+G@#V#>n3}CYkF=wl1yg@ zd3yDd2J!*sY6;28#qYmtbOIg&^an`;u&nRZQ}GLwl$2g8SF#XCWl@M@1vf%ofcTv1 zzq9}ln=WywMX8`9Fqxn5z5gahg5N8`umX*(P?dGxpjZSJ{8A_Q9(sNKv4i3ka}X$} z)Rn#$aeBy}E+XP%lj&^g_2}|#wws0HD<4tc2F-u^o}DZt57RW}K;;c`<$HU9GX6Qm zL-wA6-ysnDap%tH$rD8j)B8di4@{^=^cHeG5)*I{Cj6#6?Hs#1VfxF@HwA_+7xla9 zOwT^tf&!w)x-XW>xI$xQ3ejSKNC#jk7Bjyo>3rvk7!*1+^0gHSa~tud=hU)MfFd%y zBb%>xZVQr-A-T95BrEAj{`{j#^qm^6dCNEW?pi+9gf-Y)urOK2={4w67meH%U2Rtb zUR;36_|R+6)rAv4GNheKj1TNdbsWJIQ)Vb24Hce^_phQPkD8O_en+u)3#EPQ)g1*Q zpl6$67opXTgY(^Ag)oe-KJ!J#&6NS@NgQkk_I^Q}c*lhATr@_tNl)v3w%-Ypo7}EH z?T$cMs&r{!#diwONBCX_elI0G(1`>#K%1oJ@+nZ>4*A>jnFj+EW$7hXiw?#K6T$Z3 z;~t@(*r8#sfQ(UARzb}BU0~^f=K%wc1;YrM`SfebS z?=w=f;X*v7BIiKPnK(k$ST59X>ycQj>UxF>&*Z)f$fbsIJhS&4d;{eptU_rO(m(iCs*3SL z&qNRxuTp=0*#*X?<~`G=bPhwh>YGqlDK@iaF*{AY`>Jm`#RGy7<^m{Jtvrg8$3RC= zNLnERI?_u+YxrO{bWM#*i$$;I_GNQ&bc8yQ98a&Qd2keF~s z0jw>?vKJdDEw%Z|pg=vMFES?dXG!rU?8(VG#X)8t>)6v2Qqm@$8qoCoQ0a=e@7mXj zGzK@bOeLQDAC{O>UzHP*h!Wscb1pC^1RU)jjc(X3MJs9IjV%c9T8F`U-EQi_l^>bA9FeAey@0X4q2UmR(GD01a$d*ScQ1+zoirE)JEfRL~lLl-n$oq zHxo6CeA+#c#>p$eHexC}pQynuYJRS0V8p!EH&GySX965ygzVhUKS(UoPD)z72~vC3 z{riHoSm2@WjTvoAx{|CMZSd4bF{?5y} z-DGY`JpriZ10(%GVx+fzbmXi_aJyGty?Bbw(j*Sl^)hVbp(`sZ%T-40%1-|OaLxx| zlWB#~Y1=m&Zn7x%KyupPTKV}ptG7~1Q&o>VlTZYOgfbSduC7{2&y`djepiJb|9E>W z<7$8_z|8&+K;ZZrjagv;>urq83!8ALm5~LqXI;C3lIG(2S;W~6%P~NHNkLe4rd@>@ zPLB6|v0okiYl*@yu@uffh6Q|7zi-FO?n|%MN=PKOJ~0K?>MJrOEaFxY7d{i#sW$d1 ze7#gw{-`S;HQkwb+=83TA-G(px@~uSYKmAv+cuQH?%dstEpN&Vi=O*_8n4rkWNT2Ji6sI>Cii~}SYu#%T!VC-y zyL)?e6_DKtI@Lv-!h(WekM@;Mvh-#9zM|A)U|lZ^MOXaO>HYBQzXL;{@Vgfw0dNl_ z5-GAPjJK|4c@H zj-!`s?}=m}5DDf>6Dj!kLiO6(+IT3SlB+WkKrSpS1W`j?YwGBfT%q7B9XL2UtDgTs zZzxq&R;JAu(-&OSeui?lmcms)Q%(C^JThyNWfk|V-(0>RHjhSaz0;L!a@S(M3;Ag9 zg6`K-k9f*}r6#8qmpgI)np+ga%}uLr_t`?PD3WU}{IO|H05A##nv`^LWDV=gNeZ9R z_jfuv;fjnwfq^Kp^hChCUgt}Qin7bmOnCvjPky9ID4|*2*>2)v;($U;>kE_SOX?@vKhc zyQhqGg$&9sG>aJ|3lLN16%#8fW2NUQp&a zba&^lX_4!;?xXcweG56xA~TbUrxbHZ==*>MKRM) zx9M+CP;Pnoh=7E|IJr|;9ppY>=GU(_Uq8Rr&!2H*_NPWZczLx3oMo)J!dZOW8Ga8> z&dzS_9UgA&{^3yqP8JNS8X&|w<2gD;-__A|4=x=dE4hlgyVtZwi)n!3q(Fl?b@x6O zG}|2O$@AxUS%S1}M5hd~qNv?#v6j3M&1(S${IQbvq!F^OBptu{=B6+&fgX6SKXTt> z@b*^J-ob%KLgF!~?}M*WwZjY)8x0MObE;;EU0POm>H{qJeW;)uE=Frd2YV_Zk|}uYZ+LYtGp{J{S{LxXL0|Y?Y=wb_hS^Za?p9^T znAESL*g?E0FJ||xZY9lDuSC-oGoJTU%&M8LRO0@r1<}=UW2T?PL9{ye+%qEIgo5*; z#+C711v3V=M*LsjAkO#Yh)j9YWN}zEN-&2liMcxAUv`Ba_I1JWJ*Dskkyo2v9 zO&!D!=AOmlY<7Ete1#Ym*4+26ypxAy%@Hx@B2U;mfqRY;S&>!jtzhpTphYV%Ka8+W

vyD@KQ z7+xG%&J0#j_qYIsi28#_*h$iQWL?o>>uhJ-LmvN=aTj1=R$H^e!l(ikAwV1o=$?Fb zvOcJ5XaoX+y{#=Pvoiks-vg1h4i3|f#5Q{>gfIR8kn@X&l84po1!@Bt+Y()T=0Yh+ zI$8nbB+_J4Utgaai1_WJn3 zK?u`UXv5XsZ{Syo!5q7O`gaOxh}?ahx2B27_~33*SQ9q! zP@I~yf~tPt)!#$lVOTij>tSFWZ@F3vI_q2;0D>L>Pi0e3c**d->xXpWjy^#Dze`&G z@PK3iE2u$}qgg+1G7md)gpv=|UHqWh;g0J0mw4wtlspb)bntMATeG8a$lY1G&y9?J zuHX6Itbm)LYTs0M2T#IXF#^roS87p?M-#JWx;O%{1t{oKc6?`I`JDZz~ z#sSw>BN1KzmR6OODS5P#8vCGF-UbZ}$Qd-CoJ@rHl9Q9y^5>ImOytQJdU({^8Y?JZ z?s&HoMaXK+o%@I;Uj`OQyuEMCyi3Pu0X)G(Fz^0ra_U%2Dk`c?W=vh&jf{WrR$C#t zy8KW0jHg&>7QB)$W(-AVki>0`uLCm z6a!GDv;b2OrH+jwRAv0M_(alI>c8P4X0EFSl;1&SyRo@h#J5AK2LAWS_Ossr0h8Ed(a+()}P267VP*$N#UC#Jm> z24*P__3TCYo$kOWKv!iFfyzH9pd zg5fJGD}Pnp`o;6(0j|YYzO4Mc?7z%Z^Xv)erddP$Y7Tjfq|s~6&+nU%Q{-|fdLgEl zB2LYxI0r_aQ6|4ozcLUzn`#zxSERBs=?*|A;`lR2Ve>gv)^s=6Nz-x%JJo!3A{@^>Cqndqv1B zyDM-;2HlV^UCwXhm080hgX>F!>Y+q1O)`Jt6La} zv4Le|h*t!GRzL1g&0Yf-6qG?3c;G0QAz*|dLs6a$Kq#N@$>cwDr=mk&P9ku08T~(? zicWa$0k6-vj5|IxH3`z)3gP}^eXo%MY*NJ~C6m8?VE`Q`z+&M{`yI6^cmx27>ol+s z@|#wl61pko`0`gz2USsCxWV#4aV-shi`Wm>-+G_e9F%S^~Sb`yE{{I$E{HLU%N8npB zhXH#mU9WCu4P1!eKY#k))EALQoF}-^4U(5Yn!X8+SDOq79ZU`%Zg~s&Q<1)E`ry)@ z{66uSAEWL6U&tjY#ExtTQ#Fm2j&t3{3Re)&VMVRIU=Bs~$ zjcS9&Pyit~b`TBm=DeTgj zO#Y2ir9~x^TL8Azyq`AV=o~HVCIY|6RJ!lLI{r7pbUjc{cX#4aEgaCqB zkDD72z;xREE;$7q=RrM&LmdEU0npUHkHXzaJvKD-={NRj$H)4zpFn&BL=E_`l} z!eO-6_tde2uF=~wGl{NuFsJ=V00pIargFqhybC3=vaR8j#lR3+4_~F-)#sNB9SUwzf9I&d$!~uTiXlNRs#P7$8KiAa@;hPEZ$&6XajW+Dx18 zqVq7F*!|hrS>~iQ*3IQ#1t+J<(zEd?NT_+C1h@;>24S(WT>}+J0fJw(r2C+~2XH5S zZ-65pJufUF5nByG?x*JDkOoYz!B{(;<>VfXW}+8ZVYus(8!p5Irj0!hp1Ou?#w$Fm zi30UU^r?@VGWRwYxApMmF3#Rjo{622738z*qE}gfQJ4ZRW%LE6MnXy&KWvEyR^%Y;kp0sDzm1KGG6j0W!o-1;SMfN6 zwFn}dB?!I)%0fC;i0OatTvXTWKRfpg$z_16Y*GQBDJNU?uL(5}pHMFx&JVQMJm8m> zmKJTiqUpzvdZ{nRx_wUQ7Z(>pTvypuR8;!dR2wir9cMp9%FaqkNFR6N=LYI*pNs0p|z|J)z`*x-mUq1Lxn1eu1y`~Dfw zaysAM!$R*}BJnSHt6)W2uCu}&q2?jOTLCUCxpCeA4F?M11FI?TiW5hifZNEJb^$3I zpavZZPs`;kGIVyZH8jO2NF_{|v=9X9s!dyB?>Uy8n=7d>=O1on{y;r+&2aw)vcDkD z<4TX5n`!R>!o3ZkXHlOxVxWeU*zE-|HqcWrw)G?;gzgEWP}?FtSLX>JEItN+FEUws zDJ(gL>OnpL6nB6!-tY|<86G`=3@aZVp`x^`9CcWLKy~x4K09k56iR6KN4fR_WNSErGbOfa_5AKvToSrKQ zzbo9bmLDPebMk5z%N3AYUa3aK2zs|-#Tn1-ioY^TRxRuIZoc1j!5g8ZlHa*>4GkOQD518d6rE8~QS-bne?4TBx3{e)I{-BQdFahR9Pzbk z|HOy=uMBHpH-&d%Z#=slH<_#`^>}1dqB2{Ss)d=^Luu#ZjjUP(_Dh&zJlp^zpFxM?D1Igt)a9n>Ce686f z$CkYHAZs#1)`h=FC%h|um$%`e&+w4&4A2_HA#*AK0U+&^R=e5OkG4;F)`AJ;^ije6sQ&H;2Kxnr60SJ46qd&2{97S_?9B%94GB{hVW8|G= z0?eB=0JIL23%rMhc!Bgdq85h-9i|l#5rGXf_r=qtMbC`p3L!5KmzYIwXJVpd<>l-2 zHs$$ZRE1}I`dY#L7^Shnn~?KYMBN8|FnExc(8Uz4#8C_^-fXj^*#b`%Z%{ zH#Sk3iD8kzsb)YHaiLVZX3c7i z06Lf-3O#4z5?txbokPO|T$d6(v4^j@xlLJcmA}7BswzpI)rxFOY_hTZScw%Uo8>-P zLXDl-r~?8$CVu$40N{5RELr+R?d=(SA}!HWu*X9*8HR$Xf>>>x&y8^3*4NbJB9c*z zjtWTvRCD?G7z~2y9^{sh10tE{poV4$)RbFy0uD&ViK3)R zN#5)CE2i|map48#!a2<#%8;NXlXW$H+5`64PQ&C85C{d-iA%MADmyMdh7(ZzE-v;i=tQC&%-5m~ z#-Q}~clSF~>%F}PT3bh`mzukghoWe?IY*vN36@?_Py42c0{Iu;eg55`{AOH6{jv8x z5L|1ZnF)WXE2pC6A<|c}HY}l+4p$LY&p#B{u=-IPpw8hVWtUag&eA9F+F*n^- z$Ia9I{_YRrOW3I8 zk~^VHoNA>z(4r-JHX1x%Zxib<7(lla;=ysV-9Hu5S_syq0!S{E*}DHn6W1Bl)Ru)45fq4mf)pXNNEhj1f)4~S z6zT97DL$%{QR$$d5D=**6p2zqX`u-FsK z)F%}$O7##DgP;M(E#tX|f_{4sUE}EK}>Z%Jc`aJoGjL5esqyoyK%9^pp&LL(@VI&RH zIS(gY+NK&ELCgs1UYQD57;7MI7^X`T-K7klaqc;vHGQS0&K$`x0^RcaPE_7-Pwnh4H2j*iPZ5G@f(Y!u-R0 zw?_VWeD*$(y?uu~6fr-V7h5E$9|`01*vo#;qHM$9(Lk=Aj$zGVnhIEh-n;#`+Plpg z-iO~oI(VV#o_qV@D|k}#*DcL)YMSMFdE$Uz@NviMU>B-Sezd><-lR2hu?sZy2D<|p zKfxXJM$b`fQm@FLoZI&kw~Mx4Lej}{q!efa^e;(k-C`lbxylc zz@Sh-FL1oGvokK(5_r=nX-1P&+NdSJ^2a6TH@3UJ;e?sk$R*XW$Jr;*o88uq`X-A2 zQlOuS1+eZbK*RY6nERCIbkx>by@9ST*#hX#RN@m*>i$AS{1OKC-vR2Lz9+J*MpC)? zK%A(zrYMppPEV&c4G#W2m{3Hv^1i#0&WDd+^{1*qJi>4p=9KVH!t9~ni;yA4YdVul zuwOTZH8b1X*ywrpuH?)1-RB(Z_|4wD1~+xJ@R!>E0zE-k^L5IZzfb6uGL|=@?Hn8s zgpT2ZWpg(CyKRoTHIb9fH)2+2F9JIpIYfCPwQ6(=v;eNGYY`Y=5GA`M1)@qf_6N%@ zH!Wlc%>f|YQjS;a=Jo4B`=j~lF{btcp;<0L%gbb{YXYdW59;f|`E>aSQeZuyjQgcDUm~x)XtHIGTz~k2xL`lDps!XQ!o+Zo;(ebmriiM8vl>9HA z*E)Y1Kayu27HyzxKba9Q<0h_aXk1)hR91umJ{1Tv;X}`@3K>!us2at~kzQLnl!fCR zKn6Xi>g=08C}>q52zCu_*nR}GKAiG84>ANKCwM!-L3QxRs{45os>5=vPb{x7EI2UmC^4gAfa;2PC!&bsjOz#xz5yYjCE~tKPSID2+}#|0`9#M6GP zd4xytcsJIo0NLN8%Ry6aUU9%iDSkkkm&bdfK?P>}!u7Tq-vC@6$Y&;M_&5eJn4(8% zm!_oY2Q4bteG1d#a!~B~+32;Yw|Wk_yjo)Uhn+p5nU-Y>HN&u!oq_JJ zS?uAa;#)qaRWo0NEr^MZFk%`HXd>Tlhtj0?-DQt@#}8mW zf~lGG)9RVDj#!X`M43NP{~?rWH&k4wrEyN2NhmKz)8*cQ$qnR%_}B^$%AaLOJ%Qnm z1Ixzz@bGZ1)P)Kerb}$473w(HtkuKEigfZ3W~RP5ESs$m(_7ChP_}rq%|GMWk)G5L zJKVxWSp*ujo86CD$0WWny?UC@M`L>X@GC7I#ng1dRH90rh&avyWtQePnrq@3in32R zbMu@Fm-SHQvB^bA(Gj{q&!rCQyprB0-YHN7x)?Ujp-|r+D6<7dt%*<8>oEHTn=~5Oc!CoTuidzKWUjB$ipR={*$Z3_JVH%ZmW_=v|v{ zS5IhVHozAljdD(iZyURlrQ_aDx5>$J zO$)*acI7Gmj-Q{O|C2b}=iAWo`88ezIUQ~mg^S-Y9qV6hb95rN8rUZ49) zS!WIOsnCaMvM$Mvt74ve~s$cfkjpYG^8xgd{@)ve!y_L|f^U%fT zzujH&TijziiGV|9GE@bg%i-%w2+c39e{1;q`FW~@?Yd5qFfYF{As)ZW=A35^Cludf zupoz|=d1)FNh+%G{GIQq%{$8qoFtn40j10bY3nEXUag|}QU@1ayn)DkZ+d-|kQKun z2M=nKH)%!RUZW93)T9q5ycg7} zb&li|2ddj0O+5Fe&2GH8N03&kT??c`1X$0S6Qg+2*gjOTe1?&8{!C+osBgWRz7Bo0 z*M8AE6Bu7$;zgNlfCpUG{}Ig((P+G*NAIi1(mGdli~}wKwh4#B0VdmcvHHg{$O~H+ zNjs5Zl)cnu7AD@pz>aPKJI+{>A&jTn0QRqYpo~lcl{NfreGS-9$YI?#1lc;cTT3`E zq%cuubwb%}P4Xq>Ivo^cB`cUj5q0s?!ounLy-nGt)};!5w*jUEIKreKk8QisDN_sB zCX1UG0OI{2b{6!Ts<{Q@!!N#*?6tA>RB4_BPk1-a6}}030Lvx8fo!pK?1G3U$d$7v i+8*q&!~w;lJPTvnNmT1*?G-`5$NZAD$qQqTd;bA9)q33k literal 7407 zcmX|Gc{mi@_n#R{V{43M?0eaYv6C!AmXfh63S)~<31O@=W66@O=(UDWin1j8Hpmtl zkqFthvX9+tU+??;p5Gt$xyw2C+|N1px#ygFZ-RxHF&i^KGXMZ!yK&vX3IG5i&Wb3Q z?renEbf@#I>asAkF~sBX022Vf10XLiFCrphYHDg@V zX}PelP+MCI$Og#D%G%o6s;a620NExcCd$gnf`WoHn)24x)*1dRo);I-W&)pBnOOr6 zD-&lBfmWe5c25lM1-SWpJ$~Zl`v?F)=e>G4>l-b~-diwVsjyjo_d{)JnAhax2s;`> z*V3&U05*$e>QPtDgFxs3t0K8CVmm-I_(L&em+~a#yol5!wz_EK``wII$&6|G;5P*i ztW8YVGe-hB*R$w!9qb>EYt|>;Xe^3haijcw`U2j?^<+_ODzl6+8M?%f&Tyv+Ad#)l zvcr4HM$QFCA8m#2R;|h%tc-F$3c8Y@?kEt1HC`zgQ$OR2KDIYcWDuQ2iY!j>)d@Yl zl-)>Q(Ypm{d{%=NC>1tgosL=2yL~_C5eqzf`pM0s*?1PMUpPzsn#O|?c;{kPc352G zrsc_2Xz@lKKsmUf7u&8}_&j4Ezzwn0&?20sb4D6qu7kl%7KYBNC8HScqbs`aDUBu?D z=qTzy?cpu9NxO`$AWdZ6`_409r}Pf;fBgI3DuT`Z?Hj{iJ3%3EZ`>REcwU0G(WZD)*gS}8A4BNlBY!TJSK-cVx|{JSWW_sj%+qr>^Gjmfo0OcFOo(1o?oi5X=`E z`{WF4F-QEPuLaFL_lHlfOjhg>zx=R{F8~Pil4VdK$RtD0^R2jse+tg~dUy`{q$T(c z*Hdio>4hycycS)`IxFqak1CB0vxjMQCa#E$e6YI~3;VIt!X)4|$g$LrK9V_L4w^OjV4S}`=T{S|(b$a>FVAFT%pkidh*AZr)&UU7%$@jNc z-a>_;JEolRTOVcYeL(qnuu4Io{j4m;$(57g#;qzEUYYN|yeb2e) z%%SY=?9Y3(rwCveNKx3Ub2S;E^6PHoz+AfGAk>)Pm2qR2e1ok80dCxov_rMD+Q^T_ zmdkbrum_(%eO(cfS?WAyo;N(|e~WtXLH6X5G2+Eo_zJOq<~>ky?y5B+-2-{tI(05c zm***%({^qTA(cEQ23ijheF167UcF35(7J*@g6%Af;A0iPjx4!89FdxkZh0rMA()Jh z<;3}VrwA^E!@lJIiY`d$3p%`IptZBYlfTR>i+ZxL|8zy{w6@DpssG?6NL#Vs@HmR%O4i2-Fb*O^m`3v z-R%N$nU3})KK;((3^F>7+k`ZoTLOr)UeWYD01K|Uy0d5ey!nD^*l!meoJ2cBTkzTc@F6@Ok_*<&zE(XHppcS=kkBX;SOFIeZ& zF=FDGXK~&WR^W#B7+rDk*jsP=8=^;{8gCg%{vRXE%Dh>h3AM5K-KMj*vAaM|<=`@Kvzqd-r zAWEIuTc>rWzJabAGhY;C`g1pPwhZ#5$PR|e0A@>k>4YsSxK4&FPa6e|b(+ItgD?QsboiQ~Zi_j+f zIoE<85gaid^spR#2h<~Kz=7?Johv18M3Azz#@rYV8j&FwrbntODrOosu+wz{e~C7q zY*reasl}v?9aau5z2~J_^#=&#$Q82PL|g(10fjV(R~*4D_6g)ymNs@Re~F}B3WMna zNZ!sFHo4u&p->1n7Z3Lx>VgiNb-`f~RJG7$3^s{ zEZnwDX7-=$Zn6h#2L}#H`M<-N#HY;ITbt0otBrg0Ar5x&flgyxh4HVjWAw>7U~)%a zg!JNdEm8QWSKA3E-hy1ZRmKb7ujXMB*-8!j4BFJkf1@^-Om)nfYH*`JkYV&28>u%{ zfSU&2Y=8Imlt;`y#adznJC0*=KtGQhqtsGt=Bjtc4(XFl7h%((9l`_Ra$LSF(%a

ubQI+F*ZDnPmwABJk(3H;d&sU+eFEc2b%YqSYRrA}mnKOAu-}HCK{BLmk zI+0#VPDhA4@|!X63(N8@+%C6GqperAYd$P^BZ6-#piz!y7t~U$>?4qAwVS7y@6a#D z7ra(eqmKua#0uwxfXl6`$Iu?xLUcTyeVfy6mmTL==PC9$--}dA|DdU~1>HCoT-P7) z{#IVxS%CTTBq}>+EmXm}Wv-iC91NxSJDIz-cKf!fSRJG31(Ofr! z&C#qw;nDbL2ui9F9bd=}flk~DTk9t9oi$9|8W1E0a)frL3efr`V3BjI*O2Tt=F-hD zNCxQ~T4p6ebnQszKtg@zWWL$PEbkZ_I?IaiLhKDFekE8#+DebmJ8bI1e9yffO9x;Z zv6TdTL^fbKz2v2Cg>2d96Qdk1KVAAw-&9;FEcFm~4lN=bs+X|}s@>_eHE2IN?=9j7 zM{CQ@oJ!*)owqF;KBo%*O??K=dRERl{VMKCp3#a-?a3WPME=qF1iV73koL3)Pa7$H z;?koT7MsT^`Ay++g-oPJU5fdu-@l6RK-sq{-|LvhP18Sdrw%R?empHw{3@j}+Sh2A z+Y0j(cX4uGIBI`?x4L&rx913HR8^mjNg~6(#Y(W(V;;1P4eqsi-04l;pHIc=y6jbQ zHY7|YbX+Y?RpshF4njl3z11J5_f~JNq=H-tu}S>X5Z#X1Yjaz1ZKF*}@U^GSi>b2bYou67_0bFYX!ErT@ z5~ZFc(||f^DAC6rMw|!0KtXGsw5(av;H5mTlMuhZe`&{YEvalD=SV9pcXUy}SRGMz zVVB1kA^qdbp$?vNCtG}IpUCB;OBTUxrMlms>_-Iq_tS>T5c8#rfC^y_7yMo>0sry6 z|AuBVejU!}ef&!OG%xezt@-70G1__Ek-($_QwHXQ8P9_Pmq;w{dcTG0-D1tcPEPW`a1MyKv;H^O z^3}hO%*KS|O!gGZ)gz7YD;04=Wn+H$@z8-RaU@Wk#NwY)-l4MkpgP&v*?DI&{bm7PmOaAj_Kx1D}K4iHes48q~!`dQ^c(+}t7z8570E z{M+9GxJYf76o?|`V104$jhA7Iu>8k@POeaNzCL|EWp!}bR*Aju*7fjwgzrK#PgUww zCZSlCyNGqkqb)Y!u9ghn4vE1lxzSQ(Bj^fE1t32}M&81>ty1@!R-A?<6#UT6r}H^O z$66*v(p4oIT;t1fQ8chTyj~lp%oNCCIh$>y-d1^y^C)Eky4J}h)hV@5cFS@l#JKf>N438$mJ`Nu3fbh3pqJ8kTHSm}Zn+ z4D*oC0yeV=B$#Qnu&4FiJxPT86+5kVEx-Kc%H)^02c32zx9)?C(6{zfbc-{D!jD59 z?tVIT;HUgzPb1yRz^;jQ>MAn7>ety>)7F@e61|q7wkt+3I6YYee>ty9mkuhTHs+1z zkeZi$Oc9V-aMtFwrxP$5na3jP>mkg3y#&kzmZ=MqXN5L!Fn8A5w-^y(@9|hL3k_M` z`dg|$JpVGP(YtfvVTl_uk4aQFu{$yX^qxy&`gtVGWtqYr9EYAj%U`YXd*Ru#NRZw*DiUhU;yZom%nw}8~t z7mxD1o-B0%f94pwv6q)cr#C^g5~L2rN4~@f#MT2MVO4+IC<*$Ntzh-t`4!w0;Bxc> z^ znzTc5TX^uaZwV%1&#R`f7tJP*>6&dnJq)O6jNvhhf`Pp84DRy*8Nw&U;NxIk$lV)M zLuZoHeflOM%R8M5SmwT%=9bg%*YIPy-DT2Ldv4mX_|Do|JuSwyudA#11!mXv9j^_v z;iSU=!9YG)^i%-Bv;8mkFJnP!R%q{ji1^!DVaGHHu&$eU#ZdY~egd~E+F?z zU{fD!j?dEFA`(p(?~;QOJKlSLQicG!)#;zib1$ibe9dS)!sI{u zJt_Dvuwj`nj?9{(={vC8F-ubCzueVO?4-65f&fZ#!=grBJx)fr4;`9(fFro41+lLJl-< zB7bye-yKJ`l34=gCsc>oHY#(&PpVc%&^&2rA`>X}6QUs_IkWq8MY1Y7`gmOu75S>8 z{?c*uJ%xAekBG~AtZKOhvlVmO_vXO#lt3yt{&>C4CejmwnkD)!H|;@okBB`_dfB!r zbAwLqFzRCBAN}ZaK1Xf3kx5Xlit~H*8`u75Wcitd^JIOJL=_$8cgetNmGW?-ox5ZO(o?tYSV|x_N{gz?s&bBoO76g+K1D8sp~Q{-)#KtHUdgoS;5)8iUspK zV}K{Yl$Lv?a|4f3UnX|z*fBQ18Lu?_yUda#I@6gcCAFRk{KWE6&&0pBo8fH+xn<4@xZQS6 zBK97RYbOv38rmy^PuxiBl1|iPYEwd{Zd?1Kh2_-k%3SnGF=<^mp}orOU;0}o>IAjv z`#@%kW!oPbOQvo^`*~tLC9vtr{RbGaouHF{wB_xnb5zZ~*~4*rZr(8zxW%z85D>i# z*{X~tKg7He!nvKY;OYnJH~n4{?~>NN>0S|Lr8a}>+RY3K|7-_HJXXP=wog+x|J}@J z(z+;S3RRjL-E+tT^3C++ON{z|Nwzq7NZVCrcpdKrM1%S3IoCCo#7Z4 zmN17Z>Y0o>OW-Bi$5WOmLA*2NUyX4@&;MQ=l1h{39Onx3PFiu1A*af+?doTSs{1N3 zG^NBc!6_$;=&SQic!DM%5TEQW*V!O1M;{{x`q(Hb;X5?*UwG8$9zzc8`#D^Cr4;CAub%3wsuSy=Q5^VxP3Ee|krnK8sfmh{b2l;C>x4)nKQt8TreD6-k~mLA}OK&8cdFX4)L z?eeR`_Gjc;oqowOKN^W0~SI&8UuZzI@*l?iM}B5)Z)e7j1a&PW%lKIxh(Uf8lK?? zCs(pbHSvIXpEw?Iz;v1ZL#xXsIpPleKSkEQ;vb~_6=gFF7IP)9GZ*awfd@LnQqG^l zaUYM@lO&z?K0!XyC!LVK+$#E~NS8ArFaC45rEwNi>^NPFch)TRCa(l-sF&@j1^r_;xb+lBAdn$7Uuvo$=>L$oa``TrATSeRaR??eeyOl`un zd(Qqc|L5K+EoVzo@x+FF)Vxjm>zOq2(DhfBbZbj#c->L-49dzo6JA%g7@z#fh;tx0 zB!A*r3+{^1n(4Q@%4(39VI}LYAE#c59F6~uAW&I|5i~008*#ikPrmQ>(a|r`(a!$t z)x&Lg(Xlmp0`y2e{pQ!HUF~~t^%QJ)P05wfJ~o{Hp6Rtdn{fivBCP7L>9J>jxcCtN zr{^|*#>>cs?dC>vVHWU#8BD$SPS*RE2>N{G{DeVqcK>mDhl0sjLNhh=#FnYgsbZ7F z^9fmkJ!pJHRni?G>_w9u9~G>d0N3LNAH-0DHG#Enia$di5SUfef%YwaJv3;qXU7&{LW$EU8uY} zi?IbowxT4cIe{`PAhgfPD~pX)LWZr|^+KGq`#=4ki~&Ketqk$)A%AFH=3@eg=`?dYftI? z68*}(8uNPZ&RwdeOuki`H&s)|Er_Td<&*r<97*|X6tjWJN>!Z;@^W2{(^E%zapF8E zoO}@`hNXYOKYhpt>D{e=fv?shKn^jUuMLcOrE2=PkNyh=|3(GN?}0g+uEeJcX1qU9 zN33U|aO=J6ZE90#;;WPOeA%Ft%CJupFWa~JT_0n9TlWrAo1`F0AKJJ6xZOYN8xNv- zji(+_n>>}$Vkm*GK@&r$`qsV9-sHmel*?sh