From 6206a202bc81a84bf6f69bab3762f5eff7e5d4f6 Mon Sep 17 00:00:00 2001 From: workinghard Date: Sun, 16 Oct 2016 23:49:22 -0700 Subject: [PATCH] init. --- Cube4Fun_ESP_v1/Cube4Fun_ESP_v1.ino | 540 ++++++++++++++++++++++++++++ img/Cube4Fun_Schematic.png | Bin 0 -> 27440 bytes 2 files changed, 540 insertions(+) create mode 100644 Cube4Fun_ESP_v1/Cube4Fun_ESP_v1.ino create mode 100644 img/Cube4Fun_Schematic.png diff --git a/Cube4Fun_ESP_v1/Cube4Fun_ESP_v1.ino b/Cube4Fun_ESP_v1/Cube4Fun_ESP_v1.ino new file mode 100644 index 0000000..7c86753 --- /dev/null +++ b/Cube4Fun_ESP_v1/Cube4Fun_ESP_v1.ino @@ -0,0 +1,540 @@ + +#define DEBUG 1 +#define ANIM_FILE_NAME "/ANIMS.FRM" +#define FILE_READ "r" +#define FILE_WRITE "w" +#define FBLENGTH 65 +#define SERBFLENGTH 32 +#define SERVER_PORT 80 +#define MAX_SEND_RETRY 10 +#define MAX_ANIMKEY_LENGTH 12 +#define MY_CUBE_ADDR 2 + +//#include +#include +#include +#include +#include +//#include +#include + +#ifdef DEBUG + #define DEBUG_PRINTLN(x) Serial.println (x) + #define DEBUG_PRINT(x) Serial.print (x) + #define DEBUG_PRINT2(x,y) Serial.print (x,y) + #define DEBUG_PRINTLN_TXT(x) Serial.println (F(x)) + #define DEBUG_PRINT_TXT(x) Serial.print (F(x)) +#else + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINT(x) + #define DEBUG_PRINT2(x,y) + #define DEBUG_PRINTLN_TXT(x) + #define DEBUG_PRINT_TXT(x) +#endif + +unsigned const char lc_slash = '/'; +unsigned const char lc_question = '?'; +unsigned const char lc_coma = ','; +unsigned const char lc_space = ' '; +unsigned const char lc_f = 'f'; +unsigned const char lc_F = 'F'; +unsigned const char lc_s = 's'; +unsigned const char lc_S = 'S'; + +unsigned char myAnimationCount = 0; +unsigned int _animationSpeed = 0; +unsigned long _animationLength = 0; +unsigned long _animationStartPos = 0; +unsigned long _animationEndPos = 0; +unsigned int _animationActFrame = 0; +unsigned long _previousMillis = 0; // will store last time animation frame was sent + +unsigned char ga_buffer1[FBLENGTH]; +unsigned char gi_buffer1_pos = 0; +unsigned char ga_buffer2[FBLENGTH]; +unsigned char gi_buffer2_pos = 0; +unsigned char ga_sendBuffer[SERBFLENGTH]; +unsigned char * gp_read_buffer; +//unsigned char * gi_read_buffer_pos; +unsigned char * gp_write_buffer; +//unsigned char * gi_write_buffer_pos; +int gi_status = 0; // 0 = + +unsigned long sendDelay = 1000; +unsigned long lastChangeTime = 0; + +int gi_pos = 0; + +// Initialize the WiFi server library +const char* ssid = "Enjoy"; +const char* password = "iWLSpo8zZ3NS"; +ESP8266WebServer server(SERVER_PORT); + +const char* www_username = "admin"; +const char* www_password = "esp8266"; + +void fill_buffer_random(unsigned char * pp_buff) { + for (int i=0; i MAX_SEND_RETRY ) { + // everything went well or timeout + try_again = false; + success = true; + }else{ + // Something went wrong + DEBUG_PRINTLN_TXT("Send failed"); + } + delayMicroseconds(10); + } + send_retries++; + return success; +} + +void sendBufferedFrame() { + boolean lb_send_success; + // Send start key + ga_sendBuffer[0] = lc_slash; + ga_sendBuffer[1] = lc_slash; + ga_sendBuffer[2] = lc_question; + ga_sendBuffer[3] = lc_question; + lb_send_success = wireSendBytes(ga_sendBuffer, 4); + + if (lb_send_success == true ) { + + // First half frame + wireSendBytes(gp_read_buffer, 32); + for (unsigned char i=0;i<32;i++) { // Second half frame + ga_sendBuffer[i] = gp_read_buffer[i+32]; + } + wireSendBytes(ga_sendBuffer, 32); + } + /* + DEBUG_PRINTLN(""); + for (int i=0;i(myKeyBuffer), myKeyLength) > -1) { + // We found animation + DEBUG_PRINTLN_TXT("Found animation"); + myReadStatus = 20; // End search, we found our animation + }else{ + DEBUG_PRINTLN_TXT("No animation found"); + if (_animationEndPos > _animationStartPos ) { + // Goto next frame + myProjectFile.seek(_animationEndPos, SeekSet); + myReadStatus = 0; + } + } + + // clear buffer + myIntBufferLength = 0; + } + break; + case 6: + if( myC == lc_newline ) { // uncomplete keyline or no animation found + // check for values + if ( _animationEndPos > 0 && _animationStartPos > 0 && _animationSpeed > 0 ) { + DEBUG_PRINTLN_TXT("Anim key found"); + }else{ + DEBUG_PRINTLN_TXT("--keyline failed--"); + // Reset everything + myReadStatus = 0; + myKeyLength = 0; + myIntBufferLength = 0; + clearSavedAnimation(); + } + } + break; + } + } + } + myProjectFile.close(); +} + +boolean readAnimationSD() { + unsigned char myC; + unsigned char myBytes = 0; + // Read SD Card + File myProjectFile = SPIFFS.open(ANIM_FILE_NAME, FILE_READ); + // Goto start position + if ( myProjectFile.available() ) { + unsigned long _animationPos = _animationStartPos + _animationActFrame * 65; // startPos + offset + if ( _animationPos < _animationEndPos ) { + myProjectFile.seek(_animationPos, SeekSet); + }else{ + _animationActFrame = 0; // Start at the first frame again + myProjectFile.seek(_animationStartPos, SeekSet); + } + } + // Read one frame + while ( myProjectFile.available() && myBytes < 64 ) { + myC = myProjectFile.read(); + myReceiveBuffer[myBytes] = myC; + myBytes++; + } + + // close the file: + myProjectFile.close(); + + // If we have complete frame, return true + if ( myBytes > 63 ) { + // read successfull + _animationActFrame++; + return true; + }else{ + return false; + } +} +unsigned long byte2Long(unsigned char* byteArray) { + // little endian conversion + unsigned long retval; + retval = (unsigned long) byteArray[3] << 24 | (unsigned long) byteArray[2] << 16; + retval |= (unsigned long) byteArray[1] << 8 | byteArray[0]; + return retval; +} +void writeAnimationSDCard(WiFiClient client) { + // Send answer + unsigned char readBuffer[4]; + // First 10 bytes is a key, following by the length + readBuffer[0] = myReadBuffer[10]; + readBuffer[1] = myReadBuffer[11]; + readBuffer[2] = myReadBuffer[12]; + readBuffer[3] = myReadBuffer[13]; + unsigned long fileSize = byte2Long(readBuffer); + +// DEBUG_PRINT_TXT("fileSizeBuffer: "); + for (unsigned char i=0; i<4; i++ ) { + client.write(readBuffer[i]); +// DEBUG_PRINT(readBuffer[i]); + } + client.write(lc_return); + client.write(lc_newline); +// DEBUG_PRINTLN_TXT(" "); + + + +// DEBUG_PRINT_TXT("Filesize expected:"); +// DEBUG_PRINTLN(fileSize); + + // Blocking mode to write receiving data to file + if (client) { + // Remove file if exists + if ( SPIFFS.exists(ANIM_FILE_NAME) ) { + SPIFFS.remove(ANIM_FILE_NAME); + } + + File myProjectFile = SPIFFS.open(ANIM_FILE_NAME, FILE_WRITE); + unsigned long receivedBytes = 0; + + if (myProjectFile) { + while (client.connected() && receivedBytes < fileSize) { + if (client.available()) { + unsigned char c = client.read(); + //writing bytes + myProjectFile.write(c); + receivedBytes++; + } + } + } +/* + if ( receivedBytes == fileSize ) { + DEBUG_PRINTLN_TXT("Complete data received\n"); + }else{ + DEBUG_PRINTLN_TXT("Data incomplete\n"); + } + DEBUG_PRINT_TXT("Expected:"); + DEBUG_PRINTLN(fileSize); + DEBUG_PRINT_TXT("Received:"); + DEBUG_PRINTLN(receivedBytes); +*/ + myProjectFile.close(); + } +} +void displaySavedAnimation() { + if ( _animationLength > 0 ) { // Animation was set + unsigned long currentMillis = millis(); + // Display animation set over the network + if ( currentMillis < _animationLength ) { // __animationLength = startTime + animLengthTime + if ( _animationStartPos > 0 && _animationEndPos > 0 && _animationSpeed > 0){ // validity check + if ( _animationEndPos > _animationStartPos ) { + //DEBUG_PRINTLN_TXT("Setting mode to 2"); + setServerMode(2); // Switch the server mode + if ( currentMillis - _previousMillis >= _animationSpeed ) { // Sent data with the set speed + // save the last time you sent frame + _previousMillis = currentMillis; + // Fill Buffer + if ( true == readAnimationSD() ) { + // Send buffered frame + sendBufferedFrame(); + } + } + } + } + }else{ + // End the stream mode + setServerMode(0); + } + } +} +//END:---------FILE handler ------------------// + +//START:-------HTTP handler ------------------// + +void handleRoot() { + if(!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + }else{ + server.send(200, "text/plain", "Login OK"); + } +} + +//END:--------HTTP handler -------------------// + + +//START:------------SETUP-----------------// +void setup() { + Wire.begin(); //for ESP8266-12E SDA=D2 and SLC=D1 + Wire.setClockStretchLimit(1500); + +#ifdef DEBUG + Serial.begin(57600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } +#endif + + + // always use this to "mount" the filesystem + bool result = SPIFFS.begin(); + DEBUG_PRINT_TXT("SPIFFS opened: "); + DEBUG_PRINTLN(result); + + // Start the WiFi connection + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if(WiFi.waitForConnectResult() != WL_CONNECTED) { + DEBUG_PRINTLN_TXT("WiFi Connect Failed! Rebooting..."); + delay(1000); + ESP.restart(); + } + //ArduinoOTA.begin(); + server.on("/", handleRoot); + server.begin(); + + DEBUG_PRINT_TXT("Server started http://"); + DEBUG_PRINTLN(WiFi.localIP()); + + // Init the buffer + gp_read_buffer = ga_buffer1; + gp_write_buffer = ga_buffer2; + + // Random number generator + randomSeed(123); +} +//END:---------------SETUP--------------// + +//START:-------------MAIN---------------// +void loop() { + +#ifdef DEBUG + if ( Serial.available() > 0 ) { + // get incoming byte: + char inByte = Serial.read(); + if ( inByte == '+' ) { + if ( sendDelay < 10000 ) { + sendDelay = sendDelay + 100; + } + } + if ( inByte == '-' ) { + if ( sendDelay >= 100 ) { + sendDelay = sendDelay - 100; + } + } + if ( inByte == '1' ) { + gi_status = 1; + } + if ( inByte == '0' ) { + gi_status = 0; + } + + //DEBUG_PRINTLN(inByte); + DEBUG_PRINT_TXT("Delay: "); + DEBUG_PRINTLN(sendDelay); + DEBUG_PRINT_TXT("Status: "); + DEBUG_PRINTLN(gi_status); + } +#endif + + unsigned long currentMillis = millis(); + + if ( gi_status == 1 && currentMillis - lastChangeTime > sendDelay) { + lastChangeTime = currentMillis; + + // Fill the buffer with random data + //fill_buffer_random(gp_read_buffer); + fill_buffer_run1(gp_read_buffer); + + // Send data + sendBufferedFrame(); + + //print_buffer(gp_read_buffer); + + //DEBUG_PRINT_TXT("Data sent. Check digit: "); + //DEBUG_PRINTLN(gp_read_buffer[FBLENGTH-1]); + + //delay(sendDelay); + } + + // handle the Webserver requests + //ArduinoOTA.handle(); + server.handleClient(); +} + +//END:--------------MAIN----------------------// diff --git a/img/Cube4Fun_Schematic.png b/img/Cube4Fun_Schematic.png new file mode 100644 index 0000000000000000000000000000000000000000..323479ce8a3d765e7bc5e99ab94c7e6a8276227b GIT binary patch literal 27440 zcmce;byQVR`!IM2Q4kCS5s>bb?lJ(SL{b`wONU5FUPM6}q%Mupjf9lIRZtp)E8PMr zTvEDcA9#Q7H-F8V`PR(rwOH(P&dz5){XF}IsH-WG5K$395Jd9m;R6i_y7U%;@YFBi zf;ZpOpJaf4gw7B3UO*59Dg1|Hl`#NX(L;|O+|}|-U7l2q#I`rGnGSx@dlO9JO;~-o zgnoGTy#fgd$rdZG%Z0kPmv7HFqCMhZvgCAJtxp8QED=&_eoHB+v=QQg2 z(aPcBAr6=dg3#N3^NwdV2yJu;ab6?6-hEzSW<;Ggd-#A4@9b6dTT_Cw3jOsj#Ag*b z##fYQ732ea!Lte!^8a|CAH}E}^iC2$$Rh3%1Zz6Hz=~^N!8P>n;kpt%So5mSybi}k~2HQXykZI8zjfu?CbCU#}N;ZhmTA~ zRNLGfmdoQl1QGobB!z1JF~PXH`k_dS_!I|1_C16qA^_mfB@wGW-jm6+n0tYC_i&H` z5i<1BJ_@)<&AK*X=ton|mZiSyU)qoJ63~xNCz?OD%=@cmrOBbMur$mUabkVtevh7yPwLcG!(eDJR2pcje%Y%u3Fc0H%SVMc<9a zD)Wdo)jN+qwTrxg>1c)8FQ23@UN7xYW#IS-E~I^_*lEaLLE>XOR*-a_6r~W$eRbqm zAwW;^I7%%l>r?4Q?N*M78zI^_huyKPlzwjJct5yD25DCHq;i2%#PJ!||)b2xWPb zcdnlfvE@=3IO)eCmKd~efW3Ld`FVNPcFw#~hi1}!6kcISDg%_+jPX~qUA~Q{ap~Rp z!VTvA(L|F`9@QpNKHC+bz#{zah|A#V_vDs!EV#b0?tTIeE6nY2s z9^2uudoOwJQ78b;gyt#s(`ow4YJeTz=Bf~1BF8wa`=J=P79_S%QT zF~(F)w$l@tIfM$8Q6@rtA*3**dyjOSKl{KS%#;SmB%mB{w?+G8ajiNz`Sw~4Zz9oW z3%AKi^h$${sM^YzbdgiTG;pW0H@Wk9<%ZqIL4Ka{uQi(kD?7|KxyJ3oO#FbgMYqwo z3@w=G#~fvo0<)exaSiVBrx&3goEb6n0fXfAW{!@{gU-U0$`l&d8h`aFN%5p&8rbGQLCiB9HG91Ij4^ zsCKPf|1l1nt8UMuC?RBQ+EcMTpED*WvKNlO#Tb}6+MVU?V0zhVGMe=_ja6XmpvRg? zwfS7tUBLS$9v(4osAeGhj2@f21{(l+oUsj{`V|xP2mq3b|HfV3!JNw-RM$`kf+SL2 zie5G%i{jYbv}3mi0zHR7XiItk0YMtlY;WtqSE*0`mYdOjj1@v(PvPa6rsxI>fTRV1 zu%b>Hx*lm_m@uMcr}9mN=!0kO!sh(b^%4O;?%7Fa(5?sFetGV=bx5_-|{ z74{R5X~G#XkZA}IA5dg{DSPGw1pVv+ya{D_&V3;{#&f<4#jS4ccTeJrjXGG#o$MSR zr!|lOVf1g`XKE*l4MLNGqf_C$U$pviy(W$llG8Zd8!wwsg&_7wm{SG=sM8lTADwuw zvI4=_2BuhTkp>tBO5yXqoDA!boc-?qpEMA7(*IXfne%~UUjQ(Jf_(LPdTkgR-$1^+ z<=33(XYuqh!}*R(qh#>ZH_Gmb8qalXo8kUBA+eErab*vCe$(3y$uhe0k68a2u*K2?jxCZ}6yZ zaCeH5OoiK=OEm~O5i&x!4RpIoydk_)-GOv6@<^8@k_HEb)ctWTyaj{?UCm;ccS(Iu*RU9Kw00bI2}*ue$& z*2C8DGbIsu7}{Z;+ZXckwE&N5v_NhL>U?9)9vA^%C#^L9M&kf4UsK6AQ}<=C;{Tvo z`Dl5ZldU}Y!883%eXzOzisT3>*$fjplR5(&Nc|>2w&l(J<niTvkQoi<2$i;P7| z<+~8&7h>iLGW`d}@zL6UUZcsYsT_Jq{8~ZM&!p{4uRf=^F$&c2u2*AZ>#buuJi;DZPeJ=B_4%$db@MG7 zD&T>8F|)f*<;Hj_NkpX38Pt#*Ux?>D4#rH@WLu>Ke?VdH&RVC!x+Gkp+xsR+kPWrg zj-AU@sQ#g1`LknCzx0LJaCO^jyZ_;7l%@`$WRq|h(CR?RW<~`#m?1J$Fp;Y2=cHTMP%3+PFbrn@1Sp7 zrn{qs7(wOah1kN~ZjE^)nw8#Q7o^I)2XNu&(9|IT?uG7gi)V~QBn#;a{F%Xw^n_DB ze71PP&vGkQ;H3e)R5_!#wJ>1=ELKxA9{sr+6<{Y%JLi(tk}UuayA_0ecY#P}O*Y$( z(&}y9aP>1)G+2S5$0;gjP=v{8)rF(r49XK<1{zBj_&Ep>rjvg*_dTUf*8ER*=Qj4H zPdDiJ@9bkuP9=`|PPaXecE`F-4~CoFoql4cHa2BXUwFr!GMA^do7iq)Ur$?`Q1pjK zm7Q@n2->-2{B**^R?1s`ZT;?rT%ZLgfS$&B@-YO-4A%nbi#^d2yYA(i7Vv=c94EK)!&<5dxL(FV;&c@Nc-{$!R zsKsJn848Mrs8L%nTf9y8K&KnC`F~jb#4A(@{y8&2ri3O*^&e~9ZN@pKPv(tHgargB znH&N1s+_TD|5;xyquo|OUco=zR#S4=)`3feSb9^tQ|WKo^O^oP3`BU8|4a4^n{&=~ zYrEcyia>M5Dt|3YYvTK7qdXq<5-}6;wyHX#;ZN|P)NgSx5Za+}+Q}`@YlU6>9k2?B z+{_kz7M~VNOqZkoAr?5}&a-i*%HzWEkLb)73+b3Hpo->;HTjwS(VEgf) zZO$IH{crCcR8I6fGm=$NX1Qyg9Arw+$s+cwW>l7TSPXoIp0zA}8CuvFtSG#OdStE= zd%YW764I11oFSHW7p6wfw+2M?sDSU{y;DQZwuJ^=aHpam3@ffMi|)avHWVu>D!?VJ zVf|;hM4xK-iD#+_+>O2=qmCL);|sHS^#JF$q$i8^;!WOgnXRoo8u z+J<#ui46USTxz1o_%`V<9&4&{XUv4CZ08c9J#)R$jQLA}Q1q)*&!6Mh`+gv2r4jEU zJdFXdYPBrg^{BJ5c=SbyXXTM#?rt#?AtKXS*{W%he5c)00f7nXUlgs~p}gNtZ*>6a>*V`{?!?jj zstSB~D+bBTvz}w+=o$SVFx#0)|A}{bV|;hlV^u`1UnZmPWEv>$lm@sgm3eZX|NPm+ zwm9NK>uf+PM6FF$wN6)hpVJ!j|D{I;7AVlk%CTQFP{ki7`jL5Rn_iA7V@xbznv#~4 zD(3HlLEy-1nEl~erCa(O%LCGD-Ex<8idHHWErbueE_~-*@8EDYgBi`p`!W%B{`fm5 zAEpNLo=2M!DD~59>y#;8Qi*@+wKA|F^pB>4%dgd>OxIK;O$UsNycNTe)qf$g6jDQs z4Pq1{Ij)IC(!>v$C#(dh`X?dE@Gb;c=UYRV)2ZMQvYrTPmt85HDywmjD~R# zQ2h|X7gT@!48QRX>nML8Vp}`TezDAQ=lMBN@iT^LDQgNDo}{3K#6qGpzFwZ8{$YVH z_#<+0Rv`EG9XzMONGy!@5c~8pOI-{zFALb7U&~%=Ow3%+rpBZ`ys@`rCfP1IPK0W= zFW@DQzz{QyT6fJK#tI+J&v(PbZP+QX#GyKTTQUu&G0rrI7##0}Dzg4tcfnF+(w5ba zrJarc5fqs;gT8lU+FfWO9!X_VtlW8{>y0mHp}uF#@3LLsy3?yaNu;HQka|U_vUkVA zGb*XoU)gPC4$R?P%GE@{cF8-EqM-YuwMsHhqZLgDP@Qeb+wCJKaIb(S^ix>iw)rYf zY>oShvfYNm{mQgaguzRmzkXCFOwUPSls8M&$kyn$4aaGW%;~0=RTOpq>%<@^e86q_ zTnZi`h><)Sc)~1hyeJ%Zl}I%rbai7g>X11xVmCZGfUzBlT9M}*%q~<_eoG((Ob_}> zG;@T<>SF3U;!BoLY|UVbvVEh)Z_;nUBQ z0}eQ37mv}wa2_}BRebQOmJpa+^eJUgWqVTJ4Ph-8NdT02`bypu!auwkXD>vab`nFK zEKxB1Sce0?6K&F+eWnmo!A`X}JJ*X;9WbYpTlv3b@4(i@-s#lZ?z$|Xpcxxw*@&0- ze5k*!jBd>*Jc#_cl~hzl6gBB;=dcS)+~}^uV;%SWVTU4j^6LPlE89Am_B+W%s`IM8 zXDqbFjP+-vi2TAgOaq|sfc1`jC2USx z(%g$?7Zs3-E4+IWb1xE^(%YINd{T>1w8a`Gjs7WX+O|{kVZzCMQMW49pzH*B%sf@} zI$6pj>4`%oQ<$_1q;-{NOA+rLah{kg}_S08@cwK6?a-Pt6mwSoW{q*#V$J62* zntOLP9sO&(@M`heBnCEhFZMW7zgsHSi49*I1TGWjI$mVbNtyqvMFBFF+$$~_`XN)$ zD*9vO*3sbIq@abpcCNeH>*MAsH}-%cA}4%1t}i}UHaH_A+$agSBSEQQL@@;R<=GiW zDm6RC$5-@%?}}^hxb=(d=uX?F{f-xQrv*h!+bofZ#^UVkN?8$Ivg3O^y&8T_BMmkR z`wa#yt}@K#9z~PQe#ZxgvM>BFD&Ms~uRM~?r5KEnX$n0dU=- zb-$8Ec;!R*vG|x@g=Q73^2&nb`OvJ`gHiR1y(u)a@_`FdV#{pc_A{2f_ys7vM*lj-69>a zPwJWd00aVLUbqv(_$TY{<4g%)n-x)foccqm)`&9^U{15RUlcgNts4Kdz7yk`v~vps z`^=&6H+C!@MeqKS%v`yReb{G0L&omHkZ@vC*{3^Q7Q?T)4CFc5*R8E$ov^HdnL#^D zZK#_;(j~j%^P2hljG~h+9HNg}Bz0Et5B?X=L0hQ_82hBd8v^=vM4e`hS`=j_D-f`>enl7ynsA(WCD|{D7b3on(qg)9*z6^qeWG z->5WG;M_Qrd37u$IsUzXY-AQYSHu;$by_R<-|gW&%xx?*$^p!)yWSvQS|n(2;ZiH< zf~a5YU`##xd&1^5^O6kJ0+AG=9{?O;dyJS4-j%MMrbm<(DzP>*>c8cLTS2HSH zOQh8;@!SK>029lx5~&0CBt zD+UwD$pc|17IIlVIp=oHW5WdAtA@$Wb1wJ5r%b>Gpv+4~wWJSCf*w;#^PX{F+l@2# z_X*GKJ{3&jNz5Si2)xiZKxt4Mug@Cg3rp~b3r+vVwiGd9Z(KUKTXQNf=i;JIb89)5R)S!U+VSCs7ShsU%hf3Vx3KEIcW>i^tv zaIUXL8?D*wTJZte_|K&D)Zpo|<6p_*9~S0rT+5AU zwfEn8n4`Ek7R=%7_eMbVMWRgn^$xHw!#{EL*M^gHMslNW7b`vox~#=b_6DF!(FAv$ zXg5rY{wrx&6KFX0stoW7wyC1YPt*c?%@kTXq}(1%->c}e<>)}NZUT@Z+sya#Yu2ns z8aaPw-X8Izk6LW4vDnMdrkm!XV$Ij3K!*=d!1k*gRZATO?-ng!FD7n(|(uT2SD zLiNV5p?pj(k3LTRnJG-_#dqdoA{kd zdvFm|NO0w#Jt+Qw4P<|&+gqD60W9q}qh>F+U=M@h#`AhYvp84uS3dw~PejvP3KelE ztD+rDplN2UNiRpa)1%?B1XlD-85K%d;=$@D|9MBbC+Qh|OZTpraN|Ixu}di-wI-DBe(3zqxMN?#zJ@Ejb9BmS9_>5{~64?Ml3#6%qFmH z3uJ~Q@#C?Cs^ncRTkfL;p)NbajuwkmKG5cxQ^C6*Px&tr0Uw^VD&6%SguDP8vNKJn zyB-|`bf`SkK2kUJI@2G9!Wj=@Sd{)KM^${^`n0Z*s??M4j@TObwB)WQu)a3-l_OSp zApLJhxzf-s>Y6QO?s_bC#UJ#Tkq8J4c;_ofY{>w#k%JdgTjidM0RrnyEf=re+z6&F zJE)!B0f9LPvKMIR4OYH)nSz}KAS`HoRKL#>wJ>^>BL1Xh?NH2p#AwX3G58;AFdSN~ ztwa4f9Qef^)mhf+@YK}stGR<52B^5#5%(AIFYM+tpi=)0WkrZa(+P>IfcB823YMIc z{Eb1xG%bM;2sDscESlB`HLUL?>^eALE{{vT(iK% z>IeFqX&zA*cXH9iVJKfd^@^zJho9vPP2Ma8b#%tUYg|dX`7$?ZIbTuL&ZF?r@c#2( zpTe&#Ut@2$Gda#-k7W)Y{nPe&J6ESVxl>AsCU^F-q$Cx5SaL}RjE{Y)tu#3vRiA47 z!53VUP37Kodvs{1*;oA4Au{?}5H!GD1KGD@;IvjR)LxXG%G_5pY&=9C-#_ru_ zX^N||skC=vN9h&zQSrSc6Qo-YrQvj;HS=+C?i?pCs((gwbyWJkFx&;vU1~~aQxK=+ zv{I_zy~_}b;zpd8 zqZcth`atBhvMY;)9c!ee$oYA!lC--!;mY7s@qF0Xpd2FZGR!3<>L3$uV~#3SAC|e& zx_2n+-#7XC)nAhKE*Vsi9|6*PsYu&M9((L(V$@u3MPt*Vfhf6o?LEKyAm=Ssc;TS} z`V1v2CVxlCui_(TAQKZ1~dG+UzaM9@M95<)-0(0IrJ6Z2mC48 z6AYDS=!n_|ym@A*-kDK~YdusvkbmtkI`ioLz_aA0A4g|EPtn}q`V!>b%}uF&5YE0_ zF2u6Fq~vAF`75U8ic{rO)&rgvGGn}|sT0`6H1k%D!$u!j*chims&>5_jeM> z>!I!7Pp#gXGrqxBCH}c{0;DLqoeHmDRfVJA_7gz_;&M!YOUXFS7uMsWAeu_LQt#1l1RJl32lxGY1?O>!L&%yC=+Y~{S6`^45?iXuMAd=LW^6*uf^&&6p&a|Ez3Ffc% zcQSY(y>ah4uX{%&&GHf7Al8|5!~+>esPVos#bJSTYFN+Itmo@I>_cHK!eCN*SggQS$x5oEF!41)YqW8PBxd z*FUo@2627}*?MItQtc%6;w61W%sPxH-Q-HkCz70>E8J`8xY#J}AhD}5-zbhV&2j-~}RUnfF8JQyc7 zbl;vd|Gl~IBSi}wQ6SqxR9K4TqRtPc!P|(x{-#B%n}acbs-tVuWAVt+hkvM#ql zd&X6J=28B9t93?w5QpXIaCH=bKDw@S&)Cq&tt#5<(n15^5z;8Vl7*fr=U<`rh|X+E z6zBSch*UV)$Y*XBd4U7EOXCL}h4puWQ_i`}_olU*O%^hhFJnBov8b&jrB&0?Y@10#M?e*t@DwO zZ2bH1Q%r?tTNVr){q)t?bxO+GWp@I>4(>O+S+5mD?yn^DzR;a6mo7inoT~pg=k3<= z^XWN07#T@2O5^Fi`VdGNhI)R{chSd7N@G<^nWmBXh+Y*LzydUzXK4%p3Y^CC@L(h z!_a>$vQuOlx*(o7pxyz5^wi;T{i9zbYc%Sdt_#K@@+Su(1$}+6yf^($R%t|`7#NVM**9Lxgk_}_nirPb*5`ahi$MgX zr`=1&b~*Wsu|t-j`kma%$9|93POAEv47yY@Y;a+B3rTrc5;02$0 zF6zU0OjM#<|2YBg`4MEQu%(k+O}HyonqzA`_^%ID$18TdLp>}f&}i3l#!e;kcJpFa zpT>;W`m5^xx=-_(_C@z0_1yI@D~{FT|CRIABTxR0JgI%k8Q3by;Swl%r*QdJPiW!G z>O+uy=j;(M;B(rZdxz72&GvO)K|oEU{UG)#|Kr{dD-51JAvUz=oP^&TQdE@9B*I@9>ag3UmHaKoM(B`idq(iuR3=<7-r!oGp^_|~=#$CaU*+rXC66$pT7F`| zF56jaxhpSPm$!x#tKG7{7D;Op2>S0I?@p-BM8m!$?!19f&E75gr;|!%@;yw1c8E&~ zJr6g9YfF7^XWm|lk52RvA~`0W_(DD%hSAC&Ad_%!6=W_KI?&CiSkqH16hPtN5=q5I zIBt)Az87Tri8A5E1=29te~&Xpr(%?VI7yKSV{KBeVo^NUe_w<{^hrx)#P@GxxK%0@ zX_rgH8VRsFAH*o4mwHvmb8t(pzyynamvgVpEtV#DgP4-X(wtm-a|u>EW;kUUt}gzM zK4?8K7`9q?@6_g90+?w(7?EkURfw<|bbm$_2wd0|oVFa$iGM+cS?R(&eNJijRYrrRjn zCiI)ag{ANVBJh|IU;Z-umqt9U@k(~5UlP&gbhpn?%f#Xy=SIeXAYmvUwGx|HHTRp@ zwrPoBrz!*Q`+N->?}DLPJo0*m#PqwcYz8ymPfWP`_WIwYrNWmW>rL)%LZmCEt%mkS zOP_4*(;;$$-ke4Tv5M!JH)F!+Xib<9M`_maa>P&3sAK1F9rYe~+IeB%`GHypc^%EapnD&~?9_=k@8DIUe z+@4!EJ(R4kf^1#b!Kbay=|pb4L#6$f$Z2H|ZaODZ8`l))qv6?Ty#3u2f^>ls0+RDh zxLH(SW|`jK`K@jEsie!=k7XJ+FDEGFXZ6+6+&h&RO(JoQt*&J0&^0TN{!55}AWjiZ z8*SI&*NYJ>YleA1+t4*SoXLNrtV%<`@FpM5T_|M&sFAOYXIX3$Q+nFBH|_Y;hxjw# z7LPLqsH3N1mi(XikH1+9lsu?I+yB14{6~?}hy>(7?SgLBoz66;pLs$=KOdu4d0bEP z|JE4)I{?RwRwZw`sz$A2uh~KbuSFTS44@y$0(WAJg}v=wtKOlT!f6OFGf}p=;gF(+ zv^KryGjdTAP&1n3tYxuRnBiezeM?vw_INUHEdM#?bI_@J*ukK_L~R604rGeK$x)d) z0sjnR_a9`>uKBf?&Ht3%6-IQ;vH#tpjmi&?3-sdKBf&($} z3x60yMrd9_(5I}L)#QBBPPh`Me6bC!!6Rw>wJwtQOD+!45f7#H%#)6b*svx7t&N7q z`x^K!wd=1A4UVbh7?J!4_mwYXQM#rZmV~a#QV^<7?ulrJrwuwu^d)A}T?y-%@3q)5qx!l8TvA(R^ZhUd-!b?HPrvMx7dnXw1Naeso&Huc-7xu;fn4 zSL?+VnHm_bY^vH~o84!&2VB#2qV$ckks=3|Ea;@3#2z29R}|r_A~a({mvfbW+v^kh z3k@k}6(_sWd?A+WPsI&jsk~6T>in@mWOv_()=o>r3-4dW)!g?PIQg$M6a;>=4T7{E z^^0`Y$oI2sYyH}40U=B!V?U{*s9i5HBj{A_%i^ii~4yLr6d$l z_iO#B&6~mm4T3Zq?nJb-teO^OH^`voQbj&Iyh2fw5h$C{MX%f8Sw6U7@b2L}oGAd(=a~NHw3w)nV#E*gC-tQ-p;AM`;m#xrGpG&SS^Z?$N+*0Y8qlE zKSRLHfT;zbq+Za@NX{~@%aq*Inejy)xCIZ0%OtPJdV;-STNy?UNbyMGT7D+|FM%UP zwi|Xm|GKJwcBU%_2+`7~TyZBPI!NVp{uk!+yXg;J3DLBX{i5P%)UB4w`H$_xr;wki zMlLE__i+Lmq2jlzxAzJO^cPU9ALC;=OC2g8DNA?9sRr#-79Rragg`tOuwfNy3Vyfd zZyeQi1QPSDQ^+ka3Z0$k1?~VpkgOgAXChf(6w)@h|BL?++>f3O$hZHBM|2O&L*eqj zdmH8aiU}BieGS1aN9eq`EkVr1dC3Ua`8zm4y1$m0hG_6TN~ z$)u*a0TJuT6qVOJJmBnHqls>S=b)`_YZ26u(XxIBX)PY34$) z2?Rl=iXvmesH&Tes94XSN^)H!5GkO5=)#(YeyUm3yQkk1oI#iZg1AlqOQ5S8SC2$^ zWvyT6IoZYz`yXeVc1#i}{p^-`Dt4@L^G!wyX+x>#)(hOzgKg~E=@Ibc@1Ts7?BcGu zRR#BhK#YL*94~PQ6Bw`|me)I>l4i|t*dBG zclff&iuWl4xWhqTU_-zJ+)Buu+r?gQ=5Bu(C-?j92%%XJj~`}TOw)y|jT2izhAA8u z!Uc(o9@^M)eY1Nip#)8?TUIiREz&@V1_ zZPHq8`s#9|H~MqIwn4&Ce5i9Ck*B2J+2lN@|OIn7^>X^-E)#{;>F z#Lo?`#)?l3#u)JB+Q88Y;43hhmbkazdM5k-90xSR3#d`RK;L2cS<_|s+mG8{h@(~M-%-lkl{zCyA;6gD z`||{RR|UMXPy2QcdCnq*`NKNp3gDK8UR;EKRU6Dc2__o<{q$JPgSeL_#G z-6Fg6$}BBhu?uYpOFF|Vn6?G}3m{vvo%P?_wN|)|dV|gUkLS-<+L!B{V-h5i1^_3w z_;GPBOPMX9w+CGI0eREMr^7%va>3aXJ7Vv`+O4blhRi#3&|ZNP5A8d#*#Ibu?4+6ATzd7X@*X-BIamaLkD*DziYs_4>6o{Y`TAqJfdUQyCp z+#*zY9DDrO!%8rqYHp@(zn;g0A-d;vFbq8?A6&M2T17?ZdNs((yVd^aqg20};{1#L zgt9C0h)T+{JY47M*4=lDY(2|ElDA%e9RT{#MC>HQ%KxXgu10e4yCfE@+22q<*=#hVtGU$yExE$pj2a#DEh5&B5!uGOnT3U*2-0XUO@2T^c!s$W_EneHta6_-+6d-z@z+0xR$>Cjy!<^V>cKI@Q7}kyc;?x11TJe+ zBM*v$64}tvWsbf_C6F@o!E?A9&gx)7FnUu(827Ax8~o(v8lWntbN3lGr!jMU=hu;hp>k0`*PI<BTpd`{L;bsSRgtHY5`m>Q(!jt^?tw&JN~- zgm9O*IUXtBE~62_9`9UgZj1gi0i7xLiZb8$XvLzl?n&oQH@*H4gLL;9>$x_HNIZyl zpv-*eG;gpQfR7uD_ZDl09Gzi9{CXH0qWc?Z=zq7xDQEMg?QU;b$lQ9_!R6`7&@Z_;JcJw~R$jl>T zZl-ILA-b(trzipO{Z<|9ye>g|sY!eMj z80GZJ2T^`^X6zc6+W;=(1l)IFxm~xN1f{{i$Xg!yy~03DfQxkP4Q^wLtMY7Rk_M>_ z3#f0MhKf)X!*3$jcy%>VNo9nH`e+)kKlfR!s*{45NTF7`nqLt=pEx%SODryMN!z zGko)WGNJ6#Rsjp5;>tu4HSxU5pY*Z~kLLWI|0p-dp*&@r41Y$(f+ihK&a<0VJucrfK-{DwI~2xnaWPK{oI5r<%I8F$a3#kvKf^fu>yH52vw#~Kew`y(eA%7 ziv}wGWOW;h-f8coQ=1liDK51(n|rEtJ39yg39Fjin5eS1fu*k2jBp@;#3nT^m}~0Y zCt(hI_O0)lVXHJE)2k)t@-g*ssmz;_xXaeUnlybI_LeFAu zo&0Y5z#L1_$DVI44{(t}38jxnrXTHAo7Spw3K&XSeHv)j12%_(p>L*?U&Q^vT)|*Q z6SvjaU12=aV2~z>{&&|l)6ha}*aBt2Ep1#uHEzfaBi!%eia;WTh>3YI7GQ#?s`*v( zX~=y{uuTK4Ir)@x4^1K!R;sod$^!u=7;^smUPGw=_4;ALFS;i8-L6q^!zABe4=E{m z`t#-1Ta>|PL+KjU3QDL=wM;`7?}E#7u-2jrN+gAk79=gh<5Iw-Uo?$;!uAb(V)8}7 z66dwLCXkz1&!&C_MpC_t*e8m)WANpsrJ1nVtqdv{4og zNLgVTWOmUF^nQ3n_WLb+VyWH!Qy{U3Viiu7U*4Z*SoClzck5+f(XE^Yrb1< z;($|yoTR;xTl_Ut&~c=iAuQ2{i5jrbZzK@=VeJq&{4ZMqBh7S`*uO#CXNKLVU!~TS zpf+I7Zg;tNqm5Vi?-+^Uy?N{J)-{7!2wfSO&$>|+r>U)XG*unJ$e$OF^qD#;?H6Lp zu72~Y$7^n15>{`{iAi?!*6*xXL_7M=Nk#{H5;!id+wBgS8#Uk{A;4|FSo@VELPxd< zI%P>g4t{~^#LrSF>ujkHLHs@x8*>2T(l$R=Db0Vj7gVX%7t{+ z-zDR-5-n2$Z+u?!%ViICeY6vW%9Z%=L_bRO>)ewPG~AwF&o{4r&9YA|Se?3Uk5BA> zJK$QXrPx;i%lr$aYMgkxb7LgXPq288YrTXDAzz1t%(lpbElBwzwir5dW&YUh$FJDq zCsVyq2_}=pNg=k9B;;mIZMe$Pe1%q?`9Iy)+D2)hozQT`-1lEudrX3+#~)djI0?FB zluW-XTR0gp@B6+SU~8F4no-tg?U|Djn|<2sVgFw=z-F~iE3 z^;TNE^KY11(r}STaB9Th{rZ)TH!^63gN?LBbZE%jtjhy|b^OvvNUjYDX4D{-}^ghPd2&CjD8W$M`|*zP`xS!=vPL8)d<2Z<@I+U<5NP6(;Np0PBm5_60@$hP5m*_e%VWpS7FIH%FT#uX`K}BN4vm#HTly zxn=~8X7#M&0R<|o{Kt>5V1I&yDpO+{6?m!G&Fv(bH;bRxh=1Tm3Mdjm%N~2xl0S0o zMA6aL!^g{epX&fDl)+sH-TxJlhASAga8k?r-#iCP$O4*WnX$ zc@PpmtL+foKryw52XV%jKiDfSXPYH4y^%brkVL)Qc_U6m#S-`yv}`$i2|tG~N~=Q1 z%69YB_xoL=Goot~Q{((nItv*f4rYGu?+ z0;+Z2yQ2{sBuL+D%z0Tvx|-Q}`(9f?!%cW*P##mDZnRJ9s7nQeE*`h$noRu@Yghr(?!1k_g3hc-s3dMc{AAUB-f}AYqQlCsvK+o`9sFT zV5ZCIAi+hVvaFnWf}15<%(3I$imaRB@l*)>Q!0=xncuU`>eNx-&eEKx=9>*T9DN+I z%_hm|+i^ht05~TgC_dS@-(^o^dLR!x3?4jphm(eG@-)W3do^IryZ(^crFQe z%p6qO5r`D8o^Mh%E8qih61Zpq<^R+;5SW+}>fz(oQ_@QqySglUP<6PQy8~v=)q)o( zyu=ipGhtaPt*%fxc9J`J_EHiKC?UNfUPb5H=-|bp2-^~H({p^kdV@G%EBxyb&~POi zQ&Pz{y#t~biD0a@vki-0*L#dvOKnyJKQKcko`PLU)2_KcABuGBOK8<{p>r`aSLzc7 ziMb$6G~ES6Tx<|){<-@~O=UNUiFqa?9VK+t?BASiKOUc!W9~(qYF~~oL!|B{9Hh5F zAyTiAV$3T=sG(A_lx1U^-&?JC(_|p35*U0?`QM3T@~b%z`UU=P7Ho}0qbS!V4+Uwy z>u43#hZ_bAXNZSS00WkS@naC*nqbl32o*sRg4O9<0%!+$ori#W0ijw&uf$I*9>u&F_}Af&2`6jg?> zl(07wSyPCH(2LsQjqa*1Un`TOU$BGgvsm7P;n~CE-k&dcOd2hr%*ul*@!KJMO(1DE z*P6A6O{-6;?Hp?AKi3IA9d}u0j79+R!5kTNpWM07CN6)%$jEa+$}g&}0LFA$s{;wE znU9zv@cT?!3nQc7@%a|cKBQY?3^E{S_ogPpb#b5O%8{?kMvdlnwRvnJxzCeSSbhVaHrPV)UTk!ixrjGO8(XNLxYdX#94N|x6!Ak<91SCmM_umTxM z5*N4A7oIcuG3d;ZkZ-)RoEhs+o)O^SROl=HAFX|PIF#+*_k~KbhJ<9Plq_T4*Skez z$QF?(%g8>FCA<43RJLLmgu+A-k+Fq|7BPdU>={aveJA^KUYEL$=Q*DDcO36~9Pjzp znCo<2=kh(j-_LiQY3J=Tl^zrAAoIXj70~6$wQD6~RhQ;-E)gCnm}S%1m{ZvUejSAk zlQ6p`alQv_@Rn>H-z zOsg*y(5~f&eD7EVxu+9a!IIeauU@JPY*%_{sex_!F|4WEsCG9aG$WMR2`o6~z^y2) z5F1HjI{8l_i`hfly}{Kqu&tk;-RlLM=e|_&_mviHM`_-@mupzrGAp^lG9tk~0A)kD zh_32RaTxhR7}#rSCoZedlJ>4=4TBawJA2=-XYqR^L&lg$n-6Pf<{%w}BK)9}Moeyb zOd4h@m&@Xrl2>te_a#@eoWKc9X$QqD*f4+{d2ysGzWn)wDcH-oZb3*mI={B)b73Pp zA1gM&zbJC(xKmmSOE_!INqd}aSB%YosKg2nwDO}u3knyo|8n@`!kfVajQ~=DvbvQO zYl9&UAtUbqw}6W2Co}8{d2{e}-^uMUb=ZvsU=T464Gfz#}8~r-Wqf^fx=zmJYQJ&9CZ7X`ts!-nWgm|@z<#srdoRxTm||$@&Q=NfF>w~ z!D@T|40ATZF2z>Mjg2QB@sHo|Xz?~eBrQ10C2K*-1>QH(K6~jHx0F+BDn zIT>DY<;m3*_XXyrSj=>W-Sx&7>g*@G$C;45x^8KGY)3?djI_+I(naI(IZjB} zs!L(;%9qJH3j_uXv_*NOcSvsZ4}7X0YJGt$ISwF>kFEaztvOs1BO%W@UBYQ9;D6(q z!CCo;1;0;T51Qb~kI#eHOWTt6Zd$>^+K`d{dmEiex%|r&Zi! zAS&2d1Rphxc-VQW3@!BlC^b;2y_)cS8GdiQqpI%XJ(E2hv$^L(#XN;&7M8~IdhTGT z!}ONVx_eW_Q?Ec&xTx9QjKf^LYW(**n%CFs`a%P!CyOm3N(861`yOqJ5&AhU)YB&q zmoY=h@TOf-P(SqH%ME;STyVWsM*R_wGZ>f0DW2;$b53Z;8dTmGyCn95wA&@(ZlBtN zv{n>k{1uT1#)bK^N$uUvD#E5YNx_8Es++iL?~gE6v#^-lx91nmX*0MFI(NW+<46Iy z@fQ_IX=F_M_xWLmN>4jiA#Y<227xxGgOC`!LLI#bCR?hQ{UPeOjUOGAsR)1_nVDp3 zyzAR-;mXyd!oT{71WAU@dz|rZSF+$PUtwwBPIT6K(5&0o^>lJlr=gM6#=wq4KI2QI z_HIF^K)R5y28Op{s9H!z9~Li<1?ESlM8AI3Jm&ZJ!*s&f-?--94`};6ueL%T9=_6C zlkjzDrVoV${bzOH{-%+3uQW@Odi_KFLuazKbYu;pq;sb{`q|9*M&(FuC|V3!3(O>( z9-he=KDM97*mK=ozb`CVJ-j(8mMS(n98r@js^y>5LTZXCu^Wu?Exi5?UNA^)hf1xq z{mPwnlTY*aw)b!>U5>l_U6ypQYLXt3hT*GZtd*#W|Ix0Bn1qM1p$Z4Xa(aIq5#cH~ zPBY)5atA&H5ZDA!AFbWUobBl#d=zsy4au~E!GFR~jv9Nr>GWLmnQ3=>o)+HcnhU0C z3<6iE-ok)BuId4ZOL{dHeEf9MOu@95V^5>WH^a-((QAW^hnK&iR9`aWPIYNAFEbZd z{wh0Ezg!LGv>O&K7HCGT&aXj(L(MOgLc9VJudBSSTk%uvP`Ecnlys6Q;|r)FeI8%r zZTd5fs~>3-^1;r2Yh$xvs5;Bq!ldw~bIBHm1eT;W{viv}2Ne+{bE{j|$nP>SvySjN z!Mq9**(`0o?(jkPc67G-u5tzWj0ll3{ykD5A3-Smr4c~2<{;nEzYh9M=kWNq=XK(RmN1P=HqilMZh+76S;^2ACf_Cng?D)QKZN2XGRqBVOQQ%M@S#@%W@jW z{olNj%BH*8f^~4b!{xIVLFwQ>a*h~wz4YiOPPr?TC8sa$Z~d9;x$f@96kVDPZx?9P zKHL%9FwW!#x=}>nPbm`rQgbS&Sg^iIaWt@sSi03IHw>j{XA47L3G#%z-8y5SI z>&sE=>LuI%5XueRnR(*i`g(}pLE`E{cggm8*w#>Q9eDTrTB!3a^VPLrZ-pRkc&!5i zv}fba_pOF34FH}C-<5Jg3=c#oGErBBObS^815#>WNCl!2{_Ix@KMzGRrIlsHs*^Z{ zjgCC6at9UypiN&rd5-D31X%5Z-`_khmL}l$h;QOdUK@h-j_jN==*pvL*hQRj)$N>G zwifflYibO0EF-cJf=GwS&jq;JEIHY(o%nqq<{oCI_c@;F*`F`_Q|;^j-&z0fP2JF_ z1w;+ntguJF-}d!%%!KFQyIzL%&7k4sF1Bmhzo%u>qhJT@7w8)n?EjvP3SgxM`j*V=>*p-?Ea8nS9ZWN&Ox;Y120B61M4?FSBJQri(Vx% zhyFvp*mNx|{ft{h+So4tVj{kS>&Tx=V@2P4Z(qg$vLoiS_06w=dJS@hjW5nsIQR+x zJ=`swAd!yesUq{#-(2_4Mje*Zyukpl?KgtspIi7}$+(Okq1B$x7Sr6jBAX3+V zU{hI*8xG*{*#BT>;pcv~I(?#mVNM`=cfwKF!Mc-hG<|^+9J@Jk$u*J+z#UO}y90o* z@jzV#GpIcXG*+X2;-Gdqp||{U!)fV(s~aMNp3jPtU?~O-WR8Gn2Tx3T2}>no8O|^| z5iSY{1pssi!%C0-U#@9m=eitf6X+?Z!>9DWfU^r1n*oEbYi=--Hh*1agi@H>y}oz} zyp@V5OY_VPARL2cdx@xvT{aD(Ys?2`1k1Z76^40UE)twu)S3^ zwXVH0n#-gNb(NfT`+XaFLC^uPrSr3K6(L+*(R5f zdItA4&!yi&!$%G7hb_w=u%B4ww|UVHcIh>?UT%(D9hwF7g`6X{x1$siHoa)=b`4vr zCE7--PyX9wp zDeRqQlV;i$ZNV2U&&2NVMEkmwukdX7v6a=FE|$9+#SGzGfJ=QYVLAF>;F`YX9C=K6 z`H2i{1_D!yeo@@-hJCBW0L`MCK2Tt7AA;`M+p@3hTNMHBs7fc7Aj_Avyz8M2hFW_7 zOu&g><^1x*M8Yf!Y?g2fAf`UfRin8@((H@DE!#`C0gx4}vvm zN9a3ZLx;pbpaTH$OT|4Of1Z=gI9ZfES}L7#yqJp&<^u0Gh93 zTa}@uy=X;X5q&Ekp_4yUX03cQ810tJ!UDJ_UrwU;mc z@4SB2O`NewA>lOXU6 zv-{4~nmB{EqY-bp9X$P=fRQU{Ln;DmIer?eSTuFVMJRX8tu_sjg|EbD|Qqph{8B z9wz1d41%QkY*1_-JW9dGS=CZNl+&GCgI|^zq60KJK=ji&cni$MWwe{VoW`s$eOCj9 z07#e%Q3jUwIm$;Uh!T1~zY%?PQyi!O{D|bxSEs#-x2imTyaBwp2LY}csiGHvaNIHJ zUu12yIwl4VKosW5;ZG?9=`Ox^HBvz%_)RHrFh#$e28MQx6ZJRMCpYeF4doJuN&s)k zzy<*5x#LL{raZ-GQ;{oU_4(_SaH?GoA_6`Yup8kzQ%!U_Ej!;hp2#)F)NErJC3?Ys zx=qynWl6*Q68nAnk6qTv8Ym_ma{WIh{oq3-g(6^W!s@)4Qr*ic{+I3^9H4j`(+~Ns3YW`+^b6APZDt<9PV+A%2%iF^^^pNf9tSD( z8pb)^PGf>{!|&u?$=RP;H(;$9qflT*rBjD_;?^U7^30H4u#iS7J(Nf-=x^4!ROYKI zCyvnkQ=ZjKyhD7M)~@>i;w0)|8zqr_SLA=5#~+~IVTJ<6>K_LlOPC^{YCQ2)CA$cS z@1sh#c&3MB3xSH{_3&>5Oe2mT(~NP`0jA=(<@^9x@)fed6qX28zu+qG6$LCcZk?zzRCI2h}`-WxE{YSBXUMJ<-q5s2hvK4f?hWd zPL3i}$3L2ta0nO}x$C`Y zh~?BN%0^ap)kLU9!BD<7Y z(CZ3Zs^Ah^cPYqP-GzT*plTQ5i1fwba7 z4=7A*E{yZBRzvw{*G>wj`>Ap?;sZ(Hd?4bp1-X`Vq#W`N$}nJ?Bjo<~cRBm#P!y^ff2{prFF$a-zulHh<`7nW8( zSv)db)sYf-9M&`@p0z4OfR|YCvGeHY&(94XwJdMRazI&B{I}x7)8x3hMUItspAlu( zxRBtY%l<&I=%0On{rXtiXd}D&IZ_tfZJR3BV83mm#{r7D0enWF{c8nLv9qLdqGGJ1 zQe(Ybmo9S;INAdg1W}*fZpRDq(?L~n`Bu%Gf8*q$OJfngj_s5krZTz`@S)MgTjWVi zthHIj;?M}?$&PC%#X4}FMI*_Y3X2b*rqzCXST{4JJt*A~pD~VLKAkvw!pTFPmM8{L z&6NC{;{gZmSf0ue{Ei#1jy@qOH-RnKhXZ(mI$O77ql?&BFIXP8tK*UxAdkLzmCfBF zHCwn1%$D%+=BN#SXt|%T8*15Gw8>K~X%o*}b6_m|JR(fQE0#31fD&Z<4=Ffr^V}*f z>ar`5WXW&_VML&ose{VFUWIL5Pmou?(X%3jS!clRLqvn-9t$YvRFcG-H+JvYOQIMAqzF;vv!eUBnon)$H^#Wfh^+JMDRZeD^lT?*I-`}1f6P(ZT)H1qzqx@cg#b@&or=y zkgKk1u+VTQnJ!$yI=sFIA?_(aT!MNQq(K z1A>gf-~(?6RioTXD;!nu&wzkdYB_C<%U_}`zube}hp_8zd37;|$lZ`Dhy3s*>w5cB z@>D?>_vqvkPAd&tIJZeXI<~FI8BAXa&p8wr-k_-UWy^{csuI zS?SFNLmqZ0<>y^%Tc6eUTL#Oen}*XjE3u!x$zX9|8(W*}lUfi7Q!#kE1p~2lCuB+H zOXt4G8ry>FahN666EVww3u<%qVcVO3jy|s3SE0GP$plnpn*W9vGwxC1iIST^F3b=X zM{vQRD4XX-O9mrs>5>6+4S)8O=KILGet<6VV$O!>?2%%tZ*<{@p3zS7#?SZcKi~%3 zTo)7S0svl^)yevMSP6-d06StF1JgHPTyAdte!i!=Ly0}%`MMSftieGW!Q}=)Mzm^H za&YZZe`@GUh7-+$K0m5|moXJw^bKWYt7WEgZ^bs+DNj8Wrgi?d z1zbonRxb;552K0<8}l^@DH-SbP%k70|8UmUlwkVC0juSpRXrVsLdeNhbikTe(Is^0 z()LJ zRz2;#{5UOT(PBsee?>?77SkDs^H=UZ5KCn6o?Uh!kfJpoy~LI7RNBaglWqvoGYPN)9nX8eJv4P-PQtfXKzc)28sIQp8rAy6z z20djILexv2P3_gjfAu{Tla{?{v);Z@5ak+XY5~+9>iOFxiRc;a+lNv;{pBd2fE_># zP?bRWUztu5cxB)BzHleGBg{cZX`z%kPQ%R-8t8y!{~&J_#Xgo^_wyf*(F>zs$l0Sw zZ6O_O7q0WD zZmT-x1A>gc{~kQlp-b{H5V(}axe%8$M~)qpgLy|dO>PR#R1pv*#Ge?>ZF*bM=Dim4 zR{(WnaXN`?jsXb~opmvm)}TujK8-(q_NFbq=4D@YcjLX0&0)r6qBg^`P5kE9;RwZh zQt0-}@eg!ia3EMbTMTe6WMhejxPDzvi*i>}G7M0~4}*CA_^Hnp!wY_aD|#Tin99~T zLo5Qy2VZ} zS}0-{)Yh*1wKoUZQed&=5mKnZxfoOzuKyp?11XB@X7wyQ0UUHi)e2H{O+M(N9A$~BSfF?K$ wM-?J10O9Z8