From f2f407f6a7e84583d4903355012b3d996ef07938 Mon Sep 17 00:00:00 2001 From: Matthew Kight <70612402+mdkdoc15@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:47:57 -0400 Subject: [PATCH 1/5] dummy commit --- docs/test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/test.txt diff --git a/docs/test.txt b/docs/test.txt new file mode 100644 index 00000000..e69de29b From 0e00916fcff410babd2131e91850eb60ad58ef74 Mon Sep 17 00:00:00 2001 From: Matthew Kight <70612402+mdkdoc15@users.noreply.github.com> Date: Sun, 24 Sep 2023 20:06:27 -0400 Subject: [PATCH 2/5] Updated specs to add challenges --- .idea/.gitignore | 8 ++++++++ .idea/cse_491_fall_2023.iml | 8 ++++++++ .idea/inspectionProfiles/Project_Default.xml | 6 ++++++ .idea/inspectionProfiles/profiles_settings.xml | 6 ++++++ .idea/misc.xml | 4 ++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ project_specs/team-1-specs.md | 5 +++++ 8 files changed, 51 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/cse_491_fall_2023.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/cse_491_fall_2023.iml b/.idea/cse_491_fall_2023.iml new file mode 100644 index 00000000..d0876a78 --- /dev/null +++ b/.idea/cse_491_fall_2023.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..5cb71ef0 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..d56657ad --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..663c3710 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/project_specs/team-1-specs.md b/project_specs/team-1-specs.md index 29e5d500..90c1bf52 100644 --- a/project_specs/team-1-specs.md +++ b/project_specs/team-1-specs.md @@ -72,3 +72,8 @@ modules. ii. Params and returns will be added after discussion with other groups to see if this is wanted + +#### Challenge +1. Creating an Autonomous agent that is capable of moving around an interacting + with the world +2. Working with other agent teams to implement functionality they need for their agents From 87d3539e9baf14b0e2350a538f46ada2442d013b Mon Sep 17 00:00:00 2001 From: Monika Kanphade Date: Sun, 24 Sep 2023 21:38:17 -0400 Subject: [PATCH 3/5] Monika's version of the agent class - 9.24.23: - Added some basic attributes with potential functionality for a_star_search - Added attributes to decribe a specific type of agent --- source/Agents/AgentMonika.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 source/Agents/AgentMonika.hpp diff --git a/source/Agents/AgentMonika.hpp b/source/Agents/AgentMonika.hpp new file mode 100644 index 00000000..8ead81e7 --- /dev/null +++ b/source/Agents/AgentMonika.hpp @@ -0,0 +1,32 @@ +/** + * This file is part of the Fall 2023, CSE 491 course project - Group 1 fork - monika_k branch. + * @brief An Agent that will walk. + * @note Status: PROPOSAL + **/ + +#pragma once + +#include "../core/AgentBase.hpp" + +namespace cse491 { + class BasicAgent : public AgentBase { + protected: + std::unordered_map a_star_map; // Map of the tiles on the board with their corresponding values for a* search + bool isMoving = false; // Is the agent moving? + int intelligenceLevel = 0; // Depending on the type of agent, mobility varies + // Measure of intelligence; if agent is an enemy, are they "smart enough" to be able to use a*, or would they resort to + // another search method? If the agent is the user/player's agent they would have maximum intelligence. + int healthPoints = 10; + int mobility = 20; // Number of tiles the agent can move in a given turn? + int level = 1; // Level of character; scales the rest of their attributes. + + public: + BasicAgent(size_t id, const std::string & name) : AgentBase(id, name) { } + ~BasicAgent() = default; + + // a_star function here + + // could also add getters/setters here for different attributes + + }; +} \ No newline at end of file From 558a0cd8dd7f365d0bfc4f4c1c78d95dbcb3730b Mon Sep 17 00:00:00 2001 From: Matthew Kight <70612402+mdkdoc15@users.noreply.github.com> Date: Tue, 26 Sep 2023 21:13:15 -0400 Subject: [PATCH 4/5] Added A* agent --- .DS_Store | Bin 0 -> 6148 bytes .vscode/c_cpp_properties.json | 20 ++++ .vscode/settings.json | 64 +++++++++++++ source/Agents/AgentLibary.h | 136 +++++++++++++++++++++++++++ source/Agents/matt_k_first_agent.cpp | 8 ++ source/Agents/matt_k_first_agent.h | 58 ++++++++++++ source/Worlds/MazeWorld.hpp | 3 +- source/core/WorldBase.hpp | 11 +++ source/simple | Bin 0 -> 381536 bytes 9 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 source/Agents/AgentLibary.h create mode 100644 source/Agents/matt_k_first_agent.cpp create mode 100644 source/Agents/matt_k_first_agent.h create mode 100755 source/simple diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d057157c1e1ea4b494c834490c67d55c64e80c3e GIT binary patch literal 6148 zcmeHKI|>3Z5S>vG!N$@uSMUZw^aNf&{8hq&V!xH=@@T&K6v}F+h4Ka_FPY3s$SZbs zL`3J8-ArU6A|tq=Ty5x@?VES3mk|ZRamH5mhuwL*X_{jv`*py$Lpe($7dbuhZG%Py zr~nn90#twsd|ZJnv7_ +#include +#include +#include + +namespace walle +{ + /** + * @brief Utility Function to calculate the 'h' heuristics. + * + * @param start point we are starting at + * @param end point we want to get to + * @return double euclidian distance between two points + */ + double calculateHValue(cse491::GridPosition start, cse491::GridPosition end) + { + // Return using the distance formula + return ((double)sqrt( + (start.GetX() - end.GetX()) * (start.GetX() - end.GetX()) + (start.GetY() - end.GetY()) * (start.GetY() - end.GetY()))); + } + + /** + * @brief Node class to make A* search easier + * + */ + struct Node + { + cse491::GridPosition position; // Where node is located + int g; // Cost from start to current node + int h; // Heuristic (estimated cost from current node to goal) + Node *parent; + + Node(cse491::GridPosition position, double g, double h, Node *parent) + : position(position), g(g), h(h), parent(parent) {} + + // Calculate the total cost (f) of the node + int f() const + { + return g + h; + } + }; + + /** + * @brief Custom comparison function for priority queue + * + */ + struct CompareNodes + { + bool operator()(const Node *a, const Node *b) const + { + return a->f() > b->f(); + } + }; + + /// @brief Uses A* to return a list of grid positions + /// @param start Starting position for search + /// @param end Ending position for the search + /// @return vector of A* path from start to end, empty vector if no path + /// exist + std::vector cse491::WorldBase::shortest_path(cse491::GridPosition start, cse491::GridPosition end) + { + // TODO remove the use of new + + // Generated with the help of chat.openai.com + const int rows = this->main_grid.GetWidth(); + const int cols = this->main_grid.GetHeight(); + std::vector path; + // If the start or end is not valid then return empty list + if (!(this->main_grid.IsValid(start) && this->main_grid.IsValid(end))) + return path; + + // Define possible movements (up, down, left, right) + const int dx[] = {-1, 1, 0, 0}; + const int dy[] = {0, 0, -1, 1}; + + // Create a 2D vector to store the cost to reach each cell + std::vector> cost(rows, std::vector(cols, INT_MAX)); + + // Create an open list as a priority queue + std::priority_queue, std::vector>, CompareNodes> openList; + + // Create the start and end nodes + auto startNode = std::make_shared(start, 0, 0, nullptr); + auto endNode = std::make_shared(end, 0, 0, nullptr); + + openList.push(startNode); + cost[start.GetX()][start.GetY()] = 0; + + while (!openList.empty()) + { + auto current = openList.top(); + openList.pop(); + + if (current->position == endNode->position) + { + auto location = current.get(); + // Reached the goal, reconstruct the path + while (location != nullptr) + { + path.push_back(current->position); + location = location->parent; + } + break; + } + + // Explore the neighbors + for (int i = 0; i < 4; ++i) + { + cse491::GridPosition newPos(current->position.GetX() + dx[i], current->position.GetY() + dy[i]); + // Check if the neighbor is within bounds and is a valid move + if (this->main_grid.IsValid(newPos) && this->is_walkable(newPos)) + { + int newG = current->g + 1; // Assuming a cost of 1 to move to a neighbor + int newH = std::abs(newPos.GetX() - endNode->position.GetX()) + std::abs(newPos.GetY() - endNode->position.GetY()); // Manhattan distance + + if (newG < cost[newPos.GetX()][newPos.GetY()]) + { + auto neighbor = std::make_shared(newPos, newG, newH, current); + openList.push(neighbor); + cost[newPos.GetX()][newPos.GetY()] = newG; + } + } + } + } + + return path; + } + +} \ No newline at end of file diff --git a/source/Agents/matt_k_first_agent.cpp b/source/Agents/matt_k_first_agent.cpp new file mode 100644 index 00000000..8262af1d --- /dev/null +++ b/source/Agents/matt_k_first_agent.cpp @@ -0,0 +1,8 @@ +/** +* @file matt_k_first_agent.cpp +* @author Matt Kight +*/ +#include "matt_k_first_agent.h" +#include + + diff --git a/source/Agents/matt_k_first_agent.h b/source/Agents/matt_k_first_agent.h new file mode 100644 index 00000000..7901c6c1 --- /dev/null +++ b/source/Agents/matt_k_first_agent.h @@ -0,0 +1,58 @@ +/** + * @file matt_k_first_agent.h + * @author Matt Kight + */ +#pragma once + +#include +#include +#include "../core/AgentBase.hpp" +#include "AgentLibary.h" + +namespace walle +{ + /** + * Class that describes a matt_k_first_agent class + */ + class matt_k_first_agent : public cse491::AgentBase + { + private: + std::vector path; // Path this agent is taking + cse491::GridPosition goal_position; // Where the agent wants to end up + int recalculate_after_x_turns = 5; // How often agent recalculates moves + int current_move_num = 0; // What move # we are currently on + public: + matt_k_first_agent(size_t id, const std::string &name) : AgentBase(id, name) {} + ~matt_k_first_agent() = default; + + /// @brief This agent needs a specific set of actions to function. + /// @return Success. + bool Initialize() override + { + return HasAction("up") && HasAction("down") && HasAction("left") && HasAction("right"); + } + + /// Choose the action to take a step in the appropriate direction. + size_t SelectAction(const cse491::WorldGrid &grid, + const type_options_t & /* type_options*/, + const item_set_t & /* item_set*/, + const agent_set_t & /* agent_set*/) override + { + // We are taking an action so another turn has passed + ++(this->current_move_num) + // If the last step failed, or we need a new path the then regenerate the path + if (action_result == 0 || this->path.empty() || this->current_move_num > this->recalculate_after_x_turns) + { + this->path = this->world.find_path(GetPosition(), this->goal_position, grid); + std::reverse(this->path.begin(), this->path.end()); + } + // Return whatever action gets us closer to our goal + if (!this->path.empty()) + { + return this->path.pop_back() + } + return 0; // If no path then do not do anything + } + }; +}; +} diff --git a/source/Worlds/MazeWorld.hpp b/source/Worlds/MazeWorld.hpp index 23fab2e9..2c4e4a55 100644 --- a/source/Worlds/MazeWorld.hpp +++ b/source/Worlds/MazeWorld.hpp @@ -53,10 +53,11 @@ namespace cse491 { // Set the agent to its new postion. agent.SetPosition(new_position); - return true; } + /// Can walk on all tiles except for walls + bool is_walkable (cse491::GridPosition pos) override {return main_grid.At(pos) != wall_id;} }; } // End of namespace cse491 diff --git a/source/core/WorldBase.hpp b/source/core/WorldBase.hpp index 0411023b..e8ba91a2 100644 --- a/source/core/WorldBase.hpp +++ b/source/core/WorldBase.hpp @@ -160,6 +160,17 @@ namespace cse491 { if (id >= type_options.size()) return type_options[0].symbol; return type_options[id].symbol; } + + /// @brief Determine if this tile is able to be walked on, defaults to every tile is walkable + /// @param pos The grid position we are checking + /// @return If an agent should be allowed on this square + virtual bool is_walkable (cse491::GridPosition /*pos*/) {return true;} + + /// @brief Uses A* to return a list of grid positions + /// @param start Starting position for search + /// @param end Ending position for the search + /// @return vector of A* path from start to end, empty vector if no path exist + std::vector shortest_path(cse491::GridPosition start, cse491::GridPosition end); }; } // End of namespace cse491 diff --git a/source/simple b/source/simple new file mode 100755 index 0000000000000000000000000000000000000000..639e846a933f2681a82ebab9f15534f159f18718 GIT binary patch literal 381536 zcmeEv4SbwcmHvdbHl?r=6s5{4LHQ_DB^4^s${LiB0U9Yn1wm~E`K(G6A|M+`NduXV zqg@59qLTFk;-X7*Ed;P-0<{T#20@A9>VP6AQe+gC20{9No^$Sfzvi7Z1$O_s+x~v( zyzl)u_uO;NJ@?#m?>+BN{_@B(Gc%cnX_-uBC;aV(zm^%9Oi$O|c*sAjbMH8osqude@z>Nh!kLQ(mM%RZchU**B3i$kfa2bPN``+ga8;HrJ^%Cz&kyS- z;jL&!XOR869)rjC>0xocbVXm6Ep{ zht3NTOu}39b%VE)1H<2_p)hav}=nh{I1feCb<{ef#kyEszJrq|KGayZ&?UWRI8OCOm^~=Z0M1 zdpf)_g^T|H&#_ov$-zhV9e;du|FPW`{4q}{_SrV{q#?uw_?$Lx-fQQ-7D%0as^ZxiEuU!x z1>)t8zv#U4PygU+-{PvEbSASO{)o?-kL{FcMGFVGchYyqza13VL4h3<*g=6E6xcz5 z9TeC>fgKdsL4h3<*g=6E6xcz59TeC>fgKdsL4h3<*g=6E6xcz59TeC>fgKe1zea&2 z`ND(wm7ANf-NsF1Z3EO|;B#kSRFRjz`<{p$O^i-eO zy4A9a>-qfWY}1T8dK)tM-Ic%c%T*0QeXZDYIe{-Y+S-`QHcqW=L({*Dx@bcpZSa|G zoa@?H$~Hb4X+taSZEgJV)7p#aZY@zPO%9 z${#Ol$eeM;8L!RmwFj;;>a&s4o<_jHV zEmr8LvM8Ph^WDQ|N#ikuzXX}NO1{)7$Qa3&Ix6y;31)PT$UC28^U25lA6u+OvKVrq#_>48k*zgjZruZEG)5P(Y zDHW9E?PG=9J?yNU4D`lx+Pu*NT^Hdf@Q{p3FLX5c!<~viuU39J6N|ZCNK_X%ZCdB#U3194}%8P!0n#w1zvxc87WYnLtyXC6*uU*gt*p(Z_2w+MRQc7s& znoZjJXujA!mM`Sz;x(vi?g}Z%VAc{Y%RFi8bKmwJ!oj5!OSh!1~GxO^vbs_bh&a z6_2t0j@`lfFX2B$F`e}{06ouoC55tnI1qC7i34PhEo^vL9vxN$jP)O3-)dO@_DfU8 zr}C48Cr`mn9eowDQ7b+Xh!zE z1a%8N%c!049<)&`F)3f@?PX%Ab5O1U@wJuD=);09S_6IZ(V&6Sf|4cn%KL)Epw&LK z+I#b>*y;_P+UiNQtuhI%uCZ2o`ra3M04m52&Em@smQefpq5ZwiSp1-f*kj@pim) zOG9*KTjNEbuaNtK%qP&O>@ZaUU1xy$r0rwco8=&a5hob1Sy=8$@KPIfjsTP(Gs8W-_~CKC@#8}|Dy>0cq37dTQM)JK{ve8+$0Eh`+U=sz zqO^{^mxC{IEH$_dAzViv`7i*i)<%1KjwRsYjBD9z5W3htk$=NTwx=23S8JwPV&F9y zLn~%I5t6P8(ZR#P=j`k>d&Z`*D#r7S&jD~Sp3jmQGl@4Qo9^MoGADd#m3iSyqx=(J z+~g9`7myG3+eeH*AV9!)ff^SSRYh&&$q;Y76j>$?; zjB_Ml>BLc5@Lq#8;AgO74VLCY1|qOPl?bc>SrEcwHB~ALC7?NrMbm*I%m*4 zYMXlt)MNzKS{VnC9bRp0vb10niyZW^3$WDazv;iUkD6Ot$0Xm!=`mPc@Dm5P>7+VyCvtkb5i%r}f|MSZLsDjl@dcFUFV zUpp+|Tp1c{6u(f^xv}y2S{>yEUAaD%>jx+B&@|&^poN_0vIdw1D>nyOR1kv-;*aDN zo9b}ox>$~i9uG}3?gayc>;Pk_cZ>`jDJ!)orKgJLYnI! zF^Q1)E?{CWk9C9>hx6hfTiATo&%`7Vn95jas36?0ExU{Ve# zo0;37ULV5Wf$(d55P#ppUv{rHzg}#!@uT*A8ROzC@DesWhS1fwKqLyfhN#L0d#OMm zgyxL=ClUhNU)R)J;%>2GATE@^&bMYVi&R#J7Zo<;yEip1D%_rj`MC%yj_#qwN3k`o z7FtY>P(|xw9hgV?;u1(WbE#Aa?-m6k28{=n^INclDIHcqL3XEqY zM%ObfkP2JtPN3%?uX-Uy)izX>P03JdR6yL^82)Ro$jjMYu^k8n+`6i4GnrcfdwMo` zeIyGxDiiCOU_Ax@$uS2{o_{fJ986aK`UR8c-v<$ztp3$+nmqrMw@jYD@W|SHH<5zo zYt&za_w4Kl{S)tTUJNt@8uf_4o)73rr7DNosGuS6{(qr{H^YATNZMwZ{P2-Y`rAD` zM_$bYC4anq|f!&F5*)b*;At4x(t?WP77N2G@$gQfs&gzC{WXPAaE?VmtmEGAAOWusc z@qg!FB95g6<9L^iEa?VU&3xItInuul5JvqoFvd1D$~BnP03TD-Fy5QwllqPh@qKs> zX^_v}fS#V3C4z~b{)mZm6S1dNdkK4*1)qbS&h>h5)59g|yR)TM=v_xbdyt%ak z5PfIxrg8*Y3Dg7@xn92*e99A+W+2W4ItqCLpm`|gr4Qq0vD|~+%h&K(o`gre%bP<03`buL|NS7K#vDd5n{&GO5b+lSKag}b5FdExuv@ zotB2=fEI3=`tS!Sb09p{qWQw@a)Ie!j7ZZ*rhgTmeDP3e)D;zQCoIzy@%bZG{(?ri z7o9+3(FzIwgXs_N_#_=)g+>n9>L&}h%Tx4G5py-I(d7Jv_S<^Vz0Qf=+!p0_sbh<- zH{=TeIn&@ZVuEdiM~tdy71WVB79HfM&ZVnzKE;W~+6kQD^7+#yL|sAbt4l zLt>Y{7vbw}fOdj=Lx&aDP=pQa*T}D-1$%SXD1NYM*1#A*u_dV4(Z4!(4QdP?k=-yN zZzH}1HD0ZAMQ_NK(d)9j0C)zSyI4`-5cX|tpet1xP)KW!zl$ZD*Nw}ewDr-Lv@cgq zjLHL!B_Tj5c{0lnJeyW-BvamVhapJn?*ahh6{^QbTk?5d)%66cmtUNPmY|cafp4*n zyehLnKq-RKpk~$82HRBBSbZ6)d;0*ipIDu7Gk;S4O@5A0hZKf^TT&I;#};8W>&^Wn z-`!b-;S9Hm=jp`wdKDR(abV~HWM~=e8I}7upBHk2XmBvUFjvlg0zP|GYezOxwB(?P z$8Zj-GzD1+p$wq0flT%jFuPETlQ_^RE*X$76Y#>^Kz5a`UcG`hL7f@syV=%j6$xk2?Yq9oT0n$s6V7z~ULave{U$x{5l{>VG2W7tXq{~yb3#|`kSLu== z(fV)>-U770Hyd@#T~o+?oDC~C$FD{XO5uM_m1|`qSd7hvo^o~-hrG5iezt!CsYuw0 zkt>BHAQ(vUN%EjRNnRF$>l~e5E^N~A57_9nQ?6b}LFqMe>KSwlrR&E)xwyGd-byWD z%DhIOa=wDR72EvsKe1j2>~mlN(UljU*^p72tXdr4ppnhMBpAOhM+zmuOsXQNzP}@0loZu@9YO%Yb^t4HD3dJxVd-K*XYeXN-QAv=;4w_1>Q=c5-;BrjDPr- zA#%fV8hfww@b-@Jn{4yzr$BsPXh>G&I6lCH8aF)(T$Z{NGQn8v;f4HNjxto-Z^~rD zwJ^+^s6Q+iPnZu_9#d+Q$wDo>W3)}K4I1QJKAX(M#!D35?4V4@&)WWn_)evKZT)b( zm`zk6uOjp7zKS(yhhKD$3l_+50rnRM2Ic>}$LVlM*jJ#(B>2#K3m)=cO#Ta^KkwKq3x zy`rOK+WQ+at8>Gq$J#=dZ>5m?73K|*2Qbb-n~JPk#uZ0RfAhr!@4~jFbg|(;9mM;G z^;5#$UEL0|cV>3OpRlJK=+J2Yl)qj-UeG)nD)L%l;#-K(kMMQ8Vm!#hL9r-2^1G^* zhS!TFl(q4!Ca$WxkiMaOB=o80Z>&7!E6_EZ=~Pyt{(=x5aopdS1Eq*T$ypO~xQgimK-4VOOsOMaBN~E#&f1GTBECvmu8q?8<;r9Ib!csc zRQ=%AH=G5e8+D%T`pfBqe6h}YO7pSBRXn^gUz|mwXlP;@*%{2AD^%V*KHN%vE9qT? zdmcWS;!%yRl2ZOMr;?Ee#NSA&f8OZaFPpU*_g!-$m(m)Er;Ry?$-!Z^ zf}42Q%ii$rl>OxB{AzO$1O{Du^FR8As4>0;mo!xeyQbMK$kqgIDSw48fi~UuQEJn0 z`~~9~^G1^lo3jdn=kJbRUrO z`B2D#CD57=X&t4z-0)tvfc2_>gxg9A1%9jXZ;=Jg;w~3*-_N(T#T*+QO%la}RcD@f~F10da z=r8_Y&JT?@aG&-vw~`_;CdQk!9!d;V8jvuGF5nL=S;6WM-*D)*ZCl?^KNipw`{H#g znwEp%BXdeDIp0BFEKcyROkZNa!_Q)gqJ3DHt7KQ5X#Ffpvn@Rb(bkw8Y%)KHu_8}F zNR?flXE+a~JR2Kd7vY!Nc^s270YBu|yVzRy#>L97QTgG!YWU^PKRPvUBHu5J83kPW zWq(S#s&EWl?xDd43Zlw2Fb2>M2w4l>%koKkhvL%$19FKbV6g~?EqXr&rj_A`7|EA% z1B;5-SlMMC7!8oVBlc;O``H{NfF!5;bA{DLo4P)MdEKZipquu5pQjsP@C(sbyVNDh zXK-{0p!$G)RXF7F&__xh=BrWp7YUDxw?=so2VdA#mU)+l!XQAw@s4`-;jLJXn{20! zZ$F=6Y=`-i*=x!9SVwfip7-{E>F26kKnYUQ!NylD{3ex0FxKo@EgQ!tKEIPFU>0Zu zRj+h+&v4o1haSMBc^8t=DZf52Lb^FI^r@OX70gE@ICz{_2VWPkuCceai(c%{o}6G{ zuigc*2Ft5*pe8_xl%QES?7vRxP`9x?;8`IKfo3j_({^@QQLlP`O}De-SWy`xs7FpWSTV{^4H4?@ufb# z$zb{UM()LXR6cF~gA8DKYVIOX60|-D<$`sX)48Igh2|n@QHA8ipOe^-|Dk*tnP5UL zY{-7fdk>=Y6{yx2KEq{bIb9(6<1dGARS9QaFN;}ZFf2{{t! zPFiRxF8GaZe80GjI}`0JuCuy9t#%v{2@X>IJfiYU3`qmI^HfLKExVBU5gZ~<0ICMYM88VLqQI13jrebB_QgegSuWhtr zD(3na^XO#bHL1Ugtn4^+M8F@?6C(%5c(G9koGWsN;!n&Vgl3_T(A?l@MvKw$5nT_G zUh)uCUPS-L$NL$aD_rrR{<+X{et z8xxXwhYmzQUvMl2X1@61L3sYqrMM>xz#%-W>AwGAUe2_BMLMo z1K*PB-_UXdPeT1ldUSVAG-W^Q)mb{fqT~O*<2iu2i&f(V(&WS0zRCSsH@}7Ojxpw;Um?D1E08tX2#^`flN^rr6tgNU zRjrGpe*jtV#HH*Hw)y_xcT6rY+j)!%UCs$#%5vC*N;h(7QkKI}F7lSJ+=%?F8ZC$Q zvDXIhXN2WOuw_I)VzO|3J2cO@Cwb^!;~p7kL-U55^~Dy;aVFE7c8k(`PF;_pvpqT&g5aPqsN&UWDn& ziNG2s0$unmXAiJLhQ$tu!jiSXzY8MJo1N><9#*ou(fiRS@H%8rVE{q{hB$dxxsmNr z21EH%bEn^lVO7Nk%UpB?oWr0jw2$H!%*4$py*1SiYSHb7X%u`ev=7+AjT@6wSlj6q zBUg&*d8w6$6=r_@jo`C#^I{!V>qm6qyMB~EI$(RsnxgY2iQ@48%=I2;AulTS5b7d#L5K&bOLj86q?HyGn-&#z zkF3n!bu{N!cCu%VLgOg!X|~5MJT}^6FCLrpalMsWXJxLk{1Wp_e{v{0TI$)-eBr7V zt;pW-I<4y+Z||bzH2^$jk8AO$cV3I@t=u{*bCu*Xr#j5S7@KWfP{>3;6ZcQinb!xp?iV-awt^^a^x|L-@CV!6olgL=u?eUpI{&LZ zLHe*8_(j)vI0i0Ffyu^J1+BuQ3f3EoeS0W83ObCrcFXwXyf~m}^Ozp??J-gY{-Ic?27^IJqdkixgXe}QEGapZM!!v<3`i4wEV)I7wO)-0`0BA z-`Y9?R7PzQ2>s#0q+>+7RcKWZyi}n%uTaz%-Y@UfF+s?nNC6tA1aT|jB!knpYwPLT zX5fPMBKE(x?`BgB66=*%S@x7x+iv+nQ^Y+anzGm@VIx1Z|DyIJZO+fq=A<;xJ-1q4 zIJFCXx#6a4R34g$ukG&=fOF!*$aMZEQXhYGC6WvH>n@X?)ztCK{%Cplqq>Jsjt;4C ze;v&vG*pAO-O%2xEC>Fr6gm*EGhp;yrVdj8X>e5b7cK`QiZ==am?x*)ewjiagw zh}mhtEVLh!{1JH!JrCxj#F`phhNgktEj)YV*VLLSO1gx;iRug5*eWM*MbQ7~CW^%T zWc_#R2|I6};t%ob4f;8bJz{F>@4bU^>GDSZ%VhkxezWoyvK`iU`ZS_HT6Fv=emW08 zwp5pyye-U0cGV&5Jog6qc$IaHgBjBXwe|0R2(us@pK*J@=FzX%I7Wpu`^DyKTVr4*Zj~!pTvsfu(rRlk zq+@oa#i!nHmpL!UY?X8QtXdzsnD$Sjx^b~O1w`C6)cHv*30z`%A>VCPm-P4e^+af& za(3(jO5Q(Z^O4CL&NCQjSWd7wPYz$o@>lH!e6Pv5NaS^4xe>HyO z!X%n{xBJY?9{byX3=O#+BaWS zONI>GB#Ym$ZTsdscgE}+qu;Z&pZ$0PeN*l0?a0?_1GV;Igg$D2jmhyOy6!4q$Z@G` z>khM*)gudQu2V2tZLN_p_FR$fB*HXlHgqwAB8!X8bmPwp6w&L_t2di<(wFDMU# zx@l5--uXu`m_vHig$E}WHTwRb;iUTg1wej>e&3q)*e%Jf#YJKxOMrd!>+V9KnY_;3WIFAvQ8xb6Q zi`nl%Ih@A`vL>_NmzP`VTl$e%Gi~wp2IlX{?Dsir!H()|+kW433ikV2g=y9xT z-;dkQ)|eWK-NPfODiXEtPr}_}HJ2>*1%2syBq8d*yl4I2rv67~ux$dL@WHROWnp;B4@W5>E&O@$Kfg{YUgZHJ(j$ zescbuq&=NJ9;a$g-+1fuu5YoI>-{CYR3hpgL7$WUl8b}PR(TX|o4WpzZ{J0Tdg>CZ z@Y`jl2l4J#OzGphp1))p`fKe&3K=9$@jsZ)03!@XU$M@#^`&}K^niA^yW52V*fc30 zh>_`zL|RHeQXJOddMLtQwP)3T6Z2Or4)p~O1mIvBZWdXD5H~*z$`J2lSQvzgtU~Ms zP^*mfzn&XtJHY7(Frosq)CkTQ8>P%#LUW_hQt4#S;)C`{9^&6yFsgJ}T2| z<*jxjWUUhA=fTUS{MJo!ft{paUZ32ec^!R`OKb9k7Ql$M8(5?AJp<71(O)??K%ci` zu+48>!0tURv~59kzg{fMOL0sVBwi7AD7ew~jNWL%HMTALM&so~=%4DZsMX&|eT4P7 z?X&pxe`3EiSzg!Y{{Ax;{i*wNT#vi?F*)9Y`74xhRr<;MC(D-zEChG?BtH%uju~ZvpJuy`;&BkU;XC6C^wg9!U^<;Z5OQAdxV<2;V9 zkeGhne`9REZPD>!zC4~ws?2}lmN}>@Z`)s|J=|Y|$%`&m{Bcn3KH4mf9q~jw1Ii=% z9_S}0pLxBYm9gU)wf z94^)H6gcciJx)=x{%Q{NiL=R69{t`W$Reki4al)lbKaodeLS8c<$b*C81GbdG!#nY zK3-ODy5;))eY~yI96C|C`*?rUgel&~JDkde6lE89AFpDy(Iz*3L3XkfYJ&Iie&_R| z_wjz>66N<#D&hN7CT})&^wE|3O-^gFSueh;`uwt zqnBIW5Z&BE!S@LG zoGtgjzBqUm0IQy?oqvM) z_kZyI$MJ}efWbNn0T`3Fg)e3Kg~lii?|%fopNhO9EH@(Gij^D52jxVb@L7@LM!f&A zJXck>(2dO3ZC!t!R883M{!E*l|AwiE!r7*t zDwrO2%_Pd7=9qp{$f1s-86~*y>1Lr?e);*$@mCHt4-3$u|3O~@r7+3)TFy6eOyKMa z@r%fV_L7rycNs%wO6O})E`Gk&2$-AL)HbKV8Bpo=IPrNZ1t0b|V1#2vD#c+7IHJYo zW7R^e$1}rrj`=t+4Lg>_qrk^}6EIT~qb=Cq57sBj8`i`2x}K{Qc8@G##d`Lj6B_hq z9#I0}oPGdUWeu_hTv3o{C=UXb*fK5Zn8bPKqEGUuZl_aF( zx4yo0tHF2kPjSYk*K>73`eVVtGxWJW==v4Zz#O$Mo;${}4(~P2iMbZtz%#C0G3dq4 z6v(2h1Sh8!?Q%tXQ54ThdQr4renUE$MuvclzZNFK+x`w^adFuPm6HM?8eToa{y zvmWb4*lwgZVf`lawf2k`I-LDCDP}R*>wDSwQjIZK%l}fY72SkYON9lRD$Th*2E{G_ zh+rO6fkdi~2AKO6FF|j(Z;~JFL4u*mcTi;1<%I@QaJCrwDD~H*YTX6gBfHD z^3#kSSI`GMcT~(5X5Yi3A882(smLRAgSoNPg`WEJQiKQL0)Ig<9hPGlmiLBZ{$3p% zt8@1P_*j0+uSr!wh$&tc`9`du4)}9^`A?lQD0Y9tWPxR&n7fBC4wCavR94M1!!j6%XeZy~ z2IL&~PL$%~D~6As2hbgDMi+GP^4*&qzu6D;^+eEJ>7BS=VW+GCi0%oyU$KZqF^-je z;136u3W)`IIFh=)WZux4@)akX7P8~I-4Ea3;Snx`X4mcYu;qT_F33Fjzh zR7CsUUo@fFV1NncPG>1OgSfbBSZ!Q)u#E*jey!`=@yOORN28zMG$`IH^7gC-NJ);5 zP+sZpI1_-qrZpo3MhFy(<-pEDI5owYj^n)TT z3i1O@Ac-wH9nsmRVkXD7;RkIwz8|xlSg}{W=o9|{+OTt_nP_1h2GIB+ zBmk3sshx;`f$W5zX5d0BdqY(=e$(%u4y&oAq!{j@=RqGGl5S;9CDaYiHF&Jw|A`k_ z#-`bwZXv!!`#e^mXD-v-cd&@r3dL+#MzD~#j%o=C1pV;QqB$#yBm$Rr>gy(zixb#) zyIt+&qFEba>Kr_cb5(oPYzQ6?=BuQx@d$75pUdL8B zvkqAS;xnGn|E#klnXAml@gc4!9ZTQ7tK-vy9C;ilPxE2rMvfrS{9N?+2hTE|Mval=+}J&>wcb z6!Rp_pGInJS`AKJ7Iv8#d<6qZ_@Dq(uK4?kP$j-U0X&@_A}ZIa!&`QJdG5#_fr8?}r|4b)RUEgH#&cjcP z{CXwCclLg)p4_hq^B3-)mT&Uq*91EMt6d4v0gr5`+P6QhSNfV6klipU4xWy{BZBo) z*xpk(u@aBFn`Tc&+EO<;C{u; z+*{4_{Fg0{681RDds@JR2fgQDlckp4S_W(6&wd#)Hw^@{u~8#W33zmMSpcM@KL)Ut z1L?{5x98g?%~$;m7OUcyf5L-JdWsn>`iDQ8wtf!zwI}N)&T#H=Bth`;`GV4ts$7&P&^(;moXK>(83i_@fCzQ3#~N})tQP?5X!{|) zMS@P?8`ZbP)bSh2TQFa79gM~o(%4V|indq3{Kb=$Cw=?}p12-QbZXgWf_N77;m@}I zCB|1vpnp96jQK?W0|qSDGL4aV0V(o`zCv7wQQktd#OEKQAIiWMaP24bUr7ILnccOY(9z3&%S@={}PYS6zDO=<(%Ee#VU7ldPK%M2IpyvrN-eN*bD6M zv!}L<=Elgq=T^%MFb zO+JkuMVhVqpkw z&V}ve-k!H>?kj!n8#R|`4$38Lb|IqZUFpiL*3t$MA9hB~U~zl00#=Ag3p&F+F*)ECmNURyeusdWK|s1FH+%`7uT18$S8fM!kf`Ckn8`*T z%f72I``V%G6*j6VCq0*$oB)}Ld;|KbOIW!FwR?N^M;%8rlQmo5t}Zd-iMz5l-btG9 zJV_4UTUI7bg zfF-XUB2|a}@@C}i`q4}S%D#Ju=_C2Q@5;{ts_KLQySwrw{f4%T(L}W%YKhJ^DjqHJ z8MGPAk`8q-@Ti0vU{`8_hB|WvUD&f+-*_`6+q^9CGY7rqU(pY985eb6n*XAQan(F5 zi?IeM&Q+kFMF#VZR^}ORXiRl-z+sM5f0--n{3RUI7HJKV4xPeyZBkNoQQZVd?Yw1lijWV3<>9Pw(xKo5RP>?zFt9q>U94&X<~>B5RrXc zlfP1L#d@Zh3um!5SsK&?4Ou5+TBcP-X{zZFs6p9XpL<5a_Sf+lLd1xH(qY;CVRjFn z(RBmdIQ~W=6eU$3^NF5TghSb{X!5ajsvQp^WI$=pKUSrxB{TLE(K) zi@CUf9sT)|`Hl+f*AmmKHFq7KQ5vqpB{#`UnwG1s){`cjE9mhxmt*IXnM}IB9rF)t zRBkQLgu$Q_cKUh)^H$n?YI8gy3kZcwm-J2Y1%fg#QF}ME?}|Zz)O&9m*_8u`0y{_zZp&Vuu;1oGn z*+=KjuC6#e^CU0W?orUk`x2VIq0`gX%1=V#@m!5w8HM;u~GFRrxoAiv0csOx?GFp}f@{h;r{fUY4w zgZQb?BOr|EkOsI5YJk9rqtK95d4V!1H?k==j9zz+*a?azO|>swGL&EmF?I`` zUGsk``ze7eCZ>Ka6Qk=Lng-RShsAPhvRu3VS^6<(nj!8ygWJ)sBi$g z$^qNd*4O}mz*uJm=~R7MQlD#)YBJv_XESXW;*iMz|Ar^cjG9SPd5xCKjyCp=xy+8@Joy@>MZ9EI0m1NHGt9n)GxmZ&ZG#(m$uq)93?wHi_it8YzqG>dWUTLB*&%xA@kg>K={K=D;vBy(@d!*yfTw;janh z?bej@%2E36Y5uYl|AmeJsn9>_A5y|#%ww*WpZys`vCSHWKDG1OJ6}V)5Iq@sXoelx zZe@z;h!}t5C!a^gkjzMory5?UYDJTctJ@##y1${9=TxHmPf`2={}tW*;5(JG&1#AP zO`Vf2!W8@90eWmJq1Xzv8?y9D^L9ZVKN$R^cGex-VfIsh3 zrN7hDvdx@{yR6g$E6MsTXcKtgsFr@agmCa&Tr%qYVUX!4J<(pYyxM|56mBb}r^?vK z>RG*wd4DXRdm}JNna?JXXG~v8ycGI1p?#y(--doBKg}GZjPN`aPQk)#Qac(Sn}%Y@ zjL$P3*4X5$%-V+Cc=R7RK*PhjWAZf5XkqN?yv?|rm%9xfa0jF1sYd|!3shO0*O}j4 z&^H_aX@I5)yhV1?1^l^~chV?Wle%JH$Ev>~cTcvLCv9o{jM5IehfL<%J$&0JivW(V z8}XmHCccjp=bCsjUwAS<^rX5b?t7F_%r#NwYGl^19BW>Mk@3$dWq{p(>OHJ&V)tE# zT{*<=yTqsLu`Ba!Q2rg@h}~d--K*2FJ1hme_1JX*=^@sg z@zB`vepJykD&s$*yMiAJ;k^Fn<9GqyGs#6gRLFycBqFw4I!EDgb#d`VWx5`` zqt~=5d5iNrfN~@@bWm1 zJmlBxZA3aC<6j87I3kC$9-TEkb`qLBS7g>GGOsjb))+D#2}(wJ{MZ1FVmFA2_#@Kj z41Um;-x3oN3P@|tUa!8B82U^II!iVX&#D15#BKcnfPL-!YxqRhkKJs~cef5biT@9Ra;g3MZ(lE*GDZ4nJb&nF5U=8hC-Pbwtw^BN z+9Z13+Z~l&1;9=}>D(HLmzQd2iJA2bL2H2V(HgcgH%-}~Wgq*sloNu6;X z?vaK5fv|qmemzFW;NWVJ*{?^dHdg!9eb4Jcrli@g*)_||{we$+*-O&fbD3q7yvHX$pxXfQYD_nB9^^4cfQGMs`KbU&2(RUGk0vArwuDnyI$@zxmp=$6o z5ULz}gywlI@9E+DYP9GAr$Txl4?I{?b``C1nG7~t(0&S4^;X6eBBp-y*q>FE2(9)KIi3>~a{Zsv4N zm;7UVa3A{gI6$(4ljz-@RCc*RpEoG)gT0JTxobi(_nkuSo?`AEeE3H8t7I~;SKG!8hE9$AM8~%XLC*1uAU_W2k?&QW=Pg<<&~J86bFoLD%^`|Zm~FdAoL`5|mL z0^$|$^^=KMz)BMeO^hFkgiX1Ju&MMA%!5SssNZRXr6{;ZtaUJ>=$Z-xLWRL5ptybj z{|h)g$pXZv`@*>}9E^53DYid8JKtQ$HwVy>(tT%xB~n=Gt`BJMFJyn!b_nQ6+cu`3 z!}+PYx{+w~avw7+AJzX+d-hUDJEv@JyBW{?{AKd$=W9KGpR4xf9+E|!Cwjr<8*})ib##7|t*g-fkks_g z+Y9V}+Wfh#d^a9J1M81_FShOD$Xz4>g>e#`?*>(iZOz@48Pt6)s6coh zBB-zC<(UD`JUtgHe5EJmj5_h(RI=5FRFQl5!ow~u{@dVvfy%&os=GV~l2*ZVGp75W zAogO~qNeVH_;1%35X65Q!=Z(!Jgf-uQJVwt->mFfO0b;qQwj#7a%lWFi_ghdxN(lw zymVF;$Q`G2ToH>MT&f z+yqfW6a$Ev$g)c*)r8=cd0Rbw&>V~p(mX9b$z#F1TC2ZP{j2@b21^C~?U#G?TX>wR zFhC;l%#MZKuZhJLAYGO>+dH`I;+efx6F7pn(!sISVtW|}Dshw}H?XMKxJcu$v^6p| zP@}A5bJP;-0u9qw_@LVOE^@?ZE0*cSye*BdVn+Lz0i~wR{zpqK< zfpaJ1R<0usI{NUV_s8cjrEa`p2Vb%PtXEt9$K#=e_|yFXJ~$ft`6J#Z6$&|KjHl8mKmR zB*$NKz)#A!DhHSWhu+OGmhg9;Of9;+vpUB%>x+D?nJ)u*B3d=_7R(RO18V-(8IK(A z3nvtQY`*E<+!h&+V?I9Z7`2_8W9o@7WjTzIJJbu!ULXM0ohB~m+*`tOBhrD-=Y-`L zOUso*y!Ei$sKz5n{a(`Y@*It~ZnFaBm8gDuKH|Z>h-hpx9$bm-L)SwQj!HACYXIx9>R7oQXQFu*HLWr%#wH9^8jnXdzWoBp%$G*nDa{ zIO8ApiS(3i1r=d2x>LIM{wU2p^y?Y=6A#8Xv3aI;{to1`&Uw(-cmlQPOd%rBKU@Oh zhYMt#37vo^=Npq>j}PyL{RcbFyJ1|*UK_rYPe}On4)BiKcf{4%Lbxb17R&eZr|OqhnZxZ@+sg9u3;GMfU}YYJF@ur9 zh$t{Y)Z;LfcyfAaN8L<%mLtT^+XoRGK``hsv+2Q(ihX~+u6^4a)qk=@?K5?eRpk$X zu{O!~n#1~PqtjObgY#Ujf~?JY_JkCzOiaH;KvfR;|Jadw;r8Gw{U{W+%n za#M|0*KkTrytb~`tZN;mz`Of-hBgoGWP1b+ddsh>5!oLvAFFJ;y3vs7K{ROHRpIbb;*^{>?rwmVu zPf9$zms)UDXi(~hJz+W3t~ZUosvq)mFawTFF&^F*xe#|_vkRE}^)ul?AfWI5C*tAl zk6=U3MW5JwT{Zno9SxCk`@79H!Nu*Rn7ze0J&cFvoL#B&omv+fnk+dVsx1S9glE|} z&9?&=Izw~QY&HOXP6MDi;Kk(%E(+aO+j*0@s>^n>7vvBLZ z=y+i~JnED9cxw*Ex7jP0AI(!@|8d) zYS%yBp0*hWY;KiR>SmxV+N$wC)UE>iC;uLhc6is2qzUqe5{?A@6BA1aMuSN(j`63D-sRW&3L=VMMOJjcB15Z2=H zfCID_9FkBM-Przx+K@w-=!9$M+r4mYz$zIK&?l!+g7LZgJJQEzs=qCQ|F-fu9)VPo zJZ2sYFsMbAmlgG@Y(O8J=D@H;s#60L*2|8AjCgvqh4jE2Jp4m+gT&C|xvS1(J<=#Rg2^rC_N2@+2i zp+xVui%GEHd`&(6Zi_y3&Zouo5#~;L(Y-{4;>b>lOyfJ|e)c_fF0CTHKS!23m-aND z{Sq(Sk4nNfxl-aaTFkXM)bPbN5DzieNVw^@k;)qE6oiLMek-`=2Sn|7P(A8TZ@g#x zN|^X*`oGTihlmg3{mx}5+&|-lI{$0OD022Z@s~g23_H0k*|{^m3I?)B<&5m3BiR$n z@(7N9umCFV);%2( z{Rwz2d{-?K>iZN}rjO=23kMCy{1MK70FIz)#(wDf^5f6uW0MDz;5?hdTho#X{-apr z8~>a=>2{`!;opaWL)Lxe%{rnXc|TP~`s&<6?&fV=UL1XZAsc*g?|Q81 z=8pV1`|j`m8G$bDR``3mL=#Rc@$xdF3!_J*SyH4t0PdbbI6Fn{pxP|@#;hMTZhC{0!#_Ul9JP`pA+ ze*JtIwQqQTGalD2w1*r&q3Y4J{)_8Z4-Zml--p1Q5cg-YKj=5|=cz3m&qtm+4}_yW zh2CDEUqe4#`_Wy8`9OzSjlQh9^$}Vy;a$J=Xx%&RX!>-qUHX3rD% zpsel*VH%2!cO9QvhJD=M=+9w_{SbW#Hig`MUPCE<-eyYlO zT3C%G#3Z^8W{e6T-4VoZcbv9>DD!2E8uy>|9S3FZXGv3)HS)GNkZH3A2OY?=f;{pC zDt}}0Pdq6a#*6$D2a1mudCQGjD2NxS@t9%AoWsf-Vqv_!3?T9~hp*B`8{?y5uOEd@N znOi}hg}LpHKlOTr5yqdoTv4rwKXnk211+b=K2Mw;=rZ(5O}GB-h(DEC7m!sho5|;? zgi~szq53x$e~R(8am{d>@u%LY3JW)U3+v~gBXaV3%5;g(PQnh+*sG=Kd5B7v$?uft zqG6kjF8csl7-otYxDeUHRM!SD)mJ9(f@FD>p|3B&ZOLaK#wlT@vKVUqE@v2K>Ow-d zFjIV#55vEVoy;aYyXnry)M66XN&H@4G)rE~-A4T)mkTrXnwtqD7mq2m0@VvWA0QBh zA-V{dk2lec8i^_8;xk19OY>PpG!awk0A)xRQ%d6>L2=mm9V;9SlvH`f8U_Oek8+V7 zE3&vxMNNV-mu@}%gZ&B3oh+u5#kzumSjIjSYGY~@OIif`n(Xe*1gOjY<(vtS1VkA7 zNi4n$;(=pOf)-2zxKU>POp{vWHQIzJi@R9(Z=m;UBHfov=8AbK3o6!^%Ir;`}My~?)fjvk20rN8qF3#&m?n8pqETt4;*(dh}1yb_?WR4s<-2?ISt<{g(Q>UR5uA%z)p)a#> zsG95dSMk>nt6Sc|mor%wDu$~R3%qMJ{rbb%1N6~2gRKsI(C2Q%XF4)y+xMqAnBUcA z1s%O3<6>=_&U1cf8S!QD?iXkHk@!p>j)=wAtbs}5Gwln0`c(kpGdW<%_)IS+%wj1PpJ^7;%ri2T_)I6Gco?5) zkpi>`Rx3C5VMK78;7sJc-{2te>zzP;RX)$e`2?f6=Vvs(S?c9S<#+FIdKi<8FYx!) zm-}+5<3;5o$^Ynjp~(7><$CLd<*E55pJv-)e_G4Xtw1TM%9(sOimP2(>u(C^Aqrm` zkK%9e1Dl_^!7cVK#%dAB#?}XuttXbJmJi$CetRDKfqkluD{5??V=rU+@sk?{g%Bh5;jL>9shDaMT%3wy{hP??qmj)a} z29%JF*&Fa}9S|})K8i+UZ3*eQ2jk{*mqAY&u>>{rPk@+6Ig; zN|jZ72Fp4txQzF98c7;<0tV(m3ekN>250_Xs_(SX<`UmqB24-|PxVei2MRqcMpY1? zqhB`nqy6G~O~Z^m4OskwN!~l;KNOg-w-&3t#lZ|;KEBiQP8+pV`7TW#XA6KS$RD1N z>nzdwW6J>!AL!$pU{rJ|4qQQPl6Uj@V04|M{z*bb1JkpYy~Q_hJ;VT4H$j7{ga5R~ zd$sW_xYCJTMSPmIVHk1^fU{k1#-S4wSSEYL=M7+kZTCe`CXliX6QCH@5$1=>DAwcY?CG4~km@*uoe*wr$Np3(vX# z^YGnG6md)R<`Yl<(&FKJkGc~HL;3l`(s3QoxH(dc!)HRj$rGvV$*(?+8hsi)FHV2b zk<^39AqncL`PL|NnQc6o0L{3+H6eQbHHil}ggREFDvWZJzj^=pKltpsN4|E4cEC|N zKd-a0VIHU`KfhLCLzp_pHoSr<8#RUgtU;4Gj%bcx)?$`q{+ed(yPqGx;xghmoT%~-bE*KG1tor zKDR{rse{D`R-uq>;NGP?{59<=X;d*)_zO$nL^1)QHVWf{Vw6=JwJRGix-;@^7MtcZ zn-*=7PsfU)$}}Yq2}R*wqpi^MEazz}BUKyq3b^WTGmN2 z|0UKqIYMehI{AW{PCous?Y4E&L<5oMfLLuu?_|+vN4+G0k&)s-XCXD(*}kx|muqY6 zY+u;f0pvq_K{dz57YYrcxpG2A8-}IHaPH6F7U3#x)l9=BpvS)gT;hVia$^?|4EJY( z^$~|n70pzc$1=hGsrqsU&wfqo!;OFV%@>W1u!s&u@tcEG4tXU#dORctA=gO;O7S^a z5~2lqSV;=OSUzk4bGs#>h&sPl5gl*ew?Q9+o6h-(Ek-$*TAl;WcG(-{m6iYjQ?1-2 zyIBGmOEo=5%%P&58kEB9SQx_D{0gGWkBNL4R3kA8et!bLy1ATU?}2{s*LQb5jtR?M zC7VEH8Q&KeqmL7C&G*3&o?jXoKPW$cq=x_DenkC_0Jg2KoIDjV zaXntlJ&yFaKI`7REXF_g@dSh)2Ky9M=tYj=5%3C0_-%mC2O0%N*^5CyIrd+bJ(j04 zERTn@CRGQa4G z1p6OBeO24k(gq{OuSkD_^70hE3O!kSu75Fn9RE|{O|5*h_BWuB`np680^SkdN@PDh z#P@ot`WpJQ0bW%XW8C675y6DOY)VYUNg3|*Xd*>pgm?c}%|c_Fa$7Uw-&TsETGOYr z8Ye`Y@35Cqyi{cqRt&+$!roRM#kh%tEvAt#WHP+<&8;q6WFLPY3XJ0qc+$pQ)vgtC zV;1Lj)Z*NR?en0X6<71P>`|xL+yL~cMMvH9=y*T09MEo9oeMtx+y+J@?Aexp9$cK7 zsl5x@8O}Y8|1;yd1x%BZhpX6!eUQqpoiewW`&AI9!7ZLUUc=)fp}Z#f2R-Ke1;>6# z`IGP$g#4R|d`u!=Y9i?QLY0BIzejZ>#vX8auJL)#H!(vuQuOI$`e1obF-kA;Bh(2l z96LqJGXQ!K>sy*}{;)=DJ`Cx%kf#=FSFQD&N&hYE$^(h*nPjN`C8*IQvBqgx8ikOt9Tz*&vsFS3;g^%e(Uy7GIVoDC}o4_kUBo-Yi%L-qz7K73kkF*i%%QP`z}@!L{S)2R#xU z4{aC^k@A6>9<%w6<}uc~Pkt8dL0`KQM{``;DeK2j{wI-dOq*^v*VrpT{q3GVPk}<7 zY`iT`&0ieo1GV6w09YsDtLoY=^KWGv@DmSy11N|O? zHn1b$Q#n}gDUf(P-s4!WemvgS88T}O8IOdnNv0By_c4A&UD*KwvO9wzpk4^gh}@+m z+VO&JJ*RlQuuas24DGun)lXcHJWMi8VoyAkn%@%YH`+bWBRk^dlE!g+mGnJjiuC)N zj+gtyB7Z1DEkA0Fx9&|N%lmVhWAfnb$?U&S!*EF!u_s@q+7g!W&_ga>Zk{Q&rx~N4 z{07T1xR<6)CZD%*yD%ZYldLbiz4AP-cZ2a%=e|Mhc)@Cw$mNThg-Dqld#VX9>-UjJs9<;JlFhFN@@Brly^N(!gU^Ge5f)#ydQS^Q8i;G`wF{l zmfUZSt{rJF>S=v-62|?v{_INBr??~D?t{IcF^u?!D>k4FxXVi*F)zK-1quD9~vvVu0ql%G@?djt-v26-~Kp2VLc`L z7E;f@Nb#*K;HK!fe>Q!-NhzOP@9SFj$VTb~Ifdn&j>h-f-OUJH;8o?P7=7{YxBn0+ ziZ2cf5h;vII#A;NVW)rfPF;7I^I|+dIzAV^Tj9j?aTH%0Ulse*L{yJ3a@w-v2Bigiay^fjlsFK&3@Au; z2Isiwxq?l(8{m}vWM)$j0?}^G$oDR1h@ubSSx3$45+CQ6pBQTB?Ku&T*`66_X&j%W z0pJB2xE#ib2f1;&*R2K}VDYWbjsfXVc<&71@v#=3u6|1k&NFyx$KR7opff*OqCT2)(3*BC4cDhY2$xxl@UMNQVm*pCDo}Z{o4T?K2zdLmC90%R zCK!Km8sz?vt%ro}eRYkO4l83x4w1S;e|G&oes1CUVtKKp*9@$yl zOWo4-r>zX3ug@;y3DZ5;c0bm`z4C7IcFO?P)x#TbDQU5%k%cTuE z9yPbPPLsY5@}RZ)VOnnPV8a*5?vHX+e{< zz6RQW$91H^TG!m-I!#(+t;5U@&V2JZY<-Q~2VRfAskZesGQ^yN!qx+NfP)E)nhc}v zPa&hE-|+=fbBNRjGD;FHP+X@;Hvuk4(i}mG&jC{Q9pJaJ^{=ueH%g2umbo7@AyNr6 zCiKMkf(Aol8G#no1A(pb;MQlTDYZaxohG#y8jTS&_#C3a`tse&(2|{sw884o(9CO? zxvQc9t8(Q=3XdMQg$C{75Nh+|r#W@}lxFPu74)IorYl{cz-quD4vYnylm>JiBs}f5 z>JFlY5z{@~DmSr7oumEy*rf1juix6Jd5QTx%zqg8PI-PipEPodKZp|k>3Qub%x`Kd z(6(@UHS;mmMd%UYbFuZMF22{#2vIm9&__XiPLkn#ypbeJ#dp&AHexR+JhM*#_@98B zDo+E-b@}zMXOr`Fq`vK6)UKCRg@yQ=JUBfnXOafS+$Q;0(59u#8O}Y9Bn&KsKrbz+ z%0-C+&BM9PP-<^Rfz2o&8b88g-E4<<{|f^!^oK_A)rly9Z!~}TP9aH?_=o$?q5bH- zZ;5uJ?bXV^w>LE&qRMh@dD6#!TY~m*qEpT2ROJ3U<|Np#NqcrSNmm2EC1pI0irdwN z^Au;dxUGzeoP3h}_J-Loig3gy^NoI0u(bMI*Uw4j|05doWWboAM7}f&iA>nD_31rz zdcbvp8Tr18RPl_-3(;~NdOX+uLZ3`JKK5YK7!C4T!$E~BqK~5O&$A*a`o#EgOx=9Q za2uMz72G7p{6;ep@m+oZjBMERa9$AK z@*=NH0d+y_c)&KrXb^f){2aA)6w}^ z7qOVCXQ;4neu>GC-H#_fQs(15cm8{vk58ZVzi>WY1N(W$d@O~T|DE&kF(1)!wqrj2 zADWNvTk+iKU8{fV&&SK32maQ!7t^PhkK5^%aqCXHN&S2*Z<3q^z$d;h)S)DIbBSHU!+njxe?Uf$M|3+WFS+A5K8rgHPpL_f-wPf;-Cn5OUx?8!g3pxgxwleIBKF+Dd{4LMTAAhTITJ6e z(CX-qZTNe1>8<_{l`${Bp}sVGb4=iwB7X1`!~FFJB0gb>NZ_&TCcj>6p)(?~UQE(I z`JT3a<^2_I{h07?gz~)H2vB#ulHUIm{-X!M_mqE*6SscVkCw^%SHYv{?fVFSQ^!MX z|3ZB4yTmK}bosvZ$@=-GFDAgVW$G(X|4HQgZEjIl<3I8E`ug-UocICoQ+ZB_PVQ&c z@L$_IfOSj;#Kkw^rXp5ICB$?>po!o%1SB9u9;5Bw4Lwyao|)apsp@6}mx%ZdkFdNK z`iJ<;n>dg~*_jGj_cZvm%vJkZ9z_!It!#2YblAWdk#DflLPTrqX}6@Z=qFZr*N07hgW|vsQsHuN_ogP@l;>CF z14u8?YD>!K-UwJRA-_cK_^XlXChnkX9d1z8QfpG`W zgzB{Oh&Y`zCPOvjU3rackd?W1T4=1lNY;qKPxvk>nMPt_E%Kh6-NL^ zn#Qb>Zy5lzRgs>j*|3Xch4_45<2&v(Zpz&RR(B3Uaqg~zL~pAO%Fh&0U%n48`s7~~ z26601mFq>O%f+vD2ZHtt6Tinb!hqNza9 zf;yS;ol(*2RVZlf+;+t0TXj0xHL}W2Np3*cTHeN8g;Fcg`kRZ-_d4K@y9e7HpYN6r zlGgR(^W8$;Oo=X>&m3L$!Q=MD=Q|J00R4D;zV`yRl=yt-o)O-js2`v2E_i?;RNQ)Z zB4XpAs7Z{^w^t}VHss#U**zMcuXMI1Od6l>>x6QLjy~4_2HPQOCs3%lQ=aeE14}rJ z@u;e2D@S+t<|-Q)mW|VN1Zd%CFh1MTM_9Z&SfE(acO2biq`XnBGc3KDWiWYeB#21o zpL#OHfjZ!ebZ-<(`tG3U_v|#@o}DrR;0qk!gY>sYqw}%BH)}(!as{F2f@e^cpGAnS z@lEDG2?F|!^T>-wh@-QI5d{_b$JFvG>AS-uqs>J-pz#2;QP%)M>K&*RaZDf{Qtwq- zEG48K!x_rHn!C=0HiXrLka~w}nh&W*jm)zPcJgV9p>AGPk2e~WOZ zEik!i$~*gMCR<9epJ+QVp4=XZ{OykS_5?rbfL)Y$yf=+k;=>=QH97z@r)&OCP{wd<}9Q|KWdI6jxRyaQE*{@N4{WhqVwmxaDxif6b zn$@{SY3z^6K9n<~V`}~Q`oSve;xOI+*AgpV?>_f$tWjIMuR;fs`Uv*-tyG7T@Q*U$ z-9ul*Axk@17`ZR=2W-Vf?q731u@1lF2AsG38@PWx_Yt~&V)Uple@o-e{nGW z=rS>HRTbx%^)Tabjx%Rwd>&Ee*x`B+vCr~*!%2lW9jolfBNm1qdlv^(^#1fNY8$|J z&3d)>ryEeA-u>zMr$$ycU(&X5lzO2zB%h!A)4Kp%{QmS`-WS-|Pv#3x=7*kqGYafF z`;^ee_BWI-#p!vP8RMVx*qJ>E8cdGeRPRrJ2!>8bZUyO`znt**3YXlkU{ zH%+0wG~331U#}@$pEt+Lt3->OzJy~SabNcwY~lg&$bH?lOfg$4rtjsTzv2}8Hty@X z`5t(MpA*opTTu3$kHIjC;hYE zIsxh4Kl`QQv{2xmeWmlf9H@PJ7XI1Y3;^1y$b*bP;k_X6&(6>ze)avc3vl@?EZ+wh zebT@>s(rW9KRcn}FY5Vce`!H7(8Qo@Abp;NfA(!^)r9`pYk9!4So8gq8_?AA>Yx4f zvEZ5W&%Tc226_Ho{j;9}4Po1Cw}19!C$Zo4{j)D4Z>B_-W~!uT`~8%=;l}{_asTWF zh;fR4_9u%&>#V+icK#F4=9BtoFGZVC*RA|JW1>X;vyU9F36uI~XMsR9{@E)vx(c+$ zHvF@T?qdVPvJc%jKG3z*;ZW6&ndIrFd=(4C{j)7vXISJBW=+XI`&W(067$b~pS9!u z*?XA;q&}&?|Bt;h0dTT7`}n+ja41N;5v`4i;)z*qR5S=HH>QBMHCdJgR$({pE|;}6 zawxE(@j&rjZ@l9{y){|{tVdI8D;}+>wHnlFv=*tl^8KHA{<(Iuun1cFbr&*Ee(%gY zb06=#^G-7Bvp3p+1|&WZEnJ^{aa>m5s}k2~0Q|v~O{~w3x4LrHX9G64rt7n3T8EkS z*~NAe*lc}vo^{sJ`s@O0o4Y=Hlf9OIefFf0&DUpfpN91+dF1}3T_VOnp^Ivm(B$54 zZt?o+m2XIfHeFv0O9b<-uimc7$yr~0)n3b5U;Rwxk0>RXi7(XvHnG0?!6**a7~d8q z{zYX?*H^E%bJE=P)kShmZv|SjzWOGdXVzC=vI_I8ul{j(_WEjO{v+#!Ev;u^tz6as z@~mgc_@1=;OXR#s`%BAq&bR@ol{HR`=(5d8M)@@;<~4dgiA>7#ori7DSCF+!*^ZA- z>K!WC8j`xh!$O2Kp|{`sR<@Ak)(`zXO2lIupGW844<)f>>mi$(pCUgvU2hhDS7yG{ zs`KJUeH~wuSs`z5CRBQPyTM&+0=6A+?_G&WUfn^2LIm zl4#Ff^8eUoT8l*AIx ztAgdJ=+8MW9eo6$=iy2cV(1&9iL2mU`vp<q-9eTT;(+vY*ee|3DD= z)*mwI*Y#S2gXPy_BplQi3)mwsWfPZrfgkTo%mt@9dv*q&zGgdvJpGgE*Rck_kEE)g zSJdP8k%ZHWX`6nYc9ytpwqB$9v-=O3tH_Bybl;@BGv&8^9(~R4kGIr)^Y}D-{vid~ z!uzJF`qNT>mZyBNZt|S|zO2s4a_VbJAL=6qwA}HA=^b7#6%$3Gr=N$AGpX^wo2id> zf9jgV&br=;ih}wf8#*uOC^;#6I8V0ILwxDd!S;CQ$Yt#lYh?Jz6FJ*^t}YIvgOi^k zaa(_I@oZeyP|;=Jj3udI!F6(|0^%dXl$~vQTN;nu>Hd!MBSZwAv<^tniSZJt^aIA+ z^ygiFUY>Bbvt8!$L=U`irR!?w@Nj%(eNZ-t#1dWFNs49Xs>gO;8*TT6iIqBtBtFsp z3_fHe$FU>zW1{$pgEhmKltxC^cNo2>Q+IpF(xRc=J0u26Co8?aBtdq##nm^$lqEfM z2U0vplKi;*dnr3T##k=8?C)VB;n?3L4>i!41Coiyv^W~%iP60&Z}zc^=o7si5`Sb; z#mx(JlL$)k&R-cq`N&`@GF2Zk?V;WUM=i8R>96bINhS(E^NK`cKLT4)@I{iCw8i|` z2lhf-I}^@BZApp0Yw`P&&F7CA{*pmQVoyy1>rzdhS6cgoUxM27dZr!E+e;j68gkY{ zr4DUseu&DLa_`Gq|FDl6`nwKaUAh(_psHZ*y#(8|ud?CEa^M2wo>ZYIyT5h4En}3l z&(rNaW>VeTN)Sc;Tcc+|g zm3UqJ<}VLx|7A1#=J8GSw=ZHZ79tggN8|;1mF?8C9T3vhRDH4aQ|gyQE77$6rTb&FI~lE8s{c|yzqZ?7bDv+N ze*X^r%ov2U#BK-Dov7ig|K_;(Zt`R*I0td z+!FaMBiKt=0D{;1#8D9UC zjf;Iwv|u<~ChU3m{8=;U^o}f)Jhi7Ou|rsj1v(Vr3ZE5ESzo&zm708rpZ@Se$5wyh zfYgO`e(|L9<|VRRuxJ7HTgwi)Wp;nsx+5i4lFUVRwKdU6g0Ekov9y=ExJ;LW&~NQz zZKSE;*GE!6Q-%bI)$trih@pMjb`gWNwTWM6AeuNO4N|kC>HY){S1wLlm99yYq(R)R$+$}- zCa0|Ql=-+sa0GrNO=69oOB>-t6Z?si7WOM3y|#-OnjUYwdRF6F)J8TP)I|Bo8L5$y zc&U(3z6703i`+cqJ>A7IKU$-qq@4w>Wk;%zB{w4qG?!T&6x9a%xgPDl%L2QAAffL8 zeKrtlXkCz;`)uX68#TW<|EMo+H%>-Vsbo^X4QRj(7~6v~0!trYM`YV~3ylfuy^!7P zg75a%QDceiY_CmEUNm`e8luyMs3!Psf8ca^;vGq;j>u@}Ylbh1qm2*8ey8PKTw@;X zvg7apU3T;y2rD%0;ci@y;d&g`U0rrG7|+Ca@i=*ojX2AXvEg2Ifz7_uc%LZhi-CUo zJpILz(g8>&?rLO!LVs)fOj*A{j>&pQdLDF$4Muu+o4fJEoq7RrU6t4$^MC8*VO(7I zgk+RX9Gmq2ZnibaRtWg&6KEFvOxI%5-iY z+(f3{#6#uD8V|Djd#MTs3$8Z_|KZICXiu%2dlv z6EMqaW&0h7cQ!J$@T}+ZwO^0M2RU9pyesO@TGSupq0AQSI&)mtYWLQBNFX1iQ6>_N zU)vI}Z6^dvZ9kdk7vgfQZH8;n3}4T*@z-tRSX}x#3TEx_FaILBYR`W|t&3+T5;51z z-9&qzwfok!ckPc*C#62JPTJCrPo|x;FrO z?)qCot;ad7G7LhIEKjwU>W~;MmT1Se_|UOPhS^Gz`1}i7%}`j<*%d`)&4KriS?ytX z{j3fN8$t{BuV@bm8ES0`q?_qD{2oqlQSP48#3>=VEEGSyo1_7|<*|JD0LTX-lqTVA$!r2zM|*Yobj^N5vQ zQrYbOFZ2zZ&q%eAe%)?NwrdBrw{5=>v(I$%X;%Nd@E>jQ{P{)5U5QBZ^XEHbuw&KZ z`SbRDZn?d(H!Uci7;k6C*z@Omi7F}C+YZitUhJ~*m-~Zj_ZJ7LThHe6p+&q}}T z!%>&8l!Sapd}Q~u>g`Ok^X8`>hUjzWFT9}IPQ(=(zguoX=BG2P#rl)j^B{QGg88Mb z+E#D#`jmbD{m_0Xz4`i!OnUYHOZqCC0O`Se{V zc_B@3N#|YA;ZR>DcbfNSneu$AD3y-p=}q-_tL+2}9nCH{7a^6IS>p@p_U6uy-=zKd zAInMi=_bP4EW4^?qoA8rbVh;>bPRsd7mExX4}_okK{w-3A?6paC(2|+q`vqvVN}ri zK?~(u;p{}>5xfJn@L3+yemoMx1JZR0Y7e+xY!B34xIk=j*Gs}zm##toYPvjK z`ue=+GgzKmw8V?+^Ai2KT=<$!CWVptN6K8Oyy$!^mu^I1^xYFD&0wI8U@^!87l|&n zOOMFZ=!w^_^njB^3kJZN?bLop)4*aIPPYFTiCkA@b4MT6E?-o7tF?JmY@QOEC4C>q z2!V?W5s+H~y8X87fb69T4d}qEfaE&^T9}w8>WZ5Ov@lUAHWM_U(KaCa&LzTfNmxhZ zgk>-N`v9A$u32HpcMVHl*xW^w+9f-MccVE$RDSKN0$y0X!Ug&8^v~ zGZKjlHN*~CAYGQc6>!|+-)>AC1_Ld14Ho>Q%46)8 z$14NTXX0L}KUQ|?5mou@M495&$ocfskflfbz0#P`yD2^2XZTI}vrPZP{?@gL`F`fS z>?@=avop`?f3oKTPdtEPZ`R*u!g~=J($pU3J4nk-4bi#%4}LWRwMI53$Yz5>JL3E5 z(nnDVPz$iuy=cKgS&);vo1z~WiEvwxUxg&|H8UM6fBA0CV7s4N+joXX` zC(|3E(|}Rw(ZuoUJ&^IfLcSw-ahli{iv)|k9{eVSy~s42yO*RvPLpUzgzxBQ>+Z3NWhN=N>{wC%9a0PkTlidIA+j!v z{(fO%$BtQd!E+>Gut^+(tMC(opHSjx3#$_+?rY5FU3RoL{gAp&z#q-n7j~)Az0WR$ zEEp~kp>^Xvu&#f~UcwFaJ#ewg9Abkq(7tZEq)nbjqaf^8ePU2#L*~X)y|j;BlKuwD z16HiCy-$DGr0?hL?YWjvel0!N^TyW#JsVe%ETCcE!#1T-saKSO~u+CO6I-i0pT5K<;W4YW`Bn@XR z5{~41G@Py)j?y|cnm>lOC;OKy$)fvJ!_$4+H|&$}ENMFij%QMFD#LX_6oV+pb< zP%0g-h^4Pk3NTZH52OYoS5 zXE)S8l@K*ww3qZQh>KTV+R-+s1#7Lgr>xDA6+(#~ut}G6Cr1=o`^3@eC1$k@8X%7= zm-JnIIO4HOIv({4to5P=YcwnoiT%}MH0#ntz4WMDTJn^&S+YVXu`D}yytXgFi+$pL zSS&^beFV_u=@lZ7`48aPU1EMJ{8YuY9&Uh#bvH$ZXD`L}(sesa>goqghYlp= zTipF5Mm)eQO{t1Y*tMbx`;jEXW8hkgyEB4Cwr;=(%hEw{?~P?2Tuf#zu8{9Y#WMKU z;+}w%rpi-%qqxN~vDXd~*#(J=->2j|;`Vci+r5#LH&vE+Ny4fhbT5WcxEU;N7Ny

e5=o=ALlbk^G?yW4!0wFhh}@Fs>ks}ncLTnO{rRK~4IoQHP0 zsC1>hP+z)oQR#d2rSIWEa$@LD@GJGd#OiipUwlhfO*sXwzVzdHYuYU;{dnChP^z5Q zE-HNuQO7SEp^z7se%uMmZA@Frp?tzZWY)+vl#Ih+AnMB-Z9^dBU1UtJS4my4 zYkOYADDV22D^*`KCvYP_1nJj#Sibw`X6{k3ekU1YXLe2RXEWi;I$}P3o^<&6?w`xL z$yti&JV1dV*@J>u0YRIZW<}>(h{y3hq)GHZv8L*5T-IFVurRyiXP3+qiLOwGbYe=d zD)EiaqO9usCpOr=Ii0hThxyhs=pO5VtDAesJHO6euh<#=S4-zb zrt=Ryg3Z3X;iHUE{|1Vx2veg)TGU)_k-_{-rn0Fy{Y`e zFF>G!!~Ru?c&p9}b*Jl_uA#`XFMgY3_k8v2>I0#5N#7f+=zKH8%L&VBIWn zhwcuKOM|k%2Ze=0=8W9Rq+1R$M0(Cgmp9wLm#r_6I7#)1*Lb3v-8s*lX3na_;@reS zCz?dQ_L!UAKWs&MbIK1}sG7E)9DDRNP3?2eLzHzwEICOZfnr`g40Tp&Eq1Vl&E)S&TJXc(ZYm><9-<$Dh^Cw0HYZG^4&Vks1*UBAoYS(cr@wr&Yy9oo25*Kod zn@luf^p%Sm7kQc^al({F1Xi>$yE$u2qO096i7ic^3>4>ha%{bHun!})I}X?E;(L1h z)bo0oF#Em-^7I6GVz@SO+L5BdR&$9og2C#MtRTthxbshAp(L&lXQ@MP@34OCp|^=e zyQazoP9>YL@^8nhHIjyPSS^v{+uwC$VXaNfg8y~);Vu`9J7A+;W) z{dY3Y^CP#0Wh;>#*T9Lyd2*JLQ8(45=WiMx`@Bsj5h(i&y8m9MTj++e*XPB()|b?L2DQ^ZTfic?7UhloW)}1T4H^hfA=V(cABN?Rv~7O=!1$qDGwGp! zc-H*NeZFkd_5U(IQu7PxS-wVl({_=s|I5r@bw07y_C_y@A3M>+gS2<07nCj%w_#Wx z`ytO0f88(bMjlXNJpD>Qro;1^pC|swu4#wp%&;e<(fX8lqg&eI^Ta>3zQ;uH3Q?Z( z#D8xiBK`K-#0&|zHRp+6C!TW86Yr=QyBsN8llaC4nR}l2a$HN_JnSaTr9SIC@egs~ z2RKiBo(&g`Tknu^=4Yw)Z|~8x|JkDR#7`34R&T0(ru%bDEZq9ORgS&8#s29m)s@pf zrTS~>ds^2&q{DBO`&9aEUupZlWRw2Sla6n8`#Rp{sr}7{MB+h#?DlmwE~JYcPZ%+y z8MGdY0ttCIAgvI;cOm(P(U!N%cx05d9|LjFy)&qxiG%|UR=w;GvHSOQRwD&!Gb_*Y zj_m$pXRIEjc30WXHOIY_2l`QT=TFFLlI`1N7KjYLOJbWIWU}J7;TadK5=ZYK5##29 zIO4j&?l(!z{&1!5>VrhZt_R{FT;ecsjtvBws^iEqfZE$Q{|!cDJMVE;pXd)B|mli)%t>=5`Fj- zq|VMC>O0GG+nnd{+2J)G?=*bdJ_jV0oo16RbM}O-SE(kQsz1&BOMFoax=>Y4|d7yE;or9!6LX-@y1YCqZa_o3@s*B_h)cRBsR5jo+oKVbbtckv6cM!PI* z(DrHXK)&bp*}T5zw3jtYzf*h3wBJpfM=%Xb;^+XH_E(wq-pTKq zra!aypYnj3=M8)nMefQw^k=_h*XyIwyC-&e8DOV;dfvb*?RcAsDjLU_*MURj+C;Z! z;a_j@d7l|uRQi(WPi$1xvBZF)&7L>#&lhcg%cQO*W=d4-;RE)(fjfRe z%sf3wpEuA`tR%0d;IU)&c-6GN$e5K#yECk6Eg_Ia_Kk z94p)2*O&Q`6eJ$k$>gT#{4PDW;9Rxo`6GGy`>lFkKcx@l)9U@Qc+M?V9XFyF4rHmo z*3)?6T6;b3epx)1lqsD}ITrdP<(?MSi!$vcwb0k%e%X!tpNu7njr*T!&C{)UhBX7$ zoM_ES)|_n3sn$Hxn$xUVWzC>9Yphvk&6(DmZOwD6d9F2oWzCQ^=UQ{VH7~H{LTfIz z=0(=L*qUK$US`cJta+t1ms#@~YhGu~8?4!2&6}-xt2J-8=5lM^Wz8q8xyqVrtod7O zzGTf;tQoWBtJZwYnt!t9T5G;(&9|-j7i-3?`K~qJv*!EOOjz?nYkq9aPpp}==I7S@ z!kX)?xxt!WS@Roferrv$r<7NLHH)m-&YB&pxt%pTS#t+#x~#dAHFvS*Zr1E-&2HA* z%bI&z({0Utt=Zk02Uzn!YaVP(dCIzR|DM+LShJTk`&hG|H3wMp2x}f?&7-a9wdS$b z9BR$utU278Bds~wnq#f$v*tK!PO#>Q);!sor&{xLYo1}vfHfytbCNYDTXU*4&$Q+= zYgSn^Xw4dH)>(6=HD_D%9BW=@%^R%QV9lGYd8;*Vx8`zd-et{uta+a`Bi4M-nh#s^ z*VcU0nvYwv2sgeP_ity-4%Xbxnw_kQgRb6G>oQ$KA zJ`-xnYNw8d?pywT}z@ECCSoi8plhaY)cq4|Y;yWBZ)O`&ReP{ z9!Xv6Z~EX7o@;KQ8R5FT(44Wyt%c?;NB9}XwYt!}=IpVy&^%bMGp@W{(COoBG0GBlm6OEbpkrOU3FBeSH zYloYW#*A$LQi1syJYDIuf4{(7@8IjZPWw=yStnobD`+XQ!(kyqK4A#zj?CCeh9%<9$GB?5PP0sEwI_6R5 zDC*v;czl+h&L&_?pm@GxD)6eH#CfCBVM1}8IR)ip!#KF}m@N05On3ZHWO1oE=m^>m zD4v?Om$)BOJSm4yEIuoT-P`re;qk?FIh>P!P4hDkyLRuDi<)nM> zj{S4kRh(*d@U*?O$E%7BKCczyLD@&!$?sp<@ODIdlQ!1_ z9mP{l*k0Cj@72+h_AmN&>3nDoH!1JpzI%ooINHz~Jf<(i!y z$#=B3ql^7!i1bq%oqcTmKI*MPbB*KuxX^s)3~4MhQH)MS=B0wC(7$TE>uv5wVczc) zzwMZZrS{)jQ2b^A1{$e?&lMJbUT9Vq&c*i^ii-bTWL_ycL;Oj6x27G4|4rrZ51~Ih z|0KNZ{FX6D%eNPb_tN&)V97-DtJUo^r@X$4zNYOwn_Jt?`gRH2#T%XCI}6PGf=PI$QBZtYq4`I_6k}d1EIz-;yiqvam{mo^|12^u7TMDq zq<(wNC}T$5U%alsY%JdSuJ-14?RLiZ58CaFy*R(=FcRM{>)7jq?agD`{iXnLe&=2r zJDZiAyW@MJ^I)mN2RVD&3D52~I!@Vn#>Aa{t}QTk6coQ-;M`M?>E&48-NoK?UT$=B zT-*IB$1IU)5!`Han$InyUS;Q(lw0>E^NFo2S4@K|YTPA8WiOMSz?$-@Wi@8ohZBda$CZqOPWF;S=oRJiM&7wxX`~@F|$N*B(BpVshDxX?6bT znDqCQOXh^Cv#P3RRhbD>D{I~OkKik-W|mE>oa8RAkRav+D{yg=yLM{zjA@hHRn>Lw zi52deiZY}D5$S34KH`WY>`jB*AQ-oqi8}(MZAjWnHKL9PBH}$v4|iR)dsahs z(9_Hann@CeX%&;}OiksKsdZ*>ok{EKIW-tGBWh2SNF6x)&^ZU0p#}QROV-F_~ounfy8npLa~qZOlbQ#*D^=n{N|e%JvHl zadX98j*0JUOiUycz6a^S{Cfjr0FNa5-0hf#gN^Y)1`oj$0y2Dv#MbGHy=%x6qk zBnG7h$aopTfi&d^N3KK0AOjU>-6GMcBq1Z1;uv}L=S*Wq+w@UIX)WE?UE89pER1sR=>bVGU< zBHi~vE-|JnWawgJ4uo`FYRmw+emU0bL|$Rc$&h9#@)I(CC3e9>`Wg@(WE3(Y*Kb02 zB5y``B5y-_A;b5fe1umZofzjmk070p(PxlO$jGxur|@$~CuDFX(kc8r(h2EWg>*vt z)*u{_FCiSrIAjbm{ClKJuKx+?f;4X%(;jYEWV``(E8y=Y=zxsh?3nJ5g=lV_Org`Y2=@5%6&NR2 zfVNl&Sp->ZoG7N#$quNO+rh#1DDO_jad$>N-T`i~{u0~WATvyXtE+KjEjWnItzj?t zgN*NO9PfT;i~GS%chuSLaD%=nbRg^w#5MF!(SzU?{S*2o$K4ZlJ&hCaK(7b#Xvm`x z&S1D7Y@G11XfH!>eF(yUOb&&=Qpn?s@eM;*!*P8$+@W7ejxbJqq%rPM#)*xA{aA#D ze#z@Yc#!C6oyd5kYXaPz0Cy)Er{P3|0~t95*H6XuQ*r$?M}+5ITdnUITx%khq8T)gg}PyOJ}E6GYz? zp99^P>9|AC7ebmLgXcs4`H*v=e=g(#W1{s47kyIj5-|Fn$Wo*QeUG^c{%%A*--tZ8 z3I1;a-weJPX};B%z^!2PJq`Fo??700AfJ~*-VI&%AYS)E?*q8@0Is1=3Os`NJpnyW zK>w4_{}l2BeN*xo*gtEG?>VIJH_(qy{5SBs5`I=9PS3;5^TzS4f-ZdAt5G(;!?iy` z&+EvSH^6Vg|66eLA^d*`zyE;We;6mU-k9im#1nl=d;`M!H^Ti2@j&0=`UdLe6sMjJppw4%299JjU<6}DG8v3Ioqv(Rrj4d}DtU7;U+ly`sV*dMxj;QGP1ez4=jdP9F7$MN(9 zAA#_W1Rv!%$)nH@41)d9h}SWQtQUIm2@H0e=&_D*4}sfZ2!9xKkA$1ih=&jH@eIu^Py5Ay0w-Q=#)zgmpUH2OK9@26t28=S+lGjcQ)) zI3DyluCw9hY{x`upraQ30aiq$Z%Lj5-RHs2dGH&8&hue+KEBU|oC_U!|6Jk{f36U^ z2rCOIiztgJ(PiMz6>3k3?!$6NO6f|(9^HwRohZ?*Sl)pWJ3B4AD0igXiE?MkT_|^@ z+>H|56aHKw*>W#(4@z`XmiMGYS7rGplzUVDl+sPP59Pj;`%!kM+@JCQN_2Jjb4hn+ zCAvE+(cM{j2<4%ahf$&%#Gfm4IHiZOgwih9!M-=S4`pAouoCFPlvXHib0oK9IqSxt!{1b?p3*_0ScEMq9KvW{{FJ5lowN8 zLK&vKl=3pl%PFs*TuON*nN|Myn*sY$_C1tC~u~`h4NO)+bD0R zyn}K%<(-swQQl2?59Pg-_fg(Y8KHcD@c_<(A^}H1)Lmx(gmaDU}gI--JE>3Ej>oRyh$ zD7!+bcr}$#>Wx|Hw!X#qjs1r5*xSK3mx)luDGlZxa$W9|to=SJ<$g&x70;C*a5}%A zC$DO9eKmQFm6`Y}yFx*k<3MkivS~b`ydGgZ;+EZ3n;5C^+y^k8ltD^OPsaTV)~72J zJ6GK&DO2IPasMOn@lvM3mHQ&Oo~mEJrJhteQrBPP^_Q&7q*oc^3g$hcCrH^e-2Caa z%G!*!9B9jdwj5~7fwmlI%Yn8WXv=}N9B9jdwj5~7fwmlI%Yn8WXv=}N9B9jdwj5~7 zfwmlI%Yn8WXv=}N9B9jdwj5~7fwmlI%Yn8WXv=}N9B9jdwj5~7fwmlI%Yn8WXv=}N z9B9jdwj5~7fwmlI%Yn8WXv=}N9B9jdwj5~7fwmm@QRILdvGC!uu+W&7A?3}v)L&8R z3uM=(-@WZ{utUbRd@Cq0rg2|N>8Tj0a&&T-m+uk%@fX_?#T+zuip5ECs9=wBT{2ZS{yO_o> zKCj`^)df3zZpP<|9Zlo%olT=_H`Ca?D|B}=jX1E_IR}TAtih+~C&n3o&zbmKhtFSr zVjA6ho5nNUrt#r@P2&ySP2(5%4BsE$@rmQJ?*XQ<2A`+#*`pahBoJ3kR00#AoaYkofe(fhEiE>3WiJ=Hl}SKBu2-oLBG}eG1&1Vj6p%Y8p>I z%{0zE9eMn7q~Q!)^CSQ9c_o0nE;EfdoT;(fB;-{E!k%IpkDY27pRB~SvygAok^fb2 zUu_ycIU9LiYZ?n?z|Ty?cNWTTHa>Gqi;Qz9K4bCu)gse)7d~e! zM%?R7+Opz6|NU8sXzJ5}%W=HU;yq#sMz)yoS$L`0RC!afahF8K2NK zrr;iYV)(4br{G#suoFJ}UTYeAU2B|4kPkw>2RYz6yZ|GuE6Id zd^X^7@C|4W_*{%n6rXSLIpRjsI9uODH-7&KRkLu?n}1wI?TqOa;8Rm4EH^zodBD(` zvRQH>Tj{t_W5@dkrcYF}T-V$0FX^WzwT*!FfFU^VZ32#aD;+z&kAEP}m#Z!>!zpef z#`p7=;!kw+^}}T!e~D*CRpr?;D*VB^8u6Ms#@X8SNgXmbsbX41UB!s;L#_9*o!yU zGA&QsPM_X9O`@mIxQen#(9}YvwX(uV@t62pXxC`JC|s$Rn~DO8QRC2CD}5zueMQ;y z7HYlr3@rwk()X)WJvudRF9JrD>vzAAWn}we)41-#97KtCl#l3Unb{Erus7N5Ar(Mb{&(g z0L{Y4I?r+&bbdKuWOZyMNUe5kBZhu|!3<2F_PNc&NROmh?Kzc~na19qhnBX~J8Z%S z`-nU)CRC58np816)r&NDF#wr+Qstz&sZHv3CSFn#Z4^9(tK z)?RKl4Cfn3nhhkAWNh~L>gD(6oX%=PsK5lLzaP<(m`WrBt@{BLXU`~`=C7;PE2Aft zpx+cd$fjI9)*;nkx-Erj8>YP4q)P(=FoaiIx6sI#; zGSe1)d39B7T~-}JMwg`Qs;Va;!v^?$GiB)dq4Ny2xvlot$?T6HC$@dTNxg zNlw%LqkNhjKyZW6^d_Kr?=!v^I***bt#?jeu{FIIV#Xdy?#Mt{J(OPQWACT5!ySeG z7abq|dX?3cjvGHDr=#g7cX!h&2F^goEkCpa7h}hJ{JrG&edLyMl=jR6DywV#NOeWO zDHV0_!ZBrhT}jEb>M6J(s;H@{t{Kv+)Hh0R8DP_ET1C~Ax~Xb4v?SxDSM`iKfAwU4 zOo{43X{AD#YWpn&h6|?;6e@Mn>eg|0^N_~W(QInrj|x&J3K30=wmN+y-JKCRh34{y}+)C{?U+ZHurWKPX!vYJs+QgOB) z^~=t^N-K5gAvI6TUHB*|sjJR7P4xq|O*U293og~O)XhyP?NxDhY5Asf^{%L%obFrl z1=deyu2ZT?$CZyucTRcTX@8T|h2?YAzr1>Su&ky+oQ?18*L(Q?o#`vO%t_V$nhHBZ z*4gdM|Ft~8D3R{JEBrF1l(u@5NzY#G==wiXZ)AFJXZAHS%Ij>F=`71GNcSoUR#uc( z%&Np3B;%;AbR;^rzI8K#xD^~ZZj`+pLw`5cKSI{^@CWOh!Cp9LNM~l_y4>^G+Y37b zm{ft89wLH8ZM&8|{zM&oOQ#<{!9O&3d}_Jzf2VjbJ*k);oQ4S??@Rso4HQhprqs$E z8ggIqu!UlR)n-abC!$h32*(yfW{p6u<}0+)(usPD_rF*k1N{HNF7`)ocPBOCKRV3( z81mr1ZJ7BH50`j+^|E@W}|D)n)q0zLJ zN7nE2`CIYiW*f}OWCchj(k(rJD#xlZ>~(S1ZY0TC+6AYcCbjtJNfclN!~UGK)9ejA zvL;=+jpkNAjUs(TRqpoYM8x=9C)S6|i!!6uUAB$(5Kim4L z&W|ILH!&ubZ^3PGo}AvY4med;x9+C+N0FzS?MSOCX4msVN^_SMH~-iTH8ZQj zlU&E6ANg@uS+3o7%BJTmNVno~V4is4K@Wbewsae)8W@~`Jrfhl%Fim@`gq}S8)giB za~=tNrvx^AEXPe`^5ee~XH2%wSDWpeEbSvd5G-YNW_G9CDz9133GKRlt30(3$*i4j z%^&TS_N&Ft$C^2kQ+NU}F;7f4?SE*m+~*a|x7Xzfw5GOnTuue1ujpOWGs#M-sZaTc&tjUuzt@7SNschQswA$R>;y?eqy>fQuaXXiiw^^j7r{{^O z?NyuI1c1pW{t&6-;U%YNw$;vrt%+26V?zF%D$nRfua3lLlB=B6?Mv3!y=Lh0Q)wQD zX>oR%`=y`1r#5cqcG0Q5^qJl8(A3{PIH;bJc|4EyKNFjgW{$&dcptZLF#+ExgaOmb zX8UDa$O@v54FX%l5XM#~VPN_JOI8TI{Uec(((IHpUv=MXdYV3s;lAF?O9B3pX72>_ z;XE;4*7i?jEjD~@Vb-<~mCV*t`|RkyB{umg#ej6B7_eoPVr#P|Zw105qOrL3#M89i z7=(Of<#;*5z8`>mmaUJ+YB95d+49_W6|B{zy7{O#eSzS=A@;Ijz4aNJ^9T-I;Z|*h zD)Gx}FnH-DwYeux^UieAcuEV0Ou~@w($>G{$meT+L(=V!`{`QS>mzHw=ji6E=1p_E z^|!A2s@7P%i=~gEvfDN;jtiwYm7+I?z@v$E3#K{I@OrQgiF?RG3>Dfo)xyTN-}8;>11h z$ebGe!<0o!Q9-T7*8S`j_MeT<*2kvRTOzmpY_qg9UyU1xWVve$|?=Mn4W_E{b_ zz~fz+)GMWWN3%J%mKsqM*sMmd&Xcn56>uozT(SzDTqsNyygGySL~-mTXx( zu7(mC2Oez5KH(@fuWZMa86A z8>KBs*XGnsw|`kTF`J2=JbSZA+@eI`#W&xmoNfNSvBIM-h-oe9Q;rwFaxdT|uj~tb z%k9g%<)!IY%hV@dKx?w(pFX#Mi-?(JSd11~OTAchLgSP~r=NlOYjG-oKUh|WH+aQ% zCiZk^WzZICMx98nnEI=$Dx_XiR87h(o{rQg%#_xeHyq49vtPDKEi7+t)e7se_-m3{ zdAqN)q*rRIwmkA1ft5GR^B<}40!*#EVJkI8^dCbUn=i5b2cs!Xelx|}y4?K% zi+_vayqVnoA)}2K-?Qs&Rx@p74gS$Zc55=XRktwNJ)K=pm4lUd4pU2gp592b*z2J; z+WMe3-)b0((q?6revuf1G={`FY+IN#v9iuzhLfzMC00(VsKL7rbyI6_w2Pifq2ol_ zV;|klk=L$oImYao((KIx19^5$HI8PIJB=o9B9@k>p2m-_8;F-^r&m^C0$`O-7}4}4 zW*J8GYW5qyeU6Xt~O2i zq-j2zTOwg!QZ^0mTKe(svA<4|UNy_kb|9Kt`tf3BMNOT*rmhN3{pGXE{Cp}~;jfro zUJ;ZNy;3$4E2dOd`Ee3i`P9@UjKjGXCf8Kt@yXhh@@1=*z?9ju{Xx7iU0sDZ*Ujd+t73K~(l)(fdinIAm8i!?4iCWm86HqY(u4e% zvU4izAu*|9DDg-_XO~T^oLM5zSjy#G75i>2wkb`nR%heW{?liB<@4VQx@s#or=m#| zGI7h%ZF4_3qo%??v$CcR=bbc3NcyCkCNV7W45_ZEIDX=p73DhJo6scka-x;`Nr&9r zPsS?e;h~K~T3_lxa_-fvc~owc^E=O-Bjx&NQB~6e^_u2E?-BC;y&Ru#ERINMYTI;} z$PKilsb?OV>G;jkvG`t86ra})X7rDRrm!eH0!L;_H`e5gyDm6SYS+S|_-I(Cj*l|k zw%sXFlT4qYqK3zCx@UnsZqE#Cc6Qxm4kG!sM6%%o81YguB)U08`n?^=_KedspTD=D zRys)3_i@(V<4*3udgcY>Y4Wu~6o2>)9JZRTm-2oNv58^Fu&G4V#xu~!CutVlZybC*K9euZ?W9|`mmv@BM-;09CbvXMs-8IcL zYdUVb&dI!jV3OBL065XiXI|?#ysVbzYR=gfXTIIP9Xh|Iwio`V?E<&;!F88xzikhx zTe>~^;;SUW4Yv1)zTQIbv8oe#kC!^Z-J9Yfbx@sowNuvla-WF3YP%AdT*SlfqMiDi zFFIu(Gk0<4oFnC~=$zFs&9&R7=Md(a&S;4_LzuZbU3*K+itPrPRh?0F9(Rz0(7lq7 z(0x+An>s#i(GJ_@P^e3GKz041NGk2WY-w-e$hO996z04xrr<|#I-Oa%0~Wh6zmP?S zoL!-IJ@W@TBhM`Ag0f$4`<;iR)W3(5xi;>Ylf3`vaa;>_LTmUTk6fI$1B%zK+J8?6 zEt=1|^fvW7nF21~ns{eUNz5lZqcgcnT37VeVw7!qkC@atylwNJKPBs}UDFTXel&6V z>#i8#zSg+7MD`hNda_rO>d*GQ)`W&iq z^VJ@3c$qjXF`;fv&y%{P8+s7f!n7(QOXbESJ_pWoPJ?>6Th^gZe}JckrRegDOU#|! zc<|J--FU#%>Tdna+HTE`e_9Vu$y=p9$KJ4`Mc$Ju?%s2&-c(E-d1)Tl6QfenrYmmK zp1po;&$f|fJz|sRwfskq)wz1FO}tTujXka3SCjuhpe=i=E|ssjZ`Iwn7iwYy3bU}p zJhEpmbK72dURnEgZI|5pJj zV)AA7xp~eeTGC^yT6*gJUUPX5+;jg~LW{pBhp*PLij$j|snT_3Lp2dDP=QbmC7xjZ2 z^kCu#qsqQxS6}Xuel)yM1}gjZ-%E$u_w8Oi6b&5_{Z7XTr(SPdb!g_@JlQrVDbKu} z$16=wBt{0|4=T*sLowPuv6WNX#G%{d1;LLG!NJVGF#Y_H={5$H1#F8qb#ke!_zvcWLxz* z;e1clJxcbYEgoiFJ*?-4ESoiFK4wYGkW z+=@2}uI-Il{*g`8QmI+7$HWX>p);<{zmT!MPix*=_@>WhvkM(U&U-l@_StN9CHrhP zyP&nz*=6ST&03BqH8=H!Z@wB~Vtvu-=1X51{>b(W>+<&unZlAWAbUTzxvYP_6y?0t zu&n>4QzSZDou1abd2mDjEg0!iuN0W|{W1#)rRLWDs5Vba*2HeLgUubXUK_s7et#G< zrox>@1?yGXq=Leg6EweANh!vz3^82W~c>9~zi1pP^`^c@bgc+plM? zk{vhcyC%C}h#8-~fZYzMA15*E2DEB_O)4)j2%4*oNH3IS_Bo2h;=|F&nXivPgS_81 z(c7h2rdQ11BwtE%_PH-PDpQGD;r#NWP>La$hMJX{?AC*-r@`shPLHyqcD~_ce zq;9nga1A$#8NL=j3z?^H&E38I(V%=O&)F~j*`R!7oPUq?mxD~vSo6t|Tf5cYY&@z} zd)fa!2&IA_dK_emv+LT{AH;92>e^(3lli7ws}_6B#)F$2PGLSjY;*7Yo8-}$BP@}+ z8Czt{jkX_{YroIOC|QuZq5Fx!xtp_}9c+rwtg^SQ-#NJXcJ%uPW0r24nruR3EePVIzlzS;ZnV>h#j+q`rvX4dth zKePdjrKrTL8{EshbFAD;q_-O%Ow}!|lch_*aCI8@<&Ah;1?irHa!Ec@$VG2`EnEupmlzDzveadA1 zIRcewNqcDymx#ISQZXYiO;OHE^dzkHQ`c`L#^l9d_%etSxzWjncg-Pr^-!SvxXydt+`GHPE~= zs;KCq*JL(zi#7jk&39lnNydevbCa=Tbkk&9KDt>lt{z=f^orH^xHV&ckdWT9<_4Il zWPCYVlhHUjCmA1&&Pv8-qcs`x#z-=59GyG);GabJfG`pgF242LOil4%)s4<_9DKtqhto>&FnCWGeRVFNZz@p)Vx7aX{JV(*eK;y&b94<5JItzX^lP(i>Qb=(b(H{wJJ z;6|KV$ z<3a2^o{$4I-hjjlUqVg;;sg~)6ZEoAA_DUuoMC8JjIDvK# zf)yo5iSju&`*$#!0^5BY~!$Va|NYTQ0gz$0NGFKqOXRT7q{h3OI- z2v~X{Vx3UHNC31#c-=9SoOLIFAYIlm1pdJR3eZD62u{9vd}MJEDT)^b;3X(d@z3Y- zczqI@{f9C{yb!F!2wyT~|CgI$Uu|@Gz1X54>|1fd61__rx$flA})Ur zUPLhv40Vz#_A+x%tR;=G^~TzV3PT0)BBUei_$0gBsQ01*As_=h?r=c>F0--~g=Mo9 zA*wUURJabp7ks4hRKB|0nx$}u(y(!pi%0`(BvR-O;454lb|S?AT!2Fu-aPdJF_AwM zj{Z;QLaQAkO!@OjV(gy_r5J!7m*|EX$zz`ca2PmIMcJ)xcn(QGzl=6R&+P|E#KTP=pa+uuhXBwXGaJBD4 z4v{C28^|-rQSvq9IQh5aa4*&OF*(>y%g{5x`#{1rJ# z9(SUK7wf0t-AxYnSAL!xCI2<$p4>=|lRYOfzXquP%g90UUE~n?-{dg)w38Vh@(tu9 z*_@*Gu7Rq5f3k->nd~J$NDh%dBuB{ZQ&nG_d=lApgzBG5_K;s92gvKmA@ZQpR9^%6 zB62e2p6nW=`Ujn^?mgtk$-ZOMe)pfNeTY1W+(15u?DDGnm1GaO=nVBAARkN)k30IYfS!+(6!Ms_Ki8$C1r(s_%TVoBSv_ zKz^SbBJWzM`phu(Kbq_zpHB{uA0daye>+nK8YM6UrG*>UnfV%J!({6lw3xRkuM>8f2QF*L=KW) zCr8LT*Q&l4`DAjEd^OpOQ+>ZD`^X*Z)W3VY+Mh)Bk^e*vllPdR?jz(g$T9LgWY+}M zXJ)E<5BX4XhF9CVRT-#~tp93#I^PLfZWNBw20{~ofNTr^+p zL*&!R5%NXkI5|r8O;ml(0`(sxk0m#dFDJ*y?~+Zq`ak{xric6sa+G{0IYxey?3$$h zJ6y={$tRE-$d{9&B|SN}=!wPZ6@^|>xmdoOtsIY54$93ppKqV5~W zesYBT3fWbu`lnq?{p2snKJwB_)ILn!DXbhJ-$#y-J722yN%BInIa9;?iX0$cdl~hU z54v2rf&5!?oILUhwKr#}zI9|bdDK$1_mW>A`^ZOL$?(XJk)z~6SE;>kn(BXo93&sJ zOzqv%)&3>2hdlIZ`X|T8A@cBR)V_iI963hzU#s>>@*l~rDh+Scb!zV+KTP(LkGWp$ zA(ej6CdSwU3jZBb&1|yyI?BdpCI{*+cGqtJ(+2_mLaOhu^059?U}=W6WJ-ANi2m z)!x*q{R*;+eDEFgPkx9TARo9~?L*`n$r19vJJmi$zK5J7|MV`kchzb53&?JA=eyND zO0Ffx$#0R(4E2BTJ?h>~oW|r!k_<-8G$jiw-@>k>#dEA3^KU@9ZO7@VyA;-x- ze@NXY$#;@nbJTywht=LoK7kw{-$HI6@3KPON6BZ9H?_@W5=&$LYd_Fl& zj*<=LSyG?hAiK$*lYQiVkEp&d`C@W}{0TWq9`vZXkCT^@4d!JM-UnnC*?COe`^bIB zL9&l5^E~lCj~pdGM^2L4Kd$;hnD>eMU^VR<&tL|5j1LVD* zQTIXeFUVo?%Vf_y_1`s0_vDMn4fECh4`i7qO8$0zR^7W7DA$sMfJz3W1CKZ)!iKTi&l4}MwtK2|7ha4yG z^P<|Di`0J^*+Xt1`^cp)srw)~P7afQ`Lf!_$lYF{{w1paTC$hCksKl)^E-7PA^(MJ zE>{2DVruUr44LM96`j)!)U8DBr zki+DM$T4!Kx7EG-T6JGd4v@p-5cvagjC{nO)qj$F5!rp6>U)grA@BMZbsr+nBsY-P zl4InZ-ck2)@>sIDUiCMSedKS+LGsVz>c4^f9NBY&`tSHxwfB*$$U*XxAyNnNc zHd*H34*KJDL(Iz3XPxH|ZnlCzpJz93sC+ZXhrHhuTNU z-9J%|lOH0xZ&CfHf2#IAa&b~QOg@erA%8}Wk^P^k`y_cC+1#r7=X|dA9`cU=WO(ET za**6e4wFy)LfuEm_mN}dz5k{5aq?=i`!)@~X1&^b$#Jreyzoo450hUYN657s)IOH- zPxjoS`n&&I?E~Zra*+HSxqab3|CyX5dmHKh zKK0+>TV)UVm*gP%ujKgs>i&+6>fS_@=b#nJ^LaOUl%wn;*OJ5J3&;`j&IRf|My?|# z$={G&4`_H76smgV+bPG$Py(e`R@9@6++Om>mGby9l|`2n(*{1!P#-mSB` z50gidBjgY{N_KW&{KzqKl02-7+Pfdt_&r4qkZ*U|K2+(d&t+3 zz2q;+5%Tn%)qR|N;x5YWU#q?^$UgFAyQ+Pd+-^7J2>Et$oV?%eYVUbO^(`U?$p>{+ z`v&q0kUMabO zeDF`yK0fiaPa+rKMIYJ)lR{I#aksK#4-bd}tGpcXjeU)A0SIHjo zr2W)BME(akOkU7k?W1I8f9j8_{+Z+;x!?e`50eidN67b*qvXLo)P0=%069q>dZ607 zp4IRkBD={)9HjPM@)~l4Jm_Gx4?L&-pCE_HUyvi@!w*sSQSzl^^BeWQ{h?~_CSO4I zk)I@o$e)uVR&|mkl!YI$z2Xt_W|-ya*%u{IYu7jQTOI~)&Dfv zMIKk8_CE3}8TgVOMo%^Z#7&%BbxDOTouaHCJ{ranWxla}QtI1LFI&zG> z>i~71B#$GzUQ++F$R6^0IJw)BR{-FBTk=^9+L)AV`{sYNvFzlRqKH$Th>%K1qIs?ERzaKW@0%2gs|)A@ZORYTrP9nC$zL`mY?R z_OaKMUnQHh%7aF!y_@_sIY6!+t@h>(b-$kMB402@?LFjA$v*N6W7R%Ft~_2jNnS?| zys7#h^{IV`?EV@3lP@I4$fL$lAGvtEvg<9?_bk~*{^bPfC;#LGC zgd8WkC#t>sUDdaU>?40lj*=&qtNS?luVmNX)c?to)ZRyaiyR`KTcP&mJ$3&M*+)KU zvf2m9zaxjqeWs{=jC>o}{9X0!HC64ysiVT7U$>ocvJTPap?A zQm!S3$(NCR|4{o5LDd%`pG%IAKPAV>C!VeD%_r*rPO_W)4LLxbSVR5fcgYd*m|C@u zlOH9UPgVaRb!zV=FC_=aUywuOVKdZyn0zfcuwM0bok@H0edH*4pIM9#`Jma#=1cYe z7TH7o+Z?qIkRLyX`pGB$LOGJ+bCqM{PQO%kZD4+qL;qI3<5z0mKz`sn?lg*!ul*vbUY``Q#wEcoD;Eul7C3N%9$FcL%ke{X?WAGqJQ$Y9^Azwv~kx#o-?UUplw<#N!>i?YVCO>(*+Q)WL`#0`Tj*}l>PXD{A{dspP zhsoZ%l%wQ=yXl|&H?rAH{l9dN+Plb$?p5}Xe|Dd;mt1nca)A6#a)i7hqV`epFCS1& zk`H=N*|WQb{|dQ*y!avdCy#tsIY!=L1@)01A)BtM@0?$&y_>x6Bg!7~8)P5(sz=p6 zNo*W~`$@@N`_NJTquOqw3?VhB5@?+#MdHPe-Pkx)6B#(Mp z?cIB-{$9^0`^bAll|$qud{j34zv5 zBPYq1ys7rCgH`{Cx0K!Fj&Cdb$ZwK^Q_BzYa#9HQa> zKCbp&@)Lhm4v?q5s~jXB|2O3bdBA(hG4gxlIQeU``%n$<%D=07FS+D>u67QK2(-tPXd#e4IkCg-DWBx&X_22!i+PlevH!6F{ zuag7h(@cSVo){v3O%9X)uf2BxkR++fg`1}<;xZz_qFfvSWkJNQ>Ng_Jql?|@8D@&^ zVObHWsjkZIsh#So+N$cFnN?(bBMOXy$n`mZ_#+P;5fMRU#0My#;|meII3l9=s@KsU z`SF4N--&ZFGa@rGD=RDO(YrL8I$vdEJWrfB=fsH|A*j9f{_)51`?lcPmovU7_~1dtmj!>l;F+g!e%A$G6#SiE!RZe@ zo!_5-oa8U~%N{TJ34X#87+)3qA;C8Uf9xyy{lTy2{C?@H7?%V;`-zO(g4b_ld`a+4 zPhxyc@NWp7c?ReAvM2NVgMzodn(?gQ+n>U?B=`%yhH+c)KMKAi_|Klo?=K5}<<~O4 zDtLF6@pZw=ImR~xKQPbuz&CLHJ}UU2;FELw{*d5b6?|IoSI_hNw%|_)zEa@)?pfgX z*9CvaBIB87^84>tlJ9S0d~uoaCBZLQVSGjKE1$;ry5OgN9pjnX`TI`_J}CI|)A{`& z!QcG#j4uj)#4{LQ7W`hp*93pdH%R_P&i}SUj1LNa>|w^Ug8#SRlHhkA;rFKnZyjZP zN$^8g8DA6pl?BF!*0{XC6?|H7=b8Ney5L)GV|?Hkr_bHaxFq<$1z!~W!6LuED)^o? z$xrawG0E>Z=Qnel@oB+7CHRuy^Usp}1V8(PeE%%|{!30Wo)!F8f)5FPb4l_Sy!UMR zex1L6#X94If_oc`uLxc^#rV45j|eVp@b^FY9Dd&xeA^w2FA9Fha~WS2{8qtN1lRB6 z_tykJ@f#T*I>q^aK=3ueFM1xozae<;n;0K_4yS*&;L7JvV{f=_QVetL)BUljZn!Pf=PclrInGo1b{f)5GK_xSy3 z!S5E_7QDF2?+?}a``;AY7W|?;et$*q{mwDICiuGr-w^!p^Zb7HF3#_Df=hxQdV$|x z7W{*PuL^$bJ^cQ<;MWSCIm`LgzJ=dkY%u;q!B+$y`c{5_P4N9+$oRkxr~gjDR|P-n z+a$f<{}Mdg{@RO-uM58aw=x#u*>fs@^XHETJR?XUle@DC4PTJ@CO866I}g4et%$(^ZStC z(}I8Hhxq+f!7Hzj^yfJJ%qtlm5`0#0TkwYjUlP3b!<_z_;9nLzbDr~i@~ilLTksnN zUlRP(AK~{`1^>F>8-g3JmhUfce*Y}^lHk4n$?vZSe!t*rf}i-K{Ql5A{QX(M7X?53 z$N2rsx5#_J2L=C@;46Y3^W&WUn&58}JoBym{dK{!f{*+Jr@tupb%L)6{!PI*1pl?* zgD>R#ZvIKBzu;xTrv*RZr}%y8+d2JF!EM2tf-ejHcEMK#zeezZ@8j?PS@6Y|F#hVx zQvUZd{$9at!54_;x*D5~QSddv4}ZP9e;Mb0LGV?<9~XQ>aPen2{lS-W`gaH}3I4MGhu^maHw9l6 z{BFSqF7fxD7K}K8Gh{#eiZ}50rv)Dqd{OXQ1YZ{X`9I6)Fa98Z|678u3Z8$X>Z{qid1bW|{v8Q&1R{>zLH{7-(r@eanb zf*<-Tj86;xbHNt{|H3=@{UyOKd>7*@f=~S_a zGrl4C8w8*JG5-EP1yeYBYTrAr%J+iL{|4jhf`44_fgk7eR|S^@A9@d`KP~t#1YZ(d z|4n{>*?lkgn&6|q#qVc+g7bf);Ddr6{o9hi;1>zLDEMy#UlII>-{JJv1s@eW^OKza zJ%SGjeuLoCg4fc`xsvn{AR&3KgIdgf0y6S3V!16F+MH$ZvuK-GAoh2h7Yo z?v4EZ34|XwGxJKpi-NBSzFqJq1V2ykX9PC{&%cTDdy(Lh;2#ovM)2zef2-hk2)-it z{erIw{+QrT3I1on4}3G1_rMQx{U0OvQG%Z$_{oBwF8CROOM=%0pBB6&xF`4?!50O; zOz@CyWgMsP>)fuHC0eUIRSf`3%-tl*y$d`R$n z1eXMVNbqUF|3`3J@P7%uDEQ%jA?*?TRf4YyewyHGf=>wkgy2oVpAx($_@*n|o|g!| zMet7wzE$vB1uqN!9l^H?{)pf^1^-{cX9VB>e{ucK3x1^F7Ylx};8zQNhTt~{UKe~- z@Rr~Y3%*D2-wA%1;Liwtt>Bw}f!q6b!M6zhJ;ApM{+Qrp!T%!ocEJz+7`LY__)7)9 zLGV)rzeDg5!S54%hu{wjzDw}m34W2_&j@~{;G5pc_5WGHw+Q}q!M6(jW5LUU|4#7j zff|G z+`c~$e2d^u2)O7yNv|%Yqw%pC$OB;7!4o1fLUpS?~`Cz9RTF zg0BjGyWner-!J&O;Ol~K2>w^Wx4wka43NHN)KXitN-S6Veb+IqtxV^$x#UK4KP%7yC zr6;hz@HYrP{Z))1_Nn)mk&yHcR72rI;tzhqeg9-m|2!0^%6lB+zjm?Y--4`0@7q%T zj|sl?51js&-S=P3_-T;kRDQ3L_kw585US5d1eXMVR`3DI@8E;@`;y?Jf-gz>ZNb+C z)2-H2-U0E)f1CSW{Q3V(@a)UDKfdn4oc_j38UK{v%P(R4;LqdtS63L{<>K#W{Jnw? zN`L%{`(DcbsQX_0`#&rAvV8yLH*x+41s@T7`kT3b-X-{==+D3X`J8^{N4WfddkEv% zr!juOLm6KYy!3^PPm6!}j|jdl`tDP2=JyA`gumZ-7~@0hjL#oneB;-+K099|?^hYW zT5#$8jNjwp-(~!df=>&+`QiNiY5D$Z1z-6+PXAoN*PqV#g@P|XgzNJL!R?1Le)AV| ze%GGD`1&Il&x*hQiykTE-QfHlb_?S}2RQx19?kg5NycCNrILQ0@oitm_~JJ){+q`z zJ}CR?-}P9=m!BiwA7ngpi1F*bLcV{NV9YBuAKuCJX+56t4LRR(_6dwH{T#o)_LY+U z^^BkJM8;R%!T28p-;nbd-+n8HwnJ_6a4){p3Ltr-@~{e_|SJV z{-EFk7a2bt^P1{^xySgug0D6iKj$g@en$3}J}!86lgs~!ui^KHM8Ex}r!v0M0c`{p$o@c?FmE)Mb8u;P?6cuM3|22xDApr26yX zqd5JSJdN?}2IG$jE?wpH=e~~LpO*RdUcncu{Qi-cH)?!NGTst==~;~5E%?fVIseZH zzV<-I^Iy;3U;A$qV z`A;ryP4M+^WBk*COM)MINa`o+*%iTuzJ>FD?qPo4KF#-AD*Y9~KjOZZ^luUT z2Eo50cvy40wNfPk&EhOi9&W zDS(>+{Nez9O#r_$fIk|*{~5rKx?R=BE58=NKOeyV9>BL1&F?P-@Sg_ofi*LIA%O1* z;CBY_KLzkt9y9ZMegOY)0RKqp9|oZ2k`3y_+tV5?*aTs=2PBy zJTriw8^AjOjEm!lzP#^W6Tlw|;Lir|6Hl1mKR=@!*-6 z-+2)96g=<4^SgL{56}DYd;re}@%%oXKfr^F>}UQE&mZCWV?2L?=TGr`2oK5mAI9_N zcs_#Xqj>%T58XrmF+6{X=Q^Ih!t-%Fe~sr8c>V^@C-M9(p1;HMzw!JZJb#bp6zcXI zJa^#vMm+z3-~JKL|Hbo9cy8eNXFUIc=l{j?DLns*=hJxpKRlno^KW?m9nXK@`A^1L6O`{Q{4o(JN25S|C)`8+(|gy;Eqz8TL8@RaeK##6zwiKmLEhR4CP zg=ZVj89a47ci}mUr-A1tJfDx}A$Yz3&qMKiA)cG@JPgkPJYR(8;ds6n&m-`B37$vd zc@&;o@H`sNm*V*{JdeTiKkz&j&zIvli03QtJPyy}@jL;~SK|39JWs@PE1oCec`}}_ z#`6?BUxVkVc)k|TES?;mJf1l`^LXyYvw&w2&k~+xJS%vfhKF>xr{np0JkP+>!PCXl z!?TNL56^et`A$6Fh3C8Rd=H-Q#q(l3--qWVczyuSOYyuM&ky4HAv~|Z^GZA$c=iKb zJ{R@86A#hn^YDC*M#o2^JLvBwo)(@qo?&VB9P&7i=K`L4@VpSux8Zpao{M0XM^DfifDEoKM z(@nlBl}4jgt@K)*;>Kbbx0M$tkA*TWzMn7Wj4OvX%IfLXX+_=rm>L}$`Uh!|oJ+VMHCQxkIpfmd zH6oGVU`F)ag01fsLVdT|J~dlTQjq}N7sgi?qPYCwULW%FXC9@+RrK1V_212}|t{gG1F@G_*M3-?@z%X(h<~A$cdbM2d_Bu{wr&y(&LsZY4A+ktgN^C6q zg&&ivyK~00T{yhi+H+*uL?k)lG+O84lhACqQzlkKE|laOW0NeNY8`jBda)%foocPu zx6i~UTDi^Xo!r{$I!MM0!L5_W%aFq3T+9!wNwQ;1iU2}o++OJlW6Fa08D(gUEr-@J zV=Jy^z^@{TSwUmCl+4TUR#I&~yM5_T=%r%!j!L6WbGmF&IZwZsFN8-}Qk-fPn>FXW z%SFN|meIM-t=D>I0<`Vdi^%bIM^UYin#}iHxx9nfS8lXgZN=f2%10ZOE_lG<#&)UI zs8=r(3f0DurM=uDF56vHX%;)qp3~_%<$BNQD1o80Qz$@aP;vvBKHsj?JH=DwQ#nk2 zZ~!oMFd-f^m)VueXDZz@y&#~*woLVWjM@_Xbtj(7hZ%5Gz9s4 zxxCwKb#SA+Q!DRO+NuNx0?twy)uNhGB?zkY%g)`ql}5SO;$Mz$=D;^8A9RzMk4h-n zK-}3lQg#y)!&N*lH(xGSTf5C3KCR!q3$chw*;zk!>b}+!^IP?1&Ff_9Of~e?RQS)dDdLn!3ff@w)rrz9EbVx!@kbhJgY5@Tc zXL*Q|tCS&WXd{nlZSb}^gI5g0#ZWWhP^6IoX&j1wnOFK0Gu&g~zcrdKg?yz~Sl>9x zj7B)FuE8BHmylU*QD!2|wlZ4k6xGkhB&2jpk}fOO%(EIf=NHQ5&E4u*r&n%3=7a+2 z^Kn)mpNV$kZ=vHrmhzXO(gwXi4l7QRR*-Uit9WO(lV2_$J>yi*9`1B17fP*q6ARSQ zR+CmM=u}vdkdtaeVXrVxOH5(oP{Avv1U+4K=se% zoV&}QFD0lH>a3@`LRIxlrBm*8D)nBsSS{poy_TPp_3Vh0d8Fizi8kXh%{zA&s&RSE zIjt>`2knI|l9;#MEUZ`8kHuxQ*l?QLkS$BGsg|m(opz<;P_m7=GAq1NFr=`1yQ~M6 zS!I$|)uCzmiF$=KFt>%?ZX0^j+WIl2Re;}}C>O~HhCjRxnrp3cHPVrSq^72l0BR28 z98?4rU}gB-xPuqp!p_N4<<<5{*EVmCrgC%9YM`m(&^bKJ{V5 zF!diLmfC2zP>vb~U!kU74LQu4A)BlZ-51AWxjaD@I|Zr`QN%=-nQ7>Q{kF_ZL7xr1 z%$ywMD)XF4t}^$A(YY530n;!%83_UQIkdlIfP2w!L`<5`jfcKnl3<%71DT90KqN>< z?bcLbV#Ry5gu*P1fBSY&V0Y^!a-W7WzzPOu7B8u`VWbSWu+n5ATTMq>hLVx;vgLL19oY3IHhoFDs>VGbXGMLl?raY1u9kb8*Ew6 z&>7nDL|vo&DUK1Da+}w&n(1v`^tR31ZHGV};(6tJd?KGEW$$ZU@ORZFOdmOEZc~u15AW+88O<3{lqFM=a!5rApzBT~z> z`RkLJX(S>im^qY8=FQTmShQ9Z+dN=-kmTS2Mfrr&Rx3V!U@2i@s$OT|=LAOAV4$iO z(=pHlE|zo(h1X!a+Op`%)~N<_&1v3^Ang@9;`Q*6fqIyf1>1<_z5Mb6<%bTm zXdF8-yI=tw%$z{kWnDcRAK392lB!~e0g$17XSaj@^5s^iT&?#mDDTOg<2#G<1+^d3 zJyYN6m3Ls|(|sxXeF*n{WrBy_DqP&%V^eI$>h~>-u-><`I0!@;z@v4L;#agRpm!pV zx%@DB%*|0A=#s(eLAz<4R-u69W%Uhy|c3+Gby;aW{TyVLaJ1I z7iZTtE7h~*E>5PF+m#+pk)Qt;GOc9_mhq+;ltP8mEYxQE07iQ;)I z=tpuraHHXi?mug!76pIIP8D6wmzzD>>NqDi?{ca=bxcotW!UzKYisZ3igb8v3$EW3 za3lC-a4^h|-Ay9%SB(b;UOcOEkE0Hl2a4eX+?MkFlimEqMs#caSK-$B?`*C0-&$Mi zy*66w{Tgho|02*@|AiOcB+w|cwL53Z&UvT03&G|L!e=<08Jz5{H_@ffX`aJD<1&R# z*>R|gPaI>ZZ;=AqG@O-PoTQ);#o@>k8?)s+4(jX4mg}vqItID8?ey@8cYG?BYqYiz z7Q^XuTAiaxnp59x^m2JV9mTI!bN(m!)^4xd+A4P{&22|}k)PeH)Nq6V2NcUq=N!Z` zI$d?t|I(g7%YmZ!jGFZC43J$D9VA-lSoXy=W`;p_qJfamfX{_!NI#e`~=u?f- zl7AFYNi9qaNYXs@SST!Zoo26dfqDuXshgIX#(%$>_hyq`)A)}%-NL%Ak>sRPT7Eshe*h!X ze^{uh*c{b@$36`v8>p1WQ=!H}Y3zZ&);8MaimUWdvv8WTqV9r}DTe3Vp>DHrCrm97t z|J_pg=f2%5$*o;^2mKoC%37nOx}W|(-sccMXS-S6qc|+om(6o(I^+L^UzX85h}u@} z^l14<*Hy~m2<1RVs5)(mq~^ZabhhiwG6LLH&$vH9wKjj)>Nu7!+q)g7yjSn^5FEz+ zR7lo^ihc=fpFdwlB)M*@iFWiZl=o)o*KUtY1=TZWA%4_V9{w-eyOjs`d3~&NnWsHnDjor@X}y;!B`&>$^>vpzb@b zCf=M6y@9aA6W4v?$#~Ik+zIN+w0?_oxudP-R$ZKN0eMM517B^4<)q zL^5~Z1i4vcfo?g8_!5CqyslYZZMhMt$hzXkJ>*3y)GaH>PbCTl3G_NHmwQgT2A;(V zgW0=YvAJBmTRvB5oTcCx%00}8xuzzm*S{(!>WTnG4Q9O3C`melIfj=@glWoEAJ9Ev zkGg2PRNCUSA(;9SSN+L3jxOz6oKUOpMM@;?xt_8Cv=Gk4AabI!5WmofJLwGfK8emO zdhVy39sy>in-)BFW)eO5`D#5xdoN+aHCYdJP;L>Ng<^Z2sO%uN4UV8&xs*yezu|Q1 zSZwZ*guz&jnmA~UQ#~gM7d1TQXQ1E7uez>(J)Cv{EkT2kmrfq%2r>atICM& zyHhOf9Iwyfz|}11*vK7jH9-Q&6}Fred!oj&!&o3K~8_?I*5fx!6sBlEY|}`DrqL5FKd2IMhV09 zjbVf_Dn(_s+rhq&0ZpWtYc(sBo=Nrx*s@vb;cVv7ZCY4MiUF5!Xc5+OmIl{w+sb3V z0X75`ys1(}$3oXd%*Q6I$6n~nRArRtoCM2??(ih)0I@Js_cpx>7(+*~-`Zq|gbDy+Jfe$t|!Mf{hT-X2pdr=%DH60q#Z0s=F$rGjQqyn1K~{9=cD(ucFTD{echk zMFx%V7rTHd+OifCm8Me0ajLT8vrx`g2UZbe<1qM;FNJu+)K}U_SG#0_NG6T< zdwbBv$B7;3nk|E3lY5d#DRC9jBp7VCW*`SuBgGiv_kHCc+VzbTq_E=zKcq^nM)I>a z0m&`5bgB#{JT#-o!9t9Uw{n}~c6vnwSZ}JCg((4pNTb!<4rVJ-MXFqBR#J^A->7O2 zl|QOY`FGE>VCC%7FC$_^3tRP0*B1`V!H6U7Y-Sr~A9^5S(8k(i9>@u|cwUIWJ?2|N zc+pw!x0c^e>xOhah`iyk>_4n7CB^%fOQFXrhbWe1G5H zs{<`7-bNO<9z_^e+L5>lu&N+c^b#(_6ygaVkrJD50`Lsw1m>J?LrYNheXm-c`CUqm zF$<8Ewo^IFLHP9yjNQ+WTBS>4@PZ8R?Qn998bZmPyS;LY!zq}wO{Ph>x=1)gt! zw)Dg#w`IB#`f&cQCS&Ns=NWDIeHXpF{(MB~9r4)3S*Wm!>e(3p9+4f^cy zW{_U3gf%6SEJ8%-=~{Lw>CaZZ6Eul=1$k;H zHvw_^W0yg%rxWM1T&=VblA`CwZ84bo9Ad6`nHDj0B-)Vu)8H<1@Oz0%)xQIxn5N4Z zn()Ewz-O{i-=Q%0je=3JK$VTkV6ecN8qhL}JH$V@1q&3u&5c0qR?knS-BE<}Azm7& z%}z{h@=!w?_04L#T@HSwqQ}|VA@v!Oh$WZIs91PqWP2Ks?U670P^`PT5%l%Zd1Yi8 zjSskK+)<6*B#9Of1{?wV;?i#b60R-=g{Zxre)Q~4nk1q^J}fF&S5&K*;m`TiCT#Li z=0lNA)cGTIZp{BK#7fn%A==@TkFZ!mCZgLbmF+GZLIhi5OQN#U35@tJ8@*)u{oZ5 z$%Birus}<;`e@O<7Yu8-Law9y_OP$Mg~Ob1Z1*xYq;NV%B01BAt8{ssk+`@Pbn^p= zlyI)YIPI1o7u#oc_8cAo@?1_KWP~&FhSDx&3`l5po;3jLh!P7mFQZaP?jamL+bFp; zkzx~7Re!D(vaG6>tzn#sk#C8ZD$ORJu;q)7eUjHF(>$~T+yDr_5%$u-o~wJ>*&e z--2bH-BrCDh;z7T48IEN(`E=Yg(DTEEj*X`Ja)>D^V-`az75 zW}XyDzw)FpPy@8PxhfUh&P7g%>bgl!*QnF&kK`-C*K&0`xn(yEUr(g2hXnU?Q+OA5 zsXcwuuo5>~;8WgcMRO<2Q_W8YKFD?Qw4?#^8%N@4w1fh_<9X}!muKd{4!vrjQ+oC7 z-PUfGEEzqVX>vMVv9Jv8VWs5%^s$PmOUzd3JPm`FIWN@qTRo}kA$CKDKbyr8%%t}WTLPWA! zQQSx8I~Xy^ihPZdbKgRa7e%s2sjZP=!}SodiO*1{t43@9SNH-t9Pw zG6v~gRTE^5*@AhY=Z7wq{E~Jt@-mx39|n3EQ=Zlkl&F^lky)n<{)Y03rV4L-y#6kr zeEg^7%QP9EkG5D5E#SZ7r9GmAu=_)z?ED44Uv`EU-HzfM;zt*5H7#Vci-g#rLbsvZa&%Ws=02P+GOolLt*kXk}4xQSj}jCk;U?v$MOl<#D&N3Ju9xBqS+9f84wfD zbKZ)|lSxe;wJg{^QLZNVgel!4>R5Rp%4^Wxn(*ERi=h2GjxG`PmTJ|5UI%zoSB&k( zJzZY2@}KBIP;ALg<{FKYew%V@6*qY~)kzc`g>8=(1q<>zs;KV%#rd6 zRwG$P#+QT8akTZz%?14sK4TCzaTMaL5;3|74O+cvux&C1b>Wn(dmAO)IVSrW`4IG- zSkkETFcK zYH81{`r~VCf)d*aF#Vt z`~=xWzgmxsWArO{I+#YXT8@ct^s9_JgFL4zeG=0W2lGkje6^;TYWic;g4nMLqvRg_ z%66MS0S2-f!9YgGvgn+VYZ>5OG8O;JFoKV>blopZS3Jg92gHV0ceeoo`sZ-;Y!h7! z^)+C7FqSQzbrO^St{70B?J)_`)^QLPJ-Xo_v6_N}`8vE#2DyGF#NiqbQPOVjTE_|L z5+q#RATZKCP;zy!4@ORmk>=8ompli1$pAa+N6Ls@jsMiDGxEw=H|9rQYV=7E3MXni z+?kg8Ww|Ysu#ITk=r=kVPhbIrZl_5VG%>^W?%`U@yVITnNW8Ip6h+w-%zp9-Ib2wx zHc92v=NKV-SPdG9>bL;6QvEDwDR6qtYC&;>Px+D8sNX}EWvWhyvt`@uGlS$F;Z-Q} zK2#;wSfzDML6>F%t&cH0ge&PO262vwkvZBr&{kXjM0;E@*-7{IrM84=uP?LqfsC*W zXq|6sHT)1Tca*Q2X1G!&q=?bxSryl{8T5y%ad--sz5hqP;-uSU8jdgGYpn;_oM)fc z()`G=h_u)xBZ@?GtlxT=(#V`v?@L)+7D``cMe96L7xhQf)t0souI{C6JXSnU$Q`M! z7hAzB6}{MkqPgvew7l5bxLh_v6)(2D*wzoD-=!>dSmiEdv18EeQr2u3wJvRu+39o% zYQX1!2U6$~xv1whgnGLSQCCF|N4X%H7!>Dfwa<|4Q z5+ycHGwh#rgec!nadR^sPHS^>NhD52%Ca`)#Z}qd612TtyS~7ksY%ySlDeCttyEE& zA{Nb|l(huK+IUUG@MfZ^#a77`AhJ=@VvCBF9kSKYQdS~k1ua1>5=|#hWe^KWypLO7 zr7KY`7JY&)&@pZr8mwO79Q&$BX=_TFkJL11Tu7E>_6kkEa(QNiyo?6x;$hW~P$gqF zj^?p(WX7KvxUPwmg;1RWyi-XWiFJTPxeX}Vt0Q^tA;DDimPlexRP~rJTalY9p^RC+ zHV;|KQB!xZj%Pth#AY*6r+pJ7RI|aP;eMY7-+K|FLNDAK7s8@PFlp3IE1Ajrn}0*O z*@!(8K_OI9U$H9{Wv5)$L$$N@L)z6klzE>;Skn8~KL!pExqQzOO+OrbKr%C~lrX6) zF1rX#DCU#!sw)@aXE)8tHzRjL-R3 zIr=UQC(Yf!0W<6qdCZm9izTc;k=XCa&Nde*6$=#7j z=DKrXD7aAGi#%bRatl+Px@eu&4qlTN^w@X7VaLQiiR)z5#16g7`|r4s>Ea^mhl5VK zGWJjzYAh|24C%0l5vJHT61R2az9;^8rHd^^+2Gwn=?qNU+RBw9_7d`W5x zUNsi(CHwIBD@^q8M3QPC%W#=4tp+3IEyPC3v*Z&MI?uhscZe>Cn5NvfnKV647#wD9 z*>yawcoq@OEaRZ&nI-Oo+A)BcM;!=6c&K$1XNclM89R}-up*XHbV171gj{}XDcq7n z%%SLD95l<h^1Mgj?#M< zI+xXr$=;eu0d?{#<-=}Jy;b(=UB``#&bosLTV02e^jY_i!bU(!&XF~M0%-;+;o~mf zq$eKaGQmeyE7eyzC6hq5PIJVFLuSM-3J-vqSbc*T&4+^-MOrlNofs||b_2DnE^r7f zjzB~!weN&pKI1eHAyjoM&J@wznwCgL#}re*0C8ZVz$qKsh*~N$NT4Fi=TVW1`q0Zb z$W~n_kLA1J=oiT8`q&gyGRhh-1y$3hm`htSx8s??I0jcYbOb6lV#ebOcCZiG7>|7_ zNAOt7lmdH@Iq$J~1Xgp^+`*RXwja&NIR7?}i-7mM?28tQ8#{JuYc)ccLf%4zH3Wx; za8+;8m7f%Gj6&BaPQ_tN)eU~akrq_6y#+UwdvO!mQphdT>U1Rtg=#DJaNDyUFm9<* z+p8G&hgxdbXn>FIu|TA0;}m}qhAymqxU0B@dUEt9udxOFLPXMR5){Sd&=7{(0!M~$ zTWAU_BFJH_wNtKCs|e@sb(Ok6S+DQpCsU-QXLO>4TEwHQ`kLB`FsE`-$s54b0*#7M zN&Ckn(?Ck}s3#CsGAs$7fQ8dON%XraDWt15u(|*;!0e~V!7+<+5I*p43aUu|3?L z07VVK$`OV}Msq2Gl_N!%{b{ox%*qF-c?65MaqR(ejpOF9qlKG;ypwWs3!U3$UHiDl z&W!aa;paO${^z23$nM3wow6WFAcnDKtoWU+fs{rm|s&C=Ivs2lL zxZ#}~6tK{ScHuAp_*FBY&^^KCHRK6PSc2?~dq0|nAl}e#6Q<&G)ibz>uGgv1#Zf5B zQaD+MgEzq|v!DvdZfga$2Vg6Jm}7)xPFQbmn~LeY?`@pq|;+@&= zlQ5}N>8AwJmo{CZjQ6=L`Nvoai4tqb$V7Y(MoYS^in<75y7~p-%Xisw3;w9&RNAdH z7^g~zZ7dP6A~~qKijyQ=zB@=`y=BE{RR*-dw}6XqauC0fRAUWF9wcWlgJogO^?dE> z%`TaPeP1Nik}O9Fl?r$R@29RaeZh?&MTg5uRK?1vM!ngpIqGmS%%L=2w4dXsqXZix z(+C#$&E4u*r-!=&x;+e$coty~Auy^dY)#Zwks^&g8U1zP-=a2B&9bVnPG=k*S#!Kf zSRdj~(UXH}8$GG|Od4IhDAp+}2(!8;s@iU_`i5CLZi_04F*Rqg%)$7221O#T-aKQC zdQvgT>!}|HpFB1C>S_wp^33%j}4ZIJI|q>tHRJOl`Fl!dMz6)OmWB^;@X|l53`e zsCCQmE5k@Ds?F(vmaxc~qb_bzmpo~MQLICB0GCTR^|XaQ%VF{29cVQpdDglfYE>Og zb@WOYw2DQd?~Ni^c1vV@a1xDzPT0ayGZ9F&eia*tMvWHvE|TUlt5o)@h}K4`6UxDaANlC(Z#iO+F2u^VL`nquC2Bq*Wf4DbS&E#ad|{!AZ{S;HVXuL zwaU64oGGk6QT|L3GniH<+M`h_s@GNYT5e8t-_~xk+QZqoV0)ySN5fil?@CaN zVrA~Q?jN%*b`02DSZ(b#wGH&3w904OEA^%#Sihs?wp6#_Q)NsFZ&J9`%))vpdH7vn zblLu)fW@=U1?&R^+u_cgQE+8*>R^Atoj)#P)y&>$t>F+icH33s!q{QN|8?8#Myj7{E^3Wz2Wu7mL?OAT{(|+^vi;2qRZORo>ThjF{rwR^t8^aZdSW!uG43D=Zj7N;4dsW zxy!?N>oEs;%o~1F5*u$tmO2h@v+8PeY;er+Rwi;^J_DIqH+)1`*_5#gcVBC>k^PQ{ zE;Fb?Vbj>M!*QAQ&EwdBN5p}ITScQZIHZd$AX9LZMg{b|Wwyw?b@xPd@xqkLbrPQV zUS}>xiWpz55Lyjg@e2)}zy_67gT~szEowll3=#SQnXC~80A)xef{s(jsAAfz>S$S;iPMDhPC$0c=oOn zq1ZCzMrf^!m`z-lNQ)#*rco%1{cida>eL-%^aTK_WiS+r-L{>;GPcyH>^9-I>`7}y zI?`hJBbRV1p>Y);{Nz%6m7Dim(#2051!b}?L$PeVybX7EGvbXaOHaRNA}PU2;#aP2 z-q@IubdtMR2jt?G*iIBCMUQBiP$QwS9k6g+gr!n9H9^&IFdQ^*q)%9Db&?uOnN}6o zXRCyFLa;RlXR>Ne6RuE*LZFsh%s*C`Nf&elpmKMs-mEx9wWQxk=5`96x7}*h${iT1 zp=oc0;uv@pB@-4qT~Q%jDkZ}HT`0(55kn1KhYf0S9T+PJMy~+U!M?^zm)fM*K?u70 zW_rcoU}Wv>9mTDN!|Whi=Iof}t7i3?^nCTJGUoYe6K4mOpNC^m>sXx;$SSFlJ&xLG z!x2-vNV#j^DtaQPwmDj)k_X#7b_IlZV;eE4!FYhC8|f9qx)7>gE-K`*A(UZ1muM!} zt~*udT%GQsZ#8kci4KJK^le^R1+bo-z;aq#BPET4nUF}gs>f(%mh6jt`U1GNj$?xb z`Z`&et8KNjd;;B1`^+i|i5{vazLd4&J5V9}lt!nz{GDu79DdTvqd@}4RlD7Y=u@jB zqE2z`&Td;BX{M$;6SX6(Iw+!k8Xdd6F!}l!#?>Nqmu&CzSvPJn83Q1p6iMtbJBxzC zxDi)~ZRJZ`PG ztr(*;eA?{+eKg;G_K#>0ZiGsFs+Ra(MX`f|ouH<3zUS>}`7__x`6Anzc18>Wdc9WZ zAyRU~-|kYPx=Un3>Y8(;bGSxen#j6Mpuh)ZXzqYgO&hg)3T}>qn}RcXNi|VZ;#!5z zq3s`=vXC)GWdbH;Fuq~*bHyaH*nuQ|ZqWkPH;$N^`(%2_YIu+49~l}VX<{U9b052V zAAUJdQJD^WKeKyuPmj{-o_clG*i)9>lt>G=t;~}q$JjM5F>z)KP7Wn&o(9B!OHj;pYs_fK+g^SNEN%2w2o!$EyzAjVsb@WtoG6*vhgdeH6y z8`t+(>1J)+GSY87Nl~1gYm-SPbgj4j+EK$KNCXwu*Ru)$}fMf=M9lW+$M@+7^AycVFlSK?;*u-yjgs^*XM7uT^ySrg8 z4k8Ras2o}R4K`|X;^_O48$OGMJyn1=5P=^$&L6&H2Ib*P)B^FWHmMP|6P(tKw7#*S zvgn!xMAbudZ1oq64Hac&AHGxkVZgm(gLF!ytgJY3x{7&nkv@x7o1sY*SvDFFSh^Bb z1YC_yNaD{k6=*de%d3@EG!Y?9skkG6OV!KL9kfa1=o?jmDmP#wqtAgS%1G~GYCu%= zClj~P72RA_Dp3?+Sge}8&V|S@j>&pB*fI97;v!au;}p|K1_KHf7Q36fJ8eG_oiIzc zb*To-y9(6Tf_1Xw%msr_oyuk zH&e?hlbE}NXrIoKwbkW55$0eiH6bqtqw#pN-S#K>`P3Ujagw$#)y{8Kw4-e1-17>u zCgNG1g=r;U-N{)?On@;2Ak>FMompwEJ!e@h@7jm%Pm~mSFLxdyA9kj zg3B^+17AUTnguV#0iBcaGH_uCa%ndZHI%;`f?w&4_bwP2#h7}svANi1N;h;6Knc_3 zhSS{cohdt=PB?zRNLmNsp;E2)E_iFm2%8zTrb)xb&i$m^gaT(`$u}|k8^wS|%Y-BE zWxG(=uak!mNImON-0Bj(@+upKn=kC_nDSD_^s93?P3(kKPB|x8!YyO$UB3gm2#i7< z_;DAA*ABOsE01sOYE6j4SnayIjh^D;;XN@p8!yR8Jjj>p0q2Ji4NMf15y3gQOeLPx zdgq0f-{@H<#acA!Aqd|f4Z~m?K^l=Pj+XA>sDhPnY*K0BG;Mo@Y_w^L@hqY#{7N$F z-*l35hW#4L+(t)NvD`dU>4*4cr3rH)Srs{2L{J*xSu_u=7w0Mwb-oTy>w9pylCV2m z^1IX8b8tl;tdeY2^l})U?-7d#-@wX>9C(^KY=v_p>*^vQ94LXKm$ngL`!qe%(a)k5 z+~XSV%5JIT5GBQ2emhU9fZxMI%rv#8tZ27{S1PzCJcn>nYCyenOm(_F2J1(K5ag;}76ap75V;=Q39nBuDn}3tqva^_2)_ucK zG<^>0uGe%7Rji3jVLYO^`)geOHngSaIoxhBz(!LTyEW}o6 zb&6UOOd;ScLFETST-EERU(+@OqfmXc$+vHYYeSrY-od40xNFXbs3G=~6gOL_In~OA z;_9ht18fSCp>L=ypK%&(1fZts!k|*c@Q!puWu+30xrH0ds=&C+bb_&`MWo4iKn(O?(+(!N^{#;clMkPLR^4k(r8ObdA6@HM)2$r?0%Sg zA1ju<4=bmPSbXT`bUTT}rG@o+Yd@9_2#LB_Vq5TrC^H<0QxuwZ$Jz6$!I4eUHj8LR zlcOO;Lve(RjPngpu^nWYUsG1Iy?hD^r>pMYgRBOW`7DNW;xtwlx7!QPSm6Y@M za6OWpbbZv2t_@|%(wi9!W?1-*mgO@jF2-;}M=_MR5j_8qay1?Fm`SF^3?MLMLw`28 z!8B)#h<^NC9K%6!-V`53zzss?x#VI67^a97M`F7(ojM5I06pdYl-77+&G- zK^>BcAr@L3h6A^cdn<0Cp)UksZa+*hJ3D?ch71rcCIeP!sAz`wOvb%u6l6wO8qJR6 zYT!!l(UcPF&>r3p2K5dnsYRZx*H1~hi|c5byd32*!z$f~cC~4b%)Re{_V(fT>(3Js zQuP@*nuhnS0`bSCdb8(jcM#50ZQWE5b8J&N?&`8*8XE9+g8Q8&9qs5t=7?~)cFP_2 zjx3X1ru!&i^>74*(9s507~ON|z8v^4k{hl@$(gn)Tws*GIpSiE=7a6z!(^Mg+vVCO zeE$&Tw(KA9A&oYR8dGsDfmca zK()|vWt^ccL`{=@bZ3?4IV+17`cp+)9x_f{e%Ls5`7-wVa6;J{r;ZPd2jm-dbT?)O zWi=?D3&B^2+D$T|vQPZ-naJ6xhcB6UErZcbR-4-Lmm^C~y$ZJ`*le82j{RsO_z+tK zPVLQ>oB4Uny&i%v5UrTR`Z)-Kx9Q*5h zL0*R!A$^Qa$k!`}w{a%-2-v;yqnNKbTNU`8g7?$bY*E5jnmk(_wka%ZI@|To-KnE4 zbEyEoEk8+81H#?x-n?#!@*m(O~;xR!|Mhw3YfsJUMfjHjHeG()OoAMQQiA@)k=P zf}7(VfXU1qt9jm~b*uK6kO8V`6zjGd=>}f1Fxh0MD-vzB=~kaWfCwCCpm`GO)W1p8UcQWS(+^qlP}fwzuWRPU#ZRg{l-B z#CCZDKKVvxu=fkK0&x(!n@?rua}a%zN+vK5)nt536lthrs+m~ANd8~;)d=POhxC5H zYxRq#A4G+`=4{}Rhz(pfF)6~><3}*1;VxHC-*)=aGNO=HKnQrr8mSUq%r=wHrD}$5 zx=;s;m7L{rkwj`-`s#BfCp&bpx4OIipsx+Xi~2)#n3~=+w(&8jaWMz3q99IH7|G@C z!?yuuJK{w5S*DThHu?1ZPG83H3XLNYcR+HDd)RmdF5;y~1iGFnW6GDzkwI;oYaT2& z!{1|{zJI5HnZ?D#zYnnTg`LWIgior}%3BDs52_CN8mZPlF^hkW5{@WA2L5<+JJQ@TCqci&zZ(S!n1-(_Q&U zBmE@RTf>M%10H5sii2bypLytM3PY=Y_O^&acy^HO^reL{ zfgKylB!%KZQcYZ>UsxwbP)P^=8k$RqPU(?WBV-q;1WvR)eF6jeD^aag=BSaTPE&+I zs!-TLKr}NZHI9OjoN}(E9~|8&6i$_G6uYxisBHMm<0N8bYeIM63^j5=m+2=shC2yO z#=y`?Xl$z*QJ?8-Tev}Y#WYBp!Nr}Ooz*IITPlL>gP;F688iI_yn6Lz{;$;h&xCYrZ)7ANa-1cS8d`$Sk|KNeABEd5uDB) zBuHWb(Yj1`XOi?6U&KTP&^=l1^#s|Cynrm|63dN9F=LtWO+1N5)<%bR9U`Xk`;8D| z8yLCdPD3k`Z46m>McieeiHSv@Xetg9eHkbJ1SB3L7Xw))@(&oYxqrb|ZBDc~eZ(J` zM1H@dudH!Njxs9-57JsjCVg>v?Vicu08!K{=7!nC~5b5-r+Z+)YVXIVr&CdBY zLJm1Q)g3Ji4zjP8jwzv0H`j!3l zvtC{@4%sC%uKpUBo0Xt*h`iy8-|J@Bl>5T=CWIMfWmAV^{hrWuyIhh(8Y31uEwSC! zLDl*kqV+JsLZ%Y}&887oR#SlB#eKBAsi|~^17zlP(Hp8bnNU0mis>HBfT&fyNP0hv zk0lr|sG^v$HKz@SHF(&S>Eb3O@Pc=<9h!`$;%C<>cem=z3jFN~V2^a4e1W3ZZns*s zatH1NFko+~9P|SpUj5EG7ue@OCFzdDs9FFIB;N+Z&>J{dFy$i^t53>OWRb6AB>jmp zZu7dn2@s)ZaqWp9qVz0n!OnaRg*1&mqLM7CW^{o}IgER*$z8rI%y3E>q2{Hx-x#4^ z^)WL-+tyw7cAZRD3L0DGl9J5GJ&mo=hC8M;kvwU9P4YBr-E2x##!`*$*F=rT%En6r zI%QYUNAI87Mc<+-=L1kwd+pRIajCib?)UZ~0V+wA+PrhNs zUU`u&V`a)s=~j$hq;bg2aVL`{8v=fjq;_+76yn=QmtL9N$hc6qO}CpP$bhdGuHrtUx}nm6F4cLRbZc)P5H*Pa6lKW#6tlRm~{BRn!7l{?bc5eUOe3>XQMyB`@ zCNhaEOLX7O{OFOKroH^s(vr5|Op+fYG7?%P*Rj=Fr&xDw9{k8rKcQnEEIazaxDxDE zNo*$5!1X-S4_KeYYeyz}zumgA(VK0>w@2opg_8zCw_;CXUIz{BIR1%XsAAdIe7sAL zG^ekw7Kuc!q>cGZ(+UvFSYnoGi-Wi#@l18&Xx`apQpS0sL5j&%gO92uiA%1Y7d9$r z+rRcPkTyixlgHQHeL6c@)EQqDhwSS8o}y;1hXZ1Y{I{ z|K5%Gsg8o_3?TD%h1YXakTNPc4NgP$#hdoZs7H;pF)HSH2HPWWwx$CRK@$}Cu^Za5 z;>YeLlibM4%pl`HFu*KwbmN0D=hMW#%n3Ls-r4D+gzL!++JLmJrrRWfy=Z%)1;zWr zraF)_HXo1a9(z12)PIw#JDrBpcF-U*$DM|AHv)&*I5O_UP*bUVxLK142ph4+L^CQ* zYah+r$m0ARvO2B_Q-*g8O<-S>_VVyI zYGk_`b;hpqr107uqm9WEc2_6jZ&&IatBAcQ3_-%?tv-s<+yH9Ns@&r|x7BIX z+>n`WsLY%SrxysiP;`T$<#MG;wcgxT0VoS=J8Dlo-Ike}p-M9p&)WJHMQbEpEa5Vgu~4;^id~+xEJ3*m77Mtm zxOX9!D|U;xub_jtGfp7Rtv;`EvqkUDaWk3U0V{`VwZl~knX4|M9gad+M76awm*0RF zPqn8NRbEjnjiUDYMQbx~`KZ%qoWjx%QkvI^QN@?zdvg&Ik6xPOh_LhAPwK-k5w41a zLHlvHsejYlP+7sx3v}!E4sw8O0f#P8oGQq$8+UkVqZbr(KSnkVE|G=|8a zUf6SKF$7i3;i~I&dVvc%a+&cMjVkRSTZF}WJVwQNQFLjuLn-UVy?CHZ3zM;c?K|f$ zZIy7(rRbI)+a@1a*o61Uw7736>OaN4qr`dmBD zCU2&$Z|%Ri<}YqZ=h`&5iC}=@UDq_{IDKS=Pry|e;ln-Z-5}{I;km8|3-$OmElF`0 zpz+%H4%GPQo$x8>0dM10vnW!x&>9dJTg}Q4*`&T5s%t=FYks^V0c&0JINmM_$DIGIaz`&cWCM?JGy*i?3U|WDpx@gxV>TT)vfhM`ENWLS>Bm+@s zbYheA;z)kNs#W%@y+%wlMwz-%hKMF|rp5{@lkIbDNidhPuy4i~C0~t%jarRzID@<^ zstz<>eL2_YiESYMG|g6rQ7qlWU1Q3=(CcKu{Fsr zWQv>~mN-pQYz)$+Oq3F14>)6+9ec-iDspvPI&5IyW9)JTmmKQ3n&|%R!>q z!oAxgLL0869ue$y1*Zth$(&JoL`=g#O{qr&x@K_Zt(jwNwmaJf11-K2G1h1eq)k|L z6JCn?kKH!GG^;5{=s``4*KSGBTQl^2$+(qZZf2li{z4GZ%z>2PsqsG2NHN`xxww<} z^FErOM?|_N=Dec=%JdaBMDGueh;)tjg_pq^A8Ff}hT+eCk7Nor-Cd6eZ`{e{ zRj8YPWc7>j1({xt2)%XMQe#NkQ#d&8zL!ybf36wTw+Sq?;AW8Ygh>a8)zp;!2+ zYM4JD_YRK;ZPe15vL``w?yjO=eVuz5@!LHzNDhUYi8eypecBcw-PbQ^SI&=D9Rkbv9}xo^Y*v5;o@ED2Fr1yN2RiqbD{) zE;Kl+WlMURtq%TBXSZ}m+EQs;vi69;{71G4EG&`yVVXQ5jMmtfMSPD8tSok%ql2fzEVh?O8 zJ}i^==;$||_w73}&^v=~3P$qD5qoI$8_F?EP2#uxuk_XL${p9q3wI}S#czx#Z4B2iyE83W_~1Alf5P&y zXDN?mans^0>UO*GevaLt*5X@Cy$@`vR>k|kTGsz*@WLQfGwHC!s%!Ux_Qi`pvAr}k zegJ0h|Ea%4$(v}2xLzFBj;G>@j8DAtPb_=yr`t?)``o_7+OCV5!a=b){eXAH+<3W9 z8WD40q_(#@Ho^(+xhB1}YuX*H;ui@RNvf@#cE{;8@BY-7(Qs;xR*HeWx65aVjr-*=`II)1l$7DliD12jf% ze;>uEpZ5up?*ed#ccPoFQn+6?v&--O+mea3u$5ej55u)9w zAPtN(Jx@a``xwt-#%Oxow})U0V{>bEr3g)$6G=ilGQd(q!bKPSeBxdQxC+d@q9(oI z1@VgA4h-9t&Fx@>#Z7~VtodILA|hjHQ-m-HYhU=v$?=4hn*ys}AM4V6rXM2o<@-$g zV>Z+711BeP3pcGde23B zA5V9OFLhuPsdTkXMmB}Yl%DR&M;;)Vq_{Mw6_k6LU6yG=PO|QWP5p-3BJTQK-#m`F zNuJ`#t{0o)^XCyNB=>)$LNBaqOuL7!3aKfKs6arWOr%1}1h!ZN_nnfTV1)LejxPh$ z&$W+OLZ)kU*a>J^{PDF#fSgcti6&FrxY4TahU+PTxl%dlHn%(+mw z^A!G1einyGTCG~SgX1KSPq$PKh5gepvD-5|Pc(PA%m+5;n`oI2Q#uzkYtnw33x3td zJr^uXqB6y0%4IWU7BseSxl1a8O=D}c;f`rdq!c#3CV87DTG*Q+Re4W!zs6J}D;vKc z=#-H;E3<4k@>YWxUX&J(PDaTOVrdj}eJi`# zrWF{8kD{^wvxGDv8Bz7tj_+VZ`&4sX>r|;He$p#S^ap)Ybv$m9uGOnfx43p^w|y!{ z?Lf1RqgjOW3TNCfjVZYOKKX{(P8^Jn{Seh9vXl*_%|;mFCdQgTgV6>w%X&S& zuOXg9Kj(bBv~9tMw^Je<0RZK`WX^14t`gT*WMx3o4i>d3qy`JMc1aLVTS8Uk?cxq zCx@DNWOmBUu}z7h9bikVNc&VK6)8hmVV?H7z!MC&U~;MB&*7S~rK&VUjgD`^Qf4&L zSk_&_9-;)?+@xK%vqlq&1R(_ACBCCEyKKtRsVKTEzZ2^_?S|6DA^!#}eaeamJ7RW? zXS*aBY}e?2t|=E{fHEU0E25$gw=P5gusOP>(-RwRQr7}WToG@T0g^g&PVdn%wo>o* ziM2Ab386_lMG#SVGr$niZJ{)1KIi6Z&Q@i&;hwE4Zm40>Gbd*izS1(_$J2Fu=H z_d>c{;tT0w%@x)L*=ob2V^?td8xyR>c>NZq`7iD{;)hx`RXoYkziGfu@pCRu(~L^Q zmQ~bZcyyGjm9{6-8cUCT5@1%@=3e@0*t;}|%^-a}CfxHl>2uWGTs+mOG`nzHueX}o zG7Xty#V`qujtn9y6Xm=*_KIjsCDbc1d%{CdDHJ=b@+UCkbGcHbT5oP2-iDNj`85w$ zaHS2=ib0czc72bAcYRY8&TEslXiznRHJFnc>=AE0u>q^?sj}MD)mN`H6C<=TW?Fi% z8Bt5~ApYJ~o*K=%lWZJVE!qhgZD{ylr3sH8QINX*VpPk1N_J}P%tUO`zD!v2iyoZR z+r=Rfudmb)x7fzErQZ@4nn42-K%{u&34dB0yur~JWYJP&HbR(Iuw4QJzqB$<#BdLK zCPj{!UWneR@I)#U$X!QqKQLj?)r!-sY&M*7eXDq9x09Q%cgcTe&*}8)__;{jnq>S! zVL{2?s1)n=8rvNE$`%eRErR6eYC^u+9S0F$VD_l_VxPYGn42$`yX^+llg-_&Er(7( z4I}cAxg{ie9?cbYb|B%5r}tqg@1Co)%dK4m^Qw2MyNyam8dp%(pkRwZEbQf_)o&c# z;@uN4aynS1Ba_|wJ&s8HBQKDgzE5v!e4B61Zlvr0QH=aoXJG4a?1F*r5Smda|Vof+gq%wPoLU@uyewpW|jf3aF) z5C_6Nf&$M|5U_sj5V1#%zoqRTcT|)!OwKP6Y9SbQ7d9-#hr^yNuv{<6MizAXb!@AS zo0&(=DRC+r0|lYG#%;;4lapq0izKJW=^e;&SW2=xRu{622Z6wa*|j?5oz@J|%cp6FPbgV8#i15T z4s>ON>`R-c+w**B+;HF^$<=#B`rRXC16(>dq$lM(JBsWb4fS{EuaEY6Wp9R{5s2^-6QwS?7t8 z(HvY5d5|c}LfT@jVkcePx)`XikGrr$!iUAY#APfk;Erd>$<_j8vDIfZDR(3(;h2#& zCR!-_Vdt3|_Dyx7$kM0OPxNjX##{0;(CVNzj9cYOtwxtJ7}Q|NC^a{5dkm%-4EsXO zsa7r&S5H+NnCTFvdR`66XPibGHUO$J)aWXf21+#7?bQlP_^bhIN)fSsB|Zw<(YLdl9V0M|N*xb{01V}!y z`}2%_XAiC|=xD30$g0o{w1eoAXfe8+NFzexoubU#bF?ASjEWjNC}P_@ya!|zGa_VA z`Z*0L`(lpBF8;~~nMJlAMyJ+k`m(Xo&f~_dJ+CUm%9`T z;VIQ5$%)QJ`kP2>E6O`q8XRO#Sm$Qn~fd%aI=v#zX)%gT5G3Vsp2Sl*Xvc~$){C!p9vw68FEDq$E#Vz1!|OeE|uvttm9A07e2Ql$}v zMLAJh*r~NR(NGNk?gFG5txR2~wO2lM>F%fz7bz%R7yJLjT}ZX1e-5SEsw{@C8%824 z4VQ)$f5I;f!@=kVHmrO`uT~k+Qj9IqZW^$YRd(ZNTe{_-)W|y{;RC zOx5?Vj%K=(aUHaM@_nCige^1_ar!lwH@l$p-!-qJE??#h2t%R ze+rQxKXh?!qTv*@ha9Raug{DFa#MW{aNVO`nwc4V+f5_71C~ zVoJ#_uROQaY1D4()N2YWveCR4mXA7(#wj|%PA8W%GGPX)zFDAyPV)h)$VPdw(ClHA zRv(6^;i}SwPr%|)MC2+`i)qAFRtVpSnXB1^PhgY1h&YXuioZCa{;jCg?G>~CLj50j z?RI~}*ZKI442WGFZI``DOeZ+S&^Y>e4n8{dD$J_Aj#JqIuT%C7biq2hPc=rk(268% zb&K}=nmxPlqm5j6?uY9|-Rya471hk=18VAUC$SQp5rmjYk_;i`laIJxUCvS(s@K=X zXM7s6aB^PQ%{IuozUge&n|_(BcZ{~oIYS84H67i6RsxX+W{Qwtf~Ja%4BcKXpX=Z> z0@>P?z0BP$byqPX!Ej}US2VYffd@>TZVE5GvQ}kS=SZ7ZKYBBm&iF_!eX+w*U9yrh zC%lBkhG}mwT1i+;m|VCRomx^cKehHz@Chtj3s#;qf`Sr~1o5GCjf$ZL33B6d2y;pg zQDT@7+#*sn!9Es4Wtp(ok71D&r#_=|Xww6NfGz}>T)u=a!@Xdi4%I>wMF;X6Vnm`! z$aKz-oUTbAi9BAjr~t%J-iqT}OCYbcE|fWlh7v)`eKu#+Xc_^ZvZxiE`&O)kMiEYv z%B?pfS&e|Bi1u7TkYnN(iKuE7xC%Y-=jj(Z1RxX!FD0aN2*HNU(`gva)8ixi(EJ~RYNk#FC zE*%30(>QuyJsL_m(kU1bOid?-ObgPeF;tLqx7XU@aEe#7oDlGhHw1~{%Czp>yK<4$ zD4#@oReGP@)-HMX_eFHoV=rWd{Y+e7CXj$*Q&W>E2Ie&K*WL^XJ6T2a=!+DcHyv#! zEo*r4PFPab6rQlySR$V@uE8WjWJ)cmhEL^=OA^|Ev^y^O7YKBes9mXdio_UeVAN0) ztF2w#z844`s#%lRf{Wl=9M)KgXr4bI`-HmhMsxQuDqMnhlz(K)Wfdd769eU<b^sui)Wn+Wt}K>lk^nu3`1PQEF@Li zzqE-?GZ&Q~tQ(Bp9XX2>GWNTYnExcW!MG3+M?e}ADfSRoisEk6SLsw6`V!q2jDZh6 zm$*S35dwizW5q8jg-#060aOG7Pz&6+?_}mCX=|>m0@|oCQy*rGB36#k4N-#j^cfMJ+Xhx9;W~eQ=iUrX-~UMM`_fY+rgGypug$$aJh= zTwW(Fy@f7uZS(?Zw0!(D$_p!W84YoTp>Ny30vCA!jd{3X3OGy@ednxwW0O+Suc>hz z6&XJ=t%PN4(%1||u?EoejSQKHOkZ@YF}}x$T5Z!cuwbm(utXWfXiFcPA5s<)Z5SHW z26L=UC{-(H(y8$`SA1U~4KN9Fgs|IdGMzm*uErS7k=)=vf#k-(47CRx+fkVb4W!Wx zXgs4`4xFvKw}@tF4x83SD4M12Wt(W`sAc=L){KLSn|gsJ+Id z%-Y)pfuV&Y;tIKlTl%I(NODIviZ1PaldX^x*HMO$WZh581$@%U+#dG%4n?<5b92%F zC25g)2fMw@lXG=i$6pxGU3NAQR3jip|?6rx>5HwGr4JDAP5X&>7wHIKhIF%}vX;Lv)tWWDv1w z)2H&b{36?77c%!5*LH1HZ(YzuHitAUcY^_K2(p3-< zbq`mNq*P!R^Y+q^$l{KlUQRIg&;;Y7Y}sBcGpy7V_8FAr%(iBQT4WmnK1iGXOmb*A zVvZ#r&#koUPSrVAM{I9pPwDJddxe?XjvkfZ!HAxPJ9=hAzvM%|EQEep3H_1_XOzo@ zQ-w3n&4*IWhksfOf4Ddo`f$-w({NrZmfGhQLz(4rOP1d(-{!*=$<0~5T?n@!w-Qd5 zw{&Gb7j9WT7p_Y_zZ|M_e$Mjke7Mf}h46Ug7c6BgS-xGil(7=dZ*Df6ZqCxrbCy1x zv-Ihlr5$sYex6$lljq!`rG87{F`8Spd}|rEc^f6?!{5$Z#%SKsw)y#R{pKxGV}3qN zL-R}FahqQbw{3pe^6g4^d>1TjTd=fa!P0*VOJSN^oDI*n#hfLbg$@?y!c%&2KHRoN z3vDdUhv{$8!Zj8bE%jRt_sf!no|p3BZn}Z*1pIaK9n_Uj~ zBm!ZChaW%MQqG473X7*L<#Ko$x2z+%xmimu&COcKX3j=7b2hS>vklywh1=xjEUYDGTR-um ztx7iOYTh!XbMuxtjUO%jIX|~T#;{X&c)G>2D)%@l3Wo~Bq`go-QoIuD3l+1&%qll~ pwAFD=Zr+6;AAxVoAVcP7ns#Hpa1ULWzlPLZ1Sv literal 0 HcmV?d00001 From cfaa58119820fa4f607f791df60b22e956740fd2 Mon Sep 17 00:00:00 2001 From: Matthew Kight <70612402+mdkdoc15@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:47:10 -0400 Subject: [PATCH 5/5] Added A* agent --- source/Agents/AgentLibary.h | 139 ++++++--------------------- source/Agents/matt_k_first_agent.cpp | 8 -- source/Agents/matt_k_first_agent.h | 103 ++++++++++++-------- source/core/WorldBase.hpp | 82 ++++++++++++++++ 4 files changed, 173 insertions(+), 159 deletions(-) delete mode 100644 source/Agents/matt_k_first_agent.cpp diff --git a/source/Agents/AgentLibary.h b/source/Agents/AgentLibary.h index 7a6286a9..7e7046cf 100644 --- a/source/Agents/AgentLibary.h +++ b/source/Agents/AgentLibary.h @@ -9,128 +9,43 @@ #include #include #include - -namespace walle +namespace cse491 { - /** - * @brief Utility Function to calculate the 'h' heuristics. - * - * @param start point we are starting at - * @param end point we want to get to - * @return double euclidian distance between two points - */ - double calculateHValue(cse491::GridPosition start, cse491::GridPosition end) + namespace walle { - // Return using the distance formula - return ((double)sqrt( - (start.GetX() - end.GetX()) * (start.GetX() - end.GetX()) + (start.GetY() - end.GetY()) * (start.GetY() - end.GetY()))); - } - - /** - * @brief Node class to make A* search easier - * - */ - struct Node - { - cse491::GridPosition position; // Where node is located - int g; // Cost from start to current node - int h; // Heuristic (estimated cost from current node to goal) - Node *parent; - - Node(cse491::GridPosition position, double g, double h, Node *parent) - : position(position), g(g), h(h), parent(parent) {} - // Calculate the total cost (f) of the node - int f() const + /** + * @brief Node class to make A* search easier + * + */ + struct Node { - return g + h; - } - }; - - /** - * @brief Custom comparison function for priority queue - * - */ - struct CompareNodes - { - bool operator()(const Node *a, const Node *b) const - { - return a->f() > b->f(); - } - }; - - /// @brief Uses A* to return a list of grid positions - /// @param start Starting position for search - /// @param end Ending position for the search - /// @return vector of A* path from start to end, empty vector if no path - /// exist - std::vector cse491::WorldBase::shortest_path(cse491::GridPosition start, cse491::GridPosition end) - { - // TODO remove the use of new + cse491::GridPosition position; // Where node is located + int g; // Cost from start to current node + int h; // Heuristic (estimated cost from current node to goal) + std::shared_ptr parent; - // Generated with the help of chat.openai.com - const int rows = this->main_grid.GetWidth(); - const int cols = this->main_grid.GetHeight(); - std::vector path; - // If the start or end is not valid then return empty list - if (!(this->main_grid.IsValid(start) && this->main_grid.IsValid(end))) - return path; + Node(cse491::GridPosition position, double g, double h, std::shared_ptr parent) + : position(position), g(g), h(h), parent(parent) {} - // Define possible movements (up, down, left, right) - const int dx[] = {-1, 1, 0, 0}; - const int dy[] = {0, 0, -1, 1}; - - // Create a 2D vector to store the cost to reach each cell - std::vector> cost(rows, std::vector(cols, INT_MAX)); - - // Create an open list as a priority queue - std::priority_queue, std::vector>, CompareNodes> openList; - - // Create the start and end nodes - auto startNode = std::make_shared(start, 0, 0, nullptr); - auto endNode = std::make_shared(end, 0, 0, nullptr); - - openList.push(startNode); - cost[start.GetX()][start.GetY()] = 0; - - while (!openList.empty()) - { - auto current = openList.top(); - openList.pop(); - - if (current->position == endNode->position) + // Calculate the total cost (f) of the node + int f() const { - auto location = current.get(); - // Reached the goal, reconstruct the path - while (location != nullptr) - { - path.push_back(current->position); - location = location->parent; - } - break; + return g + h; } + }; - // Explore the neighbors - for (int i = 0; i < 4; ++i) + /** + * @brief Custom comparison function for priority queue + * + */ + struct CompareNodes + { + bool operator()(const std::shared_ptr a, const std::shared_ptr b) const { - cse491::GridPosition newPos(current->position.GetX() + dx[i], current->position.GetY() + dy[i]); - // Check if the neighbor is within bounds and is a valid move - if (this->main_grid.IsValid(newPos) && this->is_walkable(newPos)) - { - int newG = current->g + 1; // Assuming a cost of 1 to move to a neighbor - int newH = std::abs(newPos.GetX() - endNode->position.GetX()) + std::abs(newPos.GetY() - endNode->position.GetY()); // Manhattan distance - - if (newG < cost[newPos.GetX()][newPos.GetY()]) - { - auto neighbor = std::make_shared(newPos, newG, newH, current); - openList.push(neighbor); - cost[newPos.GetX()][newPos.GetY()] = newG; - } - } + return a->f() > b->f(); } - } + }; - return path; } - -} \ No newline at end of file +} diff --git a/source/Agents/matt_k_first_agent.cpp b/source/Agents/matt_k_first_agent.cpp deleted file mode 100644 index 8262af1d..00000000 --- a/source/Agents/matt_k_first_agent.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/** -* @file matt_k_first_agent.cpp -* @author Matt Kight -*/ -#include "matt_k_first_agent.h" -#include - - diff --git a/source/Agents/matt_k_first_agent.h b/source/Agents/matt_k_first_agent.h index 7901c6c1..9d5995ec 100644 --- a/source/Agents/matt_k_first_agent.h +++ b/source/Agents/matt_k_first_agent.h @@ -5,54 +5,79 @@ #pragma once #include -#include #include "../core/AgentBase.hpp" #include "AgentLibary.h" - -namespace walle +#include +namespace cse491 { - /** - * Class that describes a matt_k_first_agent class - */ - class matt_k_first_agent : public cse491::AgentBase + namespace walle { - private: - std::vector path; // Path this agent is taking - cse491::GridPosition goal_position; // Where the agent wants to end up - int recalculate_after_x_turns = 5; // How often agent recalculates moves - int current_move_num = 0; // What move # we are currently on - public: - matt_k_first_agent(size_t id, const std::string &name) : AgentBase(id, name) {} - ~matt_k_first_agent() = default; - - /// @brief This agent needs a specific set of actions to function. - /// @return Success. - bool Initialize() override + /** + * Class that describes a matt_k_first_agent class + */ + class matt_k_first_agent : public cse491::AgentBase { - return HasAction("up") && HasAction("down") && HasAction("left") && HasAction("right"); - } + private: + std::vector path; // Path this agent is taking + cse491::GridPosition goal_position; // Where the agent wants to end up + int recalculate_after_x_turns = 100; // How often agent recalculates moves + int current_move_num = 0; // What move # we are currently on + WorldBase *world = nullptr; - /// Choose the action to take a step in the appropriate direction. - size_t SelectAction(const cse491::WorldGrid &grid, - const type_options_t & /* type_options*/, - const item_set_t & /* item_set*/, - const agent_set_t & /* agent_set*/) override - { - // We are taking an action so another turn has passed - ++(this->current_move_num) - // If the last step failed, or we need a new path the then regenerate the path - if (action_result == 0 || this->path.empty() || this->current_move_num > this->recalculate_after_x_turns) + public: + matt_k_first_agent(size_t id, const std::string &name) : AgentBase(id, name) + { + } + ~matt_k_first_agent() = default; + + /** + * @brief Set the word object + * + * @param world world this agent is a part of + */ + void set_word(WorldBase *world) { this->world = world; } + + /// @brief This agent needs a specific set of actions to function. + /// @return Success. + bool Initialize() override { - this->path = this->world.find_path(GetPosition(), this->goal_position, grid); - std::reverse(this->path.begin(), this->path.end()); + return HasAction("up") && HasAction("down") && HasAction("left") && HasAction("right"); } - // Return whatever action gets us closer to our goal - if (!this->path.empty()) + + void set_goal_position(const GridPosition gp) { - return this->path.pop_back() + goal_position = gp; + } + /// Choose the action to take a step in the appropriate direction. + size_t SelectAction(const WorldGrid & /*grid*/, + const type_options_t & /* type_options*/, + const item_set_t & /* item_set*/, + const agent_set_t & /* agent_set*/) override + { + // TODO REMOVE THIS + // We are taking an action so another turn has passed + ++(this->current_move_num); + // If the last step failed, or we need a new path the then regenerate the path + if (action_result == 0 || this->path.empty() || this->current_move_num > this->recalculate_after_x_turns) + { + this->path = this->world->shortest_path(GetPosition(), this->goal_position); + } + // Return whatever action gets us closer to our goal + if (!this->path.empty()) + { + auto pos = path.back(); + path.pop_back(); + if (pos.GetX() == position.GetX() && pos.GetY() == position.GetY() - 1) + return action_map["up"]; + if (pos.GetX() == position.GetX() && pos.GetY() == position.GetY() + 1) + return action_map["down"]; + if (pos.GetX() == position.GetX() - 1 && pos.GetY() == position.GetY()) + return action_map["left"]; + if (pos.GetX() == position.GetX() + 1 && pos.GetY() == position.GetY()) + return action_map["right"]; + } + return 0; // If no path then do not do anything } - return 0; // If no path then do not do anything - } + }; }; -}; } diff --git a/source/core/WorldBase.hpp b/source/core/WorldBase.hpp index 371231e4..bbd2a773 100644 --- a/source/core/WorldBase.hpp +++ b/source/core/WorldBase.hpp @@ -171,6 +171,88 @@ namespace cse491 { /// @param end Ending position for the search /// @return vector of A* path from start to end, empty vector if no path exist std::vector shortest_path(cse491::GridPosition start, cse491::GridPosition end); + + /// @brief Determine if this tile is able to be walked on, defaults to every + /// tile is walkable + /// @author @mdkdoc15 + /// @param pos The grid position we are checking + /// @return If an agent should be allowed on this square + virtual bool is_walkable(GridPosition /*pos*/) { return true; } + + /// @brief Uses A* to return a list of grid positions + /// @author @mdkdoc15 + /// @param start Starting position for search + /// @param end Ending position for the search + /// @return vector of A* path from start to end, empty vector if no path + /// exist + std::vector shortest_path(GridPosition start, GridPosition end) + { + // TODO remove the use of new and this + + // Generated with the help of chat.openai.com + const int rows = this->main_grid.GetWidth(); + const int cols = this->main_grid.GetHeight(); + std::vector path; + // If the start or end is not valid then return empty list + if (!(this->main_grid.IsValid(start) && this->main_grid.IsValid(end))) + return path; + + // Define possible movements (up, down, left, right) + const int dx[] = {-1, 1, 0, 0}; + const int dy[] = {0, 0, -1, 1}; + + // Create a 2D vector to store the cost to reach each cell + std::vector> cost(rows, std::vector(cols, INT_MAX)); + + // Create an open list as a priority queue + std::priority_queue, std::vector>, walle::CompareNodes> openList; + + // Create the start and end nodes + auto startNode = std::make_shared(start, 0, 0, nullptr); + auto endNode = std::make_shared(end, 0, 0, nullptr); + + openList.push(startNode); + cost[start.GetX()][start.GetY()] = 0; + + while (!openList.empty()) + { + auto current = openList.top(); + openList.pop(); + + if (current->position == endNode->position) + { + + // Reached the goal, reconstruct the path + while (current != nullptr) + { + path.push_back(current->position); + current = current->parent; + } + break; + } + + // Explore the neighbors + for (int i = 0; i < 4; ++i) + { + GridPosition newPos(current->position.GetX() + dx[i], current->position.GetY() + dy[i]); + // Check if the neighbor is within bounds and is a valid move + if (this->main_grid.IsValid(newPos) && this->is_walkable(newPos)) + { + int newG = current->g + 1; // Assuming a cost of 1 to move to a neighbor + int newH = std::abs(newPos.GetX() - endNode->position.GetX()) + std::abs(newPos.GetY() - endNode->position.GetY()); // Manhattan distance + + if (newG + newH < cost[newPos.GetX()][newPos.GetY()]) + { + auto neighbor = std::make_shared(newPos, newG, newH, current); + openList.push(neighbor); + cost[newPos.GetX()][newPos.GetY()] = newG + newH; + } + } + } + } + + return path; + } }; } // End of namespace cse491