From d55dd85d4e9f656a65f08ec16f1b4599ec14428d Mon Sep 17 00:00:00 2001 From: Sattvik Chakravarthy Date: Wed, 13 Mar 2024 20:46:37 +0530 Subject: [PATCH] feat: MFA (#79) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: mfa and totp updates * fix: queries * fix: misc fixes (#80) * fix: mfa * fix: queries * fix: queries * fix: mfa changes (#87) * feat: Add support to update the signing key type of a session (#88) * feat: make refresh update the signing key type of sessions * chore: update changelog * Merge 8.0 (#103) * fix: remove db password from logs (#89) * fix: remove db password from logs * fix: mask db password * fix: Add tests * fix: Add more tests * fix: PR changes * fix: tests for connection pool (#90) * adding dev-v5.0.6 tag to this commit to ensure building * fix: cicd tests (#92) * fix: logging test (#93) * adding dev-v5.0.6 tag to this commit to ensure building * fix: flaky test (#94) * fix: make connection pool test less flaky * fix: test * fix: typo * adding dev-v5.0.6 tag to this commit to ensure building * fix: adds idle timeout and minimum idle configs (#95) * fix: idle connection configs * test: protected configs * adding dev-v5.0.6 tag to this commit to ensure building * fix: cicd (#96) * fix: cicd * fix: test * adding dev-v5.0.6 tag to this commit to ensure building * fix: typo (#97) * adding dev-v5.0.6 tag to this commit to ensure building * fixes tests * adding dev-v5.0.6 tag to this commit to ensure building * fix: Vulnerability fix (#98) * fix: updated dependencies * chore: version and changelog * fix: versions * adding dev-v5.0.7 tag to this commit to ensure building * fix: dependencies (#101) * fix: dependency fix * fix: dep fix * adding dev-v5.0.7 tag to this commit to ensure building * fix: fixes storage handling for non-auth recipes (#102) * fix: non-auth fix * fix: migration script and test fixes * fix: plugin interface version * fix: remove unnecessary func * adding dev-v6.0.0 tag to this commit to ensure building --------- Co-authored-by: Ankit Tiwari Co-authored-by: rishabhpoddar * fix: mysql (#104) --------- Co-authored-by: Mihály Lengyel Co-authored-by: Ankit Tiwari Co-authored-by: rishabhpoddar --- .circleci/config.yml | 88 +- .circleci/doOneMillionUsersTests.sh | 135 +++ .circleci/doTests.sh | 19 +- .circleci/markPassed.sh | 29 + .github/PULL_REQUEST_TEMPLATE.md | 2 +- CHANGELOG.md | 4 + build.gradle | 2 +- jar/mysql-plugin-7.0.0.jar | Bin 0 -> 213165 bytes pluginInterfaceSupported.json | 2 +- .../io/supertokens/storage/mysql/Start.java | 110 ++- .../storage/mysql/config/MySQLConfig.java | 8 + .../mysql/queries/ActiveUsersQueries.java | 37 + .../queries/EmailVerificationQueries.java | 4 +- .../storage/mysql/queries/GeneralQueries.java | 36 + .../mysql/queries/MultitenancyQueries.java | 44 +- .../storage/mysql/queries/SessionQueries.java | 11 +- .../storage/mysql/queries/TOTPQueries.java | 38 +- .../mysql/queries/UserIdMappingQueries.java | 23 +- .../queries/multitenancy/MfaSqlHelper.java | 116 +++ .../multitenancy/TenantConfigSQLHelper.java | 27 +- .../mysql/test/DbConnectionPoolTest.java | 14 +- .../storage/mysql/test/DeadlockTest.java | 16 +- .../storage/mysql/test/LoggingTest.java | 6 +- .../mysql/test/OneMillionUsersTest.java | 898 ++++++++++++++++++ .../storage/mysql/test/StorageLayerTest.java | 8 +- .../mysql/test/SuperTokensSaaSSecretTest.java | 4 +- .../test/multitenancy/StorageLayerTest.java | 20 + .../TestUserPoolIdChangeBehaviour.java | 4 + 28 files changed, 1584 insertions(+), 121 deletions(-) create mode 100755 .circleci/doOneMillionUsersTests.sh create mode 100755 .circleci/markPassed.sh create mode 100644 jar/mysql-plugin-7.0.0.jar create mode 100644 src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java create mode 100644 src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java diff --git a/.circleci/config.yml b/.circleci/config.yml index f7b3ad0..0e91623 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,6 +69,73 @@ jobs: name: running tests command: (cd .circleci/ && ./doTests.sh) - slack/status + test-onemillionusers: + docker: + - image: rishabhpoddar/supertokens_core_testing + resource_class: large + steps: + - checkout + - run: echo $'\n[mysqld]\ncharacter_set_server=utf8mb4\nmax_connections=10000' >> /etc/mysql/mysql.cnf + - run: + name: starting mysql + command: | + (cd / && ./runMySQL.sh) + mysql -u root --password=root -e "CREATE DATABASE supertokens;" + mysql -u root --password=root -e "CREATE DATABASE st0;" + mysql -u root --password=root -e "CREATE DATABASE st1;" + mysql -u root --password=root -e "CREATE DATABASE st2;" + mysql -u root --password=root -e "CREATE DATABASE st3;" + mysql -u root --password=root -e "CREATE DATABASE st4;" + mysql -u root --password=root -e "CREATE DATABASE st5;" + mysql -u root --password=root -e "CREATE DATABASE st6;" + mysql -u root --password=root -e "CREATE DATABASE st7;" + mysql -u root --password=root -e "CREATE DATABASE st8;" + mysql -u root --password=root -e "CREATE DATABASE st9;" + mysql -u root --password=root -e "CREATE DATABASE st10;" + mysql -u root --password=root -e "CREATE DATABASE st11;" + mysql -u root --password=root -e "CREATE DATABASE st12;" + mysql -u root --password=root -e "CREATE DATABASE st13;" + mysql -u root --password=root -e "CREATE DATABASE st14;" + mysql -u root --password=root -e "CREATE DATABASE st15;" + mysql -u root --password=root -e "CREATE DATABASE st16;" + mysql -u root --password=root -e "CREATE DATABASE st17;" + mysql -u root --password=root -e "CREATE DATABASE st18;" + mysql -u root --password=root -e "CREATE DATABASE st19;" + mysql -u root --password=root -e "CREATE DATABASE st20;" + mysql -u root --password=root -e "CREATE DATABASE st21;" + mysql -u root --password=root -e "CREATE DATABASE st22;" + mysql -u root --password=root -e "CREATE DATABASE st23;" + mysql -u root --password=root -e "CREATE DATABASE st24;" + mysql -u root --password=root -e "CREATE DATABASE st25;" + mysql -u root --password=root -e "CREATE DATABASE st26;" + mysql -u root --password=root -e "CREATE DATABASE st27;" + mysql -u root --password=root -e "CREATE DATABASE st28;" + mysql -u root --password=root -e "CREATE DATABASE st29;" + mysql -u root --password=root -e "CREATE DATABASE st30;" + mysql -u root --password=root -e "CREATE DATABASE st31;" + mysql -u root --password=root -e "CREATE DATABASE st32;" + mysql -u root --password=root -e "CREATE DATABASE st33;" + mysql -u root --password=root -e "CREATE DATABASE st34;" + mysql -u root --password=root -e "CREATE DATABASE st35;" + mysql -u root --password=root -e "CREATE DATABASE st36;" + mysql -u root --password=root -e "CREATE DATABASE st37;" + mysql -u root --password=root -e "CREATE DATABASE st38;" + mysql -u root --password=root -e "CREATE DATABASE st39;" + mysql -u root --password=root -e "CREATE DATABASE st40;" + mysql -u root --password=root -e "CREATE DATABASE st41;" + mysql -u root --password=root -e "CREATE DATABASE st42;" + mysql -u root --password=root -e "CREATE DATABASE st43;" + mysql -u root --password=root -e "CREATE DATABASE st44;" + mysql -u root --password=root -e "CREATE DATABASE st45;" + mysql -u root --password=root -e "CREATE DATABASE st46;" + mysql -u root --password=root -e "CREATE DATABASE st47;" + mysql -u root --password=root -e "CREATE DATABASE st48;" + mysql -u root --password=root -e "CREATE DATABASE st49;" + mysql -u root --password=root -e "CREATE DATABASE st50;" + - run: + name: running tests + command: (cd .circleci/ && ./doOneMillionUsersTests.sh) + - slack/status workflows: version: 2 @@ -81,4 +148,23 @@ workflows: tags: only: /dev-v[0-9]+(\.[0-9]+)*/ branches: - ignore: /.*/ \ No newline at end of file + ignore: /.*/ + - test-onemillionusers: + context: + - slack-notification + filters: + tags: + only: /dev-v[0-9]+(\.[0-9]+)*/ + branches: + ignore: /.*/ + - mark-passed: + context: + - slack-notification + filters: + tags: + only: /dev-v[0-9]+(\.[0-9]+)*/ + branches: + ignore: /.*/ + requires: + - test + - test-onemillionusers diff --git a/.circleci/doOneMillionUsersTests.sh b/.circleci/doOneMillionUsersTests.sh new file mode 100755 index 0000000..112e76f --- /dev/null +++ b/.circleci/doOneMillionUsersTests.sh @@ -0,0 +1,135 @@ +function cleanup { + if test -f "pluginInterfaceExactVersionsOutput"; then + rm pluginInterfaceExactVersionsOutput + fi +} + +trap cleanup EXIT +cleanup + +pluginInterfaceJson=`cat ../pluginInterfaceSupported.json` +pluginInterfaceLength=`echo $pluginInterfaceJson | jq ".versions | length"` +pluginInterfaceArray=`echo $pluginInterfaceJson | jq ".versions"` +echo "got plugin interface relations" + +./getPluginInterfaceExactVersions.sh $pluginInterfaceLength "$pluginInterfaceArray" + +if [[ $? -ne 0 ]] +then + echo "all plugin interfaces found... failed. exiting!" + exit 1 +else + echo "all plugin interfaces found..." +fi + +# get plugin version +pluginVersion=`cat ../build.gradle | grep -e "version =" -e "version="` +while IFS='"' read -ra ADDR; do + counter=0 + for i in "${ADDR[@]}"; do + if [ $counter == 1 ] + then + pluginVersion=$i + fi + counter=$(($counter+1)) + done +done <<< "$pluginVersion" + +responseStatus=`curl -s -o /dev/null -w "%{http_code}" -X PUT \ + https://api.supertokens.io/0/plugin \ + -H 'Content-Type: application/json' \ + -H 'api-version: 0' \ + -d "{ + \"password\": \"$SUPERTOKENS_API_KEY\", + \"planType\":\"FREE\", + \"version\":\"$pluginVersion\", + \"pluginInterfaces\": $pluginInterfaceArray, + \"name\": \"mysql\" +}"` +if [ $responseStatus -ne "200" ] +then + echo "failed plugin PUT API status code: $responseStatus. Exiting!" + exit 1 +fi + +someTestsRan=false +while read -u 10 line +do + if [[ $line = "" ]]; then + continue + fi + i=0 + currTag=`echo $line | jq .tag` + currTag=`echo $currTag | tr -d '"'` + + currVersion=`echo $line | jq .version` + currVersion=`echo $currVersion | tr -d '"'` + piX=$(cut -d'.' -f1 <<<"$currVersion") + piY=$(cut -d'.' -f2 <<<"$currVersion") + piVersion="$piX.$piY" + + someTestsRan=true + + response=`curl -s -X GET \ + "https://api.supertokens.io/0/plugin-interface/dependency/core/latest?password=$SUPERTOKENS_API_KEY&planType=FREE&mode=DEV&version=$piVersion" \ + -H 'api-version: 0'` + if [[ `echo $response | jq .core` == "null" ]] + then + echo "fetching latest X.Y version for core given plugin-interface X.Y version: $piVersion gave response: $response" + exit 1 + fi + coreVersionX2=$(echo $response | jq .core | tr -d '"') + + response=`curl -s -X GET \ + "https://api.supertokens.io/0/core/latest?password=$SUPERTOKENS_API_KEY&planType=FREE&mode=DEV&version=$coreVersionX2" \ + -H 'api-version: 0'` + if [[ `echo $response | jq .tag` == "null" ]] + then + echo "fetching latest X.Y.Z version for core X.Y version: $coreVersionX2 gave response: $response" + exit 1 + fi + coreVersionTag=$(echo $response | jq .tag | tr -d '"') + + cd ../../ + git clone git@github.com:supertokens/supertokens-root.git + cd supertokens-root + + update-alternatives --install "/usr/bin/java" "java" "/usr/java/jdk-15.0.1/bin/java" 2 + update-alternatives --install "/usr/bin/javac" "javac" "/usr/java/jdk-15.0.1/bin/javac" 2 + + pluginX=$(cut -d'.' -f1 <<<"$pluginVersion") + pluginY=$(cut -d'.' -f2 <<<"$pluginVersion") + echo -e "core,$coreVersionX2\nplugin-interface,$piVersion\nmysql-plugin,$pluginX.$pluginY" > modules.txt + ./loadModules + cd supertokens-core + git checkout $coreVersionTag + cd ../supertokens-plugin-interface + git checkout $currTag + cd ../supertokens-mysql-plugin + git checkout dev-v$pluginVersion + cd ../ + echo $SUPERTOKENS_API_KEY > apiPassword + export ONE_MILLION_USERS_TEST=1 + ./utils/setupTestEnv --cicd + ./gradlew :supertokens-postgresql-plugin:test --tests io.supertokens.storage.mysql.test.OneMillionUsersTest + + if [[ $? -ne 0 ]] + then + cat logs/* + cd ../project/ + echo "test failed... exiting!" + exit 1 + fi + cd ../ + rm -rf supertokens-root + cd project/.circleci +done 10yu>ZQexSBA%w1Na9IEd1J0X7GM zUE}=&;QZ_8{~0JRtRO8RuByf$FYzEhJtZeg&oGZ5OHcEAdbUM{X^D03&%qzC|BthO z_Wx^D@PA`#$N#q8e}*9a2gKFg$=t=w(bn9-^?wV;`tNX8H%Av^OY{G&8NvU*nZ38G zv)z9)j@OC~SBC%riTD>z#{bD!$;Hvs+|^ap&DhPH!PL&!)wNDzR~1hk{fhyXZrv_; z4i&Nq9hXgzxT>{nZ~-n%%@iCoc_BnYFPYbQvvFu!zT)MQsHkN2ZG#5`D$DupIPN>> zJ9e=tzeifs3R?!7(Bp>RbC!RXdzbrU=kt9)@C%}l^hXIK1FQpNot0_kvMh5=@2Gsw zV-%jobhB)^#$MBm{l%t<|W^ zPRh!X>s!gUcJx=fLEKDcd3zoyI170v->pcJlY%fb501$AFk^NZen)Lw-Fg_Qe@X1@ zCP2Rm{9(A61{mo8dxD`Sgan*x(wNM(W_^L*5+D_bupLsW*49|^=sgretJ}n^bBN{H zEPk4wI2A7l`-}c~=pR8lbHMC%v1QpwRI8-26bA-rrSfy>xWsCjp7|nN*2`CVh&Tdf zwR-&X6=tg?h#zgY55`Dq7#dDMEV1a&X`ZQ*{*(6_-Cm_K0z-^RgoSx(4oxoN+(g!q z?}%GB4cS~tQLi<4#MEJpRYKs7e7wW1&&-P{h89j>7+bVPo%%BRFqGfS$(fr#(TwFH z>r#%R$fxqUfx7c&0uEny+MjfJI;KYUET=K?1Vtt~NJRvtaUpsL_EyqU6%4t3%K5TC z4i|5F9Mp;z_ak(_D0%#aZ1+G_kfh z@lNLagoj}q4Mxc(+t#!X2|fWJG%cmJ>zcP!#RpWJF(Xf zJFbC_jX_A=gFNr^W{4S2zQq8>t3t^TQX+)r+!b4B=fcf+j)Y&>MkS&;O#ld147$&R z6^SgE;3GQ8UgzoS4U$jrxrHsoVqdTd(>7aK;IU?c>TemeyoeUg8TbZ71CFf%Wo{4` zK(=)qnzy23U*gEinxUor6iT2y6RS5^r4?ULU~UR)HU~mIRg(ssib$`3vd4_qM#LE2 zpf{=uuH4w$t?=lfaU{b%ai9QRuCEySY13edEIujIq{MV78))BX&}cTOrZ_o_Z|J)L z(L=Kr?jwG^a)rs=%Wqf|lD{`3OCea;{y(*juwD@B_&@vqEH^ZK8ABVqM*kodbB>sd zgc-9E_*r?lPO+fO6he2+BcPzsh1`O%Q2Rm!d_sl8`^un0I3T2~HaI7TXM7I;E)(rz z1zeiCv9mPC;`wIU4fR>FGtzt{D38@I^!fEgDD>E7`m4(^_avy_TTQOd`oMa0r(Zhb zh9~QhM1JidF3|BB$EmXXI9H+5B+=7yWg8gGU~8YZLq}@72I-bMA6-TE%)`QsN3z<= zy#6HmucZBtl>QgblK)Q(W$Nf)VQu-}Snf09J7gCI1f>5Ttup-|`VjqpT>S^ljcUDW z;*Ar0$C3L|G+~nw!9uK#c-WC6j{YR5h(ZPr7W;{eZOqgf-y;>P)w=_Q?B z34S^a(GQWC;@CFASZkiCP1XQraocJjAyuVkO;IkNuuuKALF3-w zOPz~rt=}kDUNc+UDZ>*f{SdjNg)6Z+!w1I7VflBP*JZDa=JQ z$%aq_3CBTUq0RA!(E!jK5;?|>I&G^_&=H67c!jM{>Lamaq#PT+CN}V!IfPfzCCliM zqKJgU$l0c>glT~(X>ewhG>ZlMdfaTVJm#gGF3;u3!eY8wV<}wOSUBud

NemDa4v zeO*zm#bNNiF}&|D7V8aIm$dg0k#|P-yY3qcY|N+1z;aeq z@s)P>p!S_a`X1`v8Atq1>((5J_gfEkz~T4Ghl}LNQT3wVRQ>5%L>d1+ABjcYOGOs5 z2$;Dru{gfW$|d-jWvvonlO)MXDIf7X6Fx=5nDEeeOG;Tnq-W=~%JyL!ZOoxrp#gTLqTrP1jnwz5Lk-DOuq#p;#}&1w zk}}e)pqE7xo$NjDm%L<#WtiuVkK<%>z=W+0!k?J-k@Yd(OZXA*$fh}!tWhV6RWk*b zhNS}1B4wVMOUr1rq{}*~t#MT6DphDOwH=TYsecx{HCs>?nJtkLYiyzGc1x_>!*KTp z6RkQaJBbZLMtoAJm2}saW90ccWH9_-WC185oL8Gv#Y>B?;=TIkp3I}$ zh+Le8!b+vZnM9tT>kwU>Cp=M0ix~e#f_D(KaE`8V%`!X2i&~aTHjAZdKrExG)Vzg- zEl9niCbW1$Vi*G$Y)<2ihx_Y{S>9^PbktUtN}%&gvcDYZuy?jDl%$-H4J|)~N{*kH z`vrFd_At`?+g`Q41kG=R6?WODL)n++u!e~jn*Mg>{=12m+;=J@I_oTD3%IV;Hiy7A zZT|t1!yJ6($w{;RXM3E6d-i}SMARz^R$9{U9+v*`RZj-lgBDR`*j-DmHsRu`aILms zWzoWvj?!AtcjF>fG#yM%?4zQck-_z%{GA8Jr+@*H7h!YN?ozrQ-cwgJZ*&k)_lE?A<=}$xKxtlhHWb{Y|R+O3)<{I?27RimNX` zpVmqW`1%0*%ODE$F{rR`>5_3}g>0*?G9qVGBIe%xDmEycqt)FyP=j!C3TvfKqm9t) z=-&6~{0hG4STtBJ>3#Sfx!kAsu}I+`#m!oIm`itsw2||bnR!kPZy(oSbwf~3vsW^^ zO{MmmQ1dn^gFcIvv7?dz54{&YrJ=)ZZj)QCpgo0~B7_5=5d}3KJZ|PYGi0tn>vh>0 zJerj;R$*`V9u^%te!n4oIY(T_KW^Oqj6%1)xTg)#oDB0SeYEcFR{wLh@uGY$p2|>D z+X=0HFMd^>fzY?n=LC9NNGLd*Fm#Ld=CaQO_JIYR4gJ!IP73!yj)JachD>GCeXV{0ZD*p2pgx+OR7Y(Ks~R%EguZquQt88ks|LK zv<}zxP1fLQIiCZ=1&_pzBWd+G|>LoGy;9I~YB$vTH9g!VGZP9i?aevk=W^q6m#0f?x!^y!83Ne`PI^ab;Ig!|h=F|WcM zH05EKgP}Bk1O$AhiH56qw| za)^uj&b5w07c4}KqCI6Tk`1G!su{qgRSSU515}bYJDNsU{zXAdfVt_TW^zW!-IBc7 zYxpVRi9eMi8a%Z5LMok*L}NIRpo81*P85LK|3FAS%kH(cYC7X-dVLYHhs^z5jh%BF zYQCRNG7Z>Zr#7>&@=RCZ&{fO)p8ln7(t1&R|I9EGV&b7$xJnl{@!kWv`4#$!3bkFa z_Wmf(egXIG*``aHRaWS_pAT~3_|kKWUE+=W9dr};UlT4lBM-|WOc0QLP7o0G|HEWS z-dj~!?muTtX}Yj}7|Y9omR^&-u%Tg%5l>AKVS}MCm9WIv+F-B{sD*UaxkvKJNg15R zI}lODb^5If-AgNwdK=YgI<_@w5TG^fZF4IO9xZhn;ysJvSI<@IXWu(n9mf&(ukYNB z$6F7ACp)gQ{8RA(@7srpsLJf$Es1QnsHH&)-l?-{Ze2~|Q6q6)l4hb8e=KsQQU^w2 zbgx;;Nm{1b(Uqd$Lewf3l@_u{(+Q*>-Ew}~-mn}-OAWUXlmO%0o+v%WN$ov)x6h-N z{&G0f)+F7?l^iL>axOKGyP>8NSRUw*yz=Emz&9PL$~nt{0_eBf32ddcG&4zXht!Z; zHsiD^@|+-TN)<}1*i?%mQO(K^x*uh5^~Ym8)!=uUc;eA;{dOESlSs!d*hoah6o=g) zypt7DAYb_kHl@g)Hx$^!jLVB~E--r+-Le_HBz=07f$Tc*Ve6=z-Ard$a^#&d?%DL6 zW8Qju(cW~?=?>#|9nY}kE_uf=l)HeQ>78_biQ4gLBP=^t_v{~Ql-_o*tR!~pCZn5I z_`hFy=#g_-`4n2F8cilgCq^kR5d_vu;VydK#D9eM+Nb-F2wNnwhy z0Kimg7Ii>zctMh_F4%ge`I5hL`{kG#R;|I=OFdR&Ox|!{R?k_k2)TF~Ft&2sY)UE1 zCkZ{Ve%fg&YBJD({+;H+YI9z_WFqipYCmmF+X0W&il&#Cj;W85T-{W_GC;FH*J;NJ zfeki+*4VP}6z8$)A+wO+LG|Ek#!Zm*snuF?gR|yEKuP#}z9f>de>(VvS*mATe-k~* z6inSRb^e>QP$x*&-G$ z78`4ojp$e101%Gl%-U-@1&E-lbI>7=!g&H>L=s*E6T|42Y^WDA{`GPgn~(=Qc>*G< ztdIxEd^FU&i_gMuR9h_c4Lhg#O)7NeR0M^1Zr#c-6Oro9fKWGAji2|VJz87zJpLg9 zurm_qKUsC!#y3UX@FJWVb>j#-&`4@$&N=#Chb7*ccLV=|Z$aM$?6n;9xG zLkpTo*ySvsDA#L;RRjcC;Urq83~_lYBHy z@{ZG|lwmGis!QLD?g*ppO*s<@_bf;mz*=~CTqORK3%e{}JxeBW=uVo+vDx|c}wvPecOS~JI4hoSTgOYqr^ZrVX74Iy;IKA!xB=Nyq+ayG_hvwInFn%*$? zF{vg^A~1pXP`i@qR(E~4w@?ndu0;J~{_s<(RegzIhL-^|Z78HH^G}HOL7Pgi#_t@? zhD3wn3~|UW8HH0B9lO{l#ewBB&qv=d^pW8ir7S!}RnXG}IbPYtG&|}Q41|no83F*e z1(!pQv6^dD*#SQtW;7C~-S|x7HlYWv@@=>|4jdnlX_{!a2y!QGuU>oK?yCU zLx)MDHj-F-_P+W4YxpD9n{DD(`C`qZ4hy)&3I!?s=r+Ab*)&xf$s4cE&xMu@t}JWS6XR74Y{otfXOOSD#qa1kSYum`=S&61s2#Co z7A*vADbD#oH=mpxPzVuyAZpus*mPaP8C$M|++bWs)`b4(h?_+2f#}?LZA-daIJ*6xx%KZm~Y0_`9 zWU#Q=<>D@wJ1O)qbuea~6J|b46y|w?mc%_-_1`_BIBcC_CwG(VY}gK#Q9nfN#G>+Q zAJ8Qd)T2(1I$=?&p}4U(A>Y~ZDjoo}l=F+(iQpkU8aTBM2iiOtaDAYO-4I1`Coam1 z5OpKJ>K!^du<7rzkY~dO)h;j&U`%u^VlfUNVRU0OXhu#-eti@+PZ!eNo3|;uHGFFaX`dkPh-~_A1#Al1*l|sqV3B9al?`~MhPb_ zZ=altgC+McByo$zNn0OG_%n7l;bU>cbncW6-9ns0P9{ zGr0@?Mr4(YEOVqh4<{vo4t}c%u83twZ#Z=>%BBf(3oxoKQC*d1nOUdd&bnTn-+6wo zYz*F;)=@HKkDwUqSEi6^h3O3jJB^E2VonR)`Kw~}Vm zJVQB19<_uFe<`_;&r`78%+kc?}g8c2)Up z?%DcwG6&vcnoa4N+B3FI58+=it{KG!WM*mwJ#kxg5I#>`C9@vIB-BcwJZMSfzhg?K zZfw{I);XeOxttX{MxE&HuF$}RfVc3!>jU<-Nzn5mQz#sNBpcHzKKDjF?XzbIj5DqiM zUOOM&Ad=M3Ux-o{yZ_APRgmQi$`lnh&t%o^%U)b6{5VtWiveaLi|HPwF}ndB^Pi zK_SNuL{a53EUs^hTn4jBfSZQ`b~{-))66-Qio2J2U)Xxn+=d`BNk{FEHKVo6j#KfY z;YD=a-(P?2`opN6SybikbrxBT+q>~aQ_X7C)xNS=;b_NP_Rw6k7@jt6g~MX0vL@D^ z+H`ZE9L}kB3C=&^p$q5~rYM~Y_5u|j*U9Th{6F`Q5+?9}I|5)T;kSec|XLt0OiF0UT%Wg-5|R) zO2MtK!b-vQh(kw+9ez?s8SF)YHxD}l5+!NgP}E4I8TPsn<{i zZ?!I$^%8P?Sx~lU>(a^A`^= z_b>u@@Tc0uK51)@Bqs~Q^&G0DNa2nk`ts;gZvu!6mpFnn&D_tBcgko%;yn@;E$W-i zsAibv_?QvO;eXdzJXA9d95hXbX_Zk}=N$GNJny_9lbTp{jQ@lR17=UK z;9kW8s3!)5re+4rvXeN1Fm^+)9 zVRaY}e|<75n)sXjLJ=)W)yZ930`iqzjs3)IllYrJmXDW~Ml>O-Tm|MzVBU%^G8r-O zbS&dk(F4eh-)no|xWN4wR+<1tlXETe)(QGS=sye+p!oYp_;e9ENzfOhPjcY|AX2~y z<3B|F7#=#uh#h9Y4D{P+j_G(S(X{PgwZ$*xgDcvA>L#+O|sB}Cx>DF=rotbTOl zV8C;5mC)}KFP`Vn)9_XKz@;uBkI+8Pu zvB8XJE_B^-CQAw&?#dzf8&mJZ+J9Fj`}`mS;9q3U!!3+M0|x^RZe}+Xl&m(DH`=cu z?8k3@2iRQyDCsSj4%krl4DkrftSnemyk_nWvHsjLeGDiMWkXb(PJo5`$m?-qj_k##*fb-cnPCvHExiqf`1~LR4 zPDL@X9w36!Ctl{4$Mzw)2erCr+s`UStcy+E@BxGHE@ESOPjR;apgn%oFcT0O&p>@X}^@0i}2;NB08Vl8=L&igmoI*mT`TG9L`3ewm?p$%A_#lX)3e zzwN=e{WqYed8t6Z9Z$PetlTS59xPBA7OV={tq2mV3)`&@3Df`$lz<(OhZL+03RHz1 z&_81{@7lYe$~#6(yN1T-E>Jxes0DMkI}o8{gt*`w(v<2 zer-tWzFW6MFbVmsQT0wp(aD1KAxZI~Dsx+`cWaosr${@5bsS=-8X{N%p?MPWT?Mf_ z^|x$L2Tt$X3GoGi;w9j#R^(w!Z^n^!2&vNJZ9bS6VW>J!pf*IXJP11VcD8EIAI>Wn z^{WsrKn;|rJS@-v^50B?(lC+AkRsJyN!l%A<({GPpls@Gr26f@?MlnMV5#3W(Cn%H zo2uF~)Eu;=*-xn4+f^EzO1+g-zg2~M(WCg7qIu~+zlD@}F{OEFfqNmP_=tl0(ue#Y zrRY_J{O$+qR|8!g38Xv$GLB_f6-1J1O=r921_Yf`NRGf!o5YPD$09p^7PkOjly4^q z$r-~0=s<3rVK)5|!4hH?F3GzYKKK*_t9a#9=Yo4%>s~S>&sG(Se!R|5<5I!~CPJWJ zdcKDVzJ|sBm`~lWDERWr5PbA;fnfvf+O7BoRxt8TUL@nrpM2ExACSw}Qw5Y1?C?an zYZNB%#_cp7aP`TOXY+7R-dV#eO5a8s&h!78PnuK~CM4~iJn|GgDaknqNnw-tPC9YijY-nmnk`wG^}i>?<@b~_zXQNB(vABTv~G^5S_x73 z7&G|z;1YBa-3meRDN(=aMfY%lb1Li|tH1cMk{E^f#X+fBGtZsAS)8q z+^p(m;QcC9A4D5FhTj&WnDv7iqd4T2`hh~+OR`L{Dm7Im>B9e)h_p62YNw($9W_== z?WHP1YU=rY(B%;h|GO5hBI6vgGn5yv{g5jK;w%lEGd;qIJ6k%Q72oPSM14h8Z!}G3 z66OPk4&3$fhk?#4{Uc$2oDR3lwq5b;&v|zIii>p#qP2Jr2hQzD#O-kg{2>%bX z-h%$07O&c^KtVCI53r40&AF_6iPd|W-RV=J#BYZ~(*C^hdjh_2qyQXmVB9ITHhuJRWEn15+{Tzit%{;lBC&7=v=8K4+&T*cci>sW36eNI zlM9CX=ZLiQDd!6>zFKqRRycoIv8KJ2)Xg2o@5sRWZ;-^?YL*#{Ff(pU%0|IuBX3}r zV!_46j3xL-T0oz@5^q0JV#wjL+MYFk&r!TBH31)^$&Lg+*onb1w`CJw+yll2{?)|q zl=br1up-~Os{0Qn%|$VxC7>y{WuGugz|+*dDZI(Ny#)SX-7{FV~1N}=2?A@xojP9PQ6y1A-uxIC1K)sWU0Rwx*a3E_S znj@V&YySNX1wRbdK}QwM1bYUA_k%9mBZ69HR)iNvRx8&or`RLJ&6Y>%t}f>wvF!qs zbrO^|lO;Lc=T`eN>$Eg3^SJND38JvZ`hhd{&Anvdr=O1O6SePjNm1iC44m~S`ijH? zzCC(gLwpg%hSr)X*s?7}t1zD8CesdBq~eB|=r2m+ZYuMXO2-uBtD~D+Pyd|h!d_Ok znER1DjGNSU;XC=*=34Nbn=-p*JPue;@2NtL^_2EW2I~~eGeq@Q=@fvX_7M|gCyf>= zpZII!*>Lhl(pI=oU}DTkDn!B|U7{n)t969{wAO8qrLZ%5UvPaGBxH%pP6&nd zqS548;}Jm11ykLotnt83t1*tl+OD1lL=E1j5Pt}n; zZnpUs5zTv>HaA70M%`&P*az9Nb!yXc6%r~03Y>*}9KfbV~*dH<_( zJD8igSvxu?IXc>@nY+6Ed*f#A;P(G&qSWnG(KOKm7=$_2^^r--Y^V!KBOuT=s>>ow zn8~|w2c=gE4YRdR?e(-h&aM$yKQg{xcuTlevJ?i~%Ll3!&(?dW$0n20aRkW!=J)*N zJK;OI`g;A_FaSz*5FGVekwUA?Dk)xf|XwzD-fByc@KA z=k=RG40CksI6Ji4_RvMd%74F+j3_eSY#W6WC1u@JN;JdvwICUcYII7*dMzPn+C zqA7;JC5wmo{#7YYnDey9(504mPmRNrAGBDwZ2kfou&~t~&4&#~j$o8@#MpDx;DpoB za|HV~A1Z!NKpiL#1HS(*{X^Exg$Q;7v}C=*X#KBJ{($&7!jj?9mE&n(m;;DvDW^0S zYo}~7;n`eCubeI1u1Q(wiL9Ryhi};Y;|L0ahHIb^U-FJ9*-I6foTlr5sIT~6)CGy` z)*xFYYmoRoo^tEna1TmSx-Fn*YxRhI8lMGKQYyqd{36_TA+A`LX)m@P~|!pf~!%H9o=V36kcoT!R@ z)0E>Cw#LPv1h<#mK=oFgsVL8=RbaHA;wSijcPKwwxN=zA26-BT7yNnhg7g9EbQtdQA;idM@Ls~#&&n&EZng=*&p)YPv2&7j z@|m6Y^*Kuv2$mUEAPP1KP{H*{v^X7b(D@|I z5LXyuu|>G1*SxpU`~~w2-l5WzD^sNNMz#m}b zCFWP$N#-N1B_D%exX_6A3BXx&2m8t_jEp_*{u+F8->j>}J&thbCS0um{+ToYNLe4E z+&ha4Fieh{mR$`KKbtoi0;jkJnHIVu?O*!M&jXehPSD+sNj#+#9mAo;zY;eAK(Z41 z19T;wL`hMu%pnqlNawKqIfXIw+AJ08rV%GIOBE7-Enp4TSYyVBo@<{x8H|^A{<}ce z43kuM_M|=>pNe1>5VkjcNE)GnX_%?qRAfs>sSdLHKDX3))|I*-L$X`i?ESbyoEw3p z!B`H0v`vMI9!A)bEl#u|S~B84uXeGw7?%Q@Ob!vi?N znv1i}&~4w9-rDD-3WQ)_y~Jv2zYOwSyomUt_ow`iE<;uS9cgOQGTo)fIcmd(ZVHZG zbQPxYx?SCph;cxKaUnl0z<-Hw$y=e(ZjGHLN>zW<-7QP2Vw(lj1B*VAafw5-%X3ky zt!r(Z9lI$Q=WSTfjV_>+kHTMo02`gUMz2 z0$f_67Tm0^uIsJ@v04i9AtE%xOP9{Wn9E`V+?lXX8a)JfTV2i7qh^``CIQ4iHRw^_ zcfJUn!`Fkg>J@miCe{y`zcZ}jy5hzdVsjMMyj`Hse`e!7NT`=Faz3mbEe9!Z3x>-3#E*9=0Rq|NbY%p3btmQ&MrJ(SiCMPn zBgaTDPNv|~)g315yeTXAC$Eau&}{W!3RfK%^-Hj~E0Vc_I+(-{JI(^q1_=RCIm!5o z1QGe~XN#ep6U9O$wrmB3mJHu`S^<|>W&x?~Hw%AdN1)vqKqd5Y21T8syb8$=Y`{z3yRz$O*#N}i=Z0>%pt z-29y%VV^m$3icmWA0-0|?2kR8NlCT9ks6?$s zt@a`=*cte*EFSpp=hN3e_HF|O0pa=)$a%$Of{S`~tvn7!wZU@E20>HIDAZbSG6B9Pi?O>9&L z4xDCr@c;1W?-$GfLB)3!17xVv*E&vgzNNKdtSn2UlkZ?Y>qkpA8+65OrKsgox>}l{ zU~;wNjIq9wgeP~SBh9kX;Dc8g;arVr~B4?>C5<=uH(UfPj3!f`V}WpE{8=cQAJ`wp0EOpZ{?(%lyzr=*#UV>Fe9% zqA9Le;)E%Tu*j<-?;y7v84R?w(3Fxq4fD>8XS5XvLpKh1R^1i#%!2$@T(daD*vDs8qF_I7hCp<3C%u`$iT$Nq{rPER{ZPd~4-I-I1MF;J>{$A?-{ z5dj9L4L}en3OS+$x$jZ-bsSS=&W zef{alJFUze0xhsgoHQa7C>1L5Xzrko`7mWRS7vt9zBN=))}+xh;jiJe z2gDH(K4)&|`#z;YQ4(}!?DcZtS_$0-I5xyQoJs_?RLxn|n99Rn-9aQdTkh)d=>Fq3 z#&J@*`0x*fYw#32sl$Fy)>jbm-7!L@B{4XF1Enx;8<5JugUGoy3)s<}D(*_vD}wM?GI+Sbpletuj6J~ATv^5jVb zwLlW3u|Z7(ZR?m4e$ZCX`66uIR(UyHp)r+uAWNmuo}_Wjnx;<1BC-&2dmvS0l*}W_ zc||ZyA<$(|>d?BrLCuft^XX7thpW0kL|i=)L^Qa?l>(Sm3TGuG&YJ?~~v0rWZF z0@k@Ifka+7L9oj@+j4Z^N6xvhkc8WExpT=xmXusEh4A3l0G;POu%!tU=JrRdc;ku@ ze_S}l)S!x*$pm=O)r7#mk6W?8>3aF+|p_Gu7%M?o&?7yKU;iE`(uqAFh~^8^2!nu*R)( zV|jLZtn1>u26tuCr&}XZUPHu$t0U<~Yv~iO{_ijX&z2O^xH!d6FgfX(Y#5DEA6-h6 zqfQb$2+j*9_@qT3rKN?L1blCLZiF6y2yn=;{1v0y0)qsz;(M-1N0BG zjOy{yx#58!oZA-`Ve3Q?<6c$|HtPK1>xiy8`SKX0&3xTm= zl|MY%a1Tb{%Bm;Ym3wP}v|*&|q;l=^XX*q7uI!}~3dZ@b-H49J+5xfOkW|@!)G=th za&C7+I{I#ZBHp0JOwPw{!v6A@7p^aM9pZu6S=|ROu4|yRSAgw>Bs#lgPRdvpc$xcI zaDI#9j!&pR&UEKr1k4aK;dDXTtk1J}W6wI{1dNGMbPxkJB?cmH++GCe)*=p6O0(Jg z5d_a~(b#V`bzH|m-eM64big&NN|?aEa03?iJ;CspuUpq0kw1!n47PFkeT{4;Rwi-I zjA%S55d1vMko#*M%bdBjMtHI4$MadMEFM#=)y{)1r?I1j{aSXdC5dPJbZ?IYHm-?)zsf@WmO)O+dU1D=IyL@z*Yr+gHGHMT;CPh z#$rp|f^)qS`hqUa$&=Z2G(*Hv53 zM}B2oX4juVKes-7NgK_uoU%i?6y;#fqkGQd z>~V$3bK7jrQ`2}^)>>b+LtP9Ke)|W8tDB^w(ygA%tzk(!jlVc2NEB!mRJWkrW}6vj z6$fJLu3>tV&oex#R!y=EbjT z{7fT+VpfkY3m&6nlZCQt${>h73v_z244?qyvq9G@u#^lUu1}a>Z(6y3 zbc^$w`h^D`{)atS>{N=j1a>dh{6}+2@1tE8Lw%uRyI3P?zqHC> z<{KirN=UDaSV$Jl)t^>bTP{9ZjChNeE5^0dTy62}V|vW2uh4_r=7c z>NkUFMhV8E2@8)Z_*kb9MdaHyz3VJS+QF*BK|dX0}oo<0IsCP?3!v? zaD?c&l#m?@k4Qw^9yDl(4uVHW0S~O7Hk0s{e=tudOntXvtef7e|w*ge?F?d|F^_g?(Fz~q}^EHFbXK$Z5< zy@AnmN&QTe$3K-1+|!LmQe$-gGHy@k3&K$egG${)=afHA5jzDMkXrXn?``zCO$^8p z`;#!EBu^T>H?2m!d^2;|JF0axh)M@8tmT}73wJI$O(Uh6y4*qe>RR43dg7c;#aRmX z(JO?3Ubcxz73psWAH@-AqjYvvRr^?Zh>E_xeN>N?Ydw=3Q`xcV3z!!8u4D1MCmSi) zNW!FP81O75!Dn!))&9$mgmD7?B^}4-zY@!Y(mLhgv1h>2qM4#9@#KQ{bf5Dw{2N+` zCV(5F+vRtKp*nb<6L{~^mVzyYN|apPVd6NfCS~-LkGyWrc>6zFGCUq=OqED^-JhX1 z!;LA0a*0i0UxlfYL4J%mk9B3h=gHP<_nT{yS%gVtK5QvOIXO75W@PmEOq0e?(>r6LLtDGv5ibiHSzvzR+!Q~Mt9TiTnhrtM!nm6c#)(akFEpRBK=@IS?5LjfNr^B& zt@wD80?OWu-Eb5#P-s>jzIcd)a=og-+i0^j-d=>Dc8*@dy~V?&{u)7n1J4|qqhZN- zPThmwM9Td$BTpM|e^|8sT&LqR z1VAq#HY|M@^@CMV%Q+VrV~0v1O8~zfYm9Ow326L{v~NBpljE9!r#xF}%Y+%k)K7@F z9cJYid1~~b03W#b=g&$|4dL(MySl<&fpkVlVbCs>6VQJAaU8KA)-Rq^g;lj5seBLI zhzPXaX&FS-59;W(sAM@tAbQ$6TG(2vV)nLf22&SIOREQ=w}%eLi6~Q8x63?^jT(-! zAu3E}*yA}~Eg22-uR8sR73#vJ6A%%>Z^z}0s%DgC8AZ(ZD8hnq5#2zbLSOq11&Yh$ znT3)7OA13vW#)JS#Vqg7p@FTR*;kCz*xJ{yJc3CDBgETW``;AvJJh_Z-z zYXxsu@|Twieyy<^$T16)K7izMv!8dbuSJuFMO>F48UcGklUTzN?c;=QmF{85(NBtWQj_McOE*p3jNC_&k)#9#@6#Q-T$-d zT7D5z>F~ns%Q1i-$`Stub(3hD@f$J@KtJF6H6Bpjo@3j}t!AqBmc3j1p!;G0#V<-n zm)Wl>3U%_y4zyN_49TNp$uJa?+p2%yeaXwTPHBl;*oj#+94PSeXLAO@>6JavMS#*> zO->mS%aly^4%w}H@O|myaweaww05h+XV_3Y+VffXuniDQ3gi$Uevi(Hbo*io2M!s} z*P*6hUZM^Waj%!~?EWSy!RY_>>+<{@rl7W-)bSe5}M~aU3<|BQ=_@Ej0d91<2%4NRmYpPbWo@80TZ7P_w zWI$T=nP3%|HzXbS!~6HCQV5Iq!Op_#Ci!B15eov2BwEoD48_gahyPb_6ThvL01K|f z8QZ&$DFshO7Eo~Eb^Id*CP35$1ghifiKK74%WxB@PC8uy;Rq^7kAf*e%KbNk=R4+D zY^Qo`EBmedsp$jnt1ct3;^F2Mi7U5#k|ay!aPC#!M%ZBx?kNN&&#kJ8ni00rehtL_ zhBLVYGnKQ}CQd7`#ZaC*@w-$M@SP=mCE)x1<5!0X=A9um)^5?TNGAM;eb$SK)W|9H z@YJ`FQZF>)X{k{qB0H#SnVklKeecL^9+=w@L`4RJT&#i{tddA`L9YmW)}V^j{{?_R zf4_z&gjW|n5o4T6PzcD#RG7`HG}c^?*^R-`g1mP!j~x1i7ekovdPRrGqbY5;PktTN z6a<=9)>Xy|ov$W=CFr6P2`s7J2nt0F4hO5G7M*p`g^o0IuWHP%s$CVRENaMW%yz_( zSoVhKs*7%-JNn!jQhCvGTDMs2G);4Bfz}vA4_)*Wy--ON>PST^)AY!`yAdfItnO`u zA&UFxqOVA15RdtS12lsP?e6HbMieIdO`^Xp28a}t#Hzsh5?age6f%t=(?M$$gLE-i zq++wiCX`qWM)8nl##0g;{!EM&=_11`GIfzfD=Cf?#F!>Dsuf;!?!B%t`#UwEqSBhNX&eD_izJ~bca(Ff);H__v`~{vp(ZyG4xwSTjLr}&MF!bg zQK*X|8fJUqFk4Go6|`nGJy2e$=3Bp>D#_EC<^KfyrE{+k$8dC{OXAIu*YD-rJEaszq={U^=Ln5psH?0yUkRhGOpvd*) z%H9~mp|sVtim+6RQwhsy4A$+r{ZB$JX~B&Qoe?Q!tDKK?;=iY64!afzjblFxPd_r+gBob z;gH%GXfhU3wbZ=XX$xY-P3$|bxH{3$RorGA>NHp)N$0s9_7Zn6=vY%# zTh>%n6DT`WZLyH|ZqdbEVk^?P!lKdjwAk!e_LOL$9QST??bO-M(O>OQ`^3HI(`F7` zR@YEw?xCAwl~3G{Sx8l5S+&ZbsR0(s%d8I6jL3OV7Y~VtF~%S{X4cyZMT>pnQ3kAn zdOfC#$Hfzv@2KwvG_}$rj~wDD;^Ao}CnpcqUa?R72W4Rr9m_r9IbA$Y+kp~+)cC}U zC~f;_mQTElMf>E znHxENGge4CC67HYB$~@<=0_D0^Xn?gs~40vR8iS{D4SMRVW-i1!u>>KW8VDS;zg)` z1eN6a(FbhPXq>uFiDqymJ15HMC_TyqA6BeFsVZu{GB)JMv5f>fl?Oi_p*K0cu0T`A z`g-HD1m=TohM>(1V0mF(ll9S&!O@NX3s9>zZuRw&Ky{!gU}qIrJ-xVSZkZ_?U45)0 z*D8t%A~?x)N`cvFQ^eV~DSNkei5PK`i<+)d%cWVnbtD`Ei{qF(gRB3Z#n#_>bpaD166hcZgHR}l8`n*8n@ ziJpxywhI5tqn9c|k8$k{2^esyYAdRnEA3B@(1$m6gD_0KT0M`?;HQht3 zBC87fQGXt2pUwalGw2yc$bNd%XffqxtE+Q}sI`AjAYE*n|5m=qSjk^Ygq5MYEpP0} zx!TB#+c;^vH%IenNn)>-+A&L_xkuxShPoQ{)+MGe%d2XQOb-kG`6ao1YO>8qDZ|W>i^aSa?!!{!r9_;i6=H%`$rP zv9m2UCl*QcMUe}&$EQ|ZRa1qOc6L!QoskWt$$m8;s3`1O>GpC&yOg!9LCjf{z>Os@ zq*LhwDKhrcO6!Pzb=b3G*!}=c1ws@1_4QVApAxpNJSox+r(pjyH?6hOc5Vd7y;2B) zEDvSK1@YeE@JgIXrxfF;uHG76Q`K07@|j!SfRhY_kzHGh(@Qg%ACO~* zZ3Uc8@#fA>sDZ*Xi? zVnR~yJR5^aUvq8ioTbsBDThc}KS9ahvHe5}dmmoo9IvIA3q2~;@-&$Ko*XHb@PjUo z>=(!W_F5Er@C6_;mV~CTPxmm$Y)=-UR`S|@VkLiuum(hm!sXnc7BG&Y#hP}dcC?-2 z1nsg=XbXALN`&v$3Q7id{ypj6UJJ2vApGNH>VQgp*w=^XVedAhlko+MkW*{nPP%=+ zIgPfLLJNPTrxF1>4y>K{cN|!Yc*KBLAu*zgVrlp}RObo1P=AS1Nq@mP+r3m$=^iaw zw|$z6MyqP)QJb-Qc+v)w_KM~Pbef*!tz$z!EH}t;R59q{%rF{D>t+O+Dpumy;UEk( z-pkpFUJI}*Ri@m-%AF%+$6$GTiR``*CB@Ucy~voI;v`s$_hqUa4m^gwCRg6n+<-HO zm;d57_FTuJ@MAIiV6O4m{_uLuU&Sm9R@Snf83{w<;3fOf0<2qb@9%hVztQo=RMX%8 z%2?}XTO1Sf=k`<5+~P(QCQ3Hd)m8Q9qnPhnlL|QpX{e zQPt%&%PPxLqJL#PW%M`(HT(GZSWsCJXTH?xoT#Uz_+D)_+cRFq20srF8f_v@W$hXK zF$}8r?T4D$6IF&uWxI})GI}(FLt0^epIKgf$U^FH^`T1R)sNx3Me8V9I5Jwd8lzH1 zk7SV6t~#w(K%#;;0%s_DufW#TH6LKB2YoQU zjByx7v}1hAD0F7gK)J!5bw^(v-s;i9)-{+MMCOu3ri>a*uc){k!Eaq{j_l889iCz^ zbDt$;?U6i+BK*F6YoI+TX0}O^b9$6AYUJ)UAF+GQhwol<^okK}tJj_3)F6&FCbTId z$J0j}+H-L`F^v`~`dHn*|7LAFERP5h7uBajQbx8nJO^JdqR*t2H#7z+t>w1eM~41? z=)QczwLNiYRrIlEh{%81d?HA92zZ`06PBQ&<7{_GEEwP#iBQ;C*7&}`JkF^7~9!=r46 zMw1wp{-g{aPe;@PHT7-G?>?cV+Ti;eAZ9m&*a zw};gyiF{P0-kKqMN9TjpNVtrVNWF?>67o$7$N6ifZ%EvB#FwH8)fQ zW>nE}#m=E?BtxhxgSf&#V^cvuebARd!nC@&rbe7p)SJ7&9X*;aR*TVMy;__OF`AC! za1duz?HXj;l!ftU-i^OBxL$1>MKm;k&ML2^Qz0q&b#<$n>)SqW5z>*)Ubgchw97X& zO%OTd)zu}a+KE0b9)pni73kr{SD=~o*<$23Ay(_8C3>~ay4FQY!l60>RK8LZZ5S-K zxQ(lEmY)9ed5^x*K-qTRw&azdF_cR8SeT>vbqzG;(|R&~q4C;PvU+PgId4XCVNq#v z?tytFr6nlMRP+7+1$3l2yEt{ssI=tixihlo=a(iAu5VseT~#qSGx#z5Hk(=BMNln9 zj!9FP3g_qNXSVuYs!Q9pUs6q;R#cRqn_XzPx5=21onMlh8T@p#Me6Vo;~dZ(uZJd2 z%bS^3SeiV)uq1D0Vea&H$&IS-+~T}~?BYeqb8;71!p#i+HGxd);}L0@Gm46Hu`e}@ zY?qc?oI4}8IJYn-*P*4521SL)dVVfyHYd9zCwqFXD?|%jEAZ^<=%BT#$K8jYhVI>) z!TF|j<`quQJun$9xs0Y>PUwwg_4XebE>pAL;RKDj2{#JGP0uaKX@e0}Pqg)AaNZu! zHezpR%Z`q;ehjYI1JXtsq}d*lnf&KUZ~%kL_khe%`-sdag*lKxc{EfyVi0yWNHr*J z6^BJRp&86zK@@0guAK-h{v9F-#sP$##^Chb4)PK4(+=b2``2aVO-i1vhq`1(tTR!h zB@;mzjPZR)ko)kn4;YA~KP19BLtwJapj)78CB9`b*5@x9eQV2+Rp+3Wsa~y5F3ml# zv^|luEs4xzg8e6qSR|vNjNP~oZRP(%4&s_3*m*(n-dNpVF>2%VY<_4cQ{Bp%>g?#a zC()8XdSZS*nezK7y8J`#@@WS!C^aWY?lfAnruP5Hm3pFr2o?~}G{Tdk%boHG zEag&ZhAw}XI}+p$pO(j$3F3rka{V*tu4#9|x%Lx0DIKFMOzfG`gvn2U7zll&P=OQ>{^ zE`OBQCdg~?K^Z+*s>|=?4_I18r3zhsC$IHsIP)JCKG}8U$%{uj?2i z8WZF#_^_HD*68vZd7V$IV{l1SfFp(FKxO_hqdf%Fdh|88SWN^s=<;h)MH6El6Hl`9 zRJ>Yh8Io?HM&U=)CeJR)D>Ujt{xFnLiS$RpvuTg)VAZJ)Ez)T8A5yg9iD3Z1Z>CTTux9Rtn=`n1Cs$bkpY z-4P6CvM4%7(Zr`6#n?@IZw0~E>O%gidON1jO0Vecp)~-}8%1jntQM{;TCBB0|K#vK zPR80p9NF16)?*lKw2if08m6|1&dqEiFozpeTlGHeI0o6Qy=Lu$Ie~#-$>;zlG4L=& znNK@~!ID3bb)R+`gEZzM0#(LYG(Mmn7Lgkmq`UIkO8YZ$&bIg7Rv-Sy>e}(Mi1yKY zSY+4eeJirBZNg_UINR1^tK`|kS{p<-%r>%FxW%>I!l(U{K`v{*VKku5Wl*$_IrM4g zo7NfGT)pvKR;x}F*fd;dS!a~(FJf?yX`St-Wl=2;S$|X#9hnT*@zDv>Zi}bq7AH?z z6b&ra-a=C{W;p+%4CfMEeks4g(q&Y-T$f+SrxN5-KJ6+7nhGU8?Hb1B>|0(#QZ>|4 zG%Ojm6iw6iQ@lxJDB+(Qc1aZXt;~&$B1$edk+84R~Ok+#J!kq`w<4-*xS=<;3p4wkl4=`mft zE#L8JPcXP<_h?#PUftLpQBfHUvgas8!NyZW_|v+4OTOgO{==Yg-xD4U8P5?J&+GC{ z`BH-RVk>`ycs4eCnHs*L%QxgJ3Gx+u@ESe%pDtflr8lVbrY`@dN^eu?9bLYrO7BtW zeO+(hU5|+NC(pS2CK|Yos zAMvYmwN4_!V(s6Bus57Xt77)(8a zL5?Y);4*NOi#Z`{UmlIXdUW|Xt$lfXREp8%cCZ1Ov8yg0k`G{sju&|Rx_nUHgQcES>ZQy3Rb3w{ z_0{Fw@*bb3Uy#UF7mKjZ0P2&X%Wbj+OM|F1SeJLnTYR201`j${jY?TQo$fAvt+wanby_H0nmPW^N!*&@JEw$VjA9=$wit zgP6+HmWEJis4nl6wx3;h|EsLAwez*<6qe@)s6=Tq#R4XRyY8E2?7@sbjP*?@-DaOQmtT zyp1$Nf9E`^<<965Ci~!$XA)tVtjo;`=Ts^kpv#-d=BF`O*`As++d~-j;<0Bs;m+0N zO_ZT|W>RUEF8?jBPmtI9JaZUSn#2_36{b2yAtlDJ&)K($ww?7~PXVDW)a52c$XqJT z)8#etTA!zc!HSUVCdxU9LC5YAGM`W{(B&2KN(OpfZEc`IeQBIt5$iCwxF{#Lq@=8* z6scj*r|r+4Fi4DiLlJW%*N>%pJqKeJXv#-83!x({!txRnV7@~N{Z0HnIKsv>))Zj}6H^O}aso9(S?&PR z!3J`48$d=!0$J_~dczCm@jHU4X^HG8@=TtRYM4XaJj#kG4D62`*MupGp)cP+g7YHeFsB zM}~*(4z+xwn(J4NM&CN_ ze+cdTvnxqELL2RLYs4U=5z|~7`9d4Txi*RqZPdw)A=V|>h;?(^_XzFW+f95d+0kJ@ zXoo?rB&CHm8sge$cxaUsz2M)RIBV3nV;9dH!hKa1nYbKr;PVIaH&BjIHn z&tHMr@ERNl|HGl^b*O{4;7E8IbDwu`V1ExThxg$|_y}6yV|Wxk!JePPoA3pE3SYvH z@D*e5HR}N1Fh6|H2Ez|*1pLURz%MKxeq{?`2djXcY&HDBj(}b46vo-POk-Cv54(wZ z*)|r-9%FIr1*WsNSV#5+OJF~v z4QwDkh7IDUv%&lVmcg%KnS3+L;`gwj{BbsdzrsfHciAZZB^%3sW8;K}jTeb*qUgh> zh)gzBjAaLi95zi9u^h34%@9>=rf6cb#4&7+IFsdzjjTXi!{&a*jd^M>|E`i>^$ufcE0v+wo$u_U8Ft4F4q3TF4f*(muVlf z%eC*>mD(B%_m+WWY_BWKjNhz-?^JMG$v4J7UpY?5O(<8$G&(9fxxdyKp?sr?#>a3bQiE zHrZ(lvog&a+eo25W<6pYbHKDVW3P@ z$yq9Nmz~ulD+@ZyE;0#(Vil92_)s>`4$m{$I9^R30s5K=P76B&V1kz6*D|yGvW1R(*DFz68I@ecWXX>u2?52{*zOp;gCe)o@_COxup_7^vYGE?& zDSMg3eT~H7R1_wW>?X)`zs$(Y+RFavm)ijg+t~RGHbL?PjUIHhALtW2e$DUM!Y=V^ z_uqzK5%$57snLr3-mws;ICvL_Wsqm)=iD?UitlWg85DUO)B z>n@C$!X(9!A?=AEcR?S}ylkzPee2~OFT2*uE&%lSi+4c+c)}|1v8wa^iZkO-LG+e= zOhMEl5ky9RTT52}6sBioWVWy?0b1BKYL@;0yEbg2EXA-)5x0$w&vx z^GP8hjE=rC*`(tzgh8{06q}Cg&{|}MUuI^tpxGiN*OS5A;6lkeXfp5H!bKQ1B`LPK zq}b+?Vwy`lPNaw?8Aek-+25pTtw~dFo2Hu`G~MEEzuzG-KSD3I!$DAQo1oq{LA`B) zdfNnbbR}qjOfd*zaVA0Q?`E49S+iVr8^B%c_QI^rY|9q5bz$aq$j-d)QkaAf?x6=_ zj7*Z5_gxA7@yUJkgo?8AGKj+m572`XB-^y>O)Nb`rSz;V>=816$4Kl?ng;OH7WT|d zc1Rh4kq_7(pdklcID=lC!$2+|i%S^GHJHjhFpK+OE|wSYI5>pI+X5K|gXBOtNLkH# zTQuwCV412!vtFjjbY#B^1SFRkruoN%+zG?HY%}Y-1Dzm3NSRRz>G^#uq!&p@ue2^C zo{U23heGO)LK=WVNIrrQs+ zX2tBkw%fl-483kL^u`wU){UY5#-~FEKEvVp18wpK+BzI4nCbc5T|IxO9A=Voq^YmL zPEu?yd(R?w;3TfFA@teh6xQsY6(qHhr14E;CJGb!kOdBjqTxD5NU(3mmoLv8uP< zyImfCH~SD%gO4Y~kg4CrKA8~f_ikaIZiMGTh<>VteT5>8^T)NYuhmUV#uoO?7WU&p zb@!`r=l9;heiz$_kO#P@1)Ue%D`JcaIYv*?Roylo%iv0wfe3iKfj~V^(p!V(tTDlz zprd=;>W}TrJEDL2vU<1pIs ziAJ>J44bh|R@jN5EP0k+;($8MAJdsnGDg(cq*#1*B@D!8=9o$kXi(MZkuj>qA}6m= zQ4Onp&vsbl*S5oQe+<%q5e=!HvV|XT5%!5~;WFIvmFa4OZW3=XTi2gzc{V>l&VTE>HWXRG&7>|r2%DG1DM4j_FZhM<1K$Y0^NVq`x{M|8t66t`E$hdxXBqqkHk#ka3i(ZJ z1;2%@=bPDa{8siaejD3@<$L&@>`~srp5b@1m-#*HU49??j6cAB;19At_#@oQALYq> zJ0HOx;}iMgd_LYU;ZN~O{w%NN&++5<^ZZo)65q&Q=9lm{`8E74eiMI(xA2enL;MqL z`5D%H&fn%=@L%|sq7(m04B%gjO#Y3S!M_ztvAmrBAnN!pVlCexj^@9K)A>$uF5e|C z6(Ft?Lfk5(cv5KM4dD?V3a{8DG^vSL886~xSJ6>siUc`Qbe1`yi<~KX$YRk`9wPe4 zRU%m)Cx*xq#ZY;s7$!H0;qpo`Lf#}s$t_~Ed_atqPhk03F+sj6Cd>E46#1!`Dt{0M z$em)EmMC(xfnt_6O&qM{ibJ$~QKl^xOSOO~*Xl)uc9;lg=ZM3!%fu1d72-(kTKv61 z9H-qOj@MokCur}96SWV;N!kzMWbJoxil>V>$EPWl?PDbhj-b=A_3k};wQFKB4?{jIg-E} zO9J%F;7r{qxav+plleBZ0)$4(G%=923zgQvoXv|3G@+M;YFhu4mwg6a_8}(tSVj(a zz`PyMc_$o6MJ)Jw_WB)C@NTRxMOCbEujsl9EhDBi6ke`C^FN?3&|G2w&Lw=<9UF9< zhL;^MYA2*qbMDy%{o4Vw3({KW23vUf4eHwDj2)q?Hxgqrr1@0h%;a3h zb)M@rMi%pv%vAmwbA~bA4)jL^XBhlQV;*nKK0@k_3ZLVvl^t;o#EbKxm-rW?i_2h~ zxY}N;ibwUUc?D+s)*T|YbN=!6oMgN`CmCUq1XNs)tlSKJ#GNomY=u$c9+)m3QtZr9Qw`&Eg@&=ix|vanPM%p8M_CCLvW_qjGYoBxdn$Li?1vvTN|8h&T!}IapdY5 z=q+A?6!BjeAzp`U@veibjwUZ7>^r2w=4zVF)ij%{X^I!2?&iC2b)Z~ia`m9e)p&#O zGff8mIYF8lI&XsJ*IIBS#Ub{RZTu<@eobK3u#In`ar}nO_WFTgZJ&crd)OT^JZ21mEH&yhOWfb_>m28mKaKk0FBGtA~@n7xoNOqQ8zp~K`-#Z3&(=M8QW zBe+p@ikrk%xG9&*Om3bv*MKJzH^jzm3$42?6EsqmM#}Q|G40;wV9nEpvSeo*<+?$V z^h00S3x>!(w$&jbo4v`lvL@TgnyeTV>TanD97(3yGz`NAqaK^lBvWl>9Wv?(W3g z@#h^zuH^PY`*Kr@WHJr&gba)^SK+ACW)X~(0l6F{QX3-EWUG}j9;4L?tCfp%SIR0=x=XM< zjY~(FQY=IXY~?SKFt>w_=CqCf7p0}1zDkawo@&O^EcN)cpg^-oo*pGn56ZJpO(e3& z#k_uR3xC5QPj9$9Rn8A%pab6Kp*&}!JoC{O3y_DoFh~|dhAe?masgzcZOoC2VZJ;F zmdd42CzmOi78{({GCj&(qB=@RlGD)|B}oAZsEtFFoeqKnF$<(f*2bP-B_1e-^ zJ&`71wpwAeLK?kl@v;-}ozO?+0-oO?39q)$d!yK6WVI!9_yoZai8Dil{$`}mE$OKM z^-fy>%8*_kvMNMF*=>TXLFthNtcEn%jJfbyN3fb{OKGMprI{+=l9Z;}QW~pdBQXgI z4_2y`l1Q2ztVj-Vz-&2$NuUPFF(h!PnbdSKeDYoLJeqT&?|m4yK_ZXFp2s@YNW0ji zcd<$DV#nDocASk!W%De_{6+}y{f)uzf*WrI?AckE4ymJUT@ol>-_Lq*G=qEnQjSy+5&luagc z&zpnpC`XjevSW&!P&gRWT4nGGgnT6qyjMXlc{N6aYml%_4x1ijGdRlLs2XKQ(@~05 zGK>txs)Sx9tIh#9L$PYsh1ztg3#+mG5ME}iZj0?G<&GFqZ_ZRp9%}Pj@w_?Rc^=o= zv@lw27jg?~c)CW!UN`}HlNH?{W1TZC*tGDSZI+r&Tye&3?4B5h%d z7y|fU1c$9++%_?V0JETxT?wgpdovo@Ezn7B0n82{S#HCetOfn#9+)EUhf?`JI9R?8 zN60tfRQVPT(eJ={@?E%Cz6Y1$@73~sxLtk#+vJCE5B@$RKZd8|C-9m46n>ST!SC`5 zrpd2Ziu{^o$Zyzq`5l`ge_+}2XEsaz!WPJ1*%G;f)ybV~joihK(}10*adxF9*i9N& z#(pJ+G~~16u%@a-Ez4@hk-n zk?XNW+;;XJxjCY3S)9$Jir8PuDC@_fS+M55m;R z_H?i9K|a67?{o8XY>x99Pv%xJ-Slm%JS(i67wYUjf*$I!{VbP7?~FwUizR1|jd1oD zi_}=EG@U)xCN<64*m|Nv&WIMV+@??BGpk(|Aw zzXLftw)S@nI(v-6*<+%1b}bfSv^eObC1OU^8IrXm7_4=LVOn>Xs`Z2g+88L)#==qB zcsN~~0B35G-~w$jT&hihEAV%dHWlvD4uJc#YwZW+6>0DSu9qY z&C;|vY?zkMrf3B$M=N48w0W#RD`rcy61G$;Wlh>bcDS~PovbZpr)dYVP1?ciHtitg z>^EXwd6enwKKR;n_E83eL-yVX_KZ6Z&^Ebkx?s z0BtR#YU^N}wjQ#z!(fhf1e9t=!ok|nupGa>q-A4#>35%q>*ZvuW46sD+eF^BiW+LM(N$N^uip7TNVBS@&n)tlneH z>ctV86}^jKIlCBE!D?v2U&k7W_62yfFHxf3Kv(Ts=&5}N{k88=qCcR0{|E)zPbkfw zVUhL=+V{6OhV8ItN)%{J&hO8VXQEWcqDlQjo~0I2E7a`CSb;Jm-4)izvoY#3 z72)aBuzG?K-gq~00(j$hp|;fNPK>4$Vr#tu1M08PFJGPT>;N)YX`b!${tCu)ir!+R z$@xF!Ii^M?we>8n^wHsCmhFvAr)KsV!+*0AB~ zLYszWlZKGjR9Sh8INKuSpG3+zuB50Xcn>1-WP#5!61sTCImpSd$;mLu>Cy^08|6i< zisW32j`N6)^IJb6=b46dNmdrD!LXQ}P>ev=Fu6-L@bj*vl@OpA?~HXAd|U9Wf;FE3LWZ7TGYmy5Sh1Y^uY z_92H%6JqI|c$2k8a{%q@m$J_`ajgWu)H1h-8@GvD1m1hH)J>3N!!*}GjAtz*dDcN6 z&w9rip@A6Gokd_@dt0uryh>he%2@?NB;^`;tx3uP^R3vP>EMCLB~zwb3}Cef#b%3^SsEN9q|9A&=q8*9h{r@vt@rhD=nN{uxc38jCtyw!v@-F*95 z&j`{Vq+3l)JTsB*S&kQ+b(>~gQOZIny-nV3!Y(rHvWKO$j;O0gwu$W=^BO6(iYJ3= zGAN(qpuC4e1sd?A16UXnci2pnm`rqYFp;6T@MGv49ogqCem8iSO&k{OFbah!w97?sd~x{D<9 zZh4QHjbzyPQ=Ck+MZg<1EFk!os~gn_tkR+2Vif+y4OF;hNc!AH#s-^nobGc2RC zct%BvE#lciEWBW(-#7x9>q*SoP}{WYnap5fmre<$_A2e7AheUa=c~+)cO+!H4ktNWl0V-v#oQ2+Q zrEnuqr)_EzkI;d$XVvrRhpR6I~`|jNtwOn()8XV zly*)KD4x$V)9;f@Gn|Iy2$$Lm$n{Im1%G>Jui(V^zxGJQp}U%Lsc39-lV(q}(#+UJ zw8sFa(@s0krJM?WaKBRUjmYXvsNkDX!8f6TZ$$;)h6=tN6?`Wucnd1{uKh#75A8bz zUyEE{hYG$H6?{D^_=bI{;D`4s1)qkjo{kFMfC@ex75ooW@L8zfvr)n4pn}gu1)sNn zDEJZisHxy4GvVneCihYb&gg{-?qw>NlY)aPRhgxBBJz1Ms`Nxu>8W;xVX2eiZBLu_ zo@U%_Ly6nvVL?h*pLqQ?xot|JqKbo|I3S7+*F&b+g!B%Q1PJopCqcxhUPTymZUz z?7Y)XJ8fa$%_}PDzDvAnnd9vl;pUizYD$MrS_TZzGLgG17_AL~DcVq&sSSf7e14!d z!ZBDbHiU;pRV<$lSz}R8*)O9zz1XfoteyT3_gozZqJ87_SY0Irv+u4T3Ul zFjQ-)wnJ+68s8AdOM^9PHv-h16`5)bP2>Mo$!95ondffgPS6o-A2+Ao_!K6dwCIRyYazZzZV zrLLV{i>`CFYv=z(*SVK#=hvg_EL}Ul5mjgLqig3kZT&7c_1nuuznPx!>5_4P_zm!h zH=(n53rGLA9lGwNc634AS-S4!qU*Qz3j2Q$`?HAsImG__9$5 z6~vz9$#lhjFJiwBvEPr_A8;&>^->E(;n?S!hx!aULsFCV~uMEsaLr`-C5^Y53*kQ z!aHSZFdRqCPpF3yfDZC^@Z!kU+nXJ_s`BYRQqe+G(SfLnsZzCHE%Hz(vr(n_kc_{BL=lV-b0J&IgSny@4iY7>N|eH3Vm_QM7T6~N zywF#vSM4R+>fNB;&r@gn%}*szEva0nJ5sq+ccgN9uV=ARxhGWReZp1##XeH`Kvel4 zRQX_3dD^~I`Iqu5lfc7~En>F6#Odx9@zGV#BcoS(FIl-od~7F|H0%8!Y}PCKL9FPH zLAoFG6Df{aZ(n=X+h4u13F^*e*4rmUW?$QL(R0n%IVEH+nr>N0rpE}QnciTnFIb!4 z36HYs>^(1sIKB+J@(Sp~DsU=&{tllclq)SY6_VyDJ+xjt!YlZ%gs7(M}o?c7ypXOruD`GbjXlexq;&Rzc* z+tKr<^v=M@)IGDeXK6<7U|6Cl&?iAdH8ejAr7#?c838@`Na)W;!*Ki^%g5Q-MK2`I zT6r61+rT&#Cz!emTY2k+=G!AgTtDuOxVoXZx+8@>q8Has@@Es@g{HW&90n08BdskN zsr_8u5oMGB9eF3{#yi6x{LSQDZTWO^$S2FTpDbHGS>f{O6d|8qZ1=7*4Y+UH?j4pF zvY#N1{R~~%FVKhm>agd&w!VxHwizFBi?ruo00*!KA)h_un64Dqy$WWi}>Xt@JiYyyu1Sq@bsw6?1>$qQQ=`|P--07FFEFix))9o(RqKZTQMre@_EOhA>YA*s{na%^ zT?eUas=B7DYo@vmQP*MWIznAXsp}YZ9j7o&&?e!3RGw;>Ux2?ZZs*l*rxJQ z?FvY1MeV21HM+S)uW{g=g-mIBu*Gw^?Wt%lQcFhb=o~oH`*5unY zMTUKQip`o*{BNO(UK%Wfd7c9g@bjH8$Fm5t{0s1RF~o?^@plQtdJgg&;#ms*{{v7< z0|W{H00;;G?W1j2(*39CVFUmG;|Kr%P5=M^X>Tucb#P^JbZ={AZgVelbZ>HDXJs#K zd2?}WFL8Bca%p9AFH>c6b7^mGQFUcV>xZf0*%Z+A^$aByXEE@NzA zb91d#-BTM?6#pFv-6ez%188ZnR;d*l%UY&jCML}xCig(S@u9c;0N>9s5&odqSN>w~n6I1q@v*>Kii4uQLP*a)g(qv|8 znlPJwRIo_}9fV_sQ`8EMQ?R5~@Elv4<-Y~tdeV)eJxKpC!pMC-OIEpHGMX>lHDO52 ztHNvdxKYtf=%^j&>%z`kvJJg>T)`7D97P`?9`YGPy(qo1aH}*lGMwbgKp+kJV{XM!c&AESFX9zTi3&MI5^&p zsCb$X+Y2}^d=cb75W^`vOK2$tln~A}45<-^)0Qks+fPRE90nB(#c&1*!tq0F37wq% zq!+06ZrF*z#_-j1&iyPQDzBGJPDmGiK(Q9X3pmF)Gg#UQi0o|?^{k4~;8Jh-Ri;X! zVmX2tdXeKWTq%5+XGGmMi&Di)TunC9Jzw~yp>N7c;OdnaE+EMfu&axXV@YBEi?@|1 zy6|eyN!%?THL!R{%^}>(9(uSklvD6Jp?e>5`nn-YK9^s?MZ&~?Tza`@&D~b*!JykJ zb&x0~@kWp^ckR)86Ruk%hjLM#8O?;ql#}P%)tQvNQ?M;zm@K%@wr$(CZQHhO+qP}n zXWO=I>uhs&_q}r`x@R7GBJycfJ*=pRKfj91uQFL}GAPj0O1g+uX;y|7V+pFW?Wg%` zDTuy1&k;7#ACsp+8emjQ-wL@K=lf7-A{V;5nr}F@f+t(<;2tdRd*>?-8)JST4yvo>mr-N15x}pETG7KKZHIa3Yf`>OrEbHDeuQ`>zy&=@XCJDqjx1 zKrX?MLzQK~8XRHRq}U4JYae3p8}L~5jQo|?A8h;Rhr<{>ipJs(PBg&Qn#jikD<@Oe znWpT}A=jCO;Lquq_)uKPN8WsD_)FO4*OPF2uFQ~JXcm|I39KyH!R)O*yK)@1d>-6# z#OoTYuI&Kph@DROm7!w?U1LlIA3HS)?{CeR6Z#E$oWq=%{5jO)TpD_Q9lf-kQFKo~ zuul}nJ1oaLuE+Zy-p%B5G3$9b0+v&b3Yt=5T&O9UGBqNKHJyG#@mUz-h9Tzi@;yq& zt0$V3#+NR1e&K-1{Iujf8kK^|fY)aoaxhuKC#3JMkmP~9y5M7CTtdp7iZo|@YWBHb zOWLF7kt%uf1?9vjc5l0W?RNjmewkok0Ceh1J>(tkzox6IrSlKNAOZl;3IPD{{ZGkE z#mU4`!uUT}>o+U=e^c833i6!Rg!0x}_V~e*YQ=ura5xgPzal17z#dOMWT#7HCw9Q* zKv;969%q%v7ih43|h^eC~w}ue)$=WHa)0L};)>EevSaQGbk*bhAJWK@8&1QvG6~x`!NL$ zY^#`IqWQk?Ely5^E{Y{iWC%RS*k;#AxKIxwNA7jpX17!Aizu+ddsnd=iOSDh2tBt?gb8Ql3l z`hSFY(02Rg%87*CBoI=?)gh^J#HC~5fCV8k=(%%T2#pGc#ObeKM~}}6`rs2%!H0t! zIIzLtWSSvWj_tYK$;riB`cBH^XAakqQbqw4JkqTRXyX=i0W0NVk@BAzsRtdAtPxf7 z6AWZzC43+_IQKEr!VrIV$Hhhki4&-~7+9$>@4KrN#7YM4xwcTzILo+I}zi8ISz0LG!gO){VrPu!J z$LTaikVn27X+vtAHWz>cjUpH%%#Ch&4Lfp19n-K^(-?kki{#2kot|CK1VGF?}|`!tJFk#UM`y43k_K7GQIT*g#7imzXu3LqCHwC8T^^j& zH5jvn0|+fw0c?+vj4)uV-7o&i*y0IgqQa;I#kNSfQ+ZN@xl=i8Fyk4&-{d)d^#EZF z#j!zUzZS>|>x;mb?zv;RS2Nt*66}RvGE^ynbQUfOgtP@a6+R#zn&l7$afnE2PZcD> zB@iR!SWiDJv# zGZ8`HX!+yp(CN>!(ShhD`3fJ)lumK-DEbvvl%U0U0lO^kY#oN=))owRh)YO9&z+4x zlL$2~lzI>x?B#$b#9)Jysjr?&-7}ITo2~+XGr4G=Up!-0=<8PE)yF$w#*`Xi zwp?6A^MTVe*X^5sAngt~0&_oB-pK8ebgpc{7Hj;>W*7pgCsD@p8&tY>6$68mEqxaU zdNOzDOn^{~;(%s5p@82UA0FnRhtoV74|bu@qR_Y&XLDRoLPf#kohU~kLssz?wt-<* zN^WI7fo$lN2~>+0aV+q_TTD(r*|i390(9uk-gkJFq!$sIJ{fGm$DEb?Y-&+v8;2K} zfb-*BXXh{SnD(L213DZq1JZZ8wThEeC!*!7w0nZVCNsXV4B|Oqy0RV41wDvlBZ6)t zNVC!2D!*RqKi}hpJQ>x2bcvdAJ4MPzlZ;if+Cr*p;4^*~viUgdX~QD6%#QaZufCaT zNr%qDONwe}`6CWr3uH+elcq=?!0~cdBio7G2;%yQsSs!vrInN9%7voKA$7)q4aOtu zaZ`7y8agtOuvkQNmvwGEdt&Txvce_b8$_pKD1|V#9FO;jnkfT7u+MpZc2so5fgvKM zc2u(+Oxo6%9?8tbv*tKU9LnL3;mzv( z8Sy~01gg@$Yz)~|D!P8pBCcU?HPzN^!TBz_Fu=en+g#Cb>t$>`CaeH$y3mZ9=&g$+uBlTPBQ{lZfb5AFo#=j@^FC|@H)f#> z-+&zitIVC3CksxNE*q>2?oTjou2*Q0W<-Oj<0VYc_pPl}rfuGXM-LfhBwCxEp__Ei zn``IQCY#WAW(@{bTBCE7l4Di*4J|b#*4bVmGpxvTn~v(?vIVwQMfH2>1Ika9W<&{$ zqNf~OT(#m+b)O_HH>O#p3fD8~;E)1hCl7Koiy6r_p8l;eZ!$zLI~*V3)?JpiL)Ph7 z3`ft?9${RYofy-)T<39bAk3SY7?5}+yuIQUats^37QSL*Uk_hDj zBSG&G8VnneFyJ9lw;)lu~ujkQf%-Zpu9e6Oj!+~Vz>ov3!DQgFd%x5hcUbG^B_ z+hD79Qg`d@(Z9cS=p7c!=)3e zXljJ+;N?wQw<}rs^iY(A(0zr_-xUN~(Y1TrWap&0`~&+CEXt%cenol`ua0C@dg+sz z;1b0yu!6~+{20_YzqIp0*Q0jyBfrl0vZ0-;Jg$kJy5TfRcu=z(UAAr+v0T5QDEh}e zDsHA>(axsP)x*o{Y!1|Iv4hO##`2QYD$J~`wq}tju`PB|i>|@4TVn-vIlxCZMt#Ws3lp3SNjxiM9OcL;hXy`9YX{L zRYn3R=v$u)B2(1phr3teB;FIma z-|}F$;6FnibOif0*=0L4-E6e`Z3pW$-7mfnKV-SvBVKJ%uXy)YLEUa)!G6b~|A1kz zPl4PdUg^3uBG@eUaCz?#BBn>PpcA>UQ;Tv6_^C&Jnsu^N)y;Qj=o>yTRF6khFV zIpF-l7cUO}WKM^yu<}4HS|q!%QN>g?m4~Dkh#%_30%MblFiok4VZI+FTBR(zgU&9P zQBc~0#wA{PutzyPMoY2Fs!N_NR^B+EM)^+<%eV|r&!lo5YEXmL^f=lhdVxTHQq4bh z{B8>?T{WvD6xs{eFCY@F&?CL-HdV6CaPzlKxDR_{KZ{jpQ>y$ z4_$r9;j1ky_9Y887JF<}=>Wr6uNj*Z_U_=M(!pB!{@Rd(wW>q2*#SDixtM9hq1?R> zCee6uQM9uq|C9%4av5(>qtn^e2efwCZ+*u+Grn_F9P7UO^Auiy_|)(nKB6nk)Og*{hR)kaQ72={)?P-X5LAIZE@p$EUyY zH`TPvTNBF1k@hA(C7Z+d@etGL@Ri|Pw4RBUof?s5rXZl$6C`W| z8FmyTEEE|Q%@J1Z!s)dw_~G{Mr4op{7*n@MbX8#bPpEM5LF=L%mslY;7BQF5kFU9K8aH{`k6R*B1CO-r#J%(+Qnpxg)VkO3`BF z!|mgn72vEz5^ZYvPxa9-M<7p2~Mu)eVoVx$Z1OPF5M9tdknn zX)PN;v|53hN`cOj?gXI4cVuaUSPDiEQq@q%PS7coQooU2=?DuW$Wn&bb5ax~Q%z%- zV2krD{YvJ4nkr7dLFx_f*oDXkhubn{@%rw-EYq_GUovG5UjZA|5z2 zI4L-=QH}>aTeZj9C>eog;cL=_3nsLB`+pWL(17WncMG@ATk~&r#PYmVZ4$R5 zB^>1%l+JTy(Dpr)+m)L#k#j6naP<(J&UbQW7VKC=UMeD0FUd0%uogp#qiuUtoL6&| zYc-Yr6Ji~0P|CI8$xQK%!*5hCvIM^tJ_VR!EJ{B1Hrz7Ks5wrYHw?`PX@iWEgOlTF zDq>mgcKmp1;=F1C%1RQ5Y-%G6;kRHDeyN6hf~i2LGWI7eHxxD>5jGzgb}v45Z#D|7 z>KsJ3B*w8=^N$r1-=FWDLVuiIDK6hQSMLsg9GI!{o7eQtL&}z`Wy6C+iNPBSS6`sK zl03TXky}N3@4p_5gtUkquNsCw&?+@%5%W%jcw7)-h-yF+8Vpnj(RB-k#zagF3(e@` zVkag;V>8F+umgJd6?1s1w>mZy#u%-%wyIVCKu-@2u(Htd`Xy>Vk`C@2fR>N=-YQQ@ zTL^o-W70o4Q5Q&hBY4%6S|v8*I8viFGMSc29X3fX%twz@tAT`Y$E=u^_>tRX`|D364D_4E4SzRM3jIT8g#VC{~sH9a*YXx9@># z4sXosm}G4=%#>fMnJOh(XUr|f`3u_bSrr|)EawE;Dsh~FE~G0~t}!vY+^5HcFCAD8 zH>PqeB!cN1L%i`^L8_ESV;e*YcX|?+gBXrq94r6AOpU9~!`-%3e6>6dYGJL3 zuF&RME96-(=Q@|mxmL<`Hj~+|(BwXr%Xzkt>8{kp!k8O*SwzqF==wbHqDb*y!&Q6< zS^m^-@KrvGsYuAOmX1dwu$o+%+E@!>ah1mS_{Tr2INIRXKq6= zb;a@Y;RO%o=FIsJ zz!K4UUkW4ZR!TdV5TS6_S5q_GO#h~Cc5eCjd;!PyG=Tp&lY@`UMbL)ssMzQz$xK&P z)}^U-(4u!XhMI(1gvJUtB8q|=fFz(7hBHiIwO)9-+<<@Jv}rG+v=*s!Xl~lCO1n%S z#`f#94C$=a*Ra93c#E!%%cmlc6j@@ZK9TIEx9#>WTm%onPoPO1XBgV17HG470Aqlh zqAQB|UzVz|RCklKHx-_1mxM=}dUD&^K=ff^rxY*G>}JU=2@|aN}(IbgE#3*4F$M{ zJ0Un9MrQA;g!Z%II*m&Pi@MQ-UZNK%tTb~9)tN_FBub4=Hx+y4nY`zkz!A+ zPiAA%qNCDzwvgN;w~!=J-v`!MnTj|;SFpth+^^VU6bcLMIEI*>8&?y@E_Y{YE5X$3q%AhiCSG%J`q_>lJmQ!-NRG%~i`+z_wNfE-n~496vZEV%OdiP2ENQD% zs(tg|MK3r&`R{{%g&t!G*Qt|foZS;n$}B7pXEe*+_}k1A`U8JWy1`yS1zu4l7LQ`e zraux8itno;=@0Gx3Ea)MPBixI4o-8I*2N!4%mv|Np>Gbm2~qAgLpuc$AEvuHFa+Rg z?_QtS3Ez2Uf@3wz%s9SaEj8Cm;gHxl&-o1t&E!}hF7b0`e1f{SiN*!_a?a1OM`{KU zu`bb?ihkqgcZMqn!HM<@Yji2@oke!tmAeCg^LYc0^LY#AMNK5j_;U#25n;rffGen(jAx^JToxDteX;Ww?1f zUtI5ekJ&5FGo}#mfbNEJGviZR9sjm(ztg!s9+sO<0TjuH;RT{X%VSlW8Jzj{;@S-y zx{Rle@xlX*&84zhDMryX5ywSfuAzAX66s_n(cN@<5?FXJff8HRv( zZVODdP;>3Zv+>)@X;w@CT9F4ChFBiY*kg4=qtDTE^$=>ESAwrGa-Fqx5k)zYk318%K?NF+CQN zq;R+yEW7lWwa1UGgwdsJQ7zoD4yJJOqD<0dxQ?U_=}<pw{hL0&`Gk)jB{>e5oCsC`033ZBy*Y|HY*aWfQY!%=x9q^FM z@YWLplmM0C6d1vvC4=Qk)3!Z&haX%%emCwe{fGP()n42`#}EjIj=D=<2B~!1qM4I) zxo`{;h|ebCGDDBn*-;gqVkP65zfTl859F~rMeR6=#-%PomQ9G_q_)yLT&*_)b3lDPBU*;P!=*gOjQ%or8$ah z>v~8Ul-pplFRQ-wPubrKv*+(u*b^)aNa(*h6d@R85;Hi}5?N)HQnq_SpBZ{@aXOu3 z(?^IjVG?+~iTIyIC#2Ht{%3bN4VrTx4)K|cLQHuIOf zLL*aiB!*Bt2gg@6XSlCGB)Yk_h((00ueV*ku)KZj`Uoh5?!LW4|Hwv^GK5#G>(?+| zeBBB)_WDh|Vc6@+bro;P=S>D_JadbKJB_hgN(`cLmPBWKL4C}b?2*%e-xo2XLa*#_ zxzHgo^XT%w0)!l&uK;bEg8#S@3@NXl?k_)Zd|dbo@U-r;L`l)@Ks5F6v7(vMVMaKn z!aCc=Z$H#W*j`hKeVRE%yLJUqwy@b_Jdhg#m45#GSHddQ`wss89sF;oRepdN=xn%a8aS_p|6S-t&G&+)dl^kK_U!DwHq2HLBfp-8&j*c3j zy^z(65AM&lUx+Qi;0XOTudH@}h#r*{`s2*F1c@O7aEfsOr7K;9wY3ADpH(n3|6u5{ zxCFf~>Oc`ac~&qsrZth=vr+k$2~mKncI@-Q7_G8?&o(A)%^_T3PZRA6EpKt;5fI>I zOx9R-G$Z}m{wT4`IR;;YPjfb$ZAuIyrhdsyv}9y*oX6M{Sim46IF0hpYC!YAijyEA zIb;8wv5lGIg}=9{V4avYBAwYf3=0GBw8$($qyzt4MWdDY~12Wjt$? zswnsT(X_Kl5oRhGMK6Z|mz>O|0zXCUx05mSez5_#l_Z(AY*y7{#Yp7cypYK`kWh4w z>^eq8+X|u}O-ejLW=y;ZBF+}jW=R0t>N#B(owwfpi_aiTW|&kK{gq;H{z0kO+;uI$ zx0}4{7~@NKao8=_*Et4a+Ezvgp#}mE|JQ_ku>;<8GyM6Tb($I7)nOr=S9_xqvJ8-= z`701kPaZlx6_F*Kg9pO+Jk1uV9}y#Jqgy8F_zTbM3%EuHA3OUaMgrU!RZ^ND4|l5R z91%|;A<8Wt#mXh(9~Ut2>MMeG+zDHe9lf(Ppw)iz5p687ftEveaaO@1fEYZ1)@}!B z!bhzCde}zx;L9G#004*+|9|+o|6hmgfBCt`IuPEN7CFjyB-I zLf~n??To|(M|%(9QjGy2#8_@@{M{(P-7Tt@GA%XF^(#o?=2bQ|t*SK3xveWjEiEtG znzKK4C(}JXT^?E1uzkMYHCHoUOm-(9AK$TW(^FCpTVXtUVE)6Y9aN!@`IQjto)HaW=8kQY-b25I^zb@7zbri-|cZ^483o$VfCm(-4vE9#p=R(hH$iw~+`r7HPNwFXnkHM_ZeH>-T zkiXaa@B;%|J3cQxNdSGqD5MSm8m4!bKudfyi^}OU zRb+}T#d(@~V`#N#)Dt7nBPBr~rjGrN@TQr4Y=5#~Rns$MM^ftq|G1A)mhZ;wtjOXi z)HAo?#jFDR;OykrWlRxWS^aCVl3RHjFwnDipqvUM1Tn3m2a80A{J63ZDx+Id=~-P} zl4!g1vB9ZXBEs-86Kf(5PGbC}I2c?%T@lVT4i3nv(<5sB_Q@&I1JN_{>#ZBRI`cAG z&2AZHMKh~4yc0;f3rfTh@xxcGPv*dk(9n?=LD^?Q;5^_7Ji;v7vax-*W;i}R*cmy< zDLF8*AMxWfO6pVRoCtdtx{@4L#{~o6QC7s%vO#k73PFx)L3wYlK>@nBN~jMe7f1F1 zO|qOKZ7|O zo?AI7W4|+XjOBtyXc_O3qmW5X49+|dBk^`Yq&AUnOxMACYz^xk=m@S)&U?)l3Am=b z0^l2H{yr|@W*+K=(ILoQt}9F$GQtdWC7?bp^RhE@7ptio-`%I8T#h1~Mv7%g__!ec zX2|f9-p5nwsOj{eh~i>^P@OM(JXKOXcnOI#RBVUYn7$g5XBmp#-OPmSGKd58QaKBR zB2PmSbP4?$Du@GZ4E;oV6<*NY502V11ff;fS8RtSXp;l)4wF{^`Vmg=*+04}UL1}@_kILLdjv(X zJyMK~6YES6&bQ4}+6V9!49VJ0N=6ME5XftbNd@j0nQ89Q-hUM7p7GaGc}3m|)&J+} z-0Vsq9b>V(uul6~Z=OOe&*}uWRnezIxdrnw_dq1DYdmVR6MKe9Az&BLz_Gt*UkCV7 zafk6r9Wh^}qmkdTJZfg77|(;f$4ns2kfdry(YISS0CeXeIh@(N3Et%N;W~kIuMAhMnr?SuBj%^?+$Yl+U z6?9nxH1?YoQl4a8E~d;rAu=v&TrMiHK#&%;#f|IuuOrQm#Z*oRO6D9nj-1hBPXae1 zSFqhypF1yskiJ)4#Y$}Bw)j`12DTfzmmhuhWIlvF2JgSKv-LunQdh1kS<7h)GI3Q0E_8 z9cay1m>B1TG*{p^t6jZRlU-)_R4ct+s9wdLl{*xH-ezFcOWWHD=;w9M$!~+DOmmoe z)8C6j!&aN!CtXWQGy z($(Uby!R|fzc4>}&9=1x_rfbZaHB%FG|-?OS{k_@GIe*l+wwa-ceH*1>V*Mf zek2W3X;Wo_+r{+TK`=<~@&Pe$Z7auqaCHNQ{0=z0xWQ$7!q#VeIpvL@M?Bb^C| zX}Nl|6A_2`QuG_;Al5?S8%Bp2$vKM`x$FTT%4}Z<_~Mw$qjj!fv8k|w$CphR32&|m zYn|9}#e*xg>@Xtnu7;okK-$QauJV1z&eTxAkb9KYlOxLPkm3S0NlUh7u(pz*%ngOQ zXeNumWK6#Huu3;C2{u7SQ?KYSq_)(G(G2fEPtxB`xj=1A8vT+;l~4Ft1dc@M;V1Q? zJx~;@23Ui@+JCzJx?IVN?jUyBQ785lmkVXuluIXzGhe_v@{%G=ZMavzEuV49HV`XoWV)KU!-{lg){9TI}nEjd{BR@BY?w5=yFi3VlAe&zD4*=tE~CSpY_9mL?? z)c}_(9VFDH?9U<}9hAe@=DXt9ftSNVb@GMwRz9yt1nyc8qP8mqLc3-h}eOL?s#z#Y)$r&W@fYl?WaBOGu6gHHZupnrqk)L60f_#kGb1~Cu)06M* zLj9L0p%FGY8vSWo-W-~83`G2uE=TG zQm|l+d-``@7#M@dx;)U1dmd6xG?;?=pVDJ5uFwA3$Y;}CU0}DSx@9r=Hy*tviC#m4 z9B3!3h;kU1;}$J)y?Gq`;=Rc)GV;GZvOUS9c0|(4tpmY=MEFK8y*HofSAH2a@MC0| z>?6>N`xLrfMzi>#f#JO!WNm0ln?7EI#st!g^5oQvseE88sBH+5%vt0%HY^Qb9RpE5 z?wop>87!v+8oU8>K9;dwM(udHX%*o~#Kh6ZN5gRu0h7}y(#n;w~8>@&C z)pLk>7PP3kRU~mb^4Yd9h=u8(1C1AL!xCO~tBE^Qk)Vm`%hd5Y zOu(D=$D7-TcR8=|R!22NFlquybx1jOaq!ZRhpm@~)tp#H{y7?GF^cdwYnC!9WpmuK z3n}C`IOpXOmG{6&6k~C}GK8e!=gO99%Y3V6Xj6JsKof;Z6;rW4SP@yT&z(dRmqIha>Qp66yuOW zG3}I;EpN8gtY>ZeMUUln0T9?H%63S{)iqCd!1lamEU7VNo|GW_%y6$eof18IXY09L z#zheiXNQe_^L2}C;ORIK>qwmV|6Uc{J&W)l7@(%WvRbi)H$o+9&W+B4k(QQn1q@dR z{=MODHR)ZSkabeFbaWkD$%JVUM9%fT&{vCEm^>PGdAF0b>lHd!IbnNwLY_OnjAH98 z?B1;ZT`6k14(HwYDTblT-51g3B;ng|llWC2?8=bQ(+*Gt&df5C8v6mP&Dyf3Bu$6A z?1!}J!-mmJ;YVg{XTccBCX3Z;1|uAaw}%gk%O8)2#b@2T{Pg2fg!!8gd3UF%*j#(5 zI$G>&soHr=+^fnoV11T4w;JYQ$QK(fYU?Sf?DVTNfUqQgp5fCj5(asA>x^07^DK!c zOmL{A?Cj+aap*RjXruyLPUx=29NxuwXvW6l6ph!6^*z(o_!L+W_hQxx9Vp~9R8b75 zV`G*K!H2ce1ARKGWKf*6}Hr zIc?LC73ysO%S94L=968tKjWJico&lE%`mC!0CZ5UU zZci4y#6t5fP^;u8YC3I$(oR*u$~mT;7n98AdP+cF?M!Tsk@{57r}SL0#{nKYgR8=c zjZF;^kouLrO?cCU<)qZ*mHq7S+YY<<{BEldCiHd)79Vl-1-) z^2!NqdfKV3Mo(pPLE}!&;(SNV@^12Bf?ZFSNK^;ZgD~1MOiBvw{^0xI@V^)rgjL(E zeVA+UxzOH{-FBt!(pz1HhR(vyoo#s?wT8}4Zk-r?Q0P!@>qZ!2Qga|V|^?KE00Nv)p%53uHJ!C?*$S7jHgqN$- zO|MC|&S;?SRjJ^`W?~O2fqch{c(=yp5rJ{&hH0sqI^rm9P%Y}HuJE_fyNSzG(q;)t z09OesrjaGGh2<8-DdxqaE(iJb=&Z_eRV{&%wT7Vj2HiHbJx!@^>(JOsBW-|Iem&%h zaKhMgxKI+|f}-3*i*TQ@W!nAea~v*rT+LGG`O8}G4_k~!M2b|7JxZ6f$tgo!kWN6o zwk7Pg%kk6AT7CP{U+o2|>6~5i8eNPA5MLRcn^PU#ibhe_*dQEXcA`?L>G-6p3(B44 zWlFBJ93i#UhpJ0uSJvBC&|nSI%-g2kEO)p(`E`xzxqjXVc`Y%XeteXw)Vuryvtqn*joZaI@I z4FVmXR6QSAlPB+2uraGJ3wN3^3uvE!xO14BQ-tMbx_r;5lfsa1I*^a&f4zQ zTtShq_Z@*UI%p4MVk)eOOUE>?t@)n^^K`K{`nU>fo+^iWGI&)OZ|I~Mk6AH~*->TH z;mSpIIKe@F-x&46zt~KduatOaR+LmGR10fKx*|Mz6{*{>z6IJjzE7W@qKEX zkVFUJ&1CnDwzmzOPr~J8)D>yrLfiHL6hcOXc~{~+n^kTNr^&C%`&Xq`ZcQ*LSM+0l zPL8#cH?qUOwmVyTH0Mi8Ilh_!zF)^apjTzx)Axbp`=pgJZSn^D%$130_;#U$GEa_& zWbxhC^;t9#86x{VRrg)k$WcumgTk@4i{MKzsxA?sBEo`V-fDRS6lyxYdpC~`t{B@l z&nD`hyfSQ5$khY;vhh@m;ZX20&;+hGN{wUF?ByZlf18fNQeqx8#v`L|L^nwkCxT=# zD3b$)_?D-AxdY z&9cIFb|5&01BC;Igqqa?2~>446l;krrQ*6~>x@Ch8XwEo%oxN!nn`2cCFGPE0~FXO ztODzNP^+0&=ACQjlp4b-ge6Ex<3N)d;8`?9Y9@qm6w1_faHd4fT*_3#UOVnVI~u`k?C{yg@pH{q5B=grkl`>F!o@5co> z6gOy(ylGN|BoG=r^hIuFSry}`7sgEmO$d!m$leIOay1@iFiV+H`wLu?AmvkZX93*) zM)K|F3GK170SI&8hx^<>V6^M^;PUstrvQHV%#(Kn-Vvc61mEJYZF1kVirrb9^>@9Y}uG)O_zw(tXWQR7yd z9<46euOifA=_77Y`_C+L&I`z_{3lZLMF+?UM7hgX?_3}##f$D7O3(8p|5W~ig5u^u zrpX7JV6R=4>+f{;>WLZY&Vjz74WQJ!6cJ;Q(HBrSP)Bc>f>)>JOijBZ7JDe{c16mV>2 zz+HATpSn#v+PzFGYD2UyHh6>iRyBO%2q6aZQEUIL8H$B9XF@1B>PiNbGbmj)xh)VU zG8_g1oioGQe3W0CD~b@|&lSW4xMM23L5cLJ8<2iw3CV8TgLcpAKBN;2*2MINjz+*o zsl=d>0v1QB68uGFZrV<&u3|v%piW>o=Y%8QyJ{SZFA+VGHzX86ecW4~tPyl^|lHTy}At^41+-dzH zIHcs>gI#9wbfFseSsjd(O#@8<q)ou_JUT++)n^&%J3=Okqg$EPJG1qXqW4e z&g!*JerA62_e_uqU~_^19brrjKn-_Nj3-F)kraE<+91p7z@`RV*8|bDC^IO{nNZ|~ zU2%-f$S1`X-HnPgaq&;C4w!I6GDH!I1AZOPqssw5eI$;#Tb6~!-Jni%GPei4cdMHt zVg9iG@!8WGdjBv#$$?KnwGdoAjXN?;Q1M}@{dcH#>40vDkZJ= zVAyA*YLbvfn~b25BbE1T{bJdk>zxVk5yE`GZ%4+?BVBxB)kBrn{LD6pom~8La_+z; z*Jnt-!VRbIT566eT7?o*8TeW<%mx$f69weOX{dVNXZ~Gqc9bv76qJ}l?gYYF517;O z9~jpT#c)!rf(^_Z$adtsQ=rL(25;^%Uz<W_%2VxUWYaMEy7ZsvVdw(8Rcw#Tq$#azqdc z3ygpj;kgMTuoIPW5Rs8eHX_HE+=OUNoIzqYU&%WNH{K3jwNF?g zi&=SXRJ4IvaRqv9T$Jg%s<53c24wPMuds(NI3BQ$(jI$u36%~uF#zoPHVJTn2-3gH zgn43F;_Gj}_;)^o(PaITsi-tXHN0peVfxg`WrHEHbbNzhV{#;xY%Q(I{|0GFJU+@A z82usuH{&Mzn;ltFJNH#Z7yGs=`DVNvdx+g@7GG&Jl3Q+Ym(sW^8Qj%O9_rF)sGjet ztfEtmD)N&fkrc*E)utFn!mbPw=AInXq!8=5CZZcjQX(6@bWS@N`ab}oRQCJJMl-1AX$yy$WgygejiouRr z1@ieZRCB0ReQD;RyrCc@ss+4MYI!oxCT{C4PwP)TC@kg0wYynbb}Q?- zYgZzVnP*~yD$#hwb3>ABT8NZU%AC$`<_cLb_EOBWmXnNX_R||7D`;*GUoiCpM@m%5 zj7ok^#|3Z=A{3oj0P=sbg5NNtsOAc7BIlAs2Ma_76AWdKFNw-4(Xvam{j1?K8Zi3E zJ|~)U&u(8{k9A5w0x&97jf%_Oa`~a3I4OyS(F#th=(X*O#d|kzwQzl!v^j~suz4P3 zl)WS1TGa7Hm~f+jeK zm$~MfDODQ`bd`T|Ml{Y#8a}oy+@vxz4|lGNvrxfVtmGoj=}DOO+UpYR1L zL!eAaYtG43hknWNbD>~!&@2iB9^qLBGhHoo5#?WyBcM>?My_ejBiN*y#fKzbOL{8LAj$z3FWkYx)_YTTEEwc3SXy&8DJnM$5Ht-EYC2XIME3-g^s!1(08yjR7AijiU>T@0VJ}f|lq)&P z7xzgg3kRc+$i}jSW^<>~sd&rVUd|>9G&1&LakU$nq8`Qd+q2!6!e@m0X~Dbj+VK3N z(wzLvM0{x@hxw^7$nzrw$p+jTzeje=|CuY_vU%MPY!^aGZ*7(P^UTXm{w>Yy3HIkv z9<=(;7Uf^V>bpqVbCi2!ODu*uAOBJ0W(#s+_mV_7C{Sg~Ng}7u2y{X;h!$FFN3W>MqFiSk(EHleAAMwps+3u6L zYWC1{gz#!}*+>l6yN`_5A7jmYLZx3CnsGaJ^w-$i&1H(tF)TK|r+?iSbCE~K|1Z+s z0mhf$>-!wf{KmFz+qP}nHtyKAZQJ%8+x8vL9o^y1f1iCfd7jNC?`AudN_Wz!q^s(5 zb)Pz)@9}LDB<7Wd`iI)G-WAiJhn0+@u;6lZlyWV9+DyvSx+k1`!N8XcLyS6Rmwc4F z{G_)()=h+PTgVxJ8AaJnGwAa)Z~$??rX>ocMeCj_m_qEbXB?~g_D$>#F_Wg9RQ9k^ zj4~>lh9~kmbU^$8P3%j6)Rzw>z?c)lz?~UlAgN~{8e$+DVjvu1ARS^L9%A6X2*qF& zUHYRj{9-O1fsb|4+5Y}E>F1I3(t^Fs!LsT%KE~8;s(7;{eAAt~?I8j3B6l(Dmkw_| zBFB1Yj_o89gk*4GGGZ2t-Iyh=t3a{}YdmuDbCDyiD@Ia>KN4Z_b89K-))d5s#0QMlpolGBtwom73=frJiO|vb__^eVi<+@w+^^uxKBSPTZYW zEHH#UddE`S!T0zB3<7#7t~dk-r&8QeiG0$H+&el?Y=R{FHju^hzXq-^c-r7SFkF^_ z|9%o+$%b=J|GMTx<95Qv9q{b{huPNy^)7U*K zb;XV!yQ3I&7WZA5hi!kmn=7`lpqLxS8EGXHTkvvqah*=U`SH6v>Z8{fp&_sOIn(J} zHQ}UzyI;W4ckhtENEgy_GS?DM#S`ZYPz}pQ-5n8vj-v=;#0mhP?u!mPIW)#KX-a6- z6w{(F>xf#F^9IwSPh2xitTnkI|08i0Qc0Z-B3E`Cp*Os`nFtbd8V8W6o3s9{IRABz zTH8Di_?IC~qlu=z4^=Ue2!W=0F{JiW074y(YUI)J(tO`LB*jYlvR^t0kIopopkM9x zV*`+kNcz>53Yt@+zq_RifW@(WI5F&+0XPktlV9;NYM>qv_oa4qe^9k|L|t2 z`om#gK~Eq8LU3P`jat*HA!l{*!6+BfP(*sF<1vr{8w zb7qDZ0GBo)Pi{kR5Jr9|rvvrIw(LP`mdy^A>^OruHQ|UX**gQ)?-Ocygh<}6msIzi z&;qi7D2(X(()=2gIMcY0bIHKHf)J0!L0mVr{HGn>tArB1a`@TH8D@P*RK=O~+dNyE zW?Jl>f;Ty4%5hv;H`#VIC{||1a-6FK%J#U{P^tmmbEQxxI}I>SBQn#f!}TS&oz;3!S1I1O!$F_e-~yN8**BKn$+(% z==pg@EEIjiHtZW3qBqDM;|&bx>t7}>K_A`_KbNG}CbBM1o?;)~%)R`gZM|^1gLmkx zZxY$^S8e!7Y;Mxo^4DzoM(~l@3=-MmCw2+a*Cb4*?A>$x^mcuu$DiqXA7k|2>aGsF zygrNgR}t0`#Af16XA~Z@G}fz&9%Y`fee_oQD%bkNT0c75&1P<&vIH9Yqq6!ZvjWc9 zzSG#gQ`v4W*a)n9wG^uxHCcPmyL;RxE>*qwg!RiOFI~NIiR#BEF98qUNj-Vg_08u5 z8we@Cj5CcU8;>_s2*EV8UK6*f@0v=1l;^{+&=LF$WM5zgrB+>2&CogN#L~FZI``iM z{(C^-V#23^5-1Q*0VEKR`v0%!-TxKM`$HO-x&A+(9h?7z@bWdIx9de2dqpa!hNKZ! zAL4*D7OkR+ZYCfKB$UFsnQhQ@>jZuq9qs|e5*shSz8=Oi?`G1Utb~aEo8Qgc;<1?J zd)d9X70B-cIv3Fn4icdjR$AU?6#0}nN-fk0)0@wi??3j+KXB~-k+}jIF7z}e4q_yx zZlSbBGQ(uS+o3`0yyS7&es-Pn&@CQ#`e)`axQHRW&DL3tFo#pdX70ILbTrFL!?VTl zagavxU zljL$DwwvQNT4t#ri|n35Wk41CwxW4i_sk>G7E zb=lZRU%!Mt;uMJ`#To;IRp`p!mlj>nNAoC%IbmBwKpI)#25zgu{gcA910!8pR1E)H zw2py!qYBu)^il?Q5*`%`3#%mvOMmD&&yK4tN;Yy72;?Z{6HXyRGt;U2WqB?roN#5# z*_Ufd7DQ>e9JQmQD~!;3+M{IZi63&Km>0tL%lRd8%Tm6MapWa%YjvtHg=H8k&RjM- zKJB!;Gn=K1?qP&kez$=fb`AA?0PDdZ17Cy=jm6HV&**G2Gy3-6`&(sT0II99s)6;c zZaJ>7F)IhwO>1vr4oP)DryBR!z1966U}Ir3F#5DdzyTaVhSUb#c9@|P?AhGm%KxeQ zcqM=^wJz-u2x+xResbn-c-cf}Yt}a3A*mVrZ@%xwqkq)+%-dgQe-;MH?XtV6qCbqc zbbE6wi+5EA95eZA4~@#od&77ii;~Z%ue~Rk53aRAbxK2p=>>Ve6#0ouYL2k4i%$r3 z(-E=l_sxMErN2Nzc7^qbrjEUU5l&eAmQaz?B7Er}La$cfmgUGzB-Wf{g_u{7*H_(g zP@ikI>kqbnPe5>!cdsFSQ{SG8;$DXk-epI^q}*C6`4=SH>i&xid603oE6xBT?g-r? zhUw~_)~>mk7r+q-$UJ~ay}NLE1{djIu!BY@!5br~UDYQtNw7*uGfW zd2zZa7WjI(;rj(5ZH0NxoH$W{6Ef46X^=kbEC zVje3xcX>M}Ze4Q;w6p0L6ldl3Ow+0EGIoO_{9&25s^vnHxukEH(+LA+S{Fj-kg~Yb z`-pE?O-K&fJ3&yw5~<)!=~d8b>V2-&uof<*=&f)Kj6EpQhmc|RN=J)KOaqR^Gf!P8 z>ZLlasdpNkbhP+Yt>8veT@BLs*V|~;Gu5!I#!`ov!~CUdQ*Lkxw^FzkoDF!I}n-9Tlm5i8CK|z2<))n z+;wBgy|;06H!?mBMkaZ-RcQm4@>(=(mD6PP2qJ92Q5(u!o~o9*UY&4$kay?btFx*i ztdUoHvlbL!l&qj8jJLLoL~e>tp2wI!HmDmtP|GzKlqjsXV|_CeVX_Nup#mp&g!5CM zcw^QM*+=B3nDhZEC`yiW1dd74n?S?hZ*b>pzjl-Dh0n2wjxn_LNGDmjn}DCQ_+f*9 zJ`V>xV?ypJ=oh$`I76lqqgclr$fwVljh zdxg3`@vfu$QLAsNiXF?d zM&ibx0`uue@^Ainf;hco=f+=by-W|Zv(UvX7*;zMz;UUf`x2th1^^%mCa179L@e?&MyDO{Yg65 zn*QGklqxz3%Yvw1<_vVpzx|Lzxdkc$s%1gbv5g@%N=ftiAlm;#%f< zPq;5pXQC0RXe0XX9FstFhJH`Gj<1W%1Cy6C<8 z7rxo-j$goG{0j8mgYfnAFcPyhSKTxm5N$?=i0Q7dnH@1kVIPTa*#5eIK`0_RJWtg- z^yp`}X-dmyLBnRTu>gG|=y0OQKhR%3XtKRQ!0A%^{u8}gEgd}+FSmfVA5WyEDPdwluJG{<$VC+d$ifLgQS*B8+ENwAYp0<=XS+jV=3`M4L&GJ(`>64rs zr6-gp1Y*>hGDo;t{{(NqF*!tjG;o+g6*&VICJhVmXi^Y0n z8JdS&osI{xDcM3lg$tC@aJ|nNL~{9BY=BSSZOJu0l6LRAxO=aeK1E8N?EDC7VVQ1% zjQJvwk^2+Vr(>-`#Oh2UDQhNed(?v9CLhzpPwpq?#FtPt;5~4XZ#}Ld^INa7KZw}f zWeu6zibS8&BBSB+%<)ZRxqGa$8jXUluOW*eCDmLFc`#=nwtP3>x1K&|{9fRw^5giS zYH4Y&&r2U|n0O)I18p09V6A%w1)KUk10#FN+`|qqNQmE}sNceTU$K*~2>Q++*R``V(4j5$Q?w3@8k=6UO?HgsV_(RBIR5)^$BFlZn4kawbw~mM@%--&_kZ4C z$_}<>F8@u0azz*5t1_PXJ(h0zj)jATV+)%W+d!++);MTr41!4#jBFBYcS9<=j-Z%8 zMl^{l=h8YOmR$nqw6qjXDwD!?W)C%VX1~5+&(7Q8yRg6I>)N_%+qv3c{p|BPT1b8* zoq{ZxVc?zX$^6&%{qh}`>BZ@F=22V^D#-J$jc+Pg253T^2*ZUCTl0kX&ho|o-YwhR zS*r*}g5aY0Noi+F7Cfyzp2o{4QU`cIoq!A#%H^0x#RpUsN*eb6LEs1_2~4o4-(>YA z^&MDa#k{+{zp?vsEP#1@qefzKUE8`tmHsTjTPWF0@nCG`t0O|3QjkY^;D!+D?7QFxD{ZQdmB4QO$mABl{?ZJVNrkq$}cxz&Q;7qx=D*~8Wm!8;XUVZ8?p z7;aFw6?;K-wWN&d5Nr_C$&?l9hQL%Al^O%3i|4}N)|M@Z5|F9_Sfs4xNn^AXErz5< zG?0JL9ECyO_-e%4Jbg*1v;0{HZ-w?I^y~Mo<0}gJ@`PMxA{Y*16OIQ-?_w$k=Ou85ETAfdE5U~^)Qc->`S7z25~Hxv%!5Q@wUnf^Sc$^nIpL{8 zO58pD;>LX}6rGMu+(&e%2r|fu&U-dFEntB~Q~+)mwgW~{vI#2{y=I1>C`+HcAX^9N zM1}KGR8Vb4nWMoJUHtuFMM0lmK=~ta38Gmm2w7ufsEi;Xj9=ws*LsAxSss=+;g2*y zZ>J{+Q`8FGQ4k$n{5oLC>2YtDgX`-DnE&I~4Olg~kuazS7=HPDcs0P&tL!_Uk0rJ1 z_>70%`x%9U%YY*5N`hewTBFz+EB3G~2*a$J02eU;=(vZfSqe45EYYT38*X;xUEmti= z5AjRmFa)b$6uQdmxN8nbldBG6fq z@EFn~f2{%WP+4e{)G6u4H2v2Yl6`>LCajrcIq3(ztw4d#ZD$>p&;p6Z37ZeEi^4#rOE2>Ku~i>6Es4A;T_&q z1odJk$+-`AfQUVkjb`8ZB6?yB{&x>!jIfItE=4gfBIyMGP>BD8*n0(63-<^%&+^rK z!&f()p?;tTN)#_}b#Onv{|v}cK8*g`f`90=H-k$mN*4C}PWd#l_NQaxg&M7zs~vdK ziWK)1Jy`?>OymshmxIX>Zua&8(5ruS!y#7)1EI3_=aBM4!a2mb%!3@5HQC^a)ue@+ zxuy=KiS&=a!DLie86iNd{@oP{AQE6-<4^1*{84E=S9sqS*hy4lM4e9xSqkSLkzFh` z)*vhy>^>p+W#K5e%I=c4ff2}T0tSv58DdB%s78J*>~w%In^7c|*pUjWE-%NjbGRV; zlJKk)tP-zuuasqfmFBfzi~MSAGdPS>pSO<*XNN$ zBOjq)$T(#Qhp#2F8CW3dQJK!6=yT*EfHo`h-=trF8(f+=!4 zgKok^VWz|4ZEL2sdQVPxTPl8U zC9)WeBD@&p+AcwryU(^B25*H{P4NH-`K_iOU`WbZ;qFzboi-AXWlbu7zt~8Q7!ktM z9E7tx(Kn#j!5FS~(rDc_Fk%ZmZ3NSJBWAL5DG;%XLR9|==ZNuL->$MF1$9Ez1a1y@4yk@zr-FjXHmP_5H+Dx;8hrxO2A1uQnMl!#mepx^C*~ zuHowiRbONG_!jI>)v~G0GjvS%nCL1ku6Oa1Ft}bMgTK_)&=^0x0j}obY}z`*YvHk~ zPGZs4*1^-2oIAa-KO5tJ35)ByUY*k0vSCw_r;+pE?Dl@wy>a8~LJDu4TRHjT^5ojp zansn|%U98~6-vm%^Txxo+J$R=YIt`E6TOW+6Kl%iI;Le(v&7)eS<9_rayF`s%aLN( zhIU6(C)yxvfGwja)a9^8wU>icAD^FfdmzCMz*edinF!3pLa&YJF5g?> z_@xZtjl#PdZ_NW)Q=PM_wpx3MRI-cJYBK!Bwp!P>3x|2VX?svBw~j;q;? ze%44-yI^>S?suqQ?0I;nL?;|CKxKtDubeX;ZbeK0+@@BX)C{ zhw`C~7$MIjow^2Om!(+^7GLJ3KjV1uo!QT03^mtPcZ#QrZDigrCCvO9mI9tU%c{YIS$`BbNl2Wst3 z8KY5K^k?4Xt=fi6Qqu^ba;Ia`S`$s!ZjSCZ8!@nhet3}X@R1ueO{6I{7KUIqE5jpn ziK)l+?8YeG)5lNJ&GH7}SGeboWf;nuUv~rpN9tWshofOqilRo)uH+zKmNtFluBtud zWcX5r;@GjO_PHj2-YlpX-|P&1`+oJ3e?;1cUv;qz=#Pj)%(H~|w+zX=s}Vs=)x@!sC?FYtebYnXkHm zD)eH^>gSSFh{i4lt){=K$AGrP2lJphK#6LF2JFFl%y9?mW$>nqfi+@kRPphrDkk$rOyAw{wAg0)# z0Aw#72&4fK{^Hk~?+i zEpF%u*iBMRGT`de$!)FZvhHaA4=WP#HVAy=J-X2Efy`1|NpcIswQuyQgh4Qneu_Xm z!~t|^!*ppw8ep+nV%J=Up{}KUezJc{1wWGZ4l6=Bl!bID^XSr+E?_O1lmWnd7>XYt z(ygwC5P;I~f=6gd9D|5qCk*L+o$zAq!-_P{DzZ3a5!?Vk0GT6f5$uC~YDo!#p-67C zKk6G`EX|Y=U+92>3$~hEaHs;A5!w)4BM+(kqyE4l99rL0UGNi~+PVUv8AYgh%Lubyim1_?VAguq{6Ni=GYs5YNyzZjrfn*QB^( zS($|;J}09ly2n1=`GcIuoF2R^IDGTjmz2(a<`2!q@WrrMa*hpu-SbX6c8^Udkmday z`+J8eDeKig*flUIRO{pLZiQJ(Ey#RLqoa`4d@UCsY|fW zH9B7nkXBkmkZcc|s68OHH)B&Az&#?rsZ6o|w0Ok`G>IQjq93Lqc8bAFRc*t4YQKC; zm-#$luK8_tK*_lL4I`V*nZF!=AwXHh{qH!TP(k-R*^P;xNa5F`e2>Cx`Qv0i8Bdhz zMLcnMYw<+!*bn#?U1FOxTP&%BztaiUfXA8MWSGWMeZz{&1+!)m#L}Jj9h0}+LVFqP zyNWPsE7-m>dx-g~J?-7|G`L$ZgN;e*Rr{cbe6nn0GKH^2SaDj$Z z-8nWN8N1P|dUZNdV-}&x7M!{tReD1@V@~}7NcBMzY!@3;(FzENVGm?LuOsfT^d1*? z#~*@!NzViQ#?TQr>hhBIB`4H}zsIO8VdZLM?VQm*h6mVp{THm zF^IxOqH!xs3GfOp2y6O~&Kk+|2{dJ&&}Dt1DwFSd zndei~s`i*lv^4xhcQc+yVg}}mk(7*4lyABmr6Z#Wa}x8VP~QB)Z1USClPKwZqVl{0 zj&l6Jsl}~O5ExmeQgK4j4WGj*CgGHlaY82H%3d{TPTp7I5l7-1KT%je%QHR&mPWJn zvK-Rgrs&z>t;xo8c8{rlp5*YF2UB2g)bkyGccxDu7A>alvlPie*uuAmD%tskBk{ta zu)Ck{zBZEoRUvGxJo)|&;^C3};SIh2uRKXT%i__Korpe6dDi$@!lA}O${J&aLH;X* zY(O9jpVkvDh!_4A17QM2VrP0;iW&>W*(U?p->>5HneqAe_~MuR4EbA~#lK%DVY>|G z%^|7Pp{de-tks7CUir%h>Za&aIX{1I`cmFkd?@3)&6Dfh2pb&)8$LiAJb9)Fv~ug9 zGUFBw?%r2;9HtJlCDx04nC0UQG@=uQn2Mk;-bKH$xm+}-VWScgaIug`!bc~@ zLt-vPzabXBL(T)F>w45`c&WwtNz8Z2-aMkedW!=3b-i?Jc!|XE(OC%4KF3F=Pp+bi zo>+at_$ajJrdDN|p3pYD#eQ&_=r0B_FUo&#&*(llzy1G55}8dRlzS8$AfPU7ARw;) zUEke*m-hTGzwD3a&QNt_h2Mf%CkbO<5(JbKi%`;B$`}zbHVBv;5f)%7qKFfI92z5Q z9+n9}q+3O+Zfo0=t8QJTZ&_{IR8Lv&T2|N5x!%>T*0Zg4clf?he-t?D<8f%?kdi!9 zPR;b$>wU?&t$Epg7sn4Uy8;HXWL`lJ1VGywstv#u7G8H1MFL29 zF}HUb^nHm?Z`4sHpPx6|oYLLNKpI7peLkd;zS0)z?Ch`)%7`<-o9!4S0#OD6=N)q{ zk)#2p>Dcj*BnPW^h9x`=G$q6-D_vX4Sr^hHK}N9}nII?Amh5zw>cfGK#Pn&LlHD$7 z8IbZJox_2A)C;!=q-~HWBFj+}p2S0cHg&5y6&@P&3kHPE^~7qj-`@c)955Sb+jwPE z7L~==$a&hOf@}(Ep4O~cA(HdBreC8mE`Xs(2uoN`o&q3ro&i`2>IPWr$vP*t1stf@ z3ep7v=PPWu*em!XdK7D0#(9M*0svVMKwa(IGPta16__mt3Lau5Bk(cVdyxRkejP9J z3ceDq`zXlh{f|JwbNu{~y&ESsaTKZ^$pY|#q%1WttZ6>Czeja&QJ$?;sCe6nbBM=m z$7flwA>_JYC%5lyDAM!e|gbQ3-%Ox9$-#9^#d)o=OOBDWrc|>b4UHAfkl2!I{YB?*Tg^f4^HbXSV8`#vd{+xbG+PNy zqNfbB4xLyuA%-hOLyDYWLj>vFB2SyvL9dn*3z%kmQcP?`6Zj0!=;(c2&U~3cAmL6W zu6dhqf3PKOjyY8{Ot7lVnm|icI0V9FxvHQ9*z7ArQe7KA`m$DuKtu`(AL61JXGL%f z^ZZCcT@JZ?E{n2uGRSIb2p?O-xr)r>c^RXS!dsD!)7JtOw`c5|GBd`*0`JtrMi6W~ z#&n&(9Va1Z>>U|Z2B30WhWv9n12z~#(2%Om?a+0GfO=6*lcH-+T}AeeC|x-PQPs$I zgvV+nc`^46Y@=A&bsUh$Uo?pLj(QCOjcknAQD6|dqRVLbfKc7{@Z|;>RAsPrGL4QP z<2@d*GoFe!vI%-k+we=od5drlk_03SC*Yop@w5RSt(+Gk-&*&cAgAp{4y7UwLAa^5 zlvp2P96Kx-Ef|jGly*X09=!H#-X+Z)*jZ2lbH{cf+zj}R3!-~xLSNLvubfE2d0-h@ zG_(*2-ykv07)EZoPkD(j;vcCYqhJLZM~bs0m2%i%=SFv3TRh6JxuG*#$8->n z;WMPu%Y&?7Q64yJ`9MXbE$fzW#!d!mM+DqL?wqoAG0&#bHn-;PHHa4_Y~*Nhl zs4&olIL#MD+9rX^Y5KnjMzwcxV7E@5u1vhZ3Y+^|(7up;(Tp@^h;86j9E^+!YQ&_S zx5uq}8vBsCff+}GFlzpHB;fwA3JXI!w#5&d>YyoNcdQ@F5OWQkd1C9VXkuk6PgdgA z*+p706@Ux@3zH9!gPIm%?U%u_ZJp3bT#=}KuDERjq8$F*+>pr+@xU{#x9BIE%GE$( z&qSECJ>`$ny^*N>mpe$D52ZkX!F(2(>;=wHPPLp*l19w?Kk)F?IzfesjP%BK&3IqZ z{=_GLaEfZVOPo8t@g2aR5k zSrqv&*Ck0>0x?7keqDl$Q42L|Ny~{F5&JA=?8nq9fT{K_em=d8flC=e-a?}pA?E8N zGN(<2jN4h@l~-g4m{Vaz<}+@CvmnXg1@|a%)F!|xpk?W%!&Kjr2=l09@)EkRjDCa^ z?hVvTcz-D5Vj5Z1;zC<<5Oz$I8mU$DF!hry1)`rLq&MybTWHRVO6g@5 zjCJ-K#mEW&{0nr!(6)t*w*a5;>;^;R`j0qS%qHAK3fkM~f+i*J>Mnz!^NW-6tthdm)0+HP}Pdo2znHLsw68YCKiB zX&>(SWgPg>y%P-Andx3<&niXuq^&?o^1D`?vq(fs`iM$0lDcfH7{ID90Ku+= zS&^po^0r61_j;ySwYZxPp3dK-%b7V&v8c$KAs!p)Dd1?ADTbDc$ zC1#00Z6&eb6if+>#V!qDNE7VGeVouP3B@P7sd&BmL>gJ(G|Idy=RAZpsZLpdLGBsy zb1dSnbjun`#izpr{dw84U2#Bp?4UIw2vqnk zP&peIvw{onqCwe%Wc?JmMxzt0X^DC9i*UV+9qZ^6r@Z8-l}ETLe2G1LWl-Fb)vwodPl}~-NkZH;ui?gmTSD#NMnFWRV%fqkN{}Qiwe<IOg&EHdnOxGhCAxV+VOJ#01W4`s@NRB8Dm58c7`A7nro zYDpU~TdcC?MKx@!8Rk}1P8uwQa^QDM;_EoO2KtzSgP6WDc!G_J;+xg z+P8k5=s-^noK1Z9#<4FE$Wm~3lAI-WF+gQu){k6KcpmT&aLqA;LRD8m!;E~Xp%bJ_ zm1f@eQhC;@YTj0TKZ2eboELD=LXRvpg3>7H3WJwL0(!rp-ct!B5W%r^hYo&v5N_!q zErkesOTs55)I!kL9+BS|OT3+dU+r8Zu4;at)h1~=C+X^oXGVM6v}Wk-eZ%U>LN8T= z5F)H++D*>mk9j|L$@4k0e8JqI_?S@{5}0&3kDsE{FJX!)tp|RbEyua-K~|)-${V}(A0F(~{%K^|b14Jeo~(m z$cqEO4k|Bj{1&s2J&>}zV@BqROek9lOCSy#T?xcEwWQZJ`vwEr>Qt}MbPN)v4D_Q~ zslxX|2_!r_T6?GVHsoNsd16?z?1=JZx~k{Qjx#GSu0r@VqVnfbuLZcG5L=dVCgn~o zFYi58>Yh3uzRt>M-8!HIBJ-OL@Sy#%Z%c#)D1cicM-(zi88fDpMu#tY9eSU!Y#xHK zr|#F{(oatJffs+DMLDAHmhQv7;`8|9A4JkWWk#v zA``iRUDMWZc@ImOx=?6pq7W#Pbb7Mg5v-F3@lOQrkr=#W;)lEytH^Emlga~D%lF%6 z9MzZOCO6pU`qeB%PFcV!0EL#=DORKi z)%5-?#cNq|y$x*vmF#J+-&v%p@k~|qG@fkwCgbBsvndZR65>OV+VNXx5#2*1!^s@j z3m@o9zQTjmch}4B>@R)A`>CFm@c2zfFH)1tesWVN+FN?9qF>>%UlP#zaT@FQR3UFt z^Rui=OR@*$(E4GJl`pg}{$=~6p7U}2grTwk8}jh8jMIA59;j|BSiV!(DU+t zli0D>Fw@Us;Co@Zqn~j;{Tg@1J&y4Dmg53Mwmkm0C@!BcfB#hnIiUUdz) zpjbH<|07G{+$Daz*K;KReKQW~{=pEGgiq_v8@4|XQ!?`F>Xmv(cO(au6hbayo;9|G zWy_kHP?fwn2!Pv|T@&%X_^6Set28RYR~x1OwXL0>X*gQ^NK1o%T%vu?%CSezRbC39 z8yvr+khPi7Gw!UO*;~Bc+!hiF%K;g&uEPhj)APYr+K{WNA$2TA~eMiMhmDf39%2m#rOtA5&vU@K7|`c91( z{KFEvYBv}B;_o#KUr~hKWz90<#5e_X%V4Y(u;W8-iREMSl zPKy~V(ly4h`b|#U#1yL;Nva+J<481PZj2xV_=MSCh+F~6Df7&UTGKdV<)K4UFYhgC z=<$S21KEbWx%RMd+7#d8+YkG-j~Z%RM$Y9_ja&`pfuL@Z*pL+-@JzkxJugPrY)LmX zYAR(f%P!Ub9biGJo zOE5LBU%INs2~GwY+c!-+PYEx$V2xgSz~ma$+uUXu+n+wxEjNSB0)Dj-aptD!7OW_M zwtd7R1r`CLlI6w*N6?kD_d=8pmI;wwwPbWnbu|LbBUN1_OEE#NwJuE3+Q%@?j8x`h zKXe8Wqm(k_h2X~-v29r}mF@x2kdAaX?N<-%OFu_;Af>v}FW<4MYe?DBypf|F*5VTH z3GCZLh(1sc{6Tg7BI7*&uOd2KTY{7hwWK8)J!48zbs~)KgMO~&83o2CNs}oZ3*Uuj z7(IT57YyH~L;-r^4dop_u;KBif=!|;SNG)zq*120kfbirUPCyW{V#{vy+Lfb^jAOO zS4_wF%K+q{vg6sO;|)CCZylhU(7xv&wNvNj+rTX&KtLv>eQ*-@cpV92!zUx^3RhT% zTPPMn|65G?4V3QwQ|w>^R2q+)#66h z;o%{IG?wOQw8KjcQWb3y7_}1d75Kb(^yG=?16HKRSR;{oX6%}_;{`(yXGKeI$o~|| zj%^%kQ+Q=VGF?;Y?NJMI$=0WkNn?gTvrCpJ3X%IL482*QxjU$NQL@21sF9Azv;2Y@ z1clJ!+&c6RI~27CPUME2vNn!bQIMZEKF9dqP2T*ms}3x>h9V&B2^GK>jAbdcVk1;UyY8X3Tc5x-tWh)ipJV)san)Ab+2Bnm;InE{S_Y=W<(Zl8FXe8^j z7yi^~bI_J@Ol=J-X8YN3gUryr$iy($;@c@^lcU_5FyPu@-bj!OI%bG?vUVuiV4tCw z-*huc(QXm{RZhavwj*l2oOYSHB0s0wYwJ;ZibZx>=6$s2lH2qa$A<*Gh*k${n^QBfL(^$i@UQ>Uq3YBL4PgIO`iR-FF4Vp_UM)Id zK5WPCDQ~OJ5cOTb&l+hzomD4#Rped?-V%V={WK?hHK=bj9lTh%jb(;qw{W}WcL{o> z!y&zAE&UJu`;+;XDs*Dy)w=wOszp{jR(Nq)P!lhI8{S-61AV%9eOl@c=C){ClXtHA z9&y_?BwR8&gduuW3NC{r4P2EQ;mVu1PAx^PwbDCk#45Z|pcZqfcJsjXhzn_lQDw6j zcLzdZQ;%CowT_ksL1OCk^@bB>pdm2URo&<3UL z50oGCqGWGJdK##TZudR$GiK4Wyc6zKTD#yHz?42e$6 zYI5O9RId=3UT6-|D^zGU{OA;D6pP5UMb#Qe(xb4Yi(FcZaZ`Mqn^y8j9$BSCx#l){ z=sa{EkdasR&}T$ZU4~f-YL~XHP$GOoEt)2jr?8Yt+cbr)^SIZV6xUVTkOKFLy${XZ zjBcFsyw*ISBO9uYSJRxU02-)IWHN~~ev=ZCSfzw8a9o1u4;i9@IpG-t8@cK=#Z!7^ zCk|CZgvssf)5#U$1uJHkA`v}hm9P@P11;PDOiP@LYQ0zL=wHed?wOP6FYv)#o8EwI79!Sg*=JShbW$x$?y>7)-@jZRzH!jF}Be9>5}T#=F8( z)@)9{Q6tduUO%)bmACBi&v=UdOwsbqke{d)kLJd}BQq2A3}S!)e!^ir>Rbiv-;CSf zJu@>{r&_^B6?ZyxUc%sYO0i<`E3Hhl&E{s|&b6c0DWz8d6jGO==*b+!sdN$sA))Uw<5^^};ZI?L>Y4)&bdh+|M$t-Qx;){5o~u)S`KxJfX(|6`u;+ zNgpuQ2YXiPj+c=mwK{`#hM_WLnUnioAon1Fo{54V>w6nG%Uv+TWQ>WIoy5`+9A89_~Qa`L;bRn#oHAPOCtIq_>gZo|gR4%gd&HZ%!t?IA z3OB6Sd|IyOvS_txR(}^qe2k2x<2kptY<7~gOJCwvFC~FXce{Q7QSFOIC1o1|ADM+*JhWiSaFG0!*eS?ldcFZz_k$E~ z#!IgXOD4oV%k@2X`*&fn2rG+A{q8-cXrx;9=h*jQ1=5t7L&e^>q?IRfL@y`gj3$Gy zXq=(IdFI|A9A~457XGtAO`ElZG1tgrX9XIH_Ixa;_W1fq z|Nd~0T-%qmAsRhARy;FRJx3XP1^5;%VlVtQz0DUhZww&;`bCIuSF+Bx`n5;ScbA@D zAS|CyrF-RgoI441vO055#C_xtMF!9Cll&Ns&F*@;b zJb`dLO)&MPa6CP?&*FT1*7Pm2@!fhQP`~s+_azkbp%nL_Met96>j8o5fkEns?EYWV zt8b`)T)_-uW(yX1^wm~Ui>z2yOc^p4v(BvRgnuT#OPy68rWTgNv(!vyp`v zgPoU)lP!ajo0+qfnG1uPtCg(_11Qjc54Z=`@ehRgX^Z{`C*uD9)|9l1gT2~+8vUD5d3n1%HV_uykrf9Y49^GuJ) z!2=4p$gB0Lf}G)0>w2cuYLoR>(2m`iHGy;4F;nk~Lx80 zLLXqXkPqwkItEle6`$0?wu{@)9ycO>1>l%AKdS9upMU7f5`7pdS*m{N^GE?zNI{Ya8n81!(|f-R|O?-?#1EW%=P1m zzC=qHGY`oux>k#^U0iihsd4ah#Qrp#S2vuCN&kil)miRUWYR)#`^!o&-yJ+_` zALNTfAYOGGU2zW^>xjk*nAQ-&wXx7fI_ZUUJk41SW$oTQjKt6pB91%>(y=5sZjj}8 zE_G`Z_n!+Bi}3!=kQcOlD23eMYSZzH(r*4D_Eqx7Q5cn}Cuib75p2>5@puan>*D-5 zr)9Gu>QOVpjP1D%EP_I3zE|*ne#N5hsA+OPZKuCKz2pD3h3EfmJN*wYs=2<^KVG^b zzXU%>8;Qv^z0XpU4=V z;Cz16v|*JpD~}kKU(1&{)u4+YBT>0c-%Gh(q|J5liuu01?Yn+SP?PNw=oOh2g5rYo zaQ!Q3&ON))oMUrdZb3Qyvq&5NQ~!$Gr!jXTGA6d(fvx-~tO0eqv_Qrioq&NCJYBDB z8^Q7prye%N0&;$5-k<(hRrERJRkhKB$~zddHeS+&WWaj?6na&Gd0LCTG?5*J)Fk6( z$C>(HN1P`Q$EK(8(+`d;PSZd~zDCA?7zl+tha%kXmS6w+F6pF(Wq=9OJ>32Zjq%>PnQQfj z=)<60@3r=?PML3|n>e`50n51J5d)@7pF>M&mA41BGG#(lY8-mKYk5I@4}~Bjwc(P@H(CnLXECn~ZFoT`*IStzJ9R-0gaWC+ zrIsH-`Nnc6Tc*N-{JEp(2u^YIycHQ>o z!}hu}{8(uUudaA~Y@jOVoFn%*`VI{viFCv%p4mWK)i_#zJdoT--&`nZ1PLc)1;jSs zo@#at9SFOJxpvAGpF%zJDfFgTu?!{&?X40{g*v2P=M(VNKmF1sMDOmmqf6QI8_fgJ zv7RZWP(H{wF_ta+hiRhyf|@|u?jD4+p4x9>!A?$ zdF!P*n^ZCxpIgp1db9Q6{p05W;lrr=>A)4#*Tx1#d`iJGe0E4jxj{MmZWnROD6^Tk z#cuC|6QaO8D@9Hm_GZS!_H}T?M8j%)M97<5Mplqv)rgXoELL5h2kS~Ys{xF)h%G+8 zqzP$r&f2qBseIUadl&W0{Fsf=)b`?XV(D^S34aI3mLI( zWX3yr2fqMO&tFF2r7?R5jlCo6A-9G(gH5e%qbr)}7Y8jS?V1Ez-pUZH;?lndWZD8A zFH&;CG{LhKtO{nGhOipSE^`XF0)-=RfFOiwuY@OC*hl98eJYM$kvoZCqOkN-J+P28 zc?zWQ?M%4<1ulK8u?P{KcpMn9E_q?u(5VZ1m1FhuwhmIG2Nv%?q=hNj zIMqj`W*s8wj~fMV8G*BsHH&7L-RD6Gs0n;F;}QA-3I85`PLQe+@Ev+<{4N#y>{Kp; zY|TcDr7wTnl3)~tcSitC1HExq33Oe1OEqRFy}@vm4Xo~V}xswIgh8pDG&1C zvkwf2^4cX%$BM+hIvsJLbykR2?nkp`>DyT$T{?BJq(9EGvpc=vbP49498!R4?lTli z3BX@Yo4Wur1l9{T3YCcjj6?Pnc*t_1!cYW@Zph?sPPk`H*u7b~{iT?w91T72jtS7Y zm9LQ*2muh|)_6U)cgfKH*{Si%8AI1=J?|f7?Fdo}^5Fi4_1)<7*$rDh%5^Sww~cz%D=ffP$Ew1yeI&@NQMzf>+UR59;u zW-MbzAJVWjwEdlkUVO`E^-X)zO0C|0mfaVIzG;scvgR+fb*8<7;+`}O4^mAZhKp9& zHg#vVe%JsbgVw%}H8CbK+$Hw*ezl4nLNys5YgP$+A6`n!8n0aRN!c9WP=uv0jASBK zuq!I!jvUfRkV978P^=CX3TcbbPm9df`Jr+~W zKj_Y=!o3@HZOG;Z1G0&QUFyv;j{$GNQ?cOXHi*afr*~cKckF3Y{dZd3)kyG8URzq7 zF9|P}rfPtBz`!@dESM}(2Dj%m#)%t?Y!_0=_!uTusUa}PALx>R34~=4WN0zrpdYMV z(R>*VnJMhPbR62IhOq~9Lz5f|<&!q?2Clz`_=gSE1t>xmkg4*mA(an95ijQBdFz4* zcya+R`Rxp%dLB-D0#=-2KV=g`tW$GjuT|8T!lvSg_=cW(sI841G-rr(-p(5>Dw<2=*e%kYAacOzPvQ2bat6 zXW>+3b%~cT*U4C14HoZ38fU!wH2Po|7pGlt0=XsmE%|L38m|V7@M2m z4|#i2Vw`Js&hRfWZ zyyO(VCfN_>=i>+^6DC)yLYlon z#W#O?nZ1_$FLqvBUj2N(J`>^ZF`J`B6A&jE->3R+pP>3CVjH%Sz2MPNq>H**%LxjS|2DMi;eT|n|M7J=%QjyzLIe!movZvKb>~RtR|(0Xd?5as7s0|> z(fvK7^3=~w0mfYB1whE}yvtgy>79%9l^xfty2&b=2Pfy-mw@AAHw#@-JdKUf_M4j!gi`BDeB zRo=4cW47kjj);sF$GUaE{@fr3PDTru4!Oh}lN<0GA0kelOy;hxEN$UBv9&AHm4(-k zS)}}`328lB0WK;5?HbyZ&ki@L_j@*lNYGz$xG&*eXQOqg9@%_^#lm^iy@{_V`BvYZ z{v1S^@bkW3AN1TpNv8}feILt$eT{DZs(K|O*#6ezpK&P$IkguD`;*Bmw;pKbB>jAjaP_3p7E5w6D%(7L$5hDUXR}7EYAC+#}Pa>Jt+dTz_}N zE=!ZKaKp(!s2-GfOChsInUiQ~lnJu8_YMciFSjSR4tJc)(#jj^sV7vWGj?58# zsTD8LTg2H3b4Crs{P>3;gGtSoPOd68ybJTNQ2Xl(ckZ&%Hscpv95+QQhea|ucm&@% zuYj;QKRJK7!)E_^u6uel_Ya`pT!ZCuaq|Qx@QpQtc&RKlx~tpo{LxVce17Kry0mDL z^pXBn;hQqGHj=?;>-yHwe6z;GLykuQRjbysbb05XGEl2Ln#IwjmM~U2EWK!#Ktbh( z7c)DD`rfG2qk5?ZNkC&tgQZ~xI%wZm@0LyaxJN*px=sHhk+X|u4?*wbu^ zEw!~GT$HS=o5b@>9cNxu(_();00_cIJ5}0 zngvB=#L+))KwS#%xUlgBAS;{XTcwpcsb|cZ zWXh69PEgb{Bd)Ow^`R*@)BmO!5nMIUyGUH8EFEyR_ZZaQoHN*3i$Gp_x5tTgXl`YL zBgQS(SQILOpBi%p7G|+p8_OzAdLvKrnj&@S8&Wi3+_qZT(zuddG@*_M6cZ#h(Ksd6 zc0pTvS3kZ6u2b1-OWBScYM6dq{dP+LIPlQiOE2EHSmW%(i?t<2j}k{x9CrF@ob^N1 zRIscecYcSSXxwX57qJNa)fYJixic*He2^D)o|iS5?7ROeAeS@SK3^6GvPkqzY_gHp zuct?2?Tzz+2qlzjKA~&2GAMjzjkK#PsMonHxY}o4%rF8~QzzzOAa0(L?dq(sTjIv- z{2*z7!^y(L6Rr=cq2>*TbHAXSIPP;bxf|E;Ld+>S>B^@_QOX`5f6Sv3eQt|mv}@E{ zT*kTR8yK>4r&=5zSx>Iw0dXwX4raS6XSY?w_NA#+`(^Rj4)I*8NozYmI+JkR6*$jh zuq#5EJdb?OgYCyx4G!yI*p*~Wm#N?lN}AL{J<-A0p`poOQOh`B4Lj+#Y6l@}NotNb zs}s=B#Uv3sj-Lg4(vDn-ivf;i7z*SPqI-Kq51fZC2T>&=aHDIb;H6416=v~^?;Yh; zXe}<4X}%ZfDWefzJw`5L_tOJT5hwicvl@$r#*EY2Ev&Iqn%IvT7FCMFw-;AWkAo;x zBb;BtcA;l@1>_OuqTPK|?mK8%>EWUzS%0J2581Cc*zxNB_4%db4NN|^#cZ3p;p2Fc z=5>2nkrbaCL-hfwpr9ka11lizM^Q`1sr^#I?9!L>;amCTVkzOk{{Adk? zJ|_*>n4=KaH7)8mV;xskO=pH+=^x+N6z*>iy0UPr21uYNsUaqrhAXt?QYImY7?a4G z=kO(&nxa?Ch0S84SKP6LE;u%XD)XXf0U%_v`FajaMeN8>l*05ju22hKY+*IGdRva3 zq1nnVre6rdrgFATS>H8Zv)`{e_;(oGK7~;2=+`-%rx-l<5j=fb-d?MHXnfT1xVFVm zVzKX|aRAod9Gbt5O>7OxbZ8`>39J%78+7@!+(VkD*XdOs0iEPeOcQHAuorl2}>J} zl=~@SMoL>Khm(?$8<~f+w~i-!Q@+Fa!kH1vqwbmdCSFat&^5C5_z|vhJGz{=J!E^D z`nd zIQt~~X7Orzt(QE8f(w3D8=n|gpLsjoOIvU4HTU43HT9iY9kuC{VdcM;!$vRoTP{Mi z?Xm}^Phc*l+|X3OTef{j=g3d@)J_X%GIiAx)%X6rkJkB8$LtDMEzJtQH?m$fugsXhg;drmBfSHa zm_9x6t49f*`IbFj6SQ2HZ#EQbwJ!~NB4>Js1X_!fP4wAEZnHOK1?B2MXgQO~52mCr zlLSs5Mlq2x=>23N*ukji$L4YbZM)mrW~`k&Hv`3qO);DugZ`#=tG`@?K#6xbj52sv)rUlw@M=51Ia%ljJ8DT^r;9PqLBWfKQkF&4wJzP#GfG! zvVTswAWH=?ehvw)4poH2-csd@>l6RLy8iWLXG#ungn3JMHW290uGLQ_+f9_H#^exi zKjD;rgIgUOD{~9w^1EfI)n08ZADphAImCxOM!%jpp_^JPHcYFC320wzglJUKkqnao zV=x(?bU=c3lq2pnP^EZn5uRW=8UazrMy+t+BV8t+109+ru)#B!#US^I70M!Rf%5TF z=ea#2;kiFU8-Hn^fuHvHI`c0W&#xQP?;oEl=<;&~$^E+m%zqO*KLI=cP1qs*&js`e zQu@Evj`b(N6WOO3z1p@jNfiYHG7s{vl9!-{94VHB1t6T%tG7UVbmy*mT^sNL5=BER z@cqgf_ap48fq#_Kv#U|g!l04x+{D%8J}u4EbpN2ncI#{Z<&Q5&IHYdEW+G_9Yt7d} zacqF8kr<9<_dyf0@QQYeDMnV2{0g7P?G$8aqEO_%e2Za~y5G`kZj;WE%~pL%4qB7H z>RnjfONOPBG_T_g)H^_F3$4byR7ap}jdiKRjKTW4mrvI)SRg~3M9p~d{yuj6$n)1B z(ndzwSB~v?gVplOxRxb^t6bI9apqJ?V9JItuuw`gQ?^gW@CT9IDY54F8+EFTYYjmoitkk(UWErB${qFJ50G+ZcuJ;LEUwq zY=P3!uP@YM1(=Fu#wZg;O)@C-VaE5s;<98KL{9yLP(o_5IZ5`?fucvj6J^V(%jU}| zs7I9LRR>to*M7e@rq5w?m?>xw%B-oBJc;S--FYr(ppQeN&Wg^AUxt*srEKDe@9h#B zr|c$o>8UkCNZ4KL?&W`%JmlgyVC6zvyT`dHYod08mjinIMlPz6g%`moiz>_mN~ANb zO2--raeI7emW4yAp4NrecH8Pb@eZkIL`sTeJQslYv6l`veUTY^Wh(ATn&zncyYD6Y zecnHajJ6>bf|^*&Oa~XPg&;o*v6r`+XK%D2g!7>1EB$#=fw>@fp0`NM1DdFKcxbz% znvIBoGd{=gR#0g0pNVGmYwxu?UO|QB7qKCqAFmj~7?%pAH8Dj;u7YE7{kvJrhJlF4 z$UFhIXJ6tNV(%-ieT0|D@u6Iq{tjd9MrRK4#_MZ5nRyc$tV$bx_uu;Ga`imeM#A>l zR=b1!@Rq|DEBlRfeWz z#h4u4H~cpYUh501MQ9>Xn#{}uZpVYkt|{;R$t>^tsXdA>vy@^ef*BweeEdVB!>%Dh zyS`nQ6*bCrG{DI8PyN;6Od~VN;$$`_COo)EFLRB-#FOi@%%c%X*2V$k!0MgQ=z>H2 zP$-v8@3B@Ao~?Ly!Shw?Ix=w63i(^2>Ydc+y+hMhYc9}%YA{Wfw7w^Z0zV}sSbjx? z{`{qvE!cGZ&!%Y4j*WR;F;+Rvb?=ST(B$gLBwkHCAxKSqxbh5Wg9+KEz?{T=ie;YE z55%|C_aoBSS%7pk?{n@pZA~3#i%*j|Q#I!tuxt9NvT!{{4v6d3J^<(^W)E?s6NTv` zo3eIR?a^-Pb3X67&5s~2bt)Mg+Ja2kWQ^@}hLGtQo#aFp+56gzLRl{B&es6IIQRe- zwCFkNKOJ20;!I|{jnqB)2R4nU@yDWE8&wj){L4M)x}Z)m1X z$3Qg^76_(fiax>Jt%=T3%$55-=+Rjj%j`4(Cp*cNJ#UwhK8u^gKI7GAUnsU+;V5Lo zNmf&W_C%R{84NPUcfBHW9>ttby$8Rx{S(lThwsHZoZfCwS?_s&aL$frQx2K>_cI_? zGRZMh`d9jnjE;X2(=7^De&ue(>QRK}htDllvyayUza>f* zAmj!hJ?J4nSWUQMsYdbjl%W5DE4a<$5X7nm9a^LVXSGPAIf#7=B>T3_wU89T^kCCA zslfQ~!3asPK#z#R5GaGXU(dIglzjB$&fL$Dtg) zM&zC0k9tB{K7QMZCl_qs(|AKHfBgO%_+74->)ZRkbZS30ssEWPVE%V^ENf>gCvzub z8+{u?_y23W;5hujO7nC7^Thk|MdW|=kJ2XkiuP9G##W#64gX~iR)cXv|BLNIv2seA zAt=Nuj;`M$!k*EeRH_6WL_&_d;x_`46By8UMFm;8q@<~nc3C%-+|M>AZ(08HZ8 zCx$(0?1rxNnUug|v`+ZQd3Vp~>(iO=%D@QDI51 z33(N^iiNmjy8fI5_Hpia0s^K7(%w2H2LVF(mNg_8mTzn)k8YBT3J#X@3J4WVdAG!> zz7OJ!6uXo*cYE;T@$yA_?B!%ZIeR`Z2h$^bbYFlGHio%COPdac|cB@W#pe< z<>r}h|L9q=`SVB$BJ7KEdaB{imQojMXgXP9iWLKti-X_-g1IB86Btzm=_ZMEicRh+ z!XgLHXaW`W?2Gb>l!YVEI3;lx<0mIeP1Mr`tBg}iwt2==eptTH3S)$ISy5+orKbVa zp_Bxgg{s7`2aSZLHTmgWk|T?WwRc{K52Yqu80x!EsZjgYCb zjWV_15R6xtkY$tY^@0uD4#z~)iik!8MA(m9Su|l*GQm3siCmSNh;XEBJa69%`EDSe z;u~O}6k$sO&iG}8tQk$4d6UHLLb4^A!^>?4nIXq!sC!D#1e1IuQ_;p3mi~?cW0K4g z>LhwBD&yp|TZ4|aiqdgML^>+0(70DIw4xDVvJ2@Z8JcLk|VPQBh zW2v%+;g3hENu`lWnf6mZv!Kvi)mzh4#C^?MB|8g-Lu1l!YB_1Majt%qSwZk zv{DCb*h32=uFc8ZgjLy$oStR^b+F|jy#vB&WFT>h*N(QT`!W#TuIFpZDQIS5=$Nx> z^k|yv{7nLBE~m}SWt;+dwE@%Tn0&fL+ZH>uG2fR8=d|sK*7LSCh$_dwC&n%nbfPl# z8=D0PsCWOxs7Gp4MH_qWCNVtZ-mU&@7QwnioYNsv4j~bu<|ob`;d`uykd|1f(RRbC z&gL83i>s*=mdT0{=U0Z5{T2d!oneZoPQ`6RX~(8jXkIhYqSzUS`Abi|9MeUKxvG=9 z9qfj3LX}nL>6w=dTobGoFZBouNZB=30`QP$Y9-hvUOB*+{%OG^wE5u#?vg>`l+;R4 zqjX7);?#!I((r%-Su=0~eILt?im`8Uz=jd72H-GEi(HaSP2(V%?~?DyxHP#(qcIjH zCQ@s>z=#`ZO^UT)7>|x@kualC_wsZrJxWj0W!eC@aFR9XN*0f>xN0oft-M!9;VrWs zhrgJIe?XPT2M)}O{IWRQ-N5ju)aL4VIG$zWFH*lhz)?ht@{}fy^YpK4#_ z!YEEnl;gn1(AsQhD{!p{ZTzAM^B(QZL`PRXooG+-HjzwYtH1IS+ZCwB2KY5wpI*A@ z(%)s(YT&?7jzq3ZV~D()A@ki2qr{~UU0)5?UM+QE&gcOQ42y;Je)3i1JAr+|RtkAG zQweu0$cNp$q`PC6)?n2VvvmobZK`37np1gIW`YW4RDgho1>4su)ZCHAvO93+&yOiK z^0as+YWnl`cTCR0LpiEEMd!y{a9XABeuQmPy_m}6$OW%~b@mo@)_tO9i%7}+R zwwaUT%!DmJvDu-FOXrfVdkU=&B0ZrQRXLv3GX3Qg z52*AUMhBAXb%PZ>)@>Zvu6YGcUFne&tPS+>5(vh#MHhDNxR9RVv^lSHG^&7(ba9ci zUKPS_I(_R#lG&L}OiB-FYgo>dnPP!^;#Krvol3B*u8ekY1)994YQn9)2V83hcMFH4s z5q4a#H%sCS?tK64@?yW2UxIGe6#Be?5uDjZlEgZU#F;%R{T%T#lEJOC>$S`ctdscdQ2Vfy}+dlJK2@9UzT)`qr zue`=ZvZ{Qe3&1Z1Js&fH_!k2&t-CI3G0f}!4|{%9JK&A)JtLJ2eEPhkl^ilAT}kb# z)03kKweLh;sU-SuOd2Uqr{+Fiy7voSc7CP;@?g}?e+KMVO@w@A^Ua?{R4_QL&xoZ)%?% zDT7UuGq~HiZMu!NlAH4<8r!Qn1MAj+v44ujh1agW=rN>46<9P@TE zr4b^fLzK58kBO1O%pOMT22ef`B9OB70GUf=ANc~C%a>B=%g^!;6SX_aWJNEg2pO`L zm6y_InVGk4#xFZRhqs8tIKC_CkZJI0CL(zhIb&1Lh%YRAM zObikBbS1N!8bs(R9u`rG?nDk?nH|AxM1s_u_GD1i^_*cybb3|xYR^T-8^j3w!J@oD zvV`i->R!=i2nHB@Q}Wo|+xPgU=l-Ybm{e%Ayhs>R(4a;Bz$Bx?xzrb0lbeO=$z&La zzv}y_0r*ogih_i?X>&tl+#$nbJHjh?gYUAA%e{ww9>ndbKjE1v5XN;wpDaz@>5bm$ zi3cT9^So3%B)fLKRJwV%oPVmIN#a*IA-R8M*rV~%5v=K!cxt)CpX7-q zyb_D_3CP*StUgUqU$Lb`tMI*;e4WX1$MfBp+A5oxTJhb^dBn8%_?P4G?F9eQ0pyo2 zQJ*7A{{O4P>;E^!DCc17V*Ux&7q&7twsBIFm-@$vmQ?9K4$e;huiyQPyf&b+p@^o6 z{;?5T3sl1($we>HsDc0&tyqAi1cc+jqd?DsH9Ntie1761bl|eCF0QUJyj)Fl5OST} z4lGhsvE&-Ba(SPA%<$*4MBkrIKs>?kd!FZRx1+mx@vmN2JRt!k;>im>xAmZk4?g`1mtN*jveADEOBJ8VQh z0A%f>l+JMMIL|1q?rpoYUN5PzOdI`=vG~&jv#W1UtK;kFl$WL5rfofQYOsROmQAS=@%n!16onULU(= z8@eY)_VXj!pcJwCw$gq%Lgm{>kUsgNnFlq|wXf13QzKd$Jf{s7j_R%PZm5FW7#$3H;q5zMXY|?nFUWa))<{7_KKi{qIB*!wG&xr zR|GzVCB`YI!TwaA2p<%LA%V~MUf51g?zS419>jsYx+IRvV5e#17pg-TOsA=|JM=S> zOQ(CH*0?SOfXLh<8|5V>3bv=@MMX9dJKR8Tu7W;g3Z1WVpk%?P6y3u%Pj7K^E@POf zF$gLxzfmJ+8=UxREJY&m!-5puT8>HifM3>WEulP#<~`JA#ppXq4TS3BRgMnweBHoV zEO_K$9fTjMoPpkF@7sbv=*N_XDypnOg2*CWZ9EPIJ=yKE;{ca{bTq6wYvm>t1$&0X z?-Z%rtmF9Qyks+2H#u3lV61uy8=5dG2kkzg5PrI(d{T@rUQ;Bn6H!NV;0m z$KhE_Bh|L5*VVzZ2GpzBRN0bGzT+@1>%($>vZaW`t~Fr=UC}rW9D{T(iTW$3e8!<4 zaDK+IB<<(1N9Fs8;h++c+8_q3)py__)*{0~6#hKCmR@RZ&7!;PY{a}Ux<@Fgar`^t z^f=ye_Rm`GMmxb^N8S!ID-f=yeYT22G>oE9FcOY}JEZ0S;`TettaW-?ECc5J8>_+# ziFW^p4@H|p{w4zC;>OT7OpkOEd2eu??;T+}# zxc`*hhyJ>#Yguq}ZYPPFf2{UH~63G|p*NfS3wKS0>|ZAaXp zaINB~EukzClEiVYH(`z{DOZT@H`U^@Pr^!)rS3u2sGA9LQ}4aaA*DpK!d7w9SE-ZE zz)OigBniV$G&04&S1n^GL~x-!V&tdmW^^S4G|`&x zSDzMMFzWpsGM>wh*mGK8<Hl37`p+68Y-?j;Zu&o!=fAWR4Hz#?XZ(-%jJ=|xwN+;*Ne)r0 z4Jn4+FC1pg(ehl$aRip_ljpVFWHlRxK%M(d$(G$J%1|gB%8>O#bbz2(iw&{x060pg ztdkoJbvOkvqwmLq&TQp~hw<)^wfmFqudNSPLI%%21ARH*$Oa{z^4~(flt5#y!z-sq z3M()Y6@3fL;$}!O{1)ih6t58Z{hL^B^%5M?D5M)eNx-O7bv`#6IF_Dwo~-C0$Dt&R zlNdOn?=4G=rKku#s#m-4YCuVt7mVVqQh3ZeI~g?2$RLM_ogh6woj9*onr_4?+wVoI$4N(ZmJCBq zj;)Dqh#BP+SbGRR1|A#>h-0Ef-w{R#lSqlup^A%x@sid* zN?-XW(QB3Z)k}>zU4=+9nCscsn`NVo&Dz9diqZPhfc(1oGjUXDvU!n`$bZI{Czl%j z$`O4X!xmZ_+>@kW4wRtI%u8QXTB@)D-@`u=i zb24~~C?8E5elxXvL|vUex_{otPEHvL&B0DiRk0`Pww8A>!bSx0HgtI$W$`m8IZm(i zyZLK59kGr-AE=F)Df=+q$-Aa}pux2|Be{MRRz7I74q*-Q6!}WxR`whzVP_A8ePB*I z)8G29N4&_XNTd^#A zqjP$@^f&T7>@tM`mTK&8N0|gk9{5T0zpf2ZYsWp7rHNsGGi&$@sNU??-awaJC^ZLc za5clUmY->~=zT>_?Yd!}mnN(A0dUf73|+xuO)bn?YK4huqp+@X6<6$EmqOjRH+vXM za%+Exk$E8G%l(ofAU_5VE^Dx%5xb#BS=!y`Km2jv;a=w$EQxp7MZ6jEfR-cdV&254 zIiD8PSRNLXRR!VYmsf@Eyy#+n9E+OL1gjN;3$aeQOYRkVJZ$g~w})L`W(N|`(?kJ< zSHiRg>-VvqgeJ%Xmu*OH)>KNlzPe^ke^(pRSr0~ndkhVId!+1(hH-o%7;O))%;8Cq zf9n#IL3Xo#{}fnLPKhTJVPbal8*-!N!>-)6mF%^HwumJY=EaNZF?V}AHT#F!t_7X1p~+EQ-c-ocz-_$OM*p`>!fThUo03K*sXRD4|5aZ*4ge}K!OZUc== z_;b&-iv;Wpnma+U9QjF^Jv~4sufD~>DWZ@J z6LdwvpE)2269gV+IO&92rclzr1$;mam* zoCY1h0uw#dONhSNkpYVBk`<2^kz>ki^1?rptxA?<1@~H@Zq&`%NMLSm51aA1_>EDw zTfQNBxplmQdbJB=9~+Br1c!@ewLj&I+gL+bxC1CPC$@B)Po14OQ1K9rJa9&exs;Dy z6uSoN52yhz|XgV;1n&?8N6iLJEP(!zPFvHZ)c@4Cn z%wN8jMsP$Di2zMu|0k?u>5*25=1~2Sele;^jSzcs#60-d7~IH@Td}D=R=8P?0$bHL z!P*xyIS|P`ksdamr0firAJlJOA=;rpPS_9_uh_}9qmJr#2=$AQ6J(B*t_F5Wb*kGefHHlym)u@h+t%-og4Bd=SQ$^GgP^d z5OXDy=xz}bs2;lBlq-zh#!M64q7t~6>F%7*MD`_z*qHqvghd-Q8MMheOuHYrJgB$J$h64fw^> zNcd@sfW?PdnQxMeB9|{xqEjVs$-g5mwmXU`uhriPx^2K zC6Fb4gm8~xe#&4rP-w`N!+Vy1q!i8EiK#b;(WeyL%sZ%B2Z#!>x=H_UDQq3{>1|aj zqL$>-mEI5;m1!X+T~M{o=r#H382mW=e%kkmIUC+z%75ZF-P^u&)W#^WFN@i1Ao)kHZ_=`wwBQWcx_imwtWiAjgxHzRLG!twSBPGPFm-po5tZ)~UpL2~iA^Yj0?um=T2u zIVul|$$zam1(w?QC}flO=vTdxXA#iAs=6(F5zq3zfY<#NtEe2FE88=5k8K%f1T zc74RkNgD7-?rm7~9O0rzxk9R1pzzf5;Vj@5+EBp-vu+oF)RCq)+9Pz~yR=U86)KuGX-Z+O~qTWayPAlZMqYE1^V_T1u-6*!Dlb zT%@+#ZT-zxrt@dCiQ{KD16O@6Y(n@B#3ov3{TIXR1Mx9qd`)FNqHqYAvPu~^rvXeQ zzl)Z&Ci2WQEb?990b?hlCE{V60o$#UY9)e0WTfBMtsXV4=!ftV|iWVLk8RJ znvkqPDl|hdUiYb#w$9|3T@op*R`fn&DcDS(yf9@LYYK5~7@mh>4U`stoBqlYx4RLy zd@_|A9V+G9&U_L@0Bp%3n`r)W3{810Aso|p+nP%0oON-{Rl3@hZ2$f0=8~?q2nNp8 z_o`G_8C95V=b|u%oBGQA7=KGm-_Ck^{OOEuJgEt&K)L(x zR`485LpOCsNsuNM`5&qFK?7ql2PohCD^TXrTcQJ#=gwcLgs4($pWiSL!qJfS<0 zDJ_{l$66M;2Tyk&WW5g3_trKOG6M@kSZqcSgvw{nay}lgpK=Z;QWpdy6EAbG*^oI~ zH1vh_OxYW+AIu~;2IM%R%!K*PxX@27x5js=Qkx>GF;u+1-AtJHS4nIRQ@mZgF@-CKkY@XDzb}M?@#CB>$5&9(tW}3DB^KFOuF6xZcN2h ze6nVx@r^O|y@-FdhQALXglw$-2A*x((WQBC@vc@*SMZ$)l#Yl?H0*MVG`$v3-%qL9 z+wrZuj4F06`Ws!Wu{}o@SGcu=L+B#$4aBZySMI{M5FT3ZQeahZY68+LXVUva{+xT= z^TJ<&pY*eRJlHH>NZ;$sH~aQHQWq2GRvCC?hfTZ|_r1aDlJspW1qj0vVC~<~(zr!W zp>#_cem{`^O-Zl~_BW)=9tDYMk+NTS@e)q0y*vho%{K_}=jbz1y=D0-lNkS-RA9<4 z8#D+=cs$lvM!P|Q=bvZuy0{s-xUo~%ODd=*?BmI(uhO{V=0HOkJ&!3sb6M*mc_y*) zPZ89St*hs$VfKgjQWiqXGLtj3p00ISGF#(A2b>PVyk0GBhG2*W1n+Xp|1%4 zJeo(HOzV^Msj0|*YAWjgyB+&~VzK`p%Kks}l?`~tGYF7Od z7n_Ser&Wsl1uB+>H7yxD zx0Z;x#+t%TYxenK{LZ&414>}|qFo0GR#q&l2^C0L zm-mV|#8=VR%5dI9>!J@{Nj#Ox@H;hjZwPS8jtgd`xHzeCVX*)^>^o|~uYu_nOPB>S zadV4R=C#D?#8E~XHGF(QW)o};E_GeO(5Ym5;#c^FmqeYU$3ct=;RcUVV~zeLBQ@ml z658R&9V6@#Jw$)g@4oCS(6Iuy8 zF+{Qi14z)q5D)ee&=vS`Xe@JQhG*@L>4_+3OhsT0b;m}5)Os$@iCj$j{dRd;PTmO- zVBhGqwGV285{bi!t@)Xx`S4}bfyVUUJKSX@q*8LC1(UFh9R3z~WxRyCl>IEJJSF#` zW!T;AB0ezZ(amf_s7uThJoY4Z5vj~bPIXlUt9x7l0^)Ed8CxSx$EM;F_4wmt0}yRe z8^C-d=3oO!GlO)I(OM)aBwn?S3S4Nigh36-6QE~9=)F~BWV6kh|rXODlquBg<1WVL}YWkC~dV z7gXF1z?K5!;YdO8F|*p3TJVzh3=`_Kw?m5MM*495%VQirJM8>87{J>6U_sq(xpCR=BL~YVq&u^L(gp!9@%sxqbk$kIIx=h2o;|IE^Oh^SXHS=EcvQ2O3P7U z5@;NU+skII8DRsMOZ9(h0;B>HAXiWRWf2a*G20Ev4F*J?NH(~v(;*>>j<+S=c4C=M%4Dd1E4Ew^$ki%+k zQg&HXP_bG-(_eRqNpEEwu9YC*JQWN`RRlcXl28wWcqk5doA3_xmyh*l&_H2sSyq&H zc@P{=c+9+VH-@gHJ9OOw^U@xIbO|4!-8-E8MGSEuOFCad)`y(~;OUf2>YbDDmiYn< zJ^wuMBqPl-6fPwu4L;L&$l`q#M+--bU5O1RI$mTYyfDK_QZ;8sMIPdy2iM~vlolaVQ0a=n&B#U=+k0AKpHE8M(iuZrfH~Yfr}L%@+0YN+-M4~wF`Ini zFx@`HN7zQ_1k?>Dq`|H|lhOO(C)#ZTb!%RC`m`o-&Y;FZ?n*7TYVu?a8r2xUqVFIx zoya(Axq4g<<0S7}Ekf;{8dU9lZGEi@8KV;^U3WI?>7K2Bo*o_lzLH0~yUX|qZBu%U z+Cl`tN?pvgnYL;*B1G|gPsPim!Ty< zl?;z{#01VvtwWKfCx*yeemh(R1DueE#om|~3qAAQ=5YddD!EOqS!r&>rpbq7!o#P7 zNmZ&N0(Z(>nInj>^7HHAEzyf9lW#EJ7p7>iA_*s&#@0H73tKHjeStq1;EH%_P1GAZ zm@qjiIGjhlR@_sxereKJ{zJKxD&mqZPS(S$YAQw)_&4S?j=;&xn{W09I|&FPr3&}R zl=WP&rE=pyWdEjoZiZy2v^S!d2owq+KjXqaTQzxm1-lvB1VD!K`3ySCl!6(!qXGzf zL>1Qc14{2$yJhZ7eZc62eE7DO3S9pZ+3o}-T39gn1X1pWp#+pDUh`*xE?o`k8ZgLT zmw867bb$V#gcH<(>FWyOGKi9K*8_E|F&I1!vAj`tcQ5&)|0cnrWY_-z=%@1~)yy+QUL&h*(DR(&=9KK~=RL$2jh9mQ4zN z(dBo0C?lgQ9bdRzTOS3~nG^S9okvDXD51@?eWOcZ444rPx>>DVHtj1!H!OmY2SCnQo|O z8!n9l*vfn-m_`8z4^(Mo_yu-BXBg#e!Ls|}RQIoHSZT{I7g|yi=?E_@zW{;-xt^f6 zpYRdhrj0OyLkd>$Q+LJV>f8f!;YOZ&=TBkGQF-3D-_TF)2O4i|mhRlJe>|D4{VN7< z!7>D3a)LNPijnS7HQL>eO3C=^L8vH+(>Rb zEKU=jwN?tf9Gj@6pxX*KZbOo5i)eCVNo)h#bf9tDW7l@&IlqSI4de+qNm-LXKND%< z{E+>3i4_bpxks$z-V^sf1;Xvqw6)0gos&nNLdrtV!KVRd{Ck8VY$9#B`}|wo1lO6? z)H^)EuNe6y2SGD`k?wbb5IC-fN3Fo?FM))o^EZTiPW%92R(QGiLy8atpI5+=Y-kFQ z*!3niZ}U)49`;037DT!DoM|Q`^@O4?P`a|;6?xct!7^F2+SAS$T@76^!x5(r4; z|B)8>Z(Y`FEhrDwWwdX5=A=|v{BcA`L{Tip15zwZQ6*W#7^bv8wDG};dE7lyyonGj zkD;$Spatq%soJmGD=RJP+A=zpmTMJ8*3HeD|4iyPmD^`K8y$1bx8CWpWAUJAety>! zh9}$JJME`C&NKcqe6KT)_BX!Bf_OStLii74Z6<9>eS6z^PgMPBiDytPuJ(!~=py|_ zbop8`m=9lSddSdN(H7OwFSK z@dT-CA`{jzY=0r{EMpY$%^hWh?9J8DVeNt*^gM)r6 zn)S?4^LlM*#-#$!)a2VomM#cpd8?5PRv}iA982ceB0@3nM6XuV0zR=?3pY05I}c6< z;!J{r8P3$(<(RNw)ajxubU!DX#uz^kAgDZE=8$}m7ZF!7j$G7MLg93oP!S)zh&h8d z2zrqco^jNe$y$nd(>F;Z!c-FgGzR3amlu9py>qbfsL&&?hG}P?2r@fmBWic5XTrw z<<{YjST`|8KX(|JLMaYHA3sNFOhs>!mLon1nYvj%8wwNg7}iiUL*H`}A8qQ>AHr(v z%ZwH2WYidqE>9~@@ub)UX{$+OSRC!c<5h3;Yb;7(TUKmEitD~`p)zmdtTMgq{RHHVfQn`;k1f%i{0 zq?>7#3MC@v&Z?DCdsCnFq{X7*PiQiH6n9qh4qs%STqDjZv7R3T%fOod>mfg`*Apj%YO{5l}zX<(M&U ze?^GkU#uOogD*|D0&pO#n`9$cty{N|-<6k~t=os(C)==Y4e#QISQ()7CRvnm?2;XE z>`D!=n!s(}061~>Nm^{AQC)r%H;E3d(cTUWA}TeYDAcPsUc9K+M}g{;Urc)Wh&Hq9 z6RDM71AwCbFAu?iAm*LPuU_I+lsi6vN}*3dm`PXe?14I$2j{UN76B>|38fxt0l>6y ztBN4y9Y}1OIn^qj-xJ6^o`< zw;`noQm?-rx?1BLX;sgK?W$DJIwuP)9ck{KqdTv$Cho47D_ zoD015Du>D*>HEs0`)fR>o)~3d&daHKH&eyo77Z!vM`Ew88ABHLLTN@$6J_IZs*K*W@WDq{t-&A&MsAe{_TXne8GToIb34ms*kww=n zq8_RPs)}uUvt4!>hG+27BVOY>rF>*qwzI?nB}!&iZoU(*vefMnBWb!(Wd=aa>7KB1 z&#_i_d95dOVtYTdaH5ZCr$0d$o#6L+uG}8d!jq< z^c#t-@%ePxUZ$S}(9N6|a%3{I>WDtKIM9zkA(4#D_pD()p;6gE#Zg3|!`=QWmHm6S z5(Wqf-o9tyPYa#KPRsP`D#9N%R++ zu($+bY=CA}P@k&C7`5ikMeNAQNT~ep6%zA4a{^kBo~Qi8j6rz|V1iy@7}#Dkn93Qv zsf05_eZ?1NBIzyC1l(t=pwQRBZ7-MbRD!8NY`jXAH;D!KOhOouTHjXGyL%Y28t1;z z+Ju4me(xgK_nB)Y&8%0J;`wsIskjf5@Vf4^BHwGI7SDo1V}9uNK(?*ZEiMzhB(e2* z^`wxmu}dywXD_jy;%i$veszg^r@*jj0}AOY()4K)e(6Dyyfs?lOvdUeg6Nb353}1o ze*w3VpM@N!r~1O-%v3qT%B-vY$tq`flu{FNDYg2!IGLHkh$dZV_9Rkhu&iuyr+yFT};pGwF&XD)-&aoXJWG8b4R-gDUe zv=Xa-?*76rwadDOu#3_BT;IsBZ4reDuTmZ6Ps~9^>nR?>2s$H9Q(Y=aqh?r&m>KEe z*y(634=m5UALz0>m#A9;Wd=z7@Lx9)=D$ z!bSC?opb|L5>QdpH-+zEK9#H5pnC^uEs;WshG~{2NN&d8;J77M>_e(}!!F$|Yj#nt z5rh+Xaff_9rOIB+GcFn4Xqw+1a*I8o&#)vJHW8LOtf+N?wY|`OI~zQ+16Dd-4f`{o zU+J^%m*6wczw_dJ zvi({UN=#CiEeWXfqL{(%|Bo97t7; z1FEfHkhXNA2lR)XYR=%zHPNjZ`4K!Dq8k&81NuLBxz_@J;KR`+AP(tH%(hNzH+%fy zAf!Rzb)Q}c^8?&$AiyTi`6SL>`tW^%_knpE5M)+BC-66eu00_Ez7w7|h_iZcvNV;h zYO{EKeIT510iAx2W^pVy>w5J9m@iJ3T zesCnEHHr88F4N?IU#XE;l%cWGrKu^BmmF^IX7{O{5~EQkf@c|zDB3ikPR)y_F6Z<~ zaqnpN%uI&_{*8k0XAYY!hPBEYmM(<#mb>kMo}m;W!C3ULv**$g%4|!`E}nY|@Xh9( zvOMWZ&SF^F^P-4d(Ymo$iVXYzw_tE5{mkLDe@$%#Bp@Ky|JSnU|2p>Y-`d>68d}ba z>Zso}DDg&9W+|W@b?6722G9UHB3dHLUo)X1(!xTNFENFpDY$e{`7qn7Vf=2~i}D12 zSMpgx1X)BTtxJ!S1r{y6YiKvMRFT11eCuLeZn$=}Zo5Z&f4(L`faKnoqY*1eRVC_v z(O|8_lqXpUYsAQEP9Bbh8`GSv+c-d}F>?$#Rh9c40=GtKr~;a)G>Q1k%&_2=unC%T0Ql>W z!ecI{a$3<}SI)0hBR^5kO0tQH18oe`BJDvGh;ffR_|YIKrIexSn)({eXj4NFNroZC z3Z>B^R)@zU=^@?Rsi*gP!AEL{A)+JZM0AK2$`-4s{$Qjx&pdFq19^dDT$Zm1qr`Lt z1?|ctBc7GNq3EnT!XGK`nys|BU{?`qh7HZZ?5VfC6*NSp#yVyp$Qx@NHs@qHDF)Zgo$e7oZE@L9cQu!#F5{zOB2Yp>O zmQu${5q}7)bNUD{WKntgEsm1zZfi%C!DKWu&of?U%jBsXuTD+np@j*;fiNWEVd_ zj>r&}sq#1xZhBHil`I_kc+q56fmKYHl;HS>s0A0y-hJ}Sh_lVcF$B3R#)20`oX2a3 zX=&1dH_tL<5NUK;EYufx1>`~}vQ~hT2$7S)-G7dR#qWnaBmZY?>vvej$ae2u z1XE0aw@l1qT4MOaW*%B$_b>g=&{mnnqcs!fM7@{03WXwrb+Lj!Pdnr7C4Je&bg`Me zes2Ag?{Z$RB~m<4e$Wjv8rM_vy!^^Pobn(p!1h3}h#zhZ7B)I?8+A>GHAYAOFQX0Y z1!V@4N^Ax`g}2}H0GX+Gzvi+1`kE2?v=J4Zby=)6(f~&kSPHcW)xin0tA}D0-H|z` zX@`17t2Ob`wF2dgAF$w~3`c7={9*~xF<)p+fmn&vZ3)(3@3PCt-O>f?~=92dog|nNt^WL0@arpOIqZ3sq{FUufR#d$?FB-F6O^)cN;O6u4 z;5?rpkNk38F5ufC$Nah359h@P5C444{d2ZXI#@PYe?BTP-U!}MG^k_~Qmo60Pm!dD zl)QLCQyp==9ezQ~%g!cQh`@9>K&LuluR4ah%orh8d!&Z8*3SK@osYP6#1}|h(sMZk z_JaJu)RNps`sjAyP{bqg2#3-HoJasXaAGy4M~kiaLuJ}vRi5<2=6;tY*BujV2}uUh z&i{yzC(Lqm(HkkQWak&iVML0nF}NtpiF|U{v_(w~RNQ83JO_>wFR6L$JRR*0Y~uTd z1)@Bm@4ROH7OM7vA&5T-d&A5{-j;e|DL4)HlW)pC!zg>l_^&5$WMyf;nec#s@XdjM zMEa$ZQq#P#(b2Tw+w4cZ z`?KSII-MxROa#1-akBlq^`mv${wnt{u=+Qbus|!N7`{O|e*bwQ~X^7Kr2X$H9{m8P;?4 zeL|--n4<;20S03IbvaRa6hvj6&45f-OIdO4WF<0$6FEhF;}u`f>+vrlPCMw17UEdZ zKgP)wThLSXm@jMg2vky`a&@<13*({onZuLh+aPbgvt)RbwXCd-ojf;Ga*Tjc9k*!F zpgt>hJlWRPkc%JT7kmQ_DOCVkJ#lKq>?cCQV(eF}3U;%Ha=BfRORym~;rYTpn>5 z$5j;VYfIDLzU8a}J5_g|vDFi}_l*40@Y-bzMl<#|Vx->|>g>si<>GeP6K9kqQhLhT z8#gev_ckwV&4umrs~ao7BI`C@TFkVs(9n_J~gm(wjO-!Sc6kU^+PBF9R80 z1_HUUQF)X{N*MqytBRx*`XU`)62NdGOi9x-+y|&?Q5U!^@H~vQPr@>IksqOHtuvwLD;b_gSz2U zIL55sRcdQ|xByxU8ij6_)&*uwszre%J4k2|;JIy5?nsFyHbx-YShw zS%@g<5^z#DXmn*tHChW;PY}aeR+MpcQC8X<$D%a(tCiY? zp`--|?R0cEbN0+kAKO6LHr;u7^6QA$Im$8Bd1Ei?bfsynC1D&_Xe8!}Z_VQEO`{hk zxY)x1o6stdCHlm7IoZKTWq2z69Jx%(C~@<%CpyDCE+y9?0O^_3upMBFoP93|P#3^aQT zn6CY2K{&J>?3mp9YxoW^Tp4=>&IIfM3_bUYClR8*Hn{u5kh%L}J#+wE+9P^I+*VD2zKDVaX9TP>8bFl>X-l3+7GIpWAjmm3Z zLMMmBUR?!?v*&6hNP2Aoi(u#NpZU)>yx3y1$MY6mOmPol8%G5k!Q{Ip9aZ)UL*4(7 zGF~KcBhUed7Iye(;YW5|l5fyro1pVLq{_WUUV}mebGNJ?-SPyHmw= z-WSA|N}+!Q+{V^8O7x2SPrn)cOXsp5*Qay#H^oiL5LzDaqP#{FkXvd{PeCmkcODB9 z#TBTyWC+=&4^F~+_!oV5UDrfEmd!G!ih1T3VTa7%LBmL!97_uraT*RsYDG;wUj`c4 zO|mB^d%vzU7Y_SON7pmg6qZ+9)z0)f_NxRdho{hr&5abiN$xf0s6);Sh$kXyht!mQ zgZkQb#T#e!3~wVYZ*Z6uudF!*g89P>J=5i z28bw`RL={I0c^R`;V0oka9vW+{S1dK>YkIKL7~yk^FepcGj1$hvb0HyNSbSWp zxh)lM5U7`11yoe_Vl_<=WQz@;TMh19o3q-6;$oC-H3$*ms|cf>cgBeKJ-Z>Ivn|O5 z*^>5dopejpQu`87SyQi$+s37!c7xkxFrrU|L_?>4EN#crrtT}8cCOHe#-l)Ddkm=5 zXm!T#5JtCzA~&=1z#qWK_d1g8m9MvujqXqp2}ub@93st`Gm@^0M{MS{Lx=(2&e}_& zTh|ET%v_IR-=-06d>m@u9q&l2@@6&rLa$dSGx$(KCT^8o&!5r zQ;;OFE|K!fMVa45e4e5@Y=Y!sgC8QU?nPOinB?V@~$Wb#BblmDHntESWO0`2R zY?1L>WS^R9EML%zz*-F!SW8kw?$O!-t$E7vShfdpuVXc#&uLNRoWCltq{LMjEu|~k z)?V2c@HR!zdO!;q(pb~at3gY0>Vee9DjV4xv^nCOOjuZ0v$Yca0s z%Sy-UoWqCLVwRr~ACBm8ArmUv%3yxWdFZTw;en<^R4`0u76(RzGf$VV-dtAVzeI5e z_NZsUHLiXTWq6^vs=KG6yjmG1T;p$xloNK%+^hqF=lHta7m*4^D$cX@VKE5#_5M!# z7`E|@QbyPBaP5MHr^scm`Rr!sc{!8}sk$NBTSAjlj0WB4=c378+{1dfYyBFk`3;KR z*Z3IKp^{Qaw1#i>FWGRIZ>nr2HeCXW+F_IXH)q2dh5jQk!I+q6WN^J@3*C#@3Pk4M zmu=T>f82c>tDkPE;V0-rR@(C$2yvsDxXGuyO7o}F0{Z)N6+8%B0ZiAQ6Z9-+>!5zP zYg@fcn*mYBZh+BSgq}ZvLPFU?OA~9KquKg9Rmp4R1z&OuzJ~E}mv&rb$%a~M(fl!2 zeo20P|8Nblz0RhUf1|ahsqb>BXpN~GQ+-*WP#6^Q&XTPAtivb*+_5DJAH zLyE~o%JND_u~?>WQi*)jB~MR}nWO2K^eXY}#F?^PD)Fh?c>3_o1=({>#^J>fAzR6s z+HLvElJ`XguOnfUp3DVM%?gNJ1vO3u^{IDc|Di(KruS^&J@y@9r0_`4(xdL=g;fgu zBc_Nt&TYQ#qg8BWxwWVUh{<94Zj7wl+xUT4YF>u)gkz&J46mV}#QNrYsVtiG6PxQJ zA4MCtXzQ{#rY>EQu24|aK|AV)H+XCbrN%0QR`jt3EfA_kAgfs?^@Da zU&QYb@x}fZYt!&QD4wh0+bo@IJueIS?ki6`F=U-No5?|^4}o3BLmg8Lf0vKkG71AO*cwoR6pwdN(oVHtee^VGoIMbs$odYr5RRd0v*Yo zZGR}E)EK3mGShlj-Tqd8COhf%u*q+k>tC-Pt6AAQ!*R#nX$rLXiGQ!Ga!P%0!08qZ zK8Htn2EXv`)q~zlRKTu!dihqN8^!X{3Aw$sZ*T(1iuyU9+}lK_iti09;GGn zb04IEM6mJqdA?@cxioSM+``9@J;JE(*p&1F)0CN0X!;YzX~r$6BW&InD7RGbcW9w2 z&20OVOvOwJD>d%jF%G74HpUV~wI~kUmk>4?wxm)8KQOsQT7wKH#-jKd3KZiBDIf14 zR{EIRdaIOS*~7&NAl6Cbl6gG@(*~>{OW4%JkfB~DqkD6*@OIf{%-N|#i3kGG{sD>o zMRJ^|Hr(6}rhvGU2#*a^kvW7c@- zLksu=DqgjPtQD;3{So6OKPT5BE;v>iL1%60jL|e!8q_4{y}K{g5)vkaP}QJtidann zG1{ooN7!iep%lZW_@YHpbwO1f<&NADl?%ASS zpi^2ZSC~^ppvmbIF01y|JX*OvoUHa3Xh7bph&}6~`bAUwWY)@;OOvMOLnI#S2reU? zVIR{75HOvHFb-V=d*B;0c1UY`FwBv2`&5fQL^KP9yh32b3qH z&{8V%@xA}O_=o`YgC*&0Q;{n9O+RhG2664cW9QwUTNzrIBC4VxVltBiTUTjyV^1go z`@B@;#t4CC;sh%x$yBFqVXt&$%lwEYdZA*O;GXw?q5X%#LXPG8_Nw45^tMVCNvOI_c*-Z09+|P%%yU!_DJsM_~du7C$h-)VZq> zR5lAyJs*VHL4BgMRqwEfDZX=@{@D(D#N)XH>CI4%1piH0c@#G_Fp+QlXLU*U;|)?s z6CfFikxVMbXgiS_(SSpDQQVK8f$v1S5^lwXx29Z+#OK)pzA$~gj|*K^=$}#RVuZ;< zv!=sylRW{u{UI|_wlJf=;_sL>{3Rc&1D=fz0QN6%U-- z^=-T(sbr04L=29A5H$9L90)S-4YI^V$d|^KcIAzhH=)QLD75?+F+&np%;JG-d-$s( zdvuXRSCYX2se5MliT@!BA@5es4ao;3$GOhvLu~dRDli91L_tV4FR2j=!fhe0{eqeh!x`;yNQP4Eqp;4u&4y!G3P!2CpW8Z{RTpAdDecn8xC~Swo2!?r47%N8`^?cR2mLOiD-1%Q4{J~tjG;*=su^(e zN5+f7)SfJzlh*u}>I(JQf?fW|>uPqvt9n(}SLj?sbC9aP-|H&^tpZ241j*LA$`7&`2^GXx^p+ZcTMT)in4(3{Os z{`Dchhq`$ay3`*%e zY_?FvGnPS=m=~=XIPywVxF$yOme3|j$sZO?ZV^I_bOFIOd6g;Nchqu+<$#pmWkdA+ zD;&2iDbH_mDw@4=%ED#9aB6DJFPWL@^b2wMF#PSF>&OD-z=Gu+%l5>oa9Wp+!?fnb zmY;=<*tLWisXG&Uo<;D97xAkLMN}!jIPQ#=Ux&y`sl0JV^vPN!`!)jb^3?`Vw{XKT z)ppPL6$AGz_pq0C5f)YWs~3K`7YwaerufsE`Vhf_+}|R@N`N#cv;f92fD6K0m1bHs z3@l-NHS=>N6T6J#Eg3vPNEdz9q()@RpNd=~Uk4HEs3qkpfA^*^j(IFwi#m6F;2YBI z-`U-f0x4@MlL9@}H(a6&_AAcmBUoB_qV7z8BnJLcq`mR5d)+}TywPyfo6+MIfT-JB zI9>CerCnKzJkp;jlHK^8c{&?(0FsyiXef#`_;(;*H!NK@vO8}MA)V}Jra@pjA>9MSAX@`1c{np!II|8j`aK0pL@rPY1yOt{BBdX0m~jymAb~vgKa0vi zcO;bt*RMF<$6c29Ce353#bg^(5g!z=jW{WSI63I}G0q{DXfHgjke^!(VT$B#v`ioj z!~;J-T*Fz0<{yA&KNQJHQJ{d(*B^c%(~o97m$ z5THej-1jpm9&5ajx@lp6r9AvbYCrm?bkay_Uej@OAl2Zp2Q~A`lrd(~F>hB|4O*_cDNF3_{+*~B9++4mfh5U5p-R!0dul>>B5=kS|gD<;MyGO(vg#ANiDNfWcT*DKM?u1Kg0!&*3 zj^2RCiQX@4Wk}>&7f-eu9-`|{sx_voDG5ehI#J5>L_(_jnN%>%MhDIN0Z$m!SyOd znhUF@rUC~*p}@c_0XYpae3GCp=p|D4gc$J=VteAEEBKjb{!pGcCXL23+v!zck%=1X zryzvFK-M-iqoz43#++1U?bau%onkhzq#vk3yQEKnYImf_RY(ERTp?E=+B_CA=^Vkr zE*ix?H5pCRv--1Tca*7Y(=@NQvgM#+-}I!gcGqh`_=WR*mm3_T4n*NRnT%8IxteNK z*xjzd$qyDg8*r%5cYmtC-xgx8##vJ4E*Fc8W%%+Cux46+uYTR#h9L`oehfHjZ+#|@ z>3=82!TJ(B8Y5ZKhR7VTIo(8y-7R~?AFX`T(kVDNom=SUZ8JfL^N2(j4LTexet6k; z)UM++zM(8^$PR6jNRHhYEu@3Qgu$jCGk|rW5L5Dk&z)Ta@&dlUC!;P+wM6d@th-}g zp06ZlKyjpO2eG4{diM|sOlu9e1^mg+8X=5AT0N}~r}}UUpfS7v8MhLhO8BkRA|CSz zmZqTEr{@dUSy-GKR#5uJiWQ&jJI=jU^YVT*Tpjg&>mvB@0Q&GiOx%X^Jcoigg6(->EE{^-B)B>LoH->JM_M3(sxNMmW@lyK-)(Cu3Jlf@+}%Z@nMUs0-rpyV$Gc_w6tj$qLE)gqqv3m=$R*w-FMK7 zyofKxK#xb#{Yn1&<~KZ{{QS#La;eD42)#KfHvxjQ z@(D;cFYbK1;(@2)!F&7ySUG~k1DTb1SfQS;sT>gyR3R>Kyqo4?iN4liPR?WNk%?luiB%^zblhb%~3if8CikwhQs zSF8R1m>__@4t)OuF(oy$QT{~vn>-s4oK?O-QE;$=30I1j$5wJD-2{bypg2nJ8-*YW zR3fIp-@@p|RT)ofVMT!_Gjq3-^lWpp)?PpVA7BI2xWw>0ArVyx5+m4Z8lP+&c6aHK z$6+)>=}^rTC))S4d?G&1R6$%QI4L~2Ijn~i>$l{FyQ06+oIU$8tA}KURd#RIE%oY1 zIb=SEnB}j-A90GYve4Jvj%azYM}pOQRZ%7uy{}#|Qie@s=GTiJT#8 zZ8W4)lH7~#QrfAazw#ZMm|1IRnxUwgEG<^&|Hy}`3dVBxN8i!3&_WkbC?Pjc@=a1P z!4|=If2ze421&>{x-d1R)bL2a(CSM4Y`=Q zDtR>e%#+Jh>}71_9Oe{1&0!`p(B%8R9K}kFls_dne-BE|$$A3=!(Kmg8cN3Y zGKpzv*Bn~6jnB16INF{nc2=$)3wDa2#JH_A4axv0waLOJBPGD=?vHyk(Ej(ACg#HRAWo|?N z^#sZz_yp4=mq;6~aTo4ez@UdQpqvvz$Trs;b@DD-VG2=7GFCKmmB$lko3&eIS}X1k z&+M*lJTPVDiZ|F~UzSB`-xRA9t7908lsF;41bB~F;&{Rb_ie4s5{1+bB5o14ntB2g z6kMb~c-%bufwsL=^u49Ja*N-CzX5;1zkzrF{z9V6DO+!vA%2JWuV#h@a88sC1Rx+U z4j>?&|LLdme;_~q#l*0z4P&6A;rT63dO7jndO+EtLLpy3YDGNhhRbu?A$7IpM7)}U zBISm^%^2x}LX$wImYA7li)Reh5o_zg3sYrWReY&^2C`B@kJ?V0 z_bcF9;1vHiUzNsDa0BlR-@nPB@1MWBKM7Cg1aw_Md8uHwn!riF8Y8haF|p}`Z{S_U zMCu>)jLjJ=_F03DUnFT0`G*Xgn&s9E#HxQ~MskJ8sBCHO zPn=)dn&h@x(FR5bYi%x!!B#*3U#uX$u*fQ1EK=_hY1nH`HD0U`d8b!fko;&nE{;2= zTn@<;PZ-{w4ciq#;>c)2(^m`R$|JjG5{9Lt#_33-MPFP@Av~`Y!zfTc

ps^)5Mu zBV#@8oX<$*&Ylrl)T~K~o^weY<5AkA$?Zg6Kn4S;F`l%~?B~E+P9`j68<|C3J&nln zhb^xdO35CtWw1C;E(GTqmXC}oJ8e19IcHMaBLyF#Ib9S$sSG(qUNS_em#~Q*U+(p3 ztIrcco<10ew}q<*`?{-%LMzefMv0q=#)rE}A38bN--1gD{lX{<*z(8F;wUKYh_>L$ z7jQTM?c#8wzgbldUU25hh7E}bhU+vuh;8~k47@dxXE7i#Mw0V$?=5;>&HWSrt0@wk z#ks1&Q-0+Z3gVu^vbI#<*5ULd+ERPm(rOr%T_Kbk>4%F{fkf-+Mq@l{q=*K~d{qsf zj7JTj7FW1M6vxz6su=qv1x0Y9GRVua-Jd6w=Yz5wj;R&S{2rq~PSftEzF&q1=hK8e z+Fl~h$m`L_^7pO*xgF0f)*a5hRs4x6&4AP6OP-j9G|q_!?FJ88o+V4)Y-fzPgVZ(a z;A>fd=}8U6LMyoZtQR^7TECh&xRI+`+kjr|!$=b^M~+;|wtp;|9XmptglfJSZgYN0 ztrZ=cS-q5tTD&%1x{8!}*>9#yZP6{{DId!$8d*}=1p6n|sNdJWDgEj1koz4x76i36g4=W=`gjaVU(Ew(3MPGT(cQ^c`wWfxShPTUb&0!d?gGs0{3|xm$yQ z9y6jNlwK(eL9cTE&FQL&hBUStO|)32gjnp0vHQwQdQr{Qe%3+y2OLxU6pi+No!TJq z67*sbey?+4ZU~s*NHuxDgdz?(DLp3I7W6Xu1mPU&pW?#IW@SS2Q0$zYF3ckKBLtoM7NTJmQYDp0EooZg zb(#~3A|&%SIxzj!a_~_}GfvC3Bovj3cT^%BzzV!DSx&I=Copq&_TV8_9XV0W7^u*Q zW^Z!WhD_EGrr;-lp?6qirMfQlK|g;n+|Z>4XZ#^+`yX+JljR+1K|TLY$6M2mGc*59 zHMpN2q3Br-?l?edg9JxqWabb=0{Mu zsEQBued|1@rVXHn4HFIQsQV{l<)27T@I6`CV0r0MaaKRB@}MOL50gg za;0jTcW>+;z~730zWeP)zcLHif=H1&vV&3rpXzSHhsHcs+`E}Kn@)vt&l(hLs4Ggd zi5_2vHbpHpoY=w6khT4f+|vFc#F8)}6xd0CUbXM)qhMhF;%5uS5U=@}4jnzhae5mI zhMXs{A;55^4~m@6O-v>k7w+&mR`1+zc6LrNo?%|%<3Vt@kekhm6YpQ){QewA4@c>G zZ-GGWy^l+TbJ$^Jd%v3WY4Zfh$tCkf)g1V4AA>qFxZ*tEy?h46IqLU&FP~vf({SCs z#l8NO=f1tqNps-FK~mBl>(8J^cz%1z<;rl(Pls!VGcNVmTxDcAeM8WdGkMU>9=gMP zeCO>2gs&X*;5a3Qjq#8$1^x~U{1KGLrhMGPywd3 z1f~!dmR{D8P}a1EuDa&Ogp*G7^bO8ahAY;Ri;7Khw^9Pf7cHcG>xe>SZ^Xp z6BD5;DS*kWnUSx&_BH#(;-#9rHW?OXqZPy)f;}Ntw}os zXZcO|yG}7OIAMHD4Tp&UjvJ2q-8&%a{lKYMafG6Rx;Mf~tv%sDAbY!Pd>IaFQb)VF$A)SA{{E&LvyTW%*WBk{IuUi-4`h?p~{o(8#nwnb#PaBbL$WEj% zUin=8!4%LkU=B>xCvwX>LM{bWq#ubg-jPTTHGhm%N^n<0MjB3JqW6m$RJ=1EkHMyP zUt27U6|~PtOa1Gg2@9@yM{7|@83R9M-?I`I!)0_M=932Ck2x~NuPUbQo=`L0ALc)6 z9r^zfa=@tX)&6J=57l~L>#F(!?#8*#_n_Sk13Nu|)SilD@2D5>1b-&F`8JpV&h#gP zvHnz(8erEr420RSEaWQNt-2rm%W>bS)rfrCXOD2B#iJQD-XV(r1hvtaG{#rt6yW)c z7z<3|sd<+T9y6>A@tQCO#BP?X4~eW3ZaJo)G^UWId`YsQ-HqNWTFF_@j%-Q2)rQH* z4%|XLA%2k=w1*0&8#s0kDD(*;Sw@^&{=&M=0JaF%e|Bqgry)=t z(6P2{;)f9RftVp1za*uMw#hB|scy(S2y|nYn-u7l{cnkA$D;*~iFjY$qvVm@;upQS zYCH&Yp!#IIH1br;?Q24^3LSGU)q*YOme9M4{{`wq&KtX3nlrjXz5dJL^>o7~OF=aJ z9n^m@KY_u~E|v3gOcW25(}_^G&k0E==`q9U#%p15h0q|N2NGyNfIpxs!Y_%V1Qe*P zRoS6?HR0(hdt#(XAm~aHpTyPS-T_O4_t=>AnwEv;{IA~qpb&hxZDrAn(!6tZ=}UJS z_}1(_Wn<`kK=e^DaDsNB9zG|$u(sES3rg6*QbT}1K@8V;zj$-$`iC07BAB9N4o~)V&>Fr3MkZhK*B%a_O4XI z|Co#Dy9)6lzu~QJLQ|A#XAj`v`z!Rg5sCy*GcP!Jl^eMHF zYE@MbE-Qt0vckMV+Z;>d@QrVnqPYV)WG<`C5nlf7UOAG!K-T3IbD0&2eSw&|sJMXm z-T?YZB!e>Yctmk4Cekrvm$T}uow);~;+Ez|D8D$5Um|u`Zzg$6eWH*th%zbuMh4kv7%R;q)( z2_fD=A>K_;;3Z2r$M1Yzquf(@Xrx0;qKQ1(DAM6L6xpGW+9=k}vU!Yai8KXzs-#x3 z!~VpSZrmRd>@V>+TZ9k2WBsef6ushNwD=ED|F9(=rI#Gf;Y13~nd?FN`0wkmQQ5k5 zjfTN(y@?Kbp3?B-e620H+MYPOE4OigtBF~snqn8RU?gVAdTCPKZ#X&dFk^b)!F%8V zeBeQR&_NGA2E7(}q^(+(Bz;_#KEbZ1+?n00lbT&NA!{zV+*KVhV1LA&WQ>1vM5VCB zjPukyF;ZhwgoUFbn0_+u^23eOKKTibbI(xW(yZ&Gnb&E?kF!s97Jl->(0C4UVuyGS zr}TG-NXA;?)6)(7eXi$h1LFP8{%nKdJznlC6P}H2RIUL)>j(ZnTLP6fhvk4I007Bh z002Dy)0V*h8wvCuJ%JrvNQ0D-7k~SvjU5|40uUgYv!FnnYy^mMNIXIi$S?p-0fiXp zrhcI&Y&UiSEzw%{9__gz73~o%_!cOV<>D8sN;R9-*0z&^K9_(17Hka`32zfHZR1mGxTMVg-UpEUq9d81FYkF6HbWwA4D9@QZePhDFebo* z7-althEhO8kl_#*LoxF6{Ub5)@yVTp^ZPHz=1M@fT#~^@9ajXGSfHfXiv}ia8U|5d zo(b^@JEspH)<9RjGpIjllLFe=^f4K^DRo_Mmi9LqcTehnhj#b5mqSf!VAMr8AXb(=ZGJV>U$N3`k(_9$eZyAPw$ol3z7Op<7d>-@F}Crh)d_ z;uW-q7Q}pQL&TjB>tUBkPBkCI$*>MSVxnq`kWbYgf&^vAr!AgWYX=RV$K^ zYbx#$MeDYLb<)?`^Q#x(1RMi4=qTXAwqYR7_F?>{bVYNr?xgx zW8gx8q#`_P@RZ;mUz4J?OB?Hal5JZIB>EgUtWY<2CPvWCT~RF|Mx<2o^giu-1#J4Rv;5U*{d^VtHv%X>VZ{?>S6p7cE5b z^m-0MQLljr8ExPL%O)I}LN0Vru)aLjY1F4#W8Vq3E`XYH=_ZivqmoVDn`Q4NP;0K6bDyeX6Ku`GfmTP{ zX!xZXrlrlx6EQJTa|m!1)wCnBgw;#x)P8=y`kpn)b>`DJ#PXvjRpoXwp)|`f$f3~5?5Tj-y>_8z=_AiuE4RHY(wwRMEN_vhC)(oui zzV@}_o!Gjki6BknGv|t<4UNkB{%!_rnH)RzsG|TL{GOrat+)rng4($T+yZijKRUSq zvgUX=BHHU5`Kg!=1pl+AR}4*Ve)Zt16>@@yw!b7k2E(&EBk3I z8yG~iPf7vh>9m{uGmM!y0a?i{3et@^;^o(YtoE5BYumRFA#LD+G^D$YnO(OF7-_8U z?61IDKitZyac6KIa7#E20RFZCXsm7se!+}Hl)mzDmbMiMCbGv&8E5B$A^f_B5B9|4 z>A&b&q>V(UqtfD26#423fZfy8U*!>*z`7@tO{pr790>Tyfc5>=Z10_5eF1Apt}DJx zA{QFo^J}M&c1yCEMBYV1gTVKH!1{vpiBT@W!C-sY?hXUy?rb$NAn2l%B3kFE<4~b> z6JbMbwCp^RWv|*HG%aDdjtVZ|M?-cS~F15?Z~m2^48lv5wo=z!Im3A2FhL#(`$u% zeJvr!$lXteEkRy`Y&YqdS#Tt8F%KdpQ0|OuV9g#(p?Mz*Q6k5WF=3}!bHK|BVAu*^ zo~=F$yZM5(MO=zVho5ms4kdfW$s~s{JMgJ(Is}HPb};JdD{Fq!OF`h-aJufhr z)lIAo?yy^~Pr8TtU{)932=LFg5tcHHy?L{8IWU9SVk|Pm;6g-$VJu$(XkE2NzKmG{iy0CCagF!r%wUeQLSQFzOJFhdMRU&D3}3NW3|%4C=Fg#> zHgD*X$VU)w_A-q2Or_!?e@&-;}@+EfiqLVfDjCEu(8R|kndvo1H;ni2t z>--B1zmQDUjoddveROMwP9X+AnQqaif@wjx{4YZNZPl%%_62N3T5#i^CP)4XN`8LK z^<`d&6S{9{Nxqn}945Xf&u6KCP=S)w%n#A>Hc@9c6II4iSi(P@gdG#g>$846!k1sd zF0ksGcDEUk?0LEJkLZhodwN-VdaOk_>TT@`)?@7(dmFKt51l}D zpQAyNvY1Itz&}5@zjA?x=(%31V!UNL64C7|)!9zh538xX-6}~|->A3VCi5Y}d5PFIwtUO~EpysSmUNt&IFxN|0gj2llEQ>UrxhW3f-vovaT++iTn zQ1)0T%1@E6Y983#Vjo1($8hjk*qI#rsvarT{Soc+?AwPBk)DZ`aeOy-p+J|L5K;>= zJ+g*$oJE`h>Wo^?G1m4bxzoT6myBvs6MO8?;PdMLJK|T6m7oHZ7#B=9L8B(M6Z}0~ z_lXVOAQM*>IC8i1cVexvriigtL;zQ2ZV&CMG+AxN{MNhAm*#QB`27m=U_Ep{rWNB7f+?thLe&#k zsEvG}8cA~T?k_Jwh@_yswn6kJ8!ZgjCelG(ss3yT(c1#a1H?;(VKBK4;&UBCooF*L zd&%V9g!=W|rM^+>@k<9w({_msB6NIcdZBWL`fDZx42dc0ZEqE4BA(fHqZoaY@sf2f zvls{It0a&pNio$wro_rpTiZzTR(tH}Y(^XchZOw-SvOvSBT;RxyO6Q>)#!qLdXf5B z8n-dl;Lg~1mw<0%ZjMOl7_pB-jYJAj_y#)D5(?9VX!rJF=R!M$QC%+bh=;X88xf2= z3jm>W?%bVat#WQ$N-`%zt@u&44zF?Q7I}DQX>;-w8}%jir(ZZny9?Q1CT~GrQ@=0C z*R()J&7ZdWxJY}_C$ksL zW7mA%3Af=Dc%LJtw=%;czy5v*2M~V#1P9TIz`m*iy#y7#ml7La*@tczj^`D3{hf?#V%F*Ub7c>fLb)3{KQHmHzFw5Sax0Cl&B6AlW_8zCNPNM09Ui zlOU9TYhS_!rMthZAosv#;6Vlp9p;znj8UKAb6zhe>y5+ELEi*4tWt(Ma zAG4!+VT{yYv)QKHUH>^%&sWmj+PA8yt>-Ikvl47sYWj0Yit1XeQ?6DUC82h#^n{8+ ztD~hZ3f#e3x1g%t+E7(j)z&l_5>@GGNjspVEXtv#wyds3Q$a=GA}_`vS*WesRdC6Y z4ni0uSRpC3Oftlu%%GS?D`UbpIJz6@;w>w;t=+hbMqOT{d^^L23HO>2VvQu&pyja@#SG>w1-Z^EASC53u~ zQ$xtR5|}N@G;19BL$io3GxlUbZt}Va(6EXrCe&3reg2PbX9Ue;DcT)mU9t{pD>RYY z@C!|2kiSXM+r89c-soc8;xJ00VCzz+TNoMH)MloR^`c1Kcms4)W%XrbsFaq=jWRK_ zr_g9gRAZEvmHM^fm>td{^3L58uoi#as44U~=Yq)$k7hJk95SY+kuDQBh+?Ykej}f( z3{o16VPmu!Nc|z}pl*GKtFwG0UUot3$<~}RI18gj%pPe(K9zIY0s~cDY0yUiuZ*0kUfgXI2sThsQ(<9~ z07zM!ioq|Xluq*3`GqNeLZx=m(WRCt5Krmiz`yxtL>?b^tJ z#n`*U&7Q3J;Q|`Qak}1MjVI8CREiA;?_@jND7%tXa^GU(Uza*A;JiJg9!X( z5i-1@O}jeY8c6W^={q8xUr+(=%mCRU-qE6)g%Dk>RlYh`E23D?op=o$U2T2UH37#; zL(BS1yToeofoPpx1?B3mB64=6ktLLiY27HDs=g8&U3}gomKREeD2_^sgk`wa!`={Bba^UECIm?zR>&TV?Y@*>LV$VyEB4Qc#Y|DRvwyux;)Ve zX`=L4QYmgQW<^c*Yk`f^C!Q&I)-Qa#rf6UYYUJR|7)Y!VXbWhqB@NYl{E>K2ufTFI zMdVVR6=?`=C8Kv>hHDQt<9FZ8kMBydvd9a!2Pn`|ymwhLmKUUAFOy);ch0AKXjvIl zQnv@`kTjGnucAuNUHymdzEzP#3bFYrOJ%ego0kxw-2~b0NQP?tPU;}yEcC76JH)D_ zJ(AbQsR6bJ@sP}K!q9}3T#Ug4yGkx0x1zmGOq{OC>)g&9pm14jsnsmHj-X`8~zizQPEaCobVo=#bee#5u z(+7LD1g*EJ&mgx$+>xnt+w~eB@GnM_)=o6-gCy=EtxJHDi_p0jqQjb${d^fcPUtCJ z#1a|VXBRWK5U;0g$j@wT9W0cKDB}fvdjw0}$u-B?CJk>$HE#yN;=<*cvu=RYX6_<*+lJnIoQ=qFrv)XeTW-!TV4X zm-b7Ue>w}a%0Uoa1F2`G;>R%HS(vhwuSh=GIBVs*XmK6zkW8WjxeSs9jr*4(*P-{H zUk78mC#Re=pv;EU?uV*D%$JK2sY&Sp?c+AByIY3#feRn_W&q&#({P9o^9549r;Os3 zC5G?o0NtRWfK{D1Gz~N5irFMvlrD6b`9Q)?nsyHL`+)bx@TX?n%`=YWQ_>f``HQ~z zW9pN_kGysPEP5(c!$R3MOo#blUpEa9VTSactb_dd%Xx8& z{+_kCLvVt@hDN!QTk4{YQp{~^>XX~rPHf~}!tUP4tXm~Z->~|*2tsjOnl8ZokPHat z(yuTLg6_xyK893xRDd-$#N~o%(PdEB>qYUJA`#mS!Hj{azU_`)6r-Kp4_a46C(#yi2DvB7=B z8#zk@s>_p^QA=P}Ewfv)ZqT+a(6fF|HWJ28skTc}4sZVm)>|p0${sO>ZL?<@_MScc z!V7h%yVI#Bs8df;Cr?~AcMfHzo%75W_?TYnUSVFG`IO3*R)a zfz~uUQv^Ka%H1uR$UP6xgU{hx5HW=F3vW0l&^`RSxM_AevOdj3i^i4;)m@NyjKc%Q zQwO~tZLERcJ=WoameR8;1BiV9qet>_t3tW$J=cuFD+^`>Xbj;{!tG`b0fqAyvg2o3 zB85&Nf{VL+G`FmP8)NccZ!O_BgygP>32)2Azp@5@V8M34GVFk5+9xrc4*O%8COL=x z@dxT`bmUYx;q(PBPVwIL9{An`Ge;~v@tEF*oU304;qzIr{6zA$U^r>((^Ei|?_JB> z2LyKlUJz%W#ShH??x!|*_q9m_T5sN!e^~z=5XYUh2za^8+j`d0P&lV^sf+4$DgY#Qz(dWWv zzSH%RuPva0<*1LlAeu(9(wj)O%f<#R{e3rAnl`Z*fWN0dPT~N732zbJZyC6iFPs6Z zR}dIURur-$uiNm;CvM=636PajfzSB>3+Q9U9KLgJ5IMuhi02Z4?dT=yCP2%hI69wvz&+V(0_#V>k-HXo z_Y{M6Ct#N1w@ZhBX@H7lsR_%Lfo0RcqQ$Van6!gS*fL;;cgbuqH_u~Ra`A!8@XXI6 z-{vWpN!pS83zU+{5$M4^M0;SS^p}WPv@_q7A4lt?g%2u!5g!SGHrE2V!D;OvT@q>% zgRz;$m*1?`sqAj#nyH$|+<6nFb3;ez`1-i=Mx+Ya8H5$qantgvV$6Z3G*!+!iwfVb zjw7pfoJSER7={t&Q3NiBMogd-15$d}f3NcDHEVQGSZpR_>M?Fs?0Fmp1Hk8}-*j zNW(99IdX_oLDC;|ej;6wCfy!%?a6{XI6gcz zF8*)}M! z4tI^i{lyEZHLxZXdU=(OXULbOn+2gp7jj3Jj2TI%=afSW+jtzwTFJ8Q_`^f-Mz#8l zmrbXhG}G9)*(T9&^NrXCMb78kDQ%LmEs`MdFQx$nwQTX)7hchcswE zF>*XpLZ)4nIf$isClN_=lQIPD&w=km6W_>5e@T=65?G#@ZZ>|SRE=MzCD+yx@*frJ znt}fS(G9Q3RDTlz2S>xe&?OOSj3X5%q6Ld(HBhk75u==NhC-pUhUTshR=b3BIbhhG z561!#J?z`MyO3UDuG{hbEe<(C)H09Hn!PKFa4}3J^y_X&q@hrU%g4Hu|EYXE#3XyCD*0?9j?QaIg%sorKxh0a!Nv1qRsleVG z3_897nScvAb_+5wry`tS@d=d|WGZymM-&x5yEYR#Lu0Dfp5Wa!6S4?0FhH|^rWBP33Y6cpy3?CQ|B>`w^k zfmr!F#aq$Wi~a(Ss5#2VDJzeVizZ!|GiE92E`I9vPn%q2KrMG3x+S?i(?Sf1G)*`@ z)L?0zM9-c5!Gw}Va;ExVq>KblE;%$X>G{K7+juL0cGK7#7iS3_UvXV!b60%`VU%y8w_mWXJ zVJjG0KNq++q;Q$4Z6~6Kwpb=B==_Wjz z-oaA__~Wtm>y|r!-eC{kzz)92jtB3QGFN19BB%rO7wK+XG5(E%81JtDJA))CfiA;I z-s2%EfI*g_D?u(heo92{X#k&b0H1ySaV)p}W;(*nwxyYGuf&nqI`x^AR^d}#gyl8; z?V05+)?(b3V&3Lsx;`0=^TyT3Chrn1ahILuEw_Ttct8u8ypIuZ=D;bY95!*8Wo0x9$mY)dvnPgezXQ|!dGJ_gsMc3tg zO)*2|y0Yafm|qWCsby2K)wphQ-&sS5_-35Vt_QN;4%Xb$O|Qqe)j648583lcHgNA* zc!If8-?HH~kqp6W0u|>$JR1Pb2FNOcY8Bwm`n@_pxF|?;pw@`b%5HCV-+v8XMa$lP5Em%sp{9b>q$vCp$4tEhcwROq0|TTRx#dGpZ;C zb!7ogu@mI8Oh~tyN(L#UXv*VC-SRn9QYgjV=a}FPA9B_y%H^y(xCc{~t$&DPIBTuA z_ggljRSBoK28rfGi*&9CA9NlA^@&RJ#D5-rD9UihY&rm__Jx*m&wYZQK9clPN+T9e zvFmT9(=VIHk)(}d6V0+R>PkE{ba`nHaPtUbNuhXbAGZ@_^-2ubaX&d|HPzBl!ll^M z*$2obn3vS{{Y5-c-VKRBBtUN%(Ak!xAcSB;WUMreAlio&rjRHj5=!4=4JsWG8dN`O zf--^u+!x8i9MCpm!f`gVqVi`F;AzRi)eIQ^*P7oc3>2L<$TBL+D2?%9zD8@F=)n!x zFoG-K5d7hl{HaawrxrymiNsQ*PMh-TsbP;wea_d@vQ1f?_uoFFQPr>3>Ne_Gr_g4r zOk*o9)ol$?kq%#QVrzA{(0L$r%(L3DYtbti)h*JZW7euuIl>xQ8Ew8&xvQ^A!;VeU z9$qt@f?IJ4PdboO{ViK~!h5jYaLTvp+_UhMQ1lmR<*{nHR;AUgI`NMBOs@LzRrMEJ z$ya{Cul$Tx{U)#SQ&{mYyR5JJw66N$`hLUSuNHH%IfQ-C9!Kay_DAq5}5_s_nXzyJX3-~a$p|6^*Ayo$nq zsq|F-J&TySSsI)EH|yr@o2*4DY7irO1)Okg3Jkw?R_yPFHX9p69Y{9kXk_yEQl z(?p?gz?RVA4jJ>`A~sN4$bK_=8oorhq8vQ8pLJOTF2~SQm>J_3<67q-q8V<$+*Zq` z6+x~S;%+5D3dVHhJLxrulY%;(QQzy2vlDr5U7CFBeTr zt-=_zfAA8F!Tbnft^=#QW3#T(eMpDK1{2$$RCabB*cN0Nuo7X^w_D|o=Z*I(LXA1( z#z(r(VerN)4l1im%$Qg!tEgPQu?!jXcMIz(aj37=GdU#Bb)t`I-;IKU^T&&oofy?aySn(x&%m((IGA@borPW`$O!Q`i<2`5rWae63!@K z9LXVgD8J_Vd6*cd-EyK8oNPrYZu}+&O=B3Cul3+uYHfYbnmK}~y<+^xwrz|bShJKa z7JLjjr-a$84zTf@QZo@y8 zvbA1f^IHgSIWiP#R)EFMCpOpFNxspkiMIfs=_Mv+K@*u42z5Bk?;_MB-Ay@6A}f~E z^V(*GI`i04BGf%OYu!ojc7$sTMW?Z{zq3sywYYgeKWD*He$CqVBnz4+lun$ z95ITZu`?zDJdf%JJnu2+HI}UF4+Vd|&-5V}TTb<5RdjsgiQ}O;>u$X>h8o?95XqB1 zPP5HgdGaNGZ*^3d8e)&2v>EhSnQ}(Jh+_r_qA!RBa|jBb7xRQw0Azlhe+mfPjT-g=UllYT~SEe=3~B>_BeP+#J(sF+rY-S74fb+eIJz zU_hMvz&{XxhR)9J_D&}Mg=AG{Q>Xu>wN)^5aS>#L8X>+@AVq26;mV-l~|Bt&f;5`@mknaG$2@E)<;J@iwfKO5mHyt zeJhEiiB_@~SApY~FL4b0^ZUl|(hgE4UUh42g1}mo8>kAW%wb1%4m7lEYVAI>qF#-{ zSxndAjE%>n>v=Ko=zzH#qZuPF%e(D?aR&5cf>ARqGSc*2dO)Rh35LN;rCBu8S}wmun%Ph)ZX-LQpNYx1h@m2)h}Ot-Ms|5AE4pr%`rV?NW^lQ* z*yAtrTV(28@yO6vE|?4!RkTOC&8P*LfgaF~#BvnfRRP22jM<`GBKkCwB=aJaI%hiw zWk_lK#!R}roFns`Kz$%=kIWzB4V-`_XVz4}DgE|HUhCa;KEl*0*A6BYLaj8O8Dqb9=cSWA7@~G4v@Gb{;HT zzf>9!)SB)vEfrmn=pxY={UZAQ2kbxTzJb%EQ}6%8^J)JlkpAxqV3Pl5<9}iLKg9DY z+VaSPC_iN=ZRsaQofQ#LLF++HR6$Z#p#-Bwm5D@<@+O;brjA|OZtX?>1Ny*O5(&fa z*Z2z-hseEHb9U)!Qphl$4bEo0xgWEfdz{Sq{=V-J1aXxJJ{C#)=?gJvVR5WKNz_qcpw2-RmH{LL^3+qM*fFPtHCLx5(B&x!Vlca{5qtJ!gQKr~r^bn=*n_6or zFHH=phLrG~ty!!cnf_{kVATRj`i!R@kq{U_6E0?kRJ^=H_arZS9!E%<7-X04Qd*q_ zmy$bZr%-c{q<#JkqaWKyW&pS_N||O;R(vrKT%;}&=VI`}!>W^z=6V{YGqVtjR2m3w zqim`@{R}9wE5kJb59@{$0m?8lMdPZp0eWGpNbNPSL(}y2N)&+4j3KtI6lrTPs_1qo zXC^t~{GwvJN?}LUU5WJ@2wIK{l-B@5Cc(J=!PBE?!YWVFOkob0UIpXQFqZMx09)k*bMXO4tMrs()J=BOvl9-%yw2#X!Yk24F>#NWx zC8J1Pr%t`%`a91H6MhR9Fnq{5&#g#cg)L51%y)^8L)4CrGlApo zf^8K=!mC@jF9~fUUS(c z^f8j7HL-J-jlYGQdB@Z=^KQ zIvdk--vRWF8^=B~{tRzIoRJ3Crd>D$!2|4(Q_zE{$nLNFvAsOB|fW+k;E#YXP@-catf%Z6TGRzjA40aDD+jR zbtx6>Da)m~4Gu_}iy)~2JdDrollda8utQpkoMA@c5&TamVUw0gdzR4V2FW;A-GZMH z2WyTpC_lQ^PoD&T(9STM`UJIzwT*)yNDiaw=*x(l%-?gw^JEwuI@C`KtIryj6rSo# z&f_XlqW;2h=9{pW{@8=a^FkAQNf75^7)!|ax`_yP2GYywn6Gzk2E0y!4YcJ&xCX`Q zx`d14())2Jk+z>YufSCHw`UvsuT{Gt7W;3l$c4sVEJ_P9yA0#1znRK|Tg{!vsw|}> zT(eZBU9v8l4@es3M6Hc|b zdthGk!XkAD_mVRK_H%JX9WRtDB@bSiJ!YHc`kOyZLZ8_!fF&VRkU$7BPELuU zBtgMKf{c_wk`OWX=nyiQoCx^ir?mEpYGObr7dc^W}6BM)mE{!)2ijV z^QY_bPo3(OpUYbO&7V3u+qdnv-R|y*Zj$79HCzA8&buAwInKA7-;a*=rTT8K2TOpN zXFc?${e=CL#8@1m1I3e&MFge6Az0q<_^KZeLUU^d92py8j;bnfopI4Tkn|Xz@sKQo z5<)&KRpZEUMphjA2y!AuQw>`T%xHXg)_3BA!hHwf>Q~WmY&GPGhaalD6zRW6QZx%X zysU`>ebzPh_3Gx^*MmSbDGC%vP$-C4W*vD7(^9Y1hNLzXSa<4h;VOfNRaSQ$wx39i z|0>1K2-^+~F-9qfQsPO*)V252;U9xTi1+QZ_T)Ga*(hlI6(?VP3YD81m)yghO@mwc<`M0U=<+o{3aeOym}(-sDM?AWj%9GfaTqv+bK z0|!Isw&)Z$T*F9LcQQ@advFmwv8RzH)p1%?##Jos?M!?KXi3h_lK@}S9PyvJ4xR*c zk##>CC=bwpYx9K_a|~q8dLZ$(3#Ftx%dz7QVQ1@6xoOQK0_}Q z`*=sm-$N3oSqOEfRU_>#*ISmQwrhNKcE7{ATBf05yeRXW}=8@dn{q zV%~AHxx_Eq9H`ppCaboZwYp4LPDTY}f2FvojM9{_C;&?8r#_igXVgI`Wv0=400&7W%?;tO1}KVN6Y&kenT}qFeSZbzKjvjRm1%Dq!=n%FuY(pi8+RFC)s8#9r9? z~St(?W!^tON_s#UbLSR~Kevb zJBerSn=j9nsjd3n<8EP%4wZ2V78QlHnRnb!;wRmdG4lrt$h1w(9mGSeeM*O`C_AZn z!&mYX!e1zizEsUBnG?~?S>93RQOsw-v_K`gFi*oIhLqw_4OXXUQ(sQB13}C1j5bN{kXr^!8X_S3 zGr#-mtQ1lVGtJ{kHA;vNEH7+Fy=XWk-8ukL+uV_GnHcs2NI%M=^CF{~A~f)yx}4KO z&h$U=Mrtb9psXvGHO~v9rI6kP(r#gp-pHtsni$Y+qr$%ucWq-pTk|we;X;?L<`M?1 zCtEG)?!-T&Ed?XMh8k|?GdPKjORTIBF3WC(;&iw-hD_qanu8%WNy=lI%5}ZCm ztC>;YJ7)kfFT^~<7yr=m{+XwDd=9dL;;RmgjYIq%h~{9Q#^?|_pbXVpd%f&Xl|ve>|@Sg&BlY^Ul}Lt zHFmJP-%R#BtR^xy(wu~IXn?JIORAs=SD8&-=`#IP>e^>5=iguuty?*intmkfL%*^i zpRVp7;GO?M$HhK~%h%)mNrFq_M2^ZvZ9c&$(cf5r?I`DT7LLg=9aT`&ZzSLB!kJPp zRnL|wn^KpJso)F_;~~fj&Bd7~Ef;T?^|mSM(qdnu3t`tu%)B2d9P9jEa5d67IVR)@ zP5Ky#I}1N%8L(aWBJ;iVXxw|1vUPg$+wWVTeg0T<&b z%RE|EH7Od&jAwS{%vY6{Qg6#}9Kh}1xjrnTl2ejkoql~CFCS%Idcy9f4t8|LP-RD+ z?g5rh?*ra?TD9=V7+JoH>fdCxIL^kV3*)B;>tL?mBJVF~%LOj`B?@kBduTqNUtcYg zqJhHy%)N5IGSb70ao{;IizrYYc;?;~$jBKMeB>IdX^!F=diZ$IaMq=Iq_(O4ASQ0& ze>Eu9rfckSr$qrkf%Xt3hME(W=vW*~kRo~;13g=jbA;UWcsGP-!#>R+W+C!0RQA&5iy$WT~RJfv7OH(e6bl6WH z?G{c|cjcz~$943Wg{>T1*?M?9KXmY|csxBmw~gr?aX9Va#DMt$Uvi$~Tb|inTAo#} z*OmWW-#WH(SUb7&sMXUc6D{gC?9H~{w9Hs?*j!#d<9ll~{gRY@JnP|fe)g%ku2s=; z9>q}GzfDTe>>bfu`nC{$Z))rGhZ99zo`T>0rc=%pj%sMEWRQ<~7AcS`Zl*XMxD zK@t$UU2M#}4x;s^#}`Epx(U;*Q_#x$o$%m771vd^| zpF=)Gg;l*kHf5a>$3aNF(kN^Pn_SS&PQ#+?S?~5lJwpxTl@4-y-u{%UuW&ML-$#DW z=>F`z&exTDr9N|bYu!;(mK8jGu{Y~rcV=T}bsr9xmD9=<*ahT&rw^s=?kD!sN*St6 z{N(zV-u19v` zPi&s*Ei35)y7hh;$vze3f?6YgTI}uIi2RTfndeZrCQ@p7;JGuEbgT6_+L<*=T>36j zTDkfSCK-UcD)1eZhy9ZE!qaigdkTebx@Yz^Ij6t8 z-}9=n40R*(fe>)Aukm7Fax4FZE{n0O``Z;BYM7p?Q%BieOR}=Vil&19&o&PC>?u1QCL-r@-@wF2cS!pzw=TiLb zx+!xig;}ybfJbi_uJZ|Tf^(P|UXF?+j*cxNIwjRlwR9q!ISq3H(*%pj2TL?Gx@yd{ zDpz~Bdh&=p)rn%F)lM3V{&r{4E7r^u&uC?W_uW~}ZVOB`r*Hi#^UbAoJl+*vV<)aq zW|i3!YAX1|>C(%#LpPx9idK8t*uvv;Ax2)p#NEmL?>$j=4a4;IZ1O<#xHEnJ1*~;u zaVGPask*h<^2FpDSOfE!v(~iMKbyqy;xZf;ycn+`uc0=Cf@)dn>5bXL`PGy*`rUlP zbOV)C2WDM+Gfxs0-YTZa9$z2)9Iwmy%e4=#$%~o(nScQd$4OsKf8Yp;-C1KIgp1jT zuG5q21y4wV6NfPKRifnEllSyvR+X+ixMyJ92n6TD%@J_l-x_}5D}0kQ0+Z9;h(f-g zWj9Qllf3c=u=j7Uar|RN3VX!-F&4L&xd$8p6E;0DGy7t`u{n_?1h6j#I%&RPua*?aoD7X+L`_<&#!A+8+8FnOe7(pIR&6`!Lg9%_1Ck521b<~K zu|-prgis-ft6}ub0Zs$aC^y*t0S7Q;7;9_Jp={9Uz2nb=HE9Kw6Rgr1O+!7ys}8{p zIx7%o&ntZNc!?oZbI%Q9d?>Oge0d~9J%o?+5tY`7t;q@ zX>20uhG-X+!36*gaNi8DfE1%!xm>T@fg7DnX&kQ_ATrhQ+mxXOdTn8|&YDCtE$NA9 z-VD`N{SW*cH1sPi@DYa)8~l=s)yYn?Dc3m2tnKQ{(XmKK7d@_swrvxKn(MkYf3{yP zbY*DZ?--iJt5$4T7hT(#>o6~d7zp33SpxW$&dZBSXTy0H<<@d4)q-4E~>3h=1R)-ss2N68QzCaQm$VnQrTs8W)$R!&Tqst=XWq5sBHdmb7N-CLr? zWoI|Ju|RVzy@`jj5L&aUfyFJ6$FY&eHT^6{>*3?}lPt>>>Wb#33kkbRX$`?ro6AdU zPc|zJydyU9_iHAf1V?Y{nZ3P2h1`L%Yl$}au@MGmVn#wQ_29!VmR9Aw_xq?1+eyBR zY#PjwGn7mrcgDoOGB{@MR6XkfPcbhUVkIJXNBMA#NT%dfL#|J$vr31wIQy_ zT@L^LZW-A$j|1!Ua#W{V>qDQy;jk)@ah)E{eTPj-UFNo#-rG;|91mQ##pkbr8;R)< zOb>lx)P7=C_ND`;UpkBkkS@<%#sWt#yfRmUEB(VRl5C5_Hs^&m*|X5E!|pY~-ub#( za8GVT6nLt*#q}|Sabx=o=KF|Uw#Ty&vICmwd_Li9Et8GGHPle~W#6+WvXHXVJnt(} zRvv)7LpFU6ljST*MKgh<7L9K~2kjWIlUQtk^NLkvL{GO*NH4}jCk940;ywI<9;(H& zWJ18UPiWUi)DF%uZ;o3+-q5b_e?zE`Aos5}?@>ijx`eBP^StXOuf`mA&m$WiJ4SnSX@2`hp+smr~;f~6WW+%CYx zW^plDF*qgaGq0ldO*m>C;XQ`#g>%E$>ChbslGSD_}70Dy}_&O zEv9~&_tcO;KpOwu=Ag8Os*06`y_LPi|7zX;zh{23rvJ;BX(tsNG1PB6$Tk^HTW`BL z<-v7zSx7{*CTUAnacdM|YTe@bIipw;9QeeJ2YVB`zQk9wQ?e(Kn z!*IIwSh_n{k@5#`TLsfmA0Qn&t)CK&VoyHc4 z_(3hO_D~njnS6*onPaxA7M%WFRR7ND5F*|}<8*1Y*vGTqZLR{v#?eGXaxcL7`*hek z_#9w6+pHn1JT-gB{9!|X zRG6DSA-%deCL6%&G9ibtVsL&2-2rOD%@?c%a~kj7%|iaNaawAzVL>?j+;`3zaH66s zZV}lmq3(bA{UqjfRq^-58jVS^h1V;cakJUtHmf<>zlwp*#Tjcz>8QK)=uNnfdZ4T} z)fl|`kaLrUU3MpJ;P&JMH?2H~giz;!AZ>(84|3p#(ahq_$7P$ zZXBp0e4ictPnjEk;f5%TIffGnX*#6&?^6Or_&;WSZ<@br=Car+oW>aP1PdVkm_5vm zaH8}{i}xV9R$zTjjkIF+Jz9zf@cc$MZg}H~ySciaHGh0AzsH%zC+cEiLGQxM;uAgI zg>>1PgP6ZlH1uMwbAoX4MZm*3+|iTWgSgw3*c>!Rl*|1f5$LxxWr$-KUExfor4x)L8nkT>{<0*!?^-H2v{3v1k z^0F?exILQ`kmTw=DJhgq?a=DLMg%62P~?EW9m`Y1&zC1k>M*)g_MDZW z_2*7HC$Y?Ws%|6-7iM}YdRxo}sR(bC@W-IC>$=V6)f_WR$iOUsg|*F1Q+Ml3p^5DF zo?-xbsD;EwGHh*rQo+Qfnc4v~hM*0^?+QQl`~gd&c;2uLm^Wour$%YZq`6r5&{l<( zaKBWZ+`VH?Bz!7Ij+6CvEkjI6(pJbl!dR^s)-IHRgirzZ1KaASUHJQuZLpc*9zv?XLUCLo?< zb~Cr2Y>E&K>kFdLL8dwgZaP*oI;YU%X#2Y=4c)`1>~_m|^4!0yOQV&|^iP4zhu!md zp_ojW?06b%Y|3|{YWQWdMXbrq3b-OVbo5w-3m4c75f`z54%q7Vl=5ucvzoh3g7X?d zF_!fC=-nT<@Iz2}d#>DCcXcygO=JqGGKKcFHmxiqzH_RD%|`@1_3}N(yu_g0IP(PF zbNNv#GUeRucLm9m;W}#@pV^;Sl4ieeMa>80jpab2_-^{!!FiG`L2U0VDHhodr9@fF zu;#vIOQo=j2aFlcRS&=_!e)M#E_;7C0#Zm&7O-GT00>}PXq|NI;~fP5AH}DYB9x3K z{c9gkgdXcO!bp~fV=DZ9P9SejFpRMN-Sb9kr&dHM)FYrdO#Ufq*ncMOPf;|QD5-jj zW7bDZq^9JyRR-zKGssR6X^5Yx_Nf|0UJa$0m*+B_tveJ+XzvCfE=ZOfY|@LyYD|H zP5+aq2j#1J)FeQWVVXDw)=vujiwJ7~lEugvl9*VCZ~_#(A2bmWwAyJ@*U*%iWm@)k zYqOe@m0o3aM^h7hxO$}+a%Iz%w%z+%?v}yM`g7ys<$L9l$FxV!W*du31H2-EK+fw` zOZN45&b`2dM^fkK?PwIxEI^=M2>(#0uTT&el{i@+b(O#p5`x$Vo7+RL_=y4uS|g0O z;1C<&o7S-cE~aP;mIXqVPq-LT2p91qaVdyDmnVpd5M#waJpFOO<{KCO`-`J7_|v{8D6@K{-dXce}L5lO?!yd;2DZ-vvh<;HlZWsCpEw6Y&hCPKc=j8bStuREs`EZm-rflJ5*v^VJ?kJwkBQTh zrDd_E(S;I0jt595T-ES>33*}2419f)_>~ISc}b`Zg+MvqbQiABD?v&5K)(?t%4tJN z7NaCQbEisFUUzDWKW1St8T!BgoHB6+x`y1kMUyb*Pz`vYP>JS%d0LZz%+G?L+Zm%D zP_ux_F7fd_Kj1{+he(7|Ud{M>)^l66C?jW_WL})i#svT6k};2Mg!5LkW;2U6 zcg~tgVuRlBWy!Gs&$`zkgb2VwUW+m_0TH2{ zgYmV?!a-|=vM&V)8FLrX7WW=)oL)8cS3{Z!uNpF=+FQns{1U+{5S<5a5%h=Jg!jakvc4o`E#iA%(SH2=fMzC5i~9bM(aM0)KCBy5~$UcHk7>xNQD z$VpN%k_NEop;Wu%S)fmLr|7{bc%B=3VrRY_Y(V24NpHjK;V>)fQsIk)~tO*D&96Jy!~wh${U#%G`%{@ z3B}~pelU^|LRz5^))iN4u68^?+Ww`&oe6{YvU00XfRW0)wmxwWF#>(g%PF)BeycXV0XYs`Cz~9^Jg2@A+5TBSl8R>^sx!!HxE%j zT$ZoPtB@fEgLWHlp|8(c#Z0dKl`6k9aXMdxbo+f<(w4S$yYEONlB-ZP`=%4R+P8r4 z@Kko#G(>8Thk{e%ONh8r#>YnCZ5A%X$=b$}yL<2wt|`P;m5FkZt5Ayv`I6nrjkr~7 z-t(AQ4F@VVYa0Xa{LxZEPJ+w%)t)yQ<3k~A#axMLkhH;%iV0=^%|Cuays!P2_Hu-} zh|H(_siH-0rX144ADhzBegkXHaTd}|T$InyxB2WgSoxm_#W(I1)lPjxE!E_iFWy&j z>zXS(n?k@NZKC&EUu<@9FkYMnJb#k1-M*Qs^sOE@?s8=&JKNk27J~V3F~+xL#puvv zsLOg25OpNGmnvZE2bO1#dMmi}WT)gIad7ypw%6NRW7wMkH@@b{-VfH+T`7e{d?6Q3 zX?kbk8&ZSqfZczFd}xZfZ>t-z%hHo5H=!TmMD+U{fh9u~=-GyxmQ8p1bqENe;^AUa z(e^=lA(hGFaWSwuqh5bnSaa`AP66r_B1fjIeFqwF>J+fSkCc~~F}~ zoHO2l$c2M5)iGu=Uf)4gp+3GnDLpS$aFLqyjglV`tDBli(t78iOj|y7F2@4r^~ys@%|gy$rzK5h^0~XcmVQw?EIT(uuB;$u z&MVi#thBj|hZp@^c}XO1TN1kBP}X1xK<>$uv{!$nBd{1twPekZ9RBrp%G%k1H9cJ| ze2e{GpPl+YwO!Or`F2?>Ce$^BllbOEe}YQAk5zlg&Gve7Yheyh;y%VUZ3)(P2S#>& zxp{QwNcIf-JN2y`xmer=$(Alc{)0~AN}!Dg6$>JTDCTh9$UQOAU9*>1ui%D$o^DM zZB3bmMhIxKQ4A++AcSCwb@SCh<(7>`ZJ}>yaFBUM7Th>Ip%p2 zc6dBgHx`vNGz@I~Q-~SWSnvxhE*fgdMdxmQ?U3@>ZXPS&IAFvjmwR4Im1+=vvTSAx zm(LUO74UGebdYs!%nYv7^PA*EmVUTA$%8Pf)Oe3jFklwFbtGhJj+B^U+!IyNIUQk1 zCllFsVvlKK#S3d2D3N1qawq7Qx3bIYnewR#HgPBDgM5mp6gOz+e;59k&lAhI+;b|P zAwMZi_idZmxx73#A~<8^vE~T0zI3X3hvjae-o4vliY`TVplt^GAXzsQT7`}Bpr-!nkoe_4_WSlM2Zi8^Lg0@b*Vp>3 zvN)B#XxlQIKRbC>h+Q2#1nOqAO(bKaqgE!-2!brW1a-bQuJ*rT{>T*k5ldUyHd(?m za*pd&@l7`-g!*q29{owreQ5jsSmI)yJ9Md-_OV1EUK|zR=L7?;W;-hq1j|Ccr+fUL z$A(|XB*0!{ADmQcab+&+kJ~V)%tBnJ_IHSRlJ%?0F&kYxJ)J_7`6b;7xoLY^<;~pk z=V>_ps$uA_MA9zNImrhL4G167uQcR|>cTHDvNqNl#LyhXKzm>|u@|B?LHPquAiB4 zg&FEoVGk;0d~bN8fyU8vC55VGSiZ@92~^j8tCAPIuMpfkFImq73V)5hl2y&fn8jOW zkIq6vlp6Y>rNvurkIsT!Zrzyt7h)u~ZESc_HOng-5>0oo<9cy@@(&YK zk?%_tAZ*8+4Shj~@Umkp`1OnM?SqbwZI)x+Lukw8w}J`@g1jUPaGXB-U zWGtIPEN*t6HlvBOA=h*{bNs_Y?^ylk{(Cl~B`Ze-Jm4}V)^8-}US{Mi(1u;ybcxI4 zm)G`}@7bZ+6z*h@N(spkElnLuX&NXiCde$JkhPZ?1WR_9j_hWJ{Ob@a!m|%Iph{X9 zYP#GvBux-USnOC++rJ5n4x!N8^bUV@QAk>Lmjn6(BJ41JFm~UN?6ikH<@rr$q-zZz8^fs;m5sDUDv!+dml>t)k)Q@9 zj7uPR%OJquVo`mE5z9Ux%d*b#t}1@Aj*)*c?T{zYl(m+)({rrGxo46&f6{ez;G`>- z=Tt8S%a>DBt7*!$HI&QC6Qx}lIx@}wnucBJpWvK+U35f}nMs3OMJkP%pu;#m* zp5k(Ihs914%}o{e7M@uHAO4_u$Avk5SxCFKNL%O>LnOlheYic!@RH0@{A=k~HfkfN zN|oqMoWZ<@!z3tey`u!Hpn!W~owr3#mCm$!$_7pW(c-VBLK>yz%o>&H)>jvfvES9R-EAKS8Ef%Z>E;vBjKg--EIO#1dsQ#GuLeJngjw0uwc1<5 zLSIhzfL50_M8YDqb~Eg7!@DxV*qZ1SW)R|B5Hlc-=`@DKXyR_x#?z^;>3}ZpaK*iM z>>hNAXe?0~L1JR08<#X@)-)x0Wy-nd3r5S~MlPFX{U585>xZZr0y7!Rb$em_tF*OT z;Vbm8TR@2sV-vX#H`e%(v#%2z&l@1QfMA5hYPdG@#zpw(!pKtgmFxZ)zD}S}OoF$v z%02Ix6WN5kqK_r6!rgAl8qF=ftIVRF^gT^FBgHh5PqKAU;Yide+tBc%dQvwzF;OD{ zNP}(8>D(mtB8^(93C>~ucy%q)R$+xQXcMN~iXH{IJMS~62OlZQ>Aw{~3T0j}g6_0dH^L0y~n4?b8E23^aQ2#qQ`xfQDbeni*B6ER?G?GVKGLD}O7x_}5uMYh<4}(orz#EVjUg+dw6OqQpu; zdLg%;Y@bJD;ReboGgf#>nC&>jMthd7f6JW;05vL-y%;;%#SAJAxCwpRK8A3 zpbvd-l=7`!LC|A)%<;&Ld+a$z_cd@j#SvU%_XP9-19dAvDn5V@Tw{8Ae|)Xgnz&|G zZwf$D$=pi(Jb4JMw{#@rAzhOUqw=YkNu5Nf?fV8*{$8f)`!$)bT|EmrhfOBY7Gb?2 zuhJxduhZlZU$ITP)Gb!wcj8&$zICYj9$RjmRaUaDA=OlyU~P~WYOPbJcIEl2`hf7d zqEYjFkUu3gh^)v*LmQf}-l%#;kV&G-C)U+DTKe~ogXnenxswQ~O|-oKTi1JScU}fN zO@F=>R9FVPzgbsg!K65M0QAlY#N8CTV2p>ZXj7tNTS45*5L?`8X-AUx?KI z+3EgF@9sba`oq-x(G2DPyFJJM-Q4rPRKx#^PgX|-R}A&byT!;5(|&?1-EuR2sSd|b zHJlvS@pM$ELm-XhhlWq%9V@MdG`>$kKoD5X87fI66IwOAdv5d zO6qbmTz+p4ZO_jq20cGuT2O)vNkXgNIzI#PA{&0UlB=i*eK%Asm>A zerrJy;H=n;bgX@EX>ZD>G%b_85$c%S@AVBM2ol(HLF&Kk(AN`;)75kFMAgp1wtt<0 zyCZscQ_6JQk$Rr4B9NTXV6DOsL-Id;B$5R0PUq6PaK!s>>pi0b2&nfMNmV0=)HY1Y zLg-yt(hDj^u@u@8UDu)m@k6%%bsf!%7!EsK+<30Ds{4j=& zibHgyH8^-RrX^C?&dQ?t-MSdN$QSGnImxGY#q_4qFx%hc#gpky)AgIEHMfKr2eB?*yP4#ld$y)ase7$2YN zD0o;AQ(7m6=0G=7QY+!Rm>bK6<>*X|;J8f1K^6sZ(bj1=$n6l^@e50qfrRV;C$h+r;w3}by@dzh`MohnG>U|U zz#>75DX9}P*-8x>!*{R;+BkDYnmG~I?;mEH!0ebGVjC0puz`2VOMlz4MWg5V)v={@ zjxvl>l??nVPuR+bkF1%TAk2OO0kNjJZl90qprZP>j6%5P?mG<`tPS}sl)qg=l+o%Q zlfoo-ea$eOYz2s*5)zTMV70rLI~9E=t>*5OST>J%k9m3&z1(Eiyt+e=mSa6>e3){^R~i*cE8{>7gXQNzT$cdwU}_U7u~ftRHU9MS zFy{*I8|iHi?Ci{NI0ASng`(gy0)pwk=$t<~IQ491uKnA&;bKKKD9|beAGf3IIhPAa zl~HukeW8QDfpR~ZM7?dB>o0+lU8K`YCQ$`zkq0%a(bzi^m@_vuZ0ed5cx$9 z1pZGKqUYMsgzC>A1M80rDf{0oO8=V>Li!)aKLyED#KH8x4B(JL<-;gS0w^&;*VI(j z{0gDBwln_C)SY& z)Taw!WBt-X`DBD@us0n0Lne&Ii{9N>3@zM2RCVm~I@pjaO6(fah<=P=zhz&maQ>)A zrCu70=0x#wQo6NoE8MPI$soH_Y60o8MDR?I&^M{?g5DARl}%KC?!(W3#r*5%%0ZZ0JY_bBGJ*a z`Vf`my0r>>xvSCjw)VL^fX{jXlYrC;?Lr65t@GMM#o;$lwpXELD=AIjUCG@Q!4@T9kA@IY~AQ zNwfTRH*;GZf*`FYKO}jd=45Z4#RkI<-34BID2!JRNd?8+KAyFKqBOpqd;1_dtLszh zQ!<9P8;F3%WbhagF_f32XLBCNfFVRJ{KFE^UB?fEcyF)+FrCPIHr`X@fLAJ})YuOU zteD6Mk5#|gcpS}vZGKc|2xK2eIDzLqxL9=OvSml{4(PvnLv0v%#uA2%j!57sjDl%S zzsa4lYiIW`Okn6qOu##ktB1^}f&UaB4+EZueA6$LS8*hNyzL}bxG~dzH z(?BvnUGc0l!E(>Sy@jD(A#dQcV#!QQ^<7}s z=K=qpyZ4xBTgDa&2&fnD|A$BMKRzGi%v_C3ja-fX4>@y6Gb%u33GX|X-A>v&5V=4b z36e}Qu~f89xBxQr0lm;_o!ko8ZQssW2gEDEXW)-*Yg<}-*uRJcxo5>^V;uV$!L@83 zhv_Z?`*)M4wd-sjpDcDO%98z;%|Ko?;8S$b47j3$an>>Ir>H4Z6LVD`M65nBt6BBN&ag#V%9KryGR+VdcEHHMyyNe0+{3EFrQgk4R)H%1~DeXhbxo(g$a{oMn|mOk`5}bY>5Y zHOI-i&cuS#kY$V6x%e`bLly2z(Nl&>bd+LjViEb3T8SivgK9a+kE|vzyzZW4FSC7h zU8ThZiQ3um3YBBXb`*=YL?Xyk)iNQ;nx`<*L(~P@y#5ZW5#F}@=C()dpqQ#GvDs

{>lCe(XfXdiu{K8D?_9Y9HuwCkf*^z0M-&Asx%GRqNu_T0`e3O2)o6%K4Y`QQojQ(ngXO4b(OVyE(pQn4i&jmB8z)X z>@=Nnm#rDXwm4Q`QT=g`mckrix+^<+h)l<6F!63}^zK*77HNs-@}~P0lR$LvZ zOV}hTl_n;jt}t~>ff0EIVccS@#js0O6?^JP*}bID0zgDOn1h;PGE9C^| zveO0wo}ra@Xqi>7p1Y$I6?|#@aU2kiq6J|*d=fDn&j3-lh(hZ@5A_M|Qc%tqoYa`yv^Wb}FR#k@8erM>0z`s$N1 zNtkcVKillYHf1HK7@$)y@>uB~y~-u3oCDw7z{>6PGQg}kDyAdfU$4NU|#Fg5360rUxO72t^guMm%7OMN|HaIP&J*yjT#FD1*{4BRV0PO!l5KQ zK5=Z2%92m+g?(V7ARSkBv_{l1K-4|tU3V@JAj6LvOR-OXd^ZazkSX6L9`tv%&v3G# zXyW2Lc(SiWM8S&{{b;aXtpWIQGP$s0!aPHmNa!Mr zO32Fjr%_E^T;qg~?fp{n=ZqP+h#d2CmW>TH6}GU07ll$4C8rVY^Q2s*>F6}w1PiS` zb~mui&#U5cjrY_mm3nS}Y73g%w(|SPG5+9#=#GnW@1)*?cp(z;33(?b?($rYmXm1Z z()oH?<{`KaA;6}#xnCYnK>r9g3NCZ^O5CC6a>Pv|>kPktU?1A4k@f^W$+|%aHQBS& zjV06Fvo!9F%tEtvVag%Vmo6Ty!+rjD-|>=%w6oVI$vKFUQZ{g7$Y3xnPX}#?aP~#D z@)-(X*qe}h;Tj0!JQAd23iAxa+AAbwZAv&baGvW)yy2a0+2w%E^$OJzLqop4=Df~A z&K+n&&$j6&z^Olp9`Xrd zpoK2<;qRll@j!ECbwBcdIM83AUL)h7y~T(nEMQ|WbtukeE=T^zxD3bX$Q$4by0}d- zM{MqO?2jC~W-8mt$kIGg1SnP?xS#*~i(Aq?V`H`$^R9@{+T8vHfO*JSX((4Kf2=}! zD?ZECVY8!~6Ng*lT5H@DaA{qz$i^r5lYVyal~LliWJc{KI(JLRv|WLVPPcXSd8NX> z3VCUE2Hz!m>AUFD%_5Yu=sQ=TBAO_cbhNG(bdyf_dNrzbi?XGh8FUk;r(YH)v+Hn) z{hgi=!2rhJCu(8|dLn7E1Kif20&ZDiricLyEC^)-b#^gk$)e)f@=ygWvxdn2TPt7j z-c`WNzRSZ$=dLNvNq&B=Nug(ate33DyIr>wuQS+~_X`g9piAkK24p60X8E>5f%OTs z9(Z0IuCbfADzyQh%<&>r4*NQn40fIlbce*)73o?AamNU{$@6_w{X6B_C*@i-ZNGh{ zN$D^}cpT2&MfTjPmGwW{2L)m~+RJ5UaEZ!4zcKg1QDQ;Wb{RVtZ7iJUEcR}-Jber0 zF9st?D)U1Ag^0ZtrZJ8J3LKESJ)M-WJERWi=Ud;s*^rMk09Cd7HV?Q(<&SRb->EMj z@ZB;ewMrFT<~2350seO;_n&U}pBBgO46@?}2Q4pMoL&>WuSITm7~HQNrx>u`y&Eqa z>tFvVYa-_GkN++w5D?Su|Bvsu|DrYYKO@urgRqLWw8Vch-PxID`Wq4QPV*P&s5Bt} z2r7sO6fzV@3P^~RKM4XfsWTlzaT9~uvbqPxdda$a-I#7UhitK=dB0mpr>SX4yJ@|B zQN7yjK;UHB@BY|sO&?S{jl<<+yX~20hwFLM<$5!N_fc*{1W2*aAQ2RVmEshflMtB5 zEZ8E6qGxQOo<3k~45#z)5)!HbTL*i?g2XaIizcxbEJ9wAnGg#W@K4;JJHVu}rFzRF zvSldm+Tpp$YuW2Qi{o9vZoKxnsme|_&43&MGUB51GVnenBPC~Bd*RB;hGFcyGrl6= z_Bhil#e9fNYL)<;lW6F7V0>i!&cHj;Ca81y$hE-K%JS^t<9phBm))24%$S@$pf5u! zMabWJeFIx(5*-33et4>6ZmOiZ8V#*FUC=|;V0dtN$uLoU~RQK zclzTpH`QIBKYDVsouqaUh;j2b5-cGf^qaOpbxX*4yk_eS(XKG+MNpXPGFSQO(1HEX2d^|>1bwH@l#;^RCM=jp1;J{IH}QGM@_uR ziDbitg;5h!#x(Dhi2?(%6%Bh;DMcmio>-ez-+A|qJ1RTdrz{!NQUK!gD*zVwB)}L@;b~KS^Pb6D?|n_~fTAVg_Bwwz zzdqlVa^$vjRC14)Ivm5>2zL(Duxm*%$!-Xb8_d{jTauRi)a3gF zZ^&(S4n*JlDN4y=h@YI~@aVIl;hD+qJ(lEKD*_)e_ih_sp)s zhb$G-lCw_oN2;#(cZg!(?nCbO_VJ#OnYcNIo4U^@XuY_Un*H{P4UJT&Nx?i+6x^R6 zGDxr-^?KW)7CV>Mv+cJS*S6)2P3cB>3fW3!apoz5c@}ozBE>OT4=0|A(}53eGfY zyL6}HAWKUJV`4Oz{_t=)Qd#Yzs|( z8FCULimkwc-{Cp{pXTNBU(S*=GAm?TqEAU* zW&E9RhfJEsch0M2kcmY5gRy#{jlSuw&L(7MVb~}A=x03_9B5YSFpE?OYvf%P)w@rV zT%az@k! zU**~d1NQA}>`(6|#WM(R56pXL>#BChi9PY&8ju0|h^ur1E!mS^j|H@aygD{hNlVzn zY>i0a@R8zgXV{A=yg;=);DBwx@)cva1+|WEUa2JhZO@!cAD5Tvet_4obo>2^B0V_^ zSQ~F5ZmoH4cCTb*&7IQRfZ}7@qfN08Op}%h8vd71yzr0%U;)1};d9FctakvA;R;VC zL%fs-VhQ998ok@tAfE)oke)DZpxxmKN*6bREH%#WS<)xT`mG>HwzU@`OHP#2rrJtw z%(Z?&C+sV{BqRCS^ci)Lvyo5GELmJ+di&NQ;ld%uNiWyf-DjK9&i@M|gK>w-AuY=Z z4b6zIuC_UZ>{{9l+dwhd7Fdaw9OT|7H^yE>AFaRnJ=>%!ytWEV#d~Ke+bckR=@V}9 z1hSxr(8!d%o(=@vHrZv^S9#+VjIe-?+4V(YH9e3|yH`#$20DaeF=LDvxgWcA@f~ch znzfiEa{G9Ws2(R7z$L($@yNKjG^qvF1#^x6N5M0_v%R7I2$@&w^tKjGWhPN9&hcPT zhOrC!nq%J%>;q?~)RyjIcWpjLT*4mJ%Le2wx_#Vvz?7^@|G>+A>OI{+o68QW9hL?t z-IJ$fS2g22e|=1Drush%t`Ny$6IEdy!JI*XH-@r!jKUcCa&JTb8g}qZMX1L4h&euW z3zNd$Y-=PW80i6Hkmrq&k`i+ui~!!=YckDwFg0kkJ}WRf`UPLGC$l1yZn{UZMJX@>6B;;HTBwluuluGJRvS@t97W&D5!Ch8 zyOYYq1Y_(-TQXQCd-fQ9c1qE0>wkFKjDrhJtd@c zu?$6d!LE3V!Ss|FO{x-*yn}tW>_Gh*cDkZzS?lXO3afyLHSH4v)J!YZffakF=t0zj z#s|l{wzROstTekl<19fQ+Hh&e;hDg#z}EI=pGFBSOVi-t;sNg|$q>+mpufz(QTChz zFKOLHHQQIiwH$x$`)NDorGcX~lK!Y~kI_m{QXlqL1)BLrtwl@;sG~o7+fhL7o?1v2 z`^Qk$9!{X$_h}4|lVoX6jGI^+FLTGN*e^y2;zDHRFriqs&pGy(f$laYB#z$lRI;~c zB#t^=VX7Xov~BgFv>_VschXsNx;Y;T`QysZPSr5lv*60{3RI&{ZEMfNbGG5JE2cmm z=#j{CQac<#>hP5%GQIIP#a;7s?`%?f8GPNPC~10^HmA*&P6Dqc+QUQ-xg&aJxiNoNstk!$! z#;(=Iu6}vh(fE)Uat8?$+V&}Btr_bx)pAW;V~Hd0wY0FXdTp>~j!Ye2Fx8>RiHx!4 znlH1mdZE2yY8jh%GOM#MVbk#{PQ@SZx>$>m8E|dRiw2LzpmRmiiQn9?J256X^tG+` zG2KXm>}yFG8JZf`Au)vC>6l@;!{$f{>~Q8x1cN>Xc<|=nsRQEKQd^omjJx84PXb1o ztr>2(+z|q!$P32{$PUn;vwTb79gTfNgU(u1X-) zz%`aTj;>sRwW0z@1a5H|k{^F!rfqtFb||w9;*IM^Inp)#jTtsS4o)iiu{2v6 z2BsUw?TkNTQHn>l{}daf+kp=C_BOLY|b}}i%`n5&L>>~m1u?RRP zJRf4?eFFx$anhly!zU?glvvCcst*8z+hisdV=VtXY2#F8JPi7 z9cux~!hXRHFkdr$sju-84Kgpn-Y9<8Lwx8jm|qNz45Zq1=Rb+V;v*N7d-y-a#VjmT zsmimJ)V1aLKy6gARazE1pOihedsuh3GM%$SV>NeX*lZueeXZ^?RzEAg>@I(m<1Wimz9{AqfVk}x{Z!*7u)Zq$Z*Qa!@54jN?i1$+ zL+5v_PKVN|Z3Jr}#IiG7&={Pi5hsM~BY&d%`2}zAT8wHRwo2G*>q)??IzbMKrJ|d+ z(>Cy;S-bVm5Vr{y&Cd~s;$v@4hNUa`1ff%I$udm&>)G=&mA=1IS}VBNpGt&y!hT`8 zhxARFSq+;<+KO-vnE3Q4G0cQPUZC%KGQ`}P;BRf7ymUB`$YNk>gu)mSPR2#p&l+iow`@nnsDJgS0EaQ!oe@;jU!HJj7R@ z?@OegDPtZoOrJOQik!rd0@N#07uL@c7w0EEKW&O1!pDZrVJci8Pr}p-RspyZ8XL}z zNjb&gi1FNLB}0_f!dN4g{|Uv4y`0uv9r6Hh)wA$rog+DgvWEI^{PmAaWP)R?>-sP3 ziaM)D+qI`fC+091wgvJ#HW-R_vL&k@mc24m-8V2fs%g(JFR;!^4s^ZP9LWdCX;a=m ztb9xs!2a1;PoIwGU~_pf)7)g*MH)Mof(3Wkqi6SohR`=O-+v(NKd$TbMiRQ*6jR>Q z)R8|=fQCn=fL)(46UFKdwJb`ZU}IJ1H}IP&g@CPYp40DI8Bw`E*8M}hT1jT-LFGt) zq9=xE{F^v*ylu%X)1_0W+puQRoE=mQnaz^$l6~-}2Ka5PU#eTIkT&z0Lv-`_;o*Bg z7PEOhDm2iO!b-XA5HE#>u2xqBr?)<&Dwn6szxPb&-Uo8J;mFx}W5yBs=yZPQSfo1QC zm<=gd2HEpmtZ@}zh@%QM{gyZU1e?fuhA+r_6jU&Sz(0nTyv(TD5;~DJ7xfMayg$sq zGz7ox;PL0*(EK3s(1qzPQTE(up$z$K!7 z0RjtD>KAMK?yXuR=U6DP{Revma^J|OeRWbz2y+}Wc<;G)@n))KvPKJLWisF^VRbnA z2Y4WZ#0-y9Z)XcLjj0y0(nxie24<$jbu@%99i^O;Hd%eKttQ0u!}?|RDR8xH`H5f^ zp~%^3U7itsFi>zbyYeqON3RUh#W7Zg&R@<1m820na$!g_*x9e}ncO|9?tk2Z`NOAs zg=q#Hu0Qu&VXw~=w7irJx83oa0>f0BFbnC3hCgf!*rj|B%*qA(`6PpaseecbrIz9E zqs4>cb3(x$&&c$cH)4w11k{w!=NjtUH{39z`NeOa3VN_4;T3rlSgmRQRc@C-7;Sb< z_sCeXGWSleVn<&gJ4N^5t#yn@t)44hddhiOWU|!}MEwGPnx~+dR4b7^-!|Wz&US97 zG;yvJJ18RB{|x1YVeP<1IEXZ!^9k3>f1^79t5dKsNyyv+)9^a@r?vZ!fx=EmNZdTp zD<2*;*i@u`?P`q~SOZf`8Qz2=qH@aSjyZR0Z~SzF&lp)o0b#^1)zZ#BGV{$wLmwe5(=O1zQ>zh-gy+ZL}a#YNG8TeQt;=c(0>Yl zP(5H{RBOUuWHTe?9&Ehhs8|X9qV&iXH2kq(a`&<);|?AP+^%rs97rlVG7OEuSd8>^ zm}QQkDBMNrA~Di5c#e!GngozHEspURX$m|?Dav8nP+^Khj_V|o6Hj6wA>(gId18bV zjU*bD)x!}j&>F;@-wRGUw}8bdh+E3(Zmu0zRH*(njJ+ZSHvc!6>fU)S7bAMF@tHQm zV2X_DS~#_2n?!LciosYXfq?ByFxIDE-1RS2L7Y{6ljq{>jL^tkNohPSEL2zNq8CGH zJTz5IY#!XIW#@QBcStgOb+TTO+MtXq3;o)Rr(>aTn!SLBW-LvUm=9^Y^^YbTMaBCc zX_cdY3AW+FKECcrj3r39nrjxckL?2c?HEeX?)Toin7zXaNylY_$7Pi|yjhcJl05fW zcJG<;I_VnE`>0cZP>5`9mTB^|`Dw?cs0Eew)7W|@sK^dl#_9{gkbVuh)!dm$a(pSx z&FL7F=S3^IT{&YR&AQo_4kE6{)cy*0`!EsFe&itov8z^^PRpiBHTr{X*l9aO&>qBN zF?LFGuBYsI|qWNW^n8S*}J6s{P9TKQDibK&Byc{$!&!Chn4XfSW&_yg_geyjG zFXfS>f;_(KyFpzHrIN=oW{!DCgMIm?*me`?^o{L6gdS0_cqMbd=R^2z@d`LCnK{Zi zs1C>jm<#qNOXwep#6lY>&WHC)qfJ}Y@c5ChJF^jKj4$ub_o6od^=rV#sfp3B)S{QS zm;$|UOfxiV5T{K%~i(`b+%e;_NF1eYk4i=`6`dPOpUF^B<6i#6ds3gh!m)*A1%XRSTa)7ug2~Tbs`=>bE_Sd; zZAz|IQ!!K5S6f8JMuxM*%u`eA0uyUNElD+%hPrx&nsQ1qSBOfNB5JJla&(_ zHVNwusmk%@$wxyX8Wu7dXI*#HhUP#A-M37}-AumX;nZ4+DoR>96CfGSG_@7#EnVE? z4WMMJ)bNf{;@#O>7Idj7I&>`yDUsHg=S}+IEu1vyDt0L0CwPqA>2#8c^&OAMa~bDU z)c>mAUOo#seS!05t}QHM6*o0GKvq4b7}j!kf^rQ1(jhyC8xls1o^!YSR#>+Gp&^7x z!z478ZI?=cf^x(v@OQ6E7Cq0gt)r{G2zqL%4`x5K&L!x$714jXuICO+ik&9bQtNTn zGAj>8Ayg!VQdJx$hX+--xAf z!D&n6c&3#0&p{1KQEY5nacjUi*5_Q?FgKNFP>DFTH<1RDE*mj)mvpfT_7oD;92Uu) zb+>`!hY-8~s`PWUi*jRT`& z@UznSLPvLZ8B-kXX9V92fl?U#&j1>&$^4~nhjT}v%rcXXCMtv(<-5m%h>oSU${rjO4tl=)3H9zAx+F1>cxcl}K}&3L~UvIVkjw zQM|g>E&Y=9N^&ZCMo>mUZRn#gSd9Qfm&+c`#AXSByE12CI_m2BD+#@(q5{eX#X3w_ zJ8D3RX908RT@e}}mH8YdKw9a(-m1yl>K~=FRa@qxUu=GH#43dgUg;HEld_F`B4Bi|qkua$Xd)whRix4yZA_BT+lRBX{&_)YiF zi?5Y=M1xxIRJj^pdOUyf8iAJE+x(K~*a~nF8=8VI&@)rc2AIx|K$dB1>c!V~e6bgW zG~F@vzedlX-S3$!e+Ix{Ts=^?m=&mC)3?V{r~GFQrt0DCtTMEou2jQ}hmEx=gF zn~=9enNRkSZK!w1DoJvGiC^eL=osc;NngmDT-WJL2tFnXPTfpa8E?X-9p)Cu%g=|s zR22Q-`rs4!wnqvtnx3rb))s8Gza4*>Gt>&lD!g}`m64rg2mZR=842O|IWHjGfUqc= zx`tyD{(8dIkt5kGyw{QI6#}oq^;l(TNmY3sa(W$DA-sLOeP&g4l{C7L_E%^@7`--Q z4n9)TFq*1}sk%UVzXI=?xHx&gNnj)dDij=^;CY5oCr6}T(yGmlcJ2TG8T|m~>e`c_ zv;^b8=Jo{n)-075c;D??DQQiF&eT8(aGSy$Qpmxw3GZj1#16K<_)XDnlrDJaUp{L> zI03jVX$p6gon{-tvWA65_8$HT`V`xUG2UmePy4F@J{q!x$)na!oJZoKVa;15X#Fru}9ae2y!3#zO=1Bx$mt z*vTlOJFzTBKV&x~McWN)VB&n$VdS8?tgzyvjt|G?(vTm$UxEqmJ4fb<8-_EgnWN~w z%DCea%Bm^lb`}jm)sa_HX-@9xwY5O8rI?r>y(HTHfEv8<0$?}gs@|F@4`tQH+F$sD zKyzM~)tjp2-1lHC+!!lk#n^C;76d9RC?4J<Aow~4AlGY2k5Vs$fp;se6UUL|$xrJkEqe;}4nmbh451Soq4$)=u1FC zzph%&&*3mXQT?GK4d9X2&atUiqC`16hQKOkP?X7laSc^js~AVQG1h_3o-~yNN_RPw ztte!0Vndk8lUd*xu3?t|pTiXPEX^t88HW3~M!1Ze`i8_;Cd#9?!Co53TM-2us@drk z=dfcDRrkadPQc3^ic6eYRh*?%M-PpZlg(wwTY5N<5_c( zj9mJTMe3R5V;IWg$7RXclpAHtYAujiOVpL@T%(s`(@qyS^q_mXX)Vx_s$kLd5*2se zikHm|BkRXH6{5WNQLgI~@N2S?DUm0=M0E221gtaZRI|(>3*)|0DTk0W8djtnreO`J zSq|k1fl)wIzM{V&&uI0@u}hz}KkNeSzW|Zgz6JYqyP_w%g8NL80l`LGXoFC8tt=u0 zQ}HUn9GV1(ccdC8jQkL*#x#+(nV?)s?NSPDA{y;wR&5qQ`HE;NY7AjB8c0>rGl^yz;-$=M@*F9)CML}FV7MeExs2Qpy1 z8Tp|H2zkyGuYrzS{oNcIhMH6SJ>>XEc9OLTbOGerPq8nH5hlQgO{XQtCZ$#V+?wU+ zw_XC_(s@If?yTG@RnWR7{9M0jqhkBKMBf_K&cEnjXyB;VuH%li6A>|KH@H00#!9K3 zIp8o&rVS0TT7bK!xpii5FF}1R)h64zzk$82tcsAvVoaHXn>OLbg#$~Ava5u1t$fZY z%UM!i4saOLbq#Gw72Eq)2LZgg@ur#qia*_u!u)j+jmV#|+`3SNwP0gnhXk^Gup*41_gx2E$G-FuzVn$0O%Kx>H%JVlwE)O3#;|8+a9Agnr;5ySczx118{pj zUl6&uTMNp2!i>R5O+#CdS4>lOAjzu6g3f#+>-Rpi0^H!)WwhPMHoF=iRE_dK!DP z%fDDA8M`}|$BZ#|c}jE}fH|S3yY-H*08Ha_;X}0sNpl2h>?8=#I4>`{82UN!Ay!|Cy#7HpgfDP7fX@Kg@YCpB^w&Aw zh9g;k8DHE?;3TRziCUqV#H0C$zVgVQw8&rv>=TRJd7x0X%6?!W2t>$jfSOF3h>jcT zH24!dLN)A@QYR6khJNxhpiRN!g>|6+%B@Odf$5jZx`*_9qx8I!^!$BnUqD@e{1mAk zcbKW4Q?c>7DNPEp5e>yiMYX5COuVFDBGR7LM9b zsCv#(Iv~#pi$;@z51VGFArnuc_#aJMO7eeWhDr*tv&bgC#qWUmPe=ZG3+8!SfgctSzM6WA6b2n_v6w?*PpH6O4Jp6fDLAIrs< z%!HD1Cl(Wc1xNZcKRg`}HEu&56or_Sqo$shKA`h4MPy5q*b>~@mLzq6P9K`)p^q4z zmo`+&BCQwNvUOG7swS*cb9@@m^JqV8=eg;3+3Q5(?ZE}xfzH*18-L%sSLxi33R~VY zNZA6`bH&eqy5M)b!#SmY41qLOY`67+>rl-QGb+~FjRKCF0Q_Ey5`$a|B6>bx2U32! z8uKIr0{}6#A7tsOc7Z#sJ3E(0iZE9MyiiE^fs4%Y1vwnhGOlz|Aa{YAM!x4sa{s0p zqT3g~CC{S34Qd?nZIkDQRSPFG2y@4{Lagnxy`}6T)@>XaNT*+ArY;NQc3@eq8AOpU zskyAHLFi3!)I)HSzaXDId?9z=l4(6}OPsi_o0+=fBMUM^5(lx_O0Bz-Vy87G^-BGR z=ay*x9PX8D_)ZbE6IY4sl~BOJ7JST~6b&lA0;bA+9ORZflYbtNOp;JL- z&rP;N%xyOx{AQEk(+hldpo1yR7i2Wln=j}MYc-6vQbmMwTp8fPc_=lpM$D$3WK$;? z36sE0Fq_6LlQ4QQah&Z|!IjR~xXS*kw`hd$tOG9L=YbQ?$8fzCSjzfv%Fr=J^>7N- zNi5^nlDTXNhoLleZ3AgafIGR+uuy&0;pYJmOI!{@zy&&1jp7IkTV4}BZ99A(45_r3 z3&(mhy~YK%0zJiyD?-b5wmwy(LFVY%gpt7{vGqDnUkejhOCB%ACT_jj*}XMOn{l~2 z`%T{O6RjE(AYkn>Z7GqpF2zgvH^A z;pOQV*49XZxQv+4X)@kH6)M~WDfYEZ3!5_HSB456oCQ15<8lO&au$Il-CSiXmOvG6 z^W4R!-BJ{UXj2He$lTCYjxYQFM!K|qu}62bnJ(LM-x^RA#$+{6WReu5s=+&MLAGN@ zI`3(+j3>Ia;XE7t#kGc1*sX)LhTd5W@bwUjXPWjvVt>TRv-&4Dy;hvofn~l6EYk_d za%OItG{|!WZEL=y*L~+bv|!_}cSXXMdahcy0*ZCzYcluR!@g8Y7-V6FLLM|{S+vV< z8|CH#PZ%C#Uc0+n8b%#N)3UuYv}(UFJR*f*&ou1TOQ;zU3UXKekeq%64|+mr%VvMa zGIu=yi}bibPtvrH2NZ!40}fV!8umq5NKG|CY#Y|cEJ)E}n8k?EN(%ilvQ`@D6}`qW z+usK1SsbI473;T+H5E<%OBsq1kO>0bFi6&Yz)lCmUx|}YEpm@T1|G3Nz}KXY2`pK% zLJciwvj_WXG2$81ojtIS8(1y0Y*W9P|0Bjjg9L4)IIuK$Sdh}nv;*LT7&S}Xt+11L z8(n^cTiq`B06~LDm=;29aHp4lipKI?2`+rPU+e&TGWjakVPN-5SoHmspDary`-y0J zH=`*xk@zs>Lc)3@jS zs~j$`UqN)>gsN`8_1Ycic8E?#fNWDk2JJhUU3_nzy7W&O(G(U2^EmuM2=E?NW=-mman6k%ps9~ z2djKZRDR5sb6dGG68pjcXQ%BA+2{$NK4#GApQ7RS1R!`L>?E(2E<76O`CmY94hHO@ zzays$`AMrD-*nvR%u+g)O|YmGJIT|kuw>3ARbc;%D`H`%rUA?*j_m0h*#~0|3L(2) z^}k2CSU_=R1_~|9xtgR42CDF3h=)_K4@&php7X_nsCu=qtjyY>rY`#z2N7mTbtSl*zg$uHPUAZ{uceEBcP%8x|V*IX() z3K)EnrC%`#VDwd+U^mPd{0gZt<@6~=3rqw8v*%Q!%ElZertR2(y6CK7+hFke0`=9k z#LP3TwM%)zX@owJ6#2&C04~^`8t)n0Cyo-Os0Vh?eB3bU@dwJ@I48X5jLoRt!~0R( zzEL-9?}=l%hS&W7UW|lCioF$R{L~oGH|DhBS${_#(xr=G`+QwNQRc}ztWSzNA5mD6 zM`jzSmuMSQl}+l377b+^C10ZS&w!9e1YH_(mr)1X9lX;H} z+yX#$(rxI!dpU<(HWh^RztDnS+`~LGvMTXdHIa>7FyObK6#QX|#lOO2fV7l* zv-6SR$zAv#Rm=T-OMZ{|0t<2;B7|ncR&cCp(zP1GN3;o)SQC zi2Hfb3qOB5HiH{-9&AbDK`$18`(Z=kx z#+Xcnpbh@Q9k2|Ks2VER_Q>nBGJ4VZPT{zU%Rb?MIMaP;@#~v^TglcbWgyi-o8P$* z$k4X%hq}hwRPKSC!~222o`^-5l>_JhM9wpx=BT`U`B9j@Kdb^P>d$+kRXNfLT zl@g&lYCqi$mcJN?O(`t=Xf1lFL!VmR3O;+E;-ARkpYA2z6D8h3eab)Gyox`u3rK$6 z4OXLizIE{w7_-PR1d{#`ONu^|koaAokO)N}vMDfDq2c^2-+Y!27?%k`LCQ{h!F$Jc zOk|M=J%tG$!->(WFj{aKh?~R!ut--yx{#^-0~`|UYR>yrH>4T%c$#lJB@a9d+Ph*$ zAjJUkk8JypC_jHGZvgNxpF!8lP{~b1%79o@>;UqN+7&?UC7fRNOJF$z!VO7K_nmUy z%tjNib1Fs|L`fT!Zk4jJ_ur$KzO{Q!6j z4Ns6^ABsA^B#59j=C(jR!rK}6jvAghHLYl&muZ-fVv4oY6O1mBB>#^KlOV*mnjXRz zA%d?z#5WAW*Jcm#N21+Nk=P-CTZdaHm`^I0Pb`>EF1Yum8sW=A4`D|j_?l?IPav3Y zDK*%S^s5?vhaW=Yiu=<%@uq@X!Nw0(WEs@ma|Pu1~x^D(lj= zzyof+Yc(=njM9@sbEffhI70Ilk7~hXDaj<&dgW zqLTP1cfFZLiY9BDy!SLK#4Ek1H;B#odY46X)^l{jh(I2d)kg*!R*t08gMBCW7^c!x zW?*a#ivl){ndkmguEbQX$W*S(R4!7G$BreEF|V=hh@RpZ>^*ZaGB9pHF~SsG^zg@m z`qV1IJsHA1?%w6eYe7KTGol^L&_@R@!*{0rF$)dnJvd?d3Eaex+5ITey;b-t(vQ4& z=?>(sunmvV;P0U$UZD)X)D3$Q()6UeR1oi_U~%ptZyEJOr)G(cCnH{8d2$nP(9$_? ztAGZGcrKLhszMGmqB<@$UX|o;$1~&_WJ^>_;;KLy-ku9&jb#=RQ2bRpVymq|IM9!D zs^AIf2-qwyjK&N{er}_%p;3TM%sB{)^^aKyDsyy#Abo;a!p}blXfcHlqw)j$q}YQ8 z1M_sW*t7%j;_L|!VvZ0ompnuBe7M*zFl{&Z`@aSP9QM)YGSA?@AQNs~(1YzByg7&P z@-IZ9dW%v0#Atf9qENw~Du&IJsPwCtl7PHG9LhLF)#QU`douFy3RFR-Mvp^oKAiGt5AbB@R5Dpv0>P> z(Dyy_4%JXNK@?u=sG3!E-5yomoI0^pXA!I_Z!bsujxWTC!4GZCTJoMS@}5-ko?0|y zxcL~xOrtLe`lC)Z+Y?%cC88Vida61DNdP#xtaIm91V=lLVesc=XgrRgF};&?7&^+^ z74R!B)#~NXi7=x632~5f=w%KO$1qSsA8$t2WT#Qf7=_HVQ-`B#k<=k}Ovgg%u-3Wr zDUt%B{X>5}yG;uD3W4d0R(6ZbwAPXA3U!oQdV#Fps7`N65jcJ;C-TA^vjr&B5J`F{ zx@c`NAG?(wMi=Db#&IoNt)I0EsAd?i&&Hi-D~PQhHzSVw58Gg&^HwZhAlVJ-_^U}# zME*HTy>MEI?y`6==D`;Crnv10cV~(qnC^{SFd4oCRz>^rJ9|K>Hh7hfCU_NFKkQg* zk9sY5k(J|EW42=$+^$0lt8@>?W3adSS%N7m>R9U~nGm$K!iq;G<0n~YhF046aiCY3 zX(A0^Rh0aqQ+N6bYTMI3&E=xsVWqk1zwx{NF*J}J-U0&GoV#ovliE|o2Xd<>XybiIu{kS4aqtjNjcVmtPG(q zdv8jKtcJjIO}THVGx^3gh`9@0bf3f+V>g7tz5Ft}`!}>*KuBxffR_F~O&sUq5zZfO z0+3g88XbaOF`II&Eu0!)GTO~W>eifuI9ic>CNs}8c}COWY2qb}qF^QoNV9mvnNSRO z*r{Qse8kztXzwVReN?Rhnv_6@bgc3~232#{3`Y$Of_x3xR=hw%rq_DZJ0o87nCiHQ z(v1&|6j18P-zg}=xzW)~ibF^cLlN{K7vi5}kKV8|x$IZdp1`yL!rD+l^&RgD4x(KR zxKa(O2~|-ND;4Msv{%9_w_%>$K&A6(+QLS6&gijB1b9*TAX552zp0y3p_ZLKz3rIT zSBfETAO^nVG`fGo-o^zf<-fRVS~N_L$`!PF43av3ifU-ahPWa!u|yr(nZid^&%_uKv|9kb$5tNn72@9oinMo$-u3SvDqZ5=qa)D3dqM#&etX}=sOCzF z+utuFK<-JuJ|cg8bfDQ5;p_f_gZI|~(Psl%TZI0lwF?!}76RxC_D7iq$k zOQ!XzX{$r3!zJ}-B{2`gRLfT9YBCV|^c>ak`KK|5w$%O&in1|#>owUPpe=%wUs)Xs z4hV5@j65j7b}}5;grcGm)3e}slboDa)66X^YvNTlDJ!KCtod86I!DUt_X3s7jAMtz-VPUKj@fI3y5`qiL(&NlOQu&8AO5}8Bo zEtqQNW>Y1x`~paCcSu#W>vlss;CW-eLUP`Nav5L;DHo(QHY3`kF#CaP2k0GG@57I8 z%o~4h=4)ialual0-XC2HzIKX#sZQ)tzIG~Cg2`wVD}JX^wzW$93w#ZGWYY?@{B6v=-n z7Wi{Hk7i5j^rXIl^87%{}{ZVZhQBa!oUO8s`16O*1*&_;sO4sq=Tig7So% z$}Ejn@%WD-$C>I3yUQ#{a-zl2VOf?0rCCEVlL}n|$D+!NG?iIOhgr-7MYH2^xfg0# z78F&f;&!9(5j7J_;cCSLRI+aI!f0jFIn0{`rB3aFZnAFe0+w=zMzIg&cFDr!!?#7> zdsgDZ;v>^TBO+pcc#Ij|U((br6+Z9;dsdv;BNhs73BK5ZTdW(`Pj60NiPiCFXmA|5 zA|pneR(YP?`POr^p!e_pgMne_cphy2gVbt5`}K?a|CM0#-^Dxs2La>N4`~$TJBG$9 zy360F5Bax&giM?@0w`4QkhY+15PwQN@n%|6zLkXyU5e}Q6_kDKgY06H#UfYtb%|I) zDC?2ErsU@C+u81XZ$WO0ohh0`OYpx98_mrP4=$$b?rW~&?)dM!*pSX&U^gfDnsbx{ z_=PZ+0G-t4O3kLcbf)?E@=4Db6LUVxv{0|Cd=_L}xB}n{Vh|H&LDN&Fsxl?ovlgrA zvl1j1?a39>2Xlv=cE#{xYNw5~h>_vGI$Ke<>qVq|W2KcpmFrjhZLg$yUpL;S%x93e z5Qf04lBWr`@EsTh-=us(Z~@$0@zdx`B?dEDiznGttSWODtYHJ=6;6ybGLwSarWjgn zwCU_d#R;vwnO&VKBb{~823880ixR%FPGkVL6!Ot!=~V-E#0oSGzD0gJHgw$M12=l^ z6@GD{6jW|PBQ)g5;KI(on)y{op%*Ukz+9UXXhdZh>}blQU#FmRJh5vwhxTrZ!W7V?kzZwG(=3*T)||2 zvGP2=79se*x%opspY(Z}9*>KLuV_%T~c2y)Zll8hi$D(N2 z8NnPj)f8Or>~Lf5aIlJ?l&N=wyl-6a$@YZdgYJq02pDp=PM=E^+aq)P%fZ4uiI$fN zkfX-fqmZGOC`{*d?xl;3K@$q(^Lx&*wL*YW;vo}&pb2|h#tnVbG(xi3X^mPxN>++P zsFa@AW|sx8m+A-yF~-V?bvFKqk?jh(qV<}Ft&!vi#LS`uAyxuvYaUG!`vs8fKTzsR??UwC(&I@(xWjI-MjrJ+>~6@157yL?SdR zDU6a_a+FfXW$XA=QSu_x-wc}@H$TR`8O*Nj>IEHOKErrK&;9fCob$-xF7JR^f~u#1y;1i&cdc#Wm{0a(2j1uS=A4*57+TYTvi6boBz*@M zK-YW!oOu}3*+$>nd?>H7K5vbc?6NyjB2w(;*Zf6y?jIfF(@CRxMkPfA776v}R57CS zn8gzn_3VA-3&eMyD|P>9>}?y9kxl1m^0Wy0bdd48OS&u&qtg21fgniey!?Vc*2(q! zn_}A`%w^}Q4OmVi=C2P9 zHlo^_N2r>mR#WdhlBX!sJ!l65F^yG?wx#p3&#xZ?e$eGCbFc8r57Iq9jzA68c`xjb z%gCZ7btUEcT6s|gacI(#xT*pjG2{B5fh73Hcqvg`jM(D8W`<{T`#}aK@;H&vB#je0 ziXIjEhfkv9N0!gn?9SxWMMWbC67{DL?vkqAan-cSw2>$ypK?n#uWWNt8I@U*S+Ye9 z6Y7+S?AeOoL???8`|6&G9Hp{vFNBd{1lSmu5|vGrrZiPW%LFXdB?p$#A_gYJA}Pcw zj6ArLLqMuw?{k6t|Hpv&FL89qaMX4KBBes4Epzrv;7r&2FjiOfa=szPZJzDx~;pPDn zv#t#7;HW$%cEFNtf=1xh?7a8zm&aC_@3ul65sy1{7C=0GnJ5}qbCR>85%=`0^Xkd% z7_<}2HG?YJg*w`%2taS3uJ4R!bvWXW*HP5^WOe+Zd#q1eLVhX&^6IXD3kOAr>wA!w z0S*_Od%=BM?_YRD+ZPg#VR;D?aL`6tH`qTM3h0PjeD>U-((nWOn)oVKOgGiNf517g z4|dSPPc(51Ag13#(IhQ13+!PyhZL|Ud1QIN&CEb&Wbt52b4E)e+<;l3^aC{Ybp&!m zdGpXLqA%DHAs@Df^10kQP~uy@TJ0BzHY2d_#3ROrZ~)-&XZViFQ>yj0WUu@{*~G13 zrmjdE5F)PFg2v&>Ve`h)g@bH` zq~3}szLW69ccs%IJ)*=*)A)&n1%Kg4d5g0Qin%X{kw2^Xv@t)+t(2uu@y3N5RatWI z^wP5H5de3$o88J3z{X|S&2PdD-HW|Io_WLA&4nqk-C%7YQ?-61b3MFf+Y3TVqzztE zR9_$9eg)fn|Nh@8UQ6&nfgM0UV9*~9pVI&93FiMoe<1#!U{Ey+XLDr}TLW8X3FH4l zLR2eG+9EL^^T=kcI-6%Ug@l@UP;cxrV4;c&SW^-Z3PM{#T9GkCOb*%Fz=h-V4k{TU z5Y+DhzmN|-GKYiesEjRSIn8EYI2pg6)L!%ba<=CYggnA@{{vM4m;^s)7H7&IJ-gcD zhvgA^>{*!L( zte~lec+xuZDa07GKI_3%4Z>fhZ^0f3p=htjp?4uIEJj?4pWtDfSgq;*)T*EZ9Mr5V zTA9v693P9c*Yc#u=Yjv4hlUAOVbIp}tzfT088=a~OYJ%-cNdmJ?Y|yksXID_YC2kl zGL2tiq$IND8XQr%NU6hp=ShNH_rHQOzlc%a$*J$>&L8W|m3(dg%{JHh1%;YW7Z^fa z92mlU6d1yt^)fuLk4TH=4yp!8lu?P)8+yw2zmE!!w{<`L&zRW!;2PEce@5kh9iRUj zx>3bSX^|h9N2|a>2!y(a-#bvf41Tv(6&ayPou6V5kef!LBZ*H;A|db{!UyUM<~_yk z`y|G(BV$A%KdSILx3%5qHk1Gs^0R=^bmqRNZD;F2bEPaCD3m6NH4tCvl z*sM#rF*_Rt(jg&hkaE?IpMzT-ERaQI?y?t zG9n+*GgZa-OzzktNf(U87ovc3ma!Riq|HCqh_z)B9WGxG(Gu-PRWGJo=bGC~)9B%sq^ruT|1{D~w zEpKXJs6Tn{7Dr63HaE=0U;QeptC3ri^O*8W{IN;Ee9S(CbQmsWIKBHVN|WucP$mTP^m1i!foXUAiId;2DN!l@;bW5w0oz8l`Lq^A}!# zgx&(scU1mwqx64CIR0hbv#F51>EA!`uYA5Ots{i^MJ}F%tB{1L^TRp>8q5TB4x|`b z3>AckctMbXV}jkDcfF{~8-#5Me#8?H z*EDK80#g*1up6ztC@KtJr2M-Hmt%0ptu#%WLV5+Di$z(eDu`%|PgGEoI9{r;*nXsJ zjiZ%@$&|Qow4y(@;6@#j$j+S&iS~l|M;T;awNRl9VRyEMwPqiIZ<;urdImRG`@?}i z&mtM0jn9QkbYy9E((2Rvx80V`oO)cmfMjT*q7@At&v`M!Ovc&RA`2M^(o3+?j-S)X zc1UCJY**|mDd;vS8;Dmi@5FoGgZppLU}Fhwk8Dkiev84KA1%U=I@&TWh%h!iT7KI& z?4Dg*z2Ugye`rY_s%BYlanw>_Y=1wV4t6ej0yrjJ^#ol-6!D(#(H2)CQ>+>qBm1ZZAd&noIbH)Uxdj{u zNd3RPXi*~vvFStUiRNKJB3icN>N+Wz@$5< z3JVEa^Q$90ZG@nVX)DyI67NJ?uNBcZw;P+(Ua`JV=0yWZM=gFN-%q_JT+n@`Dm=puVa#7X=YDmi(A+Nwi0AS?!?9^}ys#47K8PfwcpO!y*EM zq6Mo47ch4-(aNdPY`IszY@ud4(&{ic*L2gg%51o&Y=UEKxairQ&~DRr*8rQi5l)3L z(z2M@Yt}tN-!pVS+asBQ)M}h9dG{>=|DY0H4qzl```JQVNa`>T5Qwl^3 zE3M|}y-gX6Bvu#5kM@)1HXy>21+^b6 zG`<{*j0G5$sXSKcoD#CwjM2xBmn1(gbCX9k5M*~-z|n|I8BMN&zx zdPLy`{mqfrNC9A@AFRl&)WIbM+;8Qqah2Z(Lagi)J`-6>hAWhrohmI<^$Ihc7AfVq z>qlHs>(n<~SY9iY8(v?7@yBNl(`U)uV)v%)j{4ezN`gc)pDIq4rpl!g*CC1Y!CUaZ zd$chNR(=J92KExYbuN6Y$wTr*1DX zlZU9TOaIGK&Shk@uvmjiTV@m3n25!o&}tE7mp^Y z7%&q=`}38sfiTXWif91z8uJvFtsI!;*nb|Gx8?HZZa~-E!IJs}TByk|+3FNN{LAqd# zk-SGTnx>*6>cpjE*Jt8<#v!yk*sGn7iVAft6R>RO>a0izmol(Zu{hUI^0~{lqMfqa zvEs@}$PaU@#G!l!!uIveBM^C@T#1Zw0-uzs`IVSK4akw~mRT+F6=I#jGt21b2g1H8 z!Yp)9C_zskO)=LvkM(*g8z&+O!C2zW%pgW3VfBkbnpzm=(dhZ0hiI~jOh`$jpkeK( zEGT;7#q`FP_wsbrVHY@QHFb4%6*UyoouMT$$deZmUB#nu6Ofdg>LaMKDT@5Gz6-&4 zGHV6zmKte?H^q*+tG0SRm-i(LuLqXHk(s1-jeClqL1=87+FP|11k#2xXHID=VO=6w zh3ezc?kzU^F$MJ%TB%6z9fr7lr4^j`OJvam-&`t)7_lXy?&A{@>QND=ps3}CrI0_t zL9SwDIQ@b{_@@&c2kYOIapEKniH!oOrNvs0ezLQ%u|p*tQ&R^|2(xVe5E|;BEKX~tq}{JI8iFufFuNW;2+!2Dm5nMe(yI$AY_ zU^bfl=f-itPy>r19nVE*cF-#ooEWE4oc3!QLWp?Zy$fw5X{5un2EIcrfsrbtCW23a*b<2pg-RbH#)mI2rZ{`~p zHQ7g@$5G}h9706bT*OMWSzedYlNM1M3p3AAsSJwhhNKt;lFi0}veT>;9(;Sm-#~&G zlTfq`QI9GMrusgK6H3>;5Ze?}9a;MBW<}0n)o0TfZ_q#Jl@O`0XYB431xGrFC~XJU z4w^>YE<1Aky1Yjc5R@YUd7}e9@KbV&red~KS?{s}$=+9d1nsptxPdRT#c8521@<7- zvRh=Zy4sCeM%@QqgX*uKjdMM7x>@b2*Bjta^MUb@;Uveth1N2+_z6DOSE8N%HqJ^X$@0D35?=4(>fT#z zE9^rH6xLomrqa_?3de#6-aIvzTOqVpARG_+UDXE%L5h+~HP~vtMhg!9iFd6PN+6Ni z-8e1Sc%d$|KM#8vl+&|Se1HV`B&O2Hs>eqMW!0F8TMq|Hf@jNRyoeefg-s!OH|5?^ zv#q)lUf}&c*wW@SqOFIzH;BT^+L%PTZ06B$C0g>h(9-C)r}hXx(kQQtstwrgai?w7 zuok0OEx|_u4gRjiJxD_aY9`t@<0~$-xx+Ae)H$dIp+@0_?YDS}Q^Ae6o`d`5@VhB$ z{eh~hI&BGwNlpgv^^_7&T)G-hy%C((gv~4rcUR2ThKwF9_|}NbuhL)?grOMDbOg@t zKpp&_!8`3{m5D9=VR>*qEXKlT7}S2}>c-ppB_mjrOz+vAS7>o%5k(cP9Zqgb2OCdr zGU@JN=3G2^jB`ct+l3iW!0t?135>Nn;b(9Wx$bz@* z;9+i@HMVO+MoSwMoZuZV)HH`=wT~5sUKB0QldDEI6;*82ubh=q72I3?G`lTsE_igb zPyzlZ$-M~{ITGb>nl81%A}d*@_uy{h;wpR!&+0n=xrxg%UC7gUBSvl_JO){|zJGz` zR-S`Z60A{GoyFC(H(2 zdf&(`;r`3#ciyB3$hc!$*pGWL$7Fr01&b_h-vIf%5|`+x>6yjQazfO*)iGS zyJGe*)25Q9y1o)KeZ(RDXmleN7Bb5RBM%ud6*s4)Dv%`}ls;JX zMw@IzKk3C+-M^k5B%o9{4dyR!$l(9072yXN@BK5o-h|W6&b|))&apShQIIM*O?q{{ zazNf6!uw0YWTGOjSq+;@$0VOav!5j(WlNd$yrr}eTx4aWP8ayHe)C4k?a8;Yvu=h} zwfP|ElmLBL4}}ThuTE+A0&@aXFP@_<@1^c`>B>e*q@81;vOC&m>`xLj5`7|6dazPx z-w&tgC_4`FHfCm?2Eqt28*od4%kkU+wqN7QF(&4nT{|o!J3H>qqTM}*il4Pj`kBH* zrw4ht`#8e}Xm2_~Loy$VyK$qqwn5!Ryb)?owH_uTb0X;j1uc&*Bk;9!#=}#0_d;Hb z1c&whEK!U|QC99yW~oZnR89M~5J#jGi)dEyXs>A?4|-wx9hQs4A>3~pu|K?lZcmXD zc-83p50HRz1>9(oAM_wmEQ4TJgOip7r_!POoxjzb%8~@slFqw8HfIoOD7nLx=(Lxu znAdBkfa@LuqdVO08^@^$JVcTMBvx<`B_3?an9<{31`YF!I739U2Bzb!jT8&zpXPfSt7? zd`_o8lJLjaJ+F`OWsx63ukDDh`ko<-VRqL`cs=z^|5$ei!}Lxc)Bq`mnQ0=AXK(9A zcc;dQs*tw8a!0qd*DU>-YrVERAMHIa?6|8Fj}LH0Z_2I6xusVAq%1Z$Gh>bwc4}ez zoD8Q2m5_l@#1xeiS?Rqz4~hm;M(v4uZz!tn)V2$r&Hj_@C=TWoPQ@v@btl&L+J&Nu zSXpVo3X!P$xLktio^KrK5Q$XxZ;U^`Dy@P1!syR^Wlh|YEnUv>C|~@JmSua=3u=;;|YivB0R9DA#WXY&BFP24{d%)>81_G=*Ke)Y-QB^ZkH22aXo=FyOEsR zX4<=;%>-wNhfYW9hEy2d-b#33gnePIerfRAieu-E2lmnvub=?qe|O_W*^ry0hL5Y^U;Qr!M(2tNIf-m5cGdk2P7oD(StfAX3rXLl`mx=vtQn?D)ZHiGOz1u#KvecjIAn`Me;3-uLul;)!U$ z*0KYn9VL%LRo+RvS4^6h!|6VXvo(D5p&nXp1!jmm=LcEN^`irY7iX63DLH($Eq!}w zE_nt9LCwkI1kuuz<3!qHCJ!1WgGmd9xv~=F2?{j9gin008%d%G^rN?aS-9}89Fni4 zQIk9AxPhHWg#JBX=2w$}JzVtAu00yBD4zDCGO5q4l3yD1IeqB7U*@3Pc?DT>iL}`g)RJp1c}&76e4$Eo^sh5p(OQ{Pq1*r;tkYuTSgLj@p*~^9Ww$*-3FnQAQ;=}65(ED}lCWw`$#o7WTjBw*fWUuSaTs|4>K6@XK-~{0 zJjCox0D3zAtp9WVRsSd3Gfb%ofgKfo>mdvZghp42M3#!=M`av^V9^_GRCJ%bNgeM~ zE<$8u;{Pa$wqPJG7|FL{W;uP#zV$h6JRO^3*abRLk|Yj9hf~6<31^DN(eY8>>aL_V zGrDpVSx=OiQp{RBQ3&iJ#GOFQ;-Fj71ME1kU}qi1DwQ3{`7XCnyOEGOgr~7yNc?sa z(4=u(d9!jsZ%~=^y^RuHQeIeO5hmOCObVlIq<2rvNX>JiMXoAw&X#mO)Ey3wn|on| z(IXcU_!&lL*%}ntnY>rcV2)AIHq~S=MPdINz4h6`LX-@wuSFK~Fvri^(>1B*xv9-X z$6pzv!HLPUXn4M77M2{zEeaXc6@vjZc%eJyXr5}4d(_};u;-YgkVD}PCQ3xnbVfXj zWGY5>(B3Xo@lX|RzIJaN8I+7m_M09okC}q5~#W&T}8};&YJ?l3qoN< z-d#&72c2Ytc-WHaP}NEfo{SB&Yc+zhW1+T+b3v0v7&GiGC$+xxMMFg=sx=2|Hjh3Z z8Q^jR1a5?Li8_y#&M7lfeE>_bWW42)tBTL*sYO&dg6+OLmq&N%kf%@>eBL$`$46w= zz@Br`#Pv|Zp$Kj#uRm6&zUXHXyUcuow$Z8Js#|^>*D$(l@OE|3?>|EqW zaPCL+4WxP#N?7~n4JP;bP&9HD6M;LYBPXyoLKA2j@rny7p|HRPu#vx)0r)`&0w(8h zi$FV5BTyqn`Dh%|VLO5H42rNn>;BZyjJ$~>fe6AE91|vf_K-{ILX%6v6^8KKdAu)i z)<^6kQDYhKy8;mD;Cw=T48r|*AI6V=8|?X6KiEkD(91&x4EM1Amr*3*27m3g{ruqxJEq`g+YN4`TJ)HLX{|2KaqPw!E~+HcMUKf zYV^Hfa2{gxaUP~s7UeS^zOD;Q-fziGX2F}2zc}4+oqo;UX1l!P{rK|^QqM2%+fDMwD}nRU)XS06dE=g>|IyQ5symrjMOLC<9Zv7%jG$#dt5R77@nZ&SC) zv!nRfca=76k*Jx;H4jxmRc;E=9<>Jf9W69ha0r9Jht6RGO-9z)K$fR=<~Jkv*%srn zEqm3?yh2Wf)VllRFXcBMeP3)bp4!R1F3j3d1rkZxusd)O9Y@6{Ihmwhh5`tO(7V*Y zHm4jSzeKhu?_90r?#POn3;7Ds+|pLDjBo1Fg9glY2`?RbP@36Mg*cVLjzI-f{Arr8 z2YQd8ce#N&o_Pho7(0jBDN$^m#2oORfjeCfTyYbtg9Az5#}hTE3vC%;v(fITlyYud zF+o5ze@mw<*g)GK!i%IIER3|)V=j9N3xtIWlJqmuGWj?jT)Yj2Qoh&qyyJ_wjIb(O zV|0ivurg6%N*Sk z#{M*UMx98UiZY%=W+!8!i=jZ1o#^5jZ%;)sz|^WVrGBO4AC-k{f}BnvbZIIlWH5pLke_i#e*b6)G~*>I*zdO9Sa|jF;#a$~2q>YR;{-oGZ?sPp ztF^`m?iz+kjaTqjIa*=%kn5;}$@+9l0zx?d^Ws&Il_^$porobJi}5|=0(+>%Wh#Nl z8uxsd{&zLJT;BLjhnRe1Lbn#ROW%cZ`#V+n*zR6JR2VaL!bwggpfOfj{4lBX9h?lY zJoym(9UbxQ0j*4p(jNq`NWQ0Ro~!5BouJIDy;jWOqhfYTmF$J-CH_?n4d z<8X(#YmB;U0xOUhLQ1bybmZTj<{3H{QP1c{NMJBO!{h@I`we?@EMnT2PiW`~R4mc= zN09}FOc$VoNjLv~AcG@vW6HaL#ieqhpgf+JrbLjhWZ1Ov?VO zUIohxnfFlBP!cyN@Hw zlw5y^UE!z}dh z8&_0KIGO=*yq#G}RKFkq9(&|R&AtWgA$+H>~g}vxtsi2XS)^EvJHa}Ux z-cT1;SdzOP>Tx%oO^n%=+S$3TXN8y$Q$*!M5N~9=vEjkIU+*8e)psC3# zagI`Qza<0MD)=KZuGtgdD}J#lpToH7Ql`w7EMCI#7+JSV8fud>)YQ-5b4zMFHpEiv z4ywpMB==`7F7y(pIREDSw3%G7X_w9Se67bZcA5&;A>Bk`_dXUi5iL_%Z(TQ9n;JA) za#Aj*w^)W#sga3SisNd&9W&M?`ejtnpR9_b&26%9J*vK0?S!%~jn|?%J5H)RHB)al zEW3&@9duq|mNmw@634AuVpI~Vrb)->1hSHw(pE-4_bSXTrb6V2qJGgwd6 zK?!nYmc?3)rb#Gd&w&g65{u8XY!=)_wk%GH9798jc41?pgyqLml6vXNS`^YDCYB19 z07Z+9XHoH9;)u&Xa%MgF9j|85+#wG~8wYH1PO{3Z)r=F^w%>eWAKS_Tdr%~Pd7m3k z=gysaM$^^TVZlmvZBcH~$!)EYB$~9Fj>o%$jS5bGl@M#?nwxu`ijf63<`F45x!g9Q z6|;c|oUY_h{0_hqQ7oaANQ<>!`{p+VIH9$GmTDU454n|=s03{-h}dz#pE(V})0b;6S=_QwgIb$;Ska5$BTMwPLr#&K|3 z3%luyh68ni?H?d2v?%tAssiW-Z+yPbd-~@;SeBYG4<=>#JPRi3EE_UyIgsL!?apcfI3P@tDlqhkf`>9m~l1A z9#TY2-!(U`_o;7&iW0AjUc-6cmCgf>DBfR^!yizkw#$<&nrBU1Yp2M@ zR+6?@WOJIFMug6lj5wGST2x_GMU8%s_LN?~#n9wFaKCOr!BZD~r(3ZPo{8s@yq?c+ zZTfk#(?XRdLJ#hWn<_*VW!&_0$tJ5&9HYK~yYleY>$jO}rcSwBSe$!xnw^P^&RWeJ zhM9Q6!%a@rwOsK$*A*7-+?0r92QK>-dGe&KkHlDpLz*koWRj&;F!P2{v%v4+!OZdp zRoK0yhg?)fqwUL$1J2+&>Bv4JV;pLwqeV{(*XGqLj?=n6Ssj>hWaV3a-Gm_LJj_S8t zRC$y+2X>~ zN9SkH=tTElEz58n%J@fbT0W4ujJ5-hWbv+lX4p+|WVxA?%gg=Q#lY1vRwdEmocwae zYD$tg9DHh&iyrrs#<@_jcQU}zo~tEG`J6p#HH-0BHb;j0;lhdpljW8=y&qBW^VY{J zRSxFTHCrNj2b^UG%g*J&W!SVYoj5QveX^6T6lxj|-9+qNQ#T2^JG!eOJlynbqNXx?D zI=aIoW(Zy5Y2&(7u(t)zjPD6Uw+44q!%B{isRV(X<5KAQM;@`-*%1a0Iv!AWG@qG8 z2n_oip&9g;l}+*3?ilD4JYTaeYD z{TMJnldtgv^H_Y;;9@8(xS8mK%kiO;`UCwXU-`q)51-dzf}ppNRkr65&NSzQ`xJ$> zHCcE_;NAh*tNoQ#UqkW_gx^~hq6P8{1?P#AFGhgwisE|vo@NR~*QCx7-NV&@9ZY05 zOqEL@*KbXs=G80kQ;0w=FuC9D?^vvAHbU2+&_NqU-ExF6#zBQ^ia9vbd;wwuTSJCQ z70+P4W0jxlY5|3U2|o}@A$-LGLVkW%B;fa!5WM2~y@;ppw@V36xox28e^S+de;_Pt zGNmr;IpqXZc^0VF9v$16?Qk#SNLSkrrzwq?cJF%yy(RMw;gsS$DIK~G7hTP9M}CAL zgX0M8;A97K`e(%I8#`RAb4GNX-Xz*XQ&hogDfHe)Frt>|)z1RR?Gjz!<4C%Bd6RF> zkUgQua;CrX2p6c{Tnx9VrWfa3wZA6Qremg}(9z$3R zHx_qaS4^HGhc)E&hOz=S>BN-VGLVRDDewQ;j!6eSEmmBfPtKt7BQBZ28Ef@HrGyaG zdWG62xXPdF?9|>J+A;B~h1Ah&oIk{P^iCS?XFviH%{SB~xXl>NNRKE9d=mFDl6l^b zy@?$GR7!g!D>*7+FJX;XA2v6!BQi7Z1T;1X1!L5HKq)Uo|KPw2Mm5!BkPkv}h6zvoHL5|e;KJ(hfwtk>XK7UKuf7+M@_OFbD|xDLUGB^**QdUnglG?v8*ncRW!Q9Fpw?TtOxL zML6BFF^`OxcXtG$sAS=|)J>YO>xAmC+mMjBc0$5_o*A!(OMUjD1M5n_>%5_ohq12^ zCQ+@*)91*NMbV!TQ)D&aJ4f!3i%wKvAP|mz+meWN;tkE2glLRJ5=Mi1_*FcvfhIpY zYouL5j`DJb(N>E_EI|1Ao#+qimsj0#`APYFx?~vMu*$@|XKrJ0GhOi2t3B<(-H2cI zT8#5~t)EX%LF1lI<>JwI@Vn1|$-vuAh4lw3g3_+j$Ss%M-J1G830p~o8n^=rNkBoy zp>@Goj7S_L;X3KOZH>&^p)ig-D97^ZrCsUFFR;K!!>&sC(WyU;5fkYEE5T&J=BP^f zq;~}MSCUb^n?^{@oC+upI0Kqoh=yIC_*76`YW!_2qO^?VV-=>+eu+^9{sH-Gm0C?N zJV6Qu1cVC>1VsPe)fj4jD^~tdlE$d%sGv%qer4*Vn=yx1duoZzkDD>w)wk?I;iGmB4J}gi)8EKo$bOQo`l*hZySRxDHo~;m zr~!*GEmN%lLl61@`?;VC7`49hUKk_RVGUiR3}w){hxgD~j}dnRXzPf%U&TpqNT_2( zeY=^DNQ;~mcN8f!-65&Oh>p>fLgfw4V&7JNKq)lnRv}IUu8C9^jW2xIF*+b-;wubW zK0j}86i-5vEHvRreYi&c!m5+_}E;&*G_r@zuLwO?UykVJ#g_;>t zow0DAv=J^-ZI`jBRuhq-QDy5TL}p*vwd(-0bS+_FC4}pIuQ`;3Qw9_5<}zx~jI#^N z#5kdA=|D?Ov(qwA6%s=Uca8~nt@GEL7uKkfsH$$i7+4ys^2sr|Hx+BQ#3>w>w(`*s zrer2<%>i{S73L~qz~${(d%_0024`SW{tE>~7AcqflcUNIMY~umO*bvMt<33H_CAC1 z+^>#fZ`hzNX>)n|BNezjqPclA=>1$rS!63QP0{^P^>jwqj&0LYB!%}U>Gd+j zWwYHz5t~1ymD*XlDbdj9Hn}-0I&8+Be3>s8u$w7!c58xghmaP^U-D;twN6DBDm=Xcrr1M#z10T{up|uj78cgY#jJ%cwjStb95-#pyp2{v<^V10mU$qT z*X*5ZPyeu|5j4>=gvS~oulmU6PwZug3^mJ;M@P7v$E&$z$Fo(pH4sn`T%qWja(dhn zCx-1J-+(L=B2@f+rXCa5L%#rq2_=l@J*ZydV0TB|x-LIGj~qP_gpQjTiP}fpFRY#n zPXoBI)9>&SG6F&~!w^SjVd&3OKYpO35J{0CE1s9=;JWUP&d15aBBlrtvx*k^6`$|s z7c1)o#3dw3Ry4&t(TaA+bR^PY9a?x7wZ zvvxYA4suCn&n=wsKGE+X(}Q10Ot=X&u-qjl%9ARV=8AU0CVeO6)AkK*TodNR(yTwv z+ESv>-YL`>Py@q2jecHeMmf5}+A{or#pj!P%@n78Qop0?6*>6v*L({|vHt@LQT?ZU zYh-Wl06+u*2;lz)haP5@yM6->=m0>B691Qjq%7H<1pN|3xZsVbMiadf zFWsMSEnh&4qf){6L!#I>7i3xv=*4&*JDN(!b=WVp?eiO+`z27a+SVpiOzsa|-Cjk; zNJd#koES6%Df47M(q}5}klZopJMGejc?5>`CYD?CMX8NB|5P1x&KPmdSYMloF)U7G z6v`iA(wE_MF+UXRu$rIM1y_p9oDrNCDK%OK5>4jb{(7W`7ud9&2%(#RIR0tQudW(0 z-L0j(nOA)O=sw(Ek7iGBeNOc5<a zcL4B``M+3L-of>6IGnAOi7TKD`!^z$mHppnRf-M{w*Rv7l>Cq&EG~w0e)l92(eU9s z$pM;0NQU58NUUuSdRhL*JZ9a7- z3rQtM@o3^I;~zxdug+buK6uAK)_!RnSGl2?36AQst)-?Lyf0?dr+XFRVq4O+;Tn8% ztl16b%Yt@;nn_s}tH1bc;%?oKV8#_qI;X_i8Vz20qKKGgc{cjx%tv6O4?0t<>wLUR zFg&CmCb$N5YbnsX5n280bf+~e!j>%H8;3au^ij@Vq}RO*65O4 z$Acr}lMUeu=tpw<<$ymZZhFR8cih|O_doyi<(lQK6&q&xK4r5Gw~g>X&-FEq5ivC@ zitOcFEluW#6>28#@hr$q*rAj)$XZdgyRqX)XAGmT{l=bFsLvY=X4qU;JLgPkG1#&n zMGk>^`?NJQ6f)ma)#=e%{H7e)Za)(ei>ULNM1GK{ULQ*QkwmF6-SHGjrpIqw_nmfJ zu$u^`8uvPO;~=1+_BCIrruxjAJ$N$(c=B;qoFbp7fD4AVU!FJX-4_2oP#7ol9aywu z^!~pYwx4h7@NcQ21z=dQ|BE97yx86h;KUC0e{M ze&5Gs`zSn1KoXO8y>!y6k`+aK8%%>J#4(e7v?9?!wFW(tgNkk6cxOGi(FA2ac-}x} z`!(@iU~$+wrELeXWDa5dil02&O@~Jp~mos$l?VH2+7(RdhCUG;%gG{d=p& z4$$aPH?nmzQ!#UO{nw~QiHe-V62NgcgEc3SVt6=#jYmVyJkE@o zJkN(89bycCJGgtBmpPFeQYna4Qx};}M2up{FI)`qhKUavFxxY2n2`6I7tyq%*60Z# zh6Hy+fyF{k)69(-Uw9;Pf=Jr7uUiEe*ZwS|04EhVPb+kw-8oviy^jqp!EVA)fc=p) z-AF57Ry5MgJM9Xa>GyuURbZ6*jr39k4CJCLiasNC9U~9qh$*l#4f;B}FMPXuLPuY^D`<78lx^hSM-b$- zMk&1qU5uzsG<(ue?+|jK+dsb71@MK|99O`0SUJbiCRYlp9hsfe zYD7xOXbLg+d0Vm9G?}J5D<+b?pJ3F5ca3#kh$$+-9rdKvowVxajb z&^m~_y!5fn$wItSYRz}qijTBdQW7NY4)dqMU!P1keSsb(0Ea6EI2`qV3TS|%IlGcF z{Ua&XsMski3nKbG-?Z=KfXRz`{Q|3hIDkO|>obg|NM7??75Q$Mj9_|RBT?YmaBcJ{ z=BJKg61@-cS`^*%l&Dg;fSGwS%gfT#GD}>p09kJ^YO9B^av@dP`Kin@sk_s-*}!COnMk1=%3foff1vxsnqZSmY}l z!VZb0oux_V=h95CD!}33$nY%kSuiOU$8vNb94H&k$$6!ty+ThzKQ4^?^W3$#9qg;!8x!;w{=k;v1YgMl?QY6%(jINs*1l1e_$GBjbEt##~i71fQ zGqiMuz(N=J{Dx=z!|0Y0>^C>{p2X&x3nj%PkLzQRMjC%?Yd2BDjW~I4S5{N*rpHE2 zu9m@WPCaSQ*s}uoe_CT`$JAxDaHklj!Ld@u(_C(2i-wAtX`;Rs3Z76R`@I;i1$n%Z z9rntPjkeIl%1V)THuw7hXdqsJ|R4#`qU+D3dfgwi8PxD6zabT1b=$T z+et&!%)^*oh1FzAx|^v4O)$Q_uoFebh9`|NldH82DT+=3$C)76v`^LF37DB;zL^kB z9WGC3oQpL+)L)pDBphRxO3I^fi>I<09-^$>r!7KQ-u~SEK(cUoY8&U1+D9D7rN<>p zza5kTZK21d(3ITg`TijWYYchHB+Cl;>LEP3)Q$)k4Jlpq09nQe?7}z=v+cL0Vhc;% zGN#Z)mKb8|zKr;x7}iH}d!YiZOoy^muIVIPLOKy0dS2WDmn98)ABexY>OP<7A}WAv z%myGE|HlCwWiuBCH)j(wQ7ac$XDeej05j*GZksHpfTDyNy1SVwPo>g3X;FZNS|BKc z)E7@IPAE=X6G28fWz~}!z#PP)0^2vxL-S%!lz_>KWa9BfigD4gWL3}#6R|zb=Q7uG z>ov>8aXMBvX8=rk-;aQ?h0M#Wy=Qi|r39ZWDzxwrQMQhk+l1L2RavSn1AB9JWKQE_ znX;F*0G?r_{u9OADGw*LcZ!Y0NV~J($jkV4-bYW8_pnr-)!9dljZS0+ePUvd>a0UA z^yaCLgp912#dUpCOoomWpXS6}di{k2s4aYxtO!RaRDEcH4U2naZfZ*8tM2dJ_}SV+1?mYWRPHg)*sa5IBF56`in+P-B~(+FUkz3K5GGYx8$}{fQt;OI)5q`%Q)s zqsW#^e`D6sP+$t9>#8|N6(TpHIMUa2-q5OMy}4CVq*Baotv@n!N35N-U%}vLxA6U2#57O_ z9>p1ND?{v3TMj%3Q6i=|#9(^9K!*>WlI-FnV~CZ+_Y8ZenxI1X@j@oBI0VygCmP{p}_@ji3J_YnE2f0lrQ_KQF*4T(O;U~uFZQ9Y2bVo#iR-P z0y$R{^bMWYp4-E4)c&H@LL290<0$L_He34fV3QB+nC5mQkyP*D|975hiHm8kqySW-mgi}Q7@0vkONLHraM&-ZlXO+O)>VXX;j{#rTw+Y z1%=E2mz@kfqHHFj9wn{yjKqih9mxcde3HvdMI8%W-?ds?6!#QtnDo)apGcL>PR8O) zfiwlrPD3UmQ%we~&Ev6BVvR@_k&)I26hmr^!QYncg49xj1?T%c+K_Ew4UdC$ZI;!h zBHviOb;dJPcK<0sk|R_a)}Yo9bGKON!0`I)PgAbIcuD7$PVEuRyO4GOxud%v62LO;~g5C zKMK70u3)>0a_3L4IgQm}$DyL`f*Ve(Fa!du9Dgk&b!1?*=V1So;PbM!C#&QCq2*;05WPtehOy|OzF ztCU!!_7JQ-`La~?*?4h(e8Kcge7^p(9fJ+9;&#`qXQuP?@i<2rNoXO1SH)MDHTC=m z|4uYpVZ}CKxp!ELKVqOB@%C&2c5HJ#r8}=F{lK+1BzqKxLIOyiN7~~G!y>X*Mc%i; zDx_SdbP-;XvSSZ7i5$GM2fYNRjJG6Md@h=r*kAwlI~=v6k-Gx{K$j={FG!kyt!@7K zn9+jCMt$=A^K}EzR`I9(hL5O=+JUhZNPK}OdPElH;lJhN`AX>0<>CS2&2u?T>nM&Q zXHx0a@-sc0ZKFJ)c|$bjMvw5mnS9L>KW6bUquDB{)e7fBdTG>p`h|n%B@pFK1&x()9x(bFJA1DIr>+?7?d{tWPv+PCGcmN#mFhfP6rOeY-L17Q(8lS;g!abNvO+^t zSk)dbTs(N3_V!(u=3o|2TpzS^>xN+J-l9HEHXGLp+opKDmfjVM&ep%6x-wJFT~SyZ zQ}Y)QXc^{%%1pOwyF3{Kw7_TC0lh=e)10sH{(2X6kCjRaP4_s}mFnzmbb**jds9oys2n=y3 z~W$M^};>f_W_BL)Ac6{d{?QAho38v9s^VPer;&lUG*#rtL||jhxEHO;JHdi zCOFHa9BtaIXJ^z8+TN@a=f%8pDF%nvqVKu_{D~ZU86IjEUb^YBDfQN&<^7s7wO~PT za@e^Vv3Q5bVW2uOFyU!)$=6-LJ+nf!ryQXk)|^hd zUHk>FstCJIc8@@)I!I|r!w)FpiBizX29b_780RF%A8qF3PpiULtP2%@RUv1#Myl73 zjnwaK!6 zA%Y0D6_=``9GQ3hjOFBq?BD1oT1^|D*Af^-M{z32FxGlnC1lX*cl&`+Ak-c*D6SFz zA7SSdU0K|1`KqKUJVC{_ZB=ZY*tTt_k`vpuZL?xkbYk1KQ(d=j_e0;&V|)+$X}#?| z_8)W2^_zoPIy080@c9s&=^ni_OdGksrGndr2BEKo`nb`INS+h}(y_IZ#%(G1i@d1O zH*jpjb_TL!v}K1baP*wr4y;24*OatVo)< z3|~9aWX7gdsmGjxu=u5j8M{0@0lh#9)Ft~rEj%BH!CjFMx@|rO#f}(Z^6707A|_gB za;K9iQ8hlpgWVl0XGI1UV`K^eZ*1&->JBH^#lvggUd(~KOgQ0W)v#9EPa4&7`q+CO z$Visio*E8*7i%eCn2P38pPbdGaAvJh0A5Lbe{da^&IV5h+DPHE@4*dpROC&B+r8)I zSNdc!ofy^Hjf#awB%qI?%mv!WRo%xg>EWAiIc(QS;f#BheHHFA%v9f}zPT|_nL5b8 zbgpu)U)v=$wjPKB=uxVh7v0-B=_rpKw3i{vX+$V`0!d}5BT!4`PaL`7G$-e3GoEpB z$Xza$3fH{8Ia4gg)))C9PUAk4qB3rukxJ>pWZ8&DTf|*!@Ze2vo*uSfG^|8xZt)YN zkq#%COphru;}!bz{k(=!fr^D_xi14}(ovpSbG+Aw+wYP~%T7{S;(w>LmN&kVl8e7; z?dNE4T(2KK)-d*{axBQ)eMaoD-j`}}>mCCg>+($ul zxth@8qLV05o)zuR=D<(L&)MGs>CfehwKu+tzX+E<{^Ysz-KDK+m9A#dRp*JnVxs*$c7}Fve{jytWT4#O0fQ5JwO({%&VNM;TZ>y#H7=NkCV=VFG6KaAP@c42;+H z1Jmw1d4b1GrD-AUh*!)njt;xB-MsL$k8D};8BU0>3&L{GiMLiW6iWDf&#kS6A!bE$ z5Nv_E3ED2&Y}|)EeBYcQDKn*y9SThC(UZqcUmABo8W?!@_<#Z^%| z{=j#o+L61g*(k312ApSsK2yr;33GVBGBSa8Ra16@gjG@Q>P$5;YmG%u4Cg{#FHgQj z%q0x{bJ#Ts{i@Mm^F^a??&uoMLHh!Td-oa8iw5o?WHoyQ;PSB92>mi0mFYQ4!uUG-w`b zSkvF5Yzxka1+?P%c{_aI$Xrjv0Gn<)x>E87WAT~WxU>c1wbQoNCCoh|$AYQTZGcQy zKG1CiE!8UBeAGu7W7M0%gzgQl0R11oQp7vhC(mQ3$GMf*%Q8oUt`NaECG{GNmv|@3 zt*`9u7xrkcyht_py@YO7yahbH>ZV7pX)T?t#i9st@z^6A=ZLh=(Rs-)g7fVtCXpz! z*}Iy~nFQ-eRWJqiv_M5(d&Nd+Pd0#i#deO(%}H1QJJpLWY|II#sT*x(tcu;hdn{@% zRG*{?Qv0`>JOhhqv5wBE%E;85FX>ZYcyXTQw2skuafPfY&)KV%N6}c48SuW0BKkq) zFedt9&Fxa7*Kt}Ex3lbXEQjK80q$#m8tX2>t3=89M!CmNG;`|Ni9{&%ppA zl$qK3_spuQ*-W&Dx7?A<~*2S>QpC=KUDvTP#MK56Lh&8BS~u#wsB z8B;WMJPA(#$07=v+X>winwcn6aGP)mm(u^O`f^noywPJ zRn)zmz`o%rM&jJUIQ;k!x!_}{Iw(o_b3Rv+0`DAabS=@Q_i>)yPt>Tpn4GvS(>S4Y zftMS11G=Zcc%_^6Y@Qo2}FsUwtGnSpS7o1(?_UUND3o`oaKN{V*Hm{9VS zV)p2J^tn2$?`0?cK~$ud6QHh&* zs0y6c;>R?GJ7vOuaQbe3m=rU{qe-Z?fKBYVxzjwmt%<@2&y@i&8u40ch$k|X=p*lq z!+JH)RG7AwTt+bXzEh~N%sxuC&`eBcWi2_6rr6pPR;>NfR#zT49T~gLl2_i)!BSrm zHgPo&bvjPET&5gqNXEgb>NJ;9Lc_n75oI+M)cMD152nRAb+)dmqoAXqLz=P%D&ly1 zQFnx?S!he_{P676IIXhw*rCnE_s7+odq-GKNMn6#7@hw?tYOU5VI)ih*38bN*!pVR zbM)Ya*t?m?u5q}0(AAdodrXgNGsz`GH^1+Vma)gED+{vnSqIPU(C7ta_x*EDXsp~w3NyEt7T z4DS$~H?-&RD|IG6Sdz*zCq=YU1`r3fd1QC4xV}1*9u!m-{?hnEVV$Tm_Df^D#;&o6 zNr$2D>{}0e)GYgRyUvi}chisZCMOjs>RxJFJXOU-OcPp(5F65BwB345`yDtH>@aK% z3xo84=HlL{Cr(%KkulHaRxA&bikTfUIve6$uZ3`k54VrMqCQJx1lk{H1Oh?MXQ9`{ zgREiz{!rmH@QVl+Pmp2E$^6KXKutTEmLCB*L@{mXfWhVj)7HrL^e)7{Fg#g1OK7-5 z^Er%i0mXQu(`ueB&!}E=SzuQHeAvipff$J|8A`dE*`(&4>FY4|_`V`AR~l+x{kP8f z2nrrvvgIXLx)o_Uja-T)tSQ*qlWdNBozX|Wl5uxva6-)Ije9T$OAJ)uaB~UHYgF+#S=n#qmZXIs{W~352A-!Z{9>aYaSk zGFvAFyv($NomHHea9x5J0q6xX?Jg^SwZ};!n z&`R~FF2AKR(j6S~x38d~R?<}+^uGWf{ly#h1rEO>kLq1ja6sJ*J2Wc}YKNZ|B;of5 zycVd$FBi!3A={SYB~cH+he@GZpH|W)uaVTO5%Ov8UYgby8o5m-oPeCvl)HL({N$>r zSYt6WR&hUqS2phm%$N>fmmY-{(zTfGWm6}>)y;H zexOz^akF;infM z_HKIandHC|W#AblX9TrMRsJUA!_+6X%mq&*YOGeFgZMq{if~Wzc#9xp{0`8f>x6K& znyo>p+mH#~1gSbz>x?W+II4$j8^0hFI&pxFf6FA@nXcZf z>3lFO>E~C~qU6UoAJJBs)uQmnunzYK$Xy;fI*lk0oRtKZCR)kE&~}4Io=`Sl@FK24 zrf~;K3Hjl7?gXFl;+{f*(G^el?ddt~V*FIC`L9d=uNJ0z7YlFpPX|N)rv-5RCoSy1 z0BW9M9;U|sr8cXW+B(?$8^QW-IbcCuR~=OyZ3B}c{R^n<2U}8vQiYUc7>TG9ReAF) zSe#!rZ>w2^rFb?@mNHR|@Fe#n5=qzhxZkb%wZ!^?^B(hFK&A7F2^$jjxWKxd4vE!$ zs{Lu*`Em2;@b+kK>+?&TcsZu-v0A>xbsr;>Vh#Bz!d%_?s&1i{{QN~mu{~D!C@#N;g0uJ-Gi{6fR)?@6%~990IG@i1ZB zMsRL$VK$CS= zM}n_;*2lD|z+A8c%)&_HVoSb8_P{;*=5@+I?;0?BEmTQj?F&O%KvH1{!5pyjLD}e|?jOVZJ*1x= z+tbT{B2lueEpLaU-dE!g|32o(ycJ6rgY8~;5Yir?0 zW{2gt(5-`NBfOis)0T~zGZ)?wT<|^bz++>~?nY+EiKuelp4s`3YbDjW(yUw`ME8of z*g%rtqNxse(U?!l>WvV(6SW^~Ywn2`(R*Qcd%_Pgh?RL+Wy zjXIeA#CG8dU97vmsESu{KXwwO>$A8aD0%QD&}ubHo%i$R)C{}@xb&v=?-pM#)TcE~ z0>&qoaMWho^it^A*Kds2sGs%^7=8iva{~$V8fpq~uf7JR3Y0ZXiM0|dNlT`O4YlT% z_z)j3dx?yT+`|X?2wY)>=nTluD1F8;?*Byx5pR)hl6-JQC~gW&5y!y$(6$YiiFBz$ zl%C)h{{@IY6C6CfHOWolL%7vik(I}~~9m~`sWNt}D#WGWKRx`r{7 zTq}jU2kw9{s*J0E*sH|j_bkG z_<3xYWt2_dEVd%}0$$;TISWydm{)_7P!jXH7QVmmFvi^uiS&eq&54DPg}rx(B4_@h z;C}quwTI`FjiSK5k5rDL@V5}7De=PMjVT0c77is^wFGy6@&-=YXKP!z=c-?Lz}PUs z^p`tf@cB1~oW=nd;(jW{;q>iQEbMS6*PzPjpXYy2qnI&1zxV9>jTr3y!ytOBI$?oW zt!|qRZkiT`=hWck1qvvyRrLJ(X-dXabIB&IuD2aYbP4pWI;RW&kb9-}CLi;`KT*C~ zqwv9JlcGfTrd8%%VXyp%ya`|CV4zHXHohOkzd)ivQo40!x@?A6fqNn2ja$`Bd)zJ(B-v?f(Dt3(1uKS*~nMUF_}tZ}I=MG!%g{kj%)wCw83| zS{I>kdf$;w`|dY)`!E!#(5voqs`E=q!YMTSau1}gw~?+T!W%1d?nx+^uDV}F0qLzz zsp?;RZA#0Cq>(ul#iH}O(U1bI4KdzHw8uRS$`FzichZPg1=7gNShJ`meEleO>srAc zmmpUo;+NCeEo(pO?#T_Em?R`QQ||9iCF68WfJGl@?A`os3XACE_(Y#%DR*)fV9w?8 zRB#S#Dcr|F)Ijttpz!9e_7gVPa!gM3=6;G%Rbq&fX`T`s%6cXe$RKi6+l`%ZG%U$E z-|sE8=k5mp>5?@C>@syUK{g;LbK9L65bhjA z^!U4xXOCl?DAy2OW-8_di(eJWAsm#)78n-KXiEaQ?NdPAKI6a^0f`3UuA(s0RT7< z|A^P3cLXkPK=Y7lW$c3|DIn?O^Opb%D1ggtT?t(WfOriZIWP(AQ6OuZ!i2#LCGCqd zudZ!#RDNy?*|pN=TE@G5mHya~9PRDEw(k)7&Wr#SQYIDw>CI&Jg(2dWhkFPwyQ@*P zGeafP@WB6OLx0`%#_!>n?wvxtRsXhB^8me=!p8mr;mRM>g=F%>_LUinwPnwb`_J4k zJ-Mhe+c6R(RvWLl2!O){-2VE+K6b$XPgnXb z)Y^9khCdxDm`N{~1c5@38PxxcHv=c*$KkEuAg0#d&1;0URb_?DVM=v{ZciDYxWvry zJE%Z(|EHH_1};TE89L&;0Sn$>UYqfM-}wNR#a9xU{+^ivgSr3>7fGwznN#;NhEUh<-p;4Fo@`r)}_R$^F2z^yidA0u;a-#G(n{B_RvMpdeXJisAYq=FBq z?@&_NxoCOjJJiSfPC`iBv~p`X9)0}Q+%{4oMp0R;j{2dc0^*&bdcmv4kNcX)B{)d6 zz$Rgkw8m&2r)Cd#88!tKyi%bUN@PN9l=f+$7~qv;g~I01X8jl*SawA58(~4AP`DaO z#(*01**CMg>oAZpHsTccEbPpyckYBrL)DXeQ2^+7tPns)3h(}n>2&YG?rH&lp z2jC?F*eDT=Ul;(bW^8O|Q&oeA-Mcv=h|?KZWQjd*xea3XSW{NVJhOgYj=^0duh)YV z(7bmUtQ`9dTGc5Pf@EVkRy~UJ=z6F(YrIg<*a;zmbxlm<9XTt+6-HJgE)Zg^ip6!b zK9d@qW%9@rA!fsw-TD~TO4jQguYM9o;OH}J@{A_%Cwg@;yKVe-42zQmL%9d^FboG=H zdx=QUMCZa{aKaJbS^4V3fzPn8&C-TPPA&W1z&o*BLx$+yA)G9Po{@7Tu=zFPv zHts`~kCA4sM%X!Tt-+)<->=Jd^Im}iOP zAC`pGP6>lCcgWH87PrwolKa{a5tc|cw8bkiZ%&LgJii0!f{^ z3;Q~+3B(v&U7@J6;;!W z0w_@4lO#hqH5cZ5#@e4pLiz8kooO{@kwbQ2rb*giG=m^ePL z`uVt+jG^n4%1hoj8NRB=h5J$TtyXn6-y(hs>{z4s%x>#n+e5ufJ@3n#)baM3fdqD| zYwy{1a9>h5Z&77c{r=D#m2&97N{|>G4YcCCr@|CMiMW3LDh)V($cEY)K$1*x@HUA@ zo+!RQmdAOQ&C!PPw8Qe7M&#glC8c>kwaKU73oHJIRbRh`H|8p1CGMkUC5?8WVAeE^ z7*;tnQdp$lBlJ?;H@dkZ58%NkhLYi7?ONS67C`nJUdNH4M9gc&(3Ca`axulmITMq@ zSy@8{+|l~7EvDAA2@e|x-;W7L8-AdKA{07$(MlM9oX`(V+&DDqa4499*f`P<93R_u zg>_uwjc@2W7w##XC#>8s%0mY^J(w40|| zVY^j0bc{)tC3QV9pE(@C)e+9&t2{sY$kU>0zS?7c<7UGe%Hyr0;EJBXEv}!n0e}Kr zd!Y0O&0}|7_+SQ#?Koo4%c>NN_cRqN@vd)_CwW6n-2l?@0U#j0= z?zqZxIW9-#ZkVId8zEIV6pa&?1EyBk&N|U>Ziy;t$du0P2lLY>OAisj%V^TiV?Kk# z34{gpA}cC*%2Yfpg*v=DQyYvynf8=SG?`Nd1q!fiMZ1*KC}blhUecCH36L(8%cG)MI-T>Xg>|=+!FAgbpSi)F^8a|kc&#w&FKvEnv50^}DqA-UY zq7_KIfu|B2H-fb`4a)&d=f_oP5^1rl_s1Y)FK;Ej#u21cSg+L*)E5?4%iOkUF5jow z!!Ah*wK;Fn32($}R~|_(LddkQjd~k=79Br^6`x{l^ZlpNQ|9@_g9zVk;WcE||Kh$qg^T-{&%GI+6AHtW#Hc$Ok~i1T7NooTv8ZAl0S@KWWO z@5K7qUpIN>^APC)h_xML*^T~KmXHEM{@6nP+#uE`kWVWlI2ori!shSDq^q$IE=$L{=lTc9~_>;m3RR@TGx!LB6G3#hnIVvimJm1YZ@^g-vSeVvZwv zWAd^OM!-)c`U%VZ2`|<$HoZmH_^JL48xU@+#ZtrhfTxpKd)za_^_Vy8R;LE#>2@i} z%YPIFgkALAt}V*HS}&;&wSdxuU*eQF4a9}G3+!{XYl-A5XxOqmS8Vyo(5kx;g`l(< z@F)0%^ykzp2ZMZ}8o|;s>bVqDx>uf>@d+8Rzx5v#Wxy*N$S}pkQv_sRT^biI?mbY2QP@mGQSeUuY_y)5u|SRtXyTzG^hw+%bn+Z$=$W}0&(nDw&@jx5QtDT zFWx!gQCW7z{`1SB=l{~ruG-AxMcT4WUf|$zKSlY6DF0bO$Qk4(^%Yk1v+gFaI)jCU z?)xI7JS$Ezu~AAIdo9nezS-KN{5JTbth{1A)d)ZDQpmU~1lrrFR>u*b!}rOrXIxSD zf?kxssyZ`+a3!Ord7}h5m8Kty$Mza_GY0W_c=~ARh^wb))uc7tA-tuIe^%H3t+Qu- z22#Uk&TG&So*|)Hj-Q#mAfqPu>q*bLixc zvijWRX*u*7MTprq3g9S7%Io4=_q{RWa|rdZb_Lg&K|$0&&e`E{O-$yRi&?< zf8sPz3Jnt!D!v}wjZz;*czAhFAeCeVk#!(RnH=k;B93+jvs5-P*gnTWw3pL5ks%Tw zw}zzBs#5{88!T%eoI%kR?1JZj!*}MxHC)I;cPDY`S%Bdi<=}nb#c{KsEDRN+CtT|$ zJ(JQA#P5@{fYR9!Bzyl5twSasF?APorux;mDd0jIuQl#_f%Y*YKp|KMh(!g6sHI*( zi+RQ=*O{dP4*ci=Z_R8Y-JM*&urQt;^I215C>W*klJ+)sA3#pq4S-w z5IJ6-$#umHWC>FRU02DBQ7Q4c=2~axmgl!KfBiGCQNYegZj`d7Wq`?IE&w<;1|bx9 z41Y}GB6;gVu?GZctbPK!q(g@pp$P#GoUr36`p&?-jD=!~xQVkZ<_ zQu`Ext)NhOj^f*bwC)SJilet=EKMV(ac_5?n>4rr(^~L0miV%^=@|8ybB`HeB~U(M zjjk7Z^86_`8oIe)U?kuxRd%p|*D#gXvR80g7V4yZL8rL`JepgmS32?D8l|xOh6o@( zFQu^I=(NIC|J`t>RE5~X4EMSSh`xoKI(yYGdp4?EDHzJj$KZmv-uPPeQPBWfBKx{{ zyf&wwnDW=~*d{6&Y&%?E!>I}s>-AX;D_cwvdc?o!%OAn~09s%ylD7Rj-&swVEu|#a z&}27Txh?c_A6QH^oGU%|iyJ1=*enL^1*0Z_?hr`^#Bv-wM3_{}I}YF$jOZ;_?bYa$ zZ@`Lze3S8Be9P1f%)Pf?MC5g*Fyz2NiPT?N@e1R(glCkSh47VpF;uvM1O9~4;Uvn> z1Ov+ltO z72?(h*e2M9jPL88R=mUU@z78x{t z=JFR=-~?8+EupV~0aeI;Rydee&;@phNr4)=Xv>Y?v2q@(K>l5PaA3ZuSW zH{(8OcAFlm9kSh^#C?>V6T#CuLBhyT9y#zi+M$tVy#TgV34QroPLYuYYJs2TJo?qR zY;rOyX#VjcW2S#%!UN=TfCy|$j93Dbc9<{hBiR<5t+DN(VM*P0N}yh%w~(feNl2dt z_OZWhCY7G@7e;N?!Xm{*De+me+#8B0xifK9OeAEicZpdMep5tW%~~RFUYkt#-67~8 zLL`Onrc~FfxLgby3)4Hm)Q2Iji>ySKcClF{%^Ai-xawxzZ`{8J5I>#!c$Cjb{Ge7d zx>#${9dF|=hn0twXQh(+y5yn#IPORNcfE4ZLk%?tHAliI%@mfy%SI*&jh6qBpE(7E zfYGX7rhftuGQ_*A{cnQ@I{$g&&=>n>Vl(YC_bf0l6#rJA&VR>e9l zbq;!E>b_2)=%Vi$*cQ~iUYllFzI}_#;qA*R5HHFwCAR7=g}s9J7ql9Jb32!^mZ`?| zVrx!83G|;2LJE$>ifVz;@>~uqVia<&IjheoOx1$(2M5WI;*UkYUON5(2Yd8I8V3CG?K*&k{r=FltB zKBs?F9O}tPqc&qsOVGLy>=p=$4kpR`^S+X|?2){W$=udCf~eFY9mqEJ?@t`U8wPuY z9lMh}NW9z%{)>?&teS{*toR8I-TeamQ*0QK;y08bH-#SovPg&{&{zzLY`8#@SU)DmD+*U01Yw(aOGR*#-oI4g2yAJY5LU_4 zQF0+J43?u20AgM~c<>y*LXfa#$8m#tCT9i*hSJ4xRB{o*3T(MJRNP$kkz|p18f{W2 zrZ8mU@nG8)3^6hGr9ax0n7HXgM=1`sGpoy0IHJajvokfM?Cye{Htqp$!!*Mqs0|PQ$^l|@EK=k#Q8`O% z(uQ~2D@B-B2{o2vi-t0sFvQxm=`M$TzGp)P<-z2kTrKbzg^!CSU4EY!F&~(o7p4bv zhb`7Gx~*6e~TjWJYH z)l*a$3HLBSMu{{8rQyUshVJ5$_IYr8*q{4v7Jhr3$adLuEjzO$$8hA01!~}>{DTQ9 zR%)Uy&22J@9diVE%!c|oBd+?bB9rY}+eA3XbK41yaB^DhQaCp9&rc#QzVxeFpTj%~ zBax)-rGXiSV1(pqQQ2-p3sUQu*s+bhj!l5;!bs6A{AdEFWIaw56glFx`{Z2-yr}_5 zxd9jOjB~Ax*X$o_+!-D<9yxk~!ZTB=DmzG3h4w0C_|u6;-pKMDQwi{FH^L;@iYh`& zsIYF#riu(FvyGYuCL@e|Nc8HX!O%2^?-|!XLy=vA*&>VCqslv7<w{-dP$ zM3`i)jF!Ju}AIzFZMh! z-2?JBCHYAG!3|x?Ukj4j9X?4Y>OwcLKp!Qahyd+Wmu$i}6A*|&xZJL>X5@M5MNl8YMU~;~7OY9Y>Vpr)2+K1VxV(C2vZH5HppIJbhP9xP6%Y zX{YyzE|bMY`kiz6^S_X#-JiRifY)IRq>S13DFU3y(!iy+jA!Wn%3gFvYqHqscSTeI zGy!mHaoC--w;jpA%D_t^g&)Z$Habm&iVJ3gZ@u>D`{nQLfBsj_o2yqVr;P}{XMfpV zSrz`d!D-lJ8*Pa-dOvEv;)uU9%c;8p%F%+=wEdGX_XQvEq~`_*NQRHm6rVEht(QI; z0hh42W|v=iwybvjhyD`t?8MBpSBK{9HBC;~+;{`u146p|V9%MwI~j*^*>22lFrh?@ zSG>Hly#M%-9Kf`E%NVryDsRTJY$ugOrkcQ>ub`B`*=M1@^~`}(((sU`g}z(34=!Tc zHP#2k;;Hc^QWpPw%c}2YSWPD_ex%_80+)^d93`zE%Mr7C&+1{N&b0F1UpT#{luKzg z^=i7j!By-QiXZE>P#nx$8k!(sz6eMA`KIDbphB`yr{-W`ZRmogU^9+1uOj*6ViCYa zeQX;Ci|u&6-enXBg%dAkriN(22@YJx4|l6StlbCLErZyUa`X2$E#nDkyesLRzwFBOrnpbpp?M#|J|&kbd`{9=pm zi^JObM8fc_AyPq{FB$_20fsZZ?NB&W^TFHw21Nw9wEBgFjB_H9otE)QE_D?6D7s|m zjd($uD!>f!A#kF_OH{dcb01n$)pKU{EK3-CgAWgpqeF+ zPghs=PNg8Tlm(bUI%&$Jl-i>46!QI9K)Gk?dyP)wp$t4$R5(4ABuhS@%3@n_*?duO z5mUS4qpj+o6)}cXq-wcVqE*qVN^0Qg-TpALDI!?2{>xU^*!F3T0^+jVOI?#nVv1NQ z`EZ}@@wn6AI7EtO3_1STb{LwQe;mWNTuRNFJLWb zX7IaDBLTyJrfkoa+SNdynuJxPOAm!Ek#5*m?AHKA`*vQ1GuYY3I-Z@U*_2J6xGs&v z=L)|Fh6jlP2HFdjU)OpyQtENbrqD}o!nnep9yj@vHQ=I3SW;3bOK55@r%DQ4T3z!) zl-&b|+-=!6V`)wca5NYg{-v;-3TdW(f&#OntNsJ7)uG9S6=AT|Wd}L7ShQn}?ZmBI z42jMnJ9erwD{e<1ii(A_>+cwM7cRHNamL^LFydl}whCX6v zSm;tqVVim>;whNS#!U?m2QsuxS_wtUY)AN1%4L0PB%vkPCO5Db{9pDjgAf`{tS#Q2E$%BAHk!E^fv zB`IInXj_bvqr^9W_fR)P8~|m?X)CZZ_zvI{RRPkNZLMd1Ug0A~P8ZN`EoZa>%gnA! ziz*bB52|OmmqensYq$Duvq|yC{2OQd^MDGzVn1;`LGb;TSSs42F7t5*$v3OtM1S0B z!x)p+T`XlUb9GFRc|hQf9G&ax_EY8ZZyoXX{mr?eC#m4!<+8vV8@z)1Dd>!QiSc2y zGXjV8pRY!3X(;3+iTvQA*g~<&8%CVlmob8IbMH(HDSz<6U2VoaCxll5{>&_QuiN(U zlE6aIbkX#KCI*_lmv71o52*T$XldQk4AmiPLf;Ck4i>-yNEUh7jI8b7WqTLBJ0*dO zYJ)RXPcrvO9?`V(pjvhaPXsdV>63q?i(n4%yX^UA+~eEI?3W-MA3=Y7CB*z7WIK^K zp=6~+U$Q`22_LnqWQhv$bJR0ms@EewNc205AZG<)NVdFEPGG2ud5MEf(lLIUjnMy! zj`@+kouV3D-au8~*LBbjk;b`W`0}s)Tg7aJv{La4`Uxe)wC#-JriJpg;En6wIN2O`QE3pshj;_w#$v|D1Lidz?`yGO~J0;olvU;iRZ z4u0w+nvatMZe5oaMT_S#AJu|SQCR6?AM;E^Pf;vyW0`WQ$BLcOJyYU#VjPOFt5zrv zl64{ut!{bSbr^4SPA#vOCU4$ws6MvbtJn$k_X;oVY1lE+1uU?HDJd-I1Mbcu=9GE@&YrfxF0UyVyf;`9U$r%v*D=0lMHiXLA zGrH7jB=}tWx%D)ZbljQ+@UHEM#_Kb>V%$FQL`$zU!V;*MqBHRFP%6JRsg(^*xF5k# z^8ectM`lGJGa>Q$Fc$Y=(3b$x%YR94+8;8ygf_!U*0itgYG_OMz7B|Is$@)6nj}mc zo?TYW!?hBPXR^O|tfrV0T(pppf0eFKff6w}fmHpPYbrq|ye|smm*UstoUEt!qCz$Q zJJlmtxlT`?AV0gWd@zS4D_!kGrpK(r26*#-cA!d&o1WQc4TnR`l9AbUE{WW4WPibX z(SdUAR4_x4Unup4Q|(j>4OH^)q0kpp65tjquZ4@p)E-94s3I-yluTr#D9*%J?yv}U zg`>|?(o$hV03XP(zp!9Mar_y{6|5~o+lvdybJwkA#1pDJ$){y|k@ljZ-9jy~h-q*y z{$#ROO0FGlH7=qF=kIHMcb`xXI8LZFWhyPHDzI_0-8`=#hqoTVh?=+yy6f_EuBfEB zd$;fqiSBCgR>iu|Dl`{XrV9J&m?mD_WqLPWF>xzxet@6i{@f({?Z^w*Bh(WwC%*gX z%-VjX+H#cdO2r;2+(UtMKzd@JpjG*2O_&ioJ^aJs)}HOf47-qTp_Lg$ShJ{`0dKYH zF<3Fr3eYxw{}h;Sd2(xedr`4oFxH!VCAbDQBxO?!kI$Q4i%PZjjRqpX5J7_&c3O44 zk15;(2)sjDCSUYUZgp=tRC}}&uktlFWtA-_Ij|(Z7PZN2PW|#cd3j@h`T8OR1!o21 zzSuMKPSW-4Sf{yCIp6^LN%~<)=ro>?{c%~D)h|lapSZB*aXyeZ{+%by3Aa(0RJ$>` zJusE!YgTXcM$Nr;vL4+eI` z&+ps~kFLP?+V_wRJ;9ApZ1eKta}uVYcY0t3UGL;}0s$2F0$=dHJNpZtg2K}Kyjod1 z^{&~~xc|&PlH{H9sgL1!ZyF?&rMdGmxqnziC1J`w`5U)1+qrJG}a~jJ*_*15c zU+Oz7WUF5(KbAP;E#{rOGE-3RU$f5=$5nFw@w`;Wtu$ztv0PTH0{y!s_U9_ynIwZc z?97*hK825XasS_2%j;>+78=QacYGqG@8itQ$dVlO8o4ox$MxMGMG0k`9ZT;ua6d3X zrsZrnt>N}Y1CFKNv~m8%-i`ZDEas@4u#n1GJO4FR*qy<%H4nZJ9VuG2Y)mohF;+O4 zkzMyPfY(_p?pvhrcd$#?|HI3;3NCWhENmXjV;RYn9o^c@_62mk)hiBuY^%kL7m%K=d+_TamT%2>Rd5lb%>2LXear~@U@%veRdvi z8ne*(pPR)CC&f$H@6}c(X~rXOAU8JxzDm9}-yGWp(bE^JVf(r%qsywu3a-XyS9>{U zn01VoD?iA!BQ^K;;`xE?W9yBm1$$HvCPcCsE0r7nZe2-BMTd#qO2z6y_S3QX^4#Lm!#-Z`rJwe@{;m~^6q>sI%4)z58z2Y|1NyQi0& z%!+ZR8E!>S6dh0r&qKOZ;a0=I2BY8 zaZc@Mt_&4s`RIYQ)d%1vH?NEN{ZV&u&g_ipClpNP?$M+6RuKSX7U;*R>4tzm@K_64GU zE_A+i^|OTGGCxz?_~t1;P6#1UXJha&V>UHY*GgHHW3AJGGZ@>*$~)R;H+D2P;OoJ; z%K8n%J=Tgb)7&=}0~frnKlCnDuBowkp!q-3wrflju+UDpBaumzG1G*eU+JC7%7%UgSkVnyvTKo9#=@08>IgX32Ht8U5TK)gq91y&CSOD7Y!&Gr$Xqt5sfuo6 zZUw6U_vLoe?UP+c902kjOjp)QL4N6Dync+tqd@Cv_#r2 zqxC8@c1L}i``3Amxr$2c+O5Z>sZXeJT{UnUQL}@6C95GNUIkw`xU9D92Tgu2N6!KF z#4#h8tIu~XS)xsHYAr!9bJf0u&nuSA8A{`lLP1J40FECBJBb@c8_S80%NuDGPB$~A z`J|k$u*dw@?wIN|`TFlLrcmL%U0Ws=;{-M#$CflZuQjFz@*6ogYI9;~;olJuc;{xB zD6zEEuHcg-4)Z%N3zdoQ-o-sf=m;MLQN0cVg8KyN`YhDv=Qh3@a!Hzx#0DMqSUX8> zvBYE{vEok)EOh-j zhBcJp!Ttk`8mR6wEjD(}<}Ufs9Xi!&-bkMBi>cO@>LN`<$2OZ>6k!#fxJa95UBjwg z&e{UQpLbV6?2rW6A;>KH_yzta$^*JBs0rxRS;h9#g&&{j|wUSH)LQC`+x7hPJdfBHk5 z6(2hC!kP>HyomdE35i8ANdII)Czx@9cDeVwVdx-F`MNS*b-aupd%_f2I_r2tzByOB z)ppfLoQ*ctO;}3Tye3=n_R(smzSxt}QjjmpsNY`_pM5X;1VUMM7LC;4I4_I{X&b0I zNr0bhaoil&e+quf?x^fejUkG?gc#N~W~w|xPN&=%B19*!*TLz?B6IiH@Oox7 zfNiosJ`g8NtvtfTgr&HFmv@=^I`FxGz@OwTPf80-jlhbndbo3#e#tQ-R;&sCsK z?dDn0h{u;a2+AA-=-0*W$y0un*`#cYyk0Ky=E1ghotT1?^C;DhaWQeY>v6E?fV&NT zYsa8a`xt38X;}jq_(SY##9H`kurKr>$npCB^po70mfIo77n9pb;`3Hj)pKJwZ1GJN z(h8#M>8Xxi!?m%n0~`x%9((3HrB1V-yKp$>8U#oAcS8p*3_-qO0h(@@>LfNOpM8-A z+bUtK5mH#+EpB7qs9YcH=U!~Vf3H6HtA41b_MV%zpgjwD zBr=hR=n#o3nJ7Pfe&~tlJ*|~1S{9utI(ko@T`fAn|5MU*2*p^F;{XeQ;m+tp8`h`! z=>TLo_eFW)Z}>S`7@7T(eQ8!tbOTXtsYToP&i>B2YIXPO?z(Grb^X=7s_tM%w_oLy#$sz3a&nDa!nPan z2o!9yYr++pv+%|at9by?V`>9dPxFoegR{K0FvZ3OWT?m_ABW_7<_SdhMPr46HiD*2 zX`zn=gW^%b`cwMJ>^CfwAGF~Nf2LC4mBb#Gmgl`-)yFa-4i@7_)^{B?!}eAXBCr5V z@qb#lH$w!swh2y-?_D*mjF<3b;78?RCCeqV*YE`1T<3e(h7qBMT)vZUzetRs6a;?# z%JNyhvdC&5)Kt?(G}qh_P4B!1-YZLC<+OZOnhPWu*For(Oy>; zI!bUT4B-h##eTc)+a6+m!2@V*W5KD0{VGeM-fnZeCXi5ddg<((acU1*If?W*uhi(y zoT_nVZQVg(h(Gc|C}0Ufa9sf>Wd^IDO54emk#_x*gsY@;TOWl@;qBY&_l*%Q_eIS< zAgCZ}TYFY*dDVbQ=Gu{O17!d!~5W*VbD;*qpYV`V?rf*-EDyHo@+xn)PMo9&v!``Pr*9Y&=*S5MIL(!(z; zXGN-e;|S?8=yX`tVLrQI5Apv27F{FYwJ2P`S*eL7A1%fGB;d#oAU;b`Y1@z6@y#X? zdaXXfb$6i;Rj4Ig(mB0_wmLs0B8Cb^z1O(KI6Wc|8>=m2@y6lPoeoF53!i-GCP`{D z8SOOGFR9K&*!TlBzObyb^p+?aR`+A62GOBhO|Pq@+KaPwe%De*_xHHGAIGNw)WOJz zTMe`OaU88Mnao3XQwp*_2)JXXJJ*FJTyW&2-HuJ?S9#E);WCF1Hp+`#Ccw8?yBa3L z4?)0;16ryGW^1R_S+#Z@6P8(@d4B&y{w9L6V{R?WDH_GRZ!>lU7ovq*6re;&^DfVy zD7fv>X`LxD)jOSx!g=`XXEJ3aQzdR|tHelc@wCPx+;Q%JCrR*zS8GDHM=Z;Y)A}RH zCkRyS={A&qA7N&HpYEW0V(vkC4c(TH_B!km*GM}2yn*^_g%a0P0g{z686K=>mWw&@ zrncg*_T?67b2gHf33-$11T(A6C>EY738zYT@TuG$p;`6aD(Zq-%dZeSCZ zsE-1uwYEE3?T+?NWYgVh%Jxdf@8xEAxw1i;=i1L+fkrEl>O(lSQczaE)gSFxPQX!H zj-Y5?HiLSRtUEs;^6t(X%c0V(-Tv#s^lO?7R#}|mr%E#}^iZCqWsJ{@84Uk?rRMddC97MY_Mk`$ ze5Dcx5zcw$OR2=oJ#YC+;Wtg#xT-CyIF0OVEx7Ng_!)JbtE;T7q+M3k#*8Hw=G|m| zAf{i@zWqC^jL3s}3EF>ff{ESDegFgVl$meXmA&S_vtjx_ zwZ0KV_5RiHV;p`QxqaMpDfz}8Di+tJqyC63hUnsUJ+VgAnkkm zi-~B@K42b_I}rT>%=JZ1VguCfZQYzxZ*miK4RQf-j2_v&FX3+mFFESxF-UIQLWDhG z{Ax~wZ$6Z#Lt0X(`uA?p()^^@e3@~@SKMy&1N@(qm^?67muALry&knkrfWW)Ae%<_ zPI~*3nCm?`KLD(Hda*7EH%;n-dx&GWZy<+Ao**MbH{*xyjKb9n;uCtH*be0O4Fdj? z7AU=rwM-we&(t^eL$D~`I3)nK*K7k2+ASo=$a=e$J{nQO(D4am?e293WsD!u5{R3Y3wS%!R5~s9#ang_0kvxvHia5P2iA+EMeZg8gm)fKYQoI-YQ+TOK?Bc4 z1n9G@0>%ClA5n*25G)N$X%+J+w47pZ<+MAFk{|K_&mj&+fI_tg7>XXQXuT7U_%*h} zJ>w_?tw^&DJbXUgzJzI?$07a~@66{?B2HihNLQG|J3+n&{_8-t#mcr&!L}I0cIfy` z&v-)MTsWz4HK&Al82C2sP<}yQ2=2?^nFKB8<`a><$XiZC0aOG#WboYji9|_Dzavs# zSdgHt1J5>J2P89%dw=HS=ygaFidh(MoQNvVR)8y5mPG&(%1S))89#AXJ`wmwko-G7 z!e06F1?KaEIS`639DG+A(Vf7J4{9N0d_V;8NhBE-H8nUuB?~Aayzr!3FmP(A2pi0D z`)N9$A#DGn9@~qzrr^epqYj;6%}z-H^Ua>lDBJ8Yu}nr0afHtZPD&k-2|}~KyiPc| z@W)Bv5^)yQHnBH=N#*u+(U)Qxxm==L8c^DSUc1VtI+IEmj@vp=pwoeF=k>MD(wufP z%Tt_o(-i?Pjs8!j3yaJt^wVST-`9TdwFOPv`eMQhtKc2ajok*5iJ-F$^d^RV>46(-pQ?cZyjUbG)3)DBH*->_`9WP58_{B+yAF>Q47Xs<)~ zuf(Ft3Ns!8f5gt#jQn=3uoUl0tl<4dY4)8NZP#Do@;ZTse^;4*PnlnsV!;k*>_C;g z3scsYC=-?{1Ih0!2reD|M<#eu18Q^3OBntf+`Xx%KG<}CVI`i$45~E^7RiCBVE)oF zSycXU|W!jU$ zy*SuQ`}zsTr{N1yz-5SqMdRE0KvF-&mRHR%R(2)^ zFz3V^jGVsR`-R+Nu;xD97ba%-GH4MR1kdGS1DJmb+OYu|H3<$I_Y@|?26)nt;8!g) z#zy*#*buEWLFtSS3?XTSjxh(BY`!fuffJ8W43692}jqocWKRRMiALRUvnfD!yO6GQUU z59V;~mwt*uC{o4ayT@1R`vjg>tZ=A1bsIf0n_Wzi(77%yGuJkfsiO%W@Z-)~oJ9X; z5B%d$NKu&g06Mnj*dyC~8b@$aNAN-JpbLmTYm}SPgqbwrU1`PExPT8EPG}!ywoSrK zJO`3V2h^Lr39!ALy&s?2GU3tvR^@>c;8Ydguo-i0c3Z!31jww z+iI*=EH@|i`~9QlZh-v;oZA}`f**y1+QA-6g?Y~gWZKsI$=3apJ462_=Jk;II!2QI zxIPOtFb%g-seyB`I!p7fn#fkh#>p>&{R(JES0PPeL!>a>nyCAZIk4{f@SDLh?a-MH zNX&aPQisC!(0uj6siIt~7RqRL_UYIL#naQNaM1)Ns5hU7Y;F$lQ@g>m*=`7EySpQZ z#h^*k8C4jEG#ys7*{Q?Ft&Mlq0vp3L>6lk0s%gY=8tGvI2+WGdS8y8;mKPpaeKSJ2 zoG4-S$p&cL*dtB!z{p&RE!t%cV zP))Nl9ZtxdmP*a}V`QWT0lI7qt_eYJOeCr- zeryq&8w84u99qjqgg{qnJ9?xqw@E!lGjba#j{AVXqqa--RlxiO!y*EXO@W9Cu5l6T zh=^qjwUn`pB90YGX}<|0)Oxg%R~HO5?FqN|t@B`D?N7oHo6rZ{i;5%ewfWBRR2$PD za6@XXTC<|fOoYDJN^=uux1SC4z-BPXhAT&mE-17I>j=b9kuZz|8mjtnG4>MyGDu&w zqMh1g6O7l`zSd&Eb~x!T@Ub;~i8wW^5x1gwAFPqDw2IL9KF|wIj)ZqaiYD>G5MJ2( zTX%AAoZPtIGUs-xejf~^y*)1ux-*YfquK->-J?94{VMS3pC z6ILhP8d$6`?f~F!$lJviO5cwVol12$zvxhoN=(b!8h~pI^y-VYnCx2E9XOixdXOF6 zPApn$VRWsWGj6#B8w~Vi{hATy%PSh`-3Xc&sAGoLMeklncdLJ?B>V$N9>p{I`9eA_ zN_uPtUf+XP zzt}q5$6TN!Tj8bXf3Z{0_*sDccO_)RG_b4=R#rdx!k2!oz-LAl@B6G;7Zh+5XU{ty z4DVoeQ%$lyhTV|32_0!tUZOA`B~O3qMEkn|F~t*;;c4;Uw@?E)5{TcluC0e0zY_6+ z0966P-34WGh{KfC*8zB#wAMC(9S)tOz;2WbJ{XxDyZzWc2C>v;@M9%&11KV32h5a! zxIvN8IT@9DCX`>U;V#Skt4`pAis8DYZYCK#t4?Of9ue#d3<{#&fW(Dmilu$A!n}7T zhIe!n3%jIaD~+}7sbdQZFI@eT(1ouLC0S{Yu-9h6GlD_SJ{I`YUZ$QKzNQ7WdZUI# zrjgkl(|o6h{e77mUGwm$()`qrriCH1kpo9NBpz-EwS@^{Sl|FLP$vT}Im8kun*nM% zAj8s*Z=qp<9fpgcB{=C*ak@9f#FS@j#3MeM;eT)?urx7azcWEII`H*TBAVO>dha9; zcmZ4bl|lIktIu~7NJ`Nut7$&Dqn-282~w#X_*Qcfa`)#nq1T-X0SbtT!>1j`htt-O zW~)XhEB~nZTq@j*=Gg-9bPYL;v&3+pI)fJ{o?sFm!z)D*=S%d5-({zUJ9-nLx>gH< zN_pD<9^_=k7>GAv zND0lnu`hr~a?PRaP83?);qH@dd*PP9U{Y|4X@W<-BMZHzns81d()fF9%?h_O9q*7e zPA;oEc*@te5cC#Sz@IooYXKrS^uVAQ`Pc(LbXFYS_>QVN&Jm3<+Sq1S^jA^O1lCpI ziQIQj(yCLoPL7p9*S0nE_&>JanvmMusYbEeubDMCx_}b{I+X!36X30eg8GN@JS(^; z=hIYclq8t(;+|ZfcOl6#cE=j+maz^G7qYA?#MR-r1UON|Ez@XXAHNIvn_x4iqM^ z=|msq{UCcbCHg7TeSwR~x}vgD;nidBSuAY|Z3{$N$J$Y}t#E*$Kw>AbfvS z!y;?eFskUk%^QS6-xHTe0rZA4p!5dyW-s*QWRw5#m%-g= z$9-?iiG5*hwJ+Q1LUP|=zTV`lXDZIG%E6STHHaQ`^}-8xAm z9~@tzaQ+)k-kX@C5B}<>jn!Wp)z}zapF1b-iEkh7xA-ncd-_F4lMoRg^ZA(%wL}>L zS4Q&mgrD^Rp!;%y#hejDuL$RgAB;iSdl+v%5PG4%WPD*1;dDJ9m_v31TW_dvI<|m< z9)L2K_(8fo*otp?A*KV$^;#Y{K?6uaI=Gz1JMqNH_STZU0`i6bpy5o)(&+y zTs$OQUn~9X`>h8yZhqb%`Ve(N=fhqPVh#}Qa_@nc!4W!9*ozsCL&>fM1cpN>-)x9| z*kXq@WLr3d$C{m;(sXrdauW1zndx~?bUk{}i4Hdw3kB~0FbR5d3%HT#wApucfWHJk z^9?epayXLTL2gh1vA+04aGGz{2$>Fk=OvjHYsk_T^JAsj9^o6^PUem6ArVfEK)rOG zTYCwxiN4Dyd05S(=iQ(IxWII?$36jQNW( zja-_;q#THzO<&@MXdOscvvuH(CiuoMwQajxAq8%cbVp|>mj-hFS(au*(G5A%b~e+jJ75G>O(Cs8@`z1CBI^b>3CM{iz)%y>*2{{? ztyGqR$Fotb>W2)i8IW3{W$fV?iqh@!+6oWeC(3|r+H+ZILZDhMKiKu8$N~RV2yqcc z8S?Gp1ujmHpP79!;CvOJHoCI^+w{WAEx9tBv5#zNus4Y04Z#aGzmWP93@)^87xTf`GFTXTuze}~Zvy1W({QAsd)5ql2bOWCgpf{FT1oJxrFoO!&t|elNf^LDT zTd#cqDIa0yAte*8E`p$k%ChU*!2YIt0j?kIyC=>R-7(CQMvQ3GJ=||oz!7p3J-7=3J34IdQALO z;@{Q`#QYENl3As_pL%|(RGI~iQa(;f1Ia=dyq;U~3Bmro;yXo|dMDjEbOK^IkNKrJ zwt${VWa7K{M#aHjSKrT>KkDjDw_aCcF8`z8}NLJ&6Qu~j?Virjx@dzUl# z6{6c^WvL}(r=44&%T0Z2ZH6n?3#O3e0RR3`y)_csq#b(SDwKG8PV!-`@j(9Zqwe-x z>1}wY7i_0@!iQhFJW?gzwdA@etF;jIA%>k!`l)jdw z*^&6?91#PQY;~BP5yD|q3s6P}>|n?gsLBIo7CC7c*$&pVpXiX|fo6lDK2W(o?~v&M z*d+4W)pPuQ@vZwNNdwwG@=uvEFF>n9`7+3{K9+mg5(}%hQYYY>%y^Q#Opl+DS8jfU ztr*B#q(ju6ia&|3b%<`h#E#;s>6A$oI+aInpWw5)X_F!=k{a|^e!f!&;OFgE=%Wu{ z^N2bYIwkHUZP|<5krsnuXc++N8%x>txU!LH`4ne#6>m8tP=yo7*@WY;!a$86#3Ih8 zo27BADBRzf0wO$DNo94!v-(#gSXOZ?%Lc`1FpJ|!M7LH;BOOy6>YO5p8&#M^WW5zl z2+`~YKHK&_clJL!*F!qB3!Ds5(l<{<(G(Pi1V}b%HZjrLpcOZ@+(&E0Arb8_hqRF{ z<;D`sNyQYUWC8&tL$C?-dEsaru%^c*W2kL?7Pl%HBzaIQLyL-bGXap#9U45SY0j<)_|mc^aq1+=>oQXwXwqrYu_d!?65<4+-T=injLdJ)SkK^Mn`XQr z^~xT|mJbn59lGBnJyw|_$@Ji=Jh0n`Cb<(?ZBMBp$#}|i4B@AWXZm!)`*h;_Hs^G) zb@r%_q{0)FJV-(llxzgi+rgQKJLgpFodMLvbDGYgZCoKKBQjOCwGtk39W+e(Nf9F~ zl}FM;&?w1jC$xMa85bgFJh+-#!7r5Z@`F4 zT~a{i6TJY5USRY~ixG3l75Vaop>%) z8=g4@eef?AwSme$qeAfw6ueS0UMU$5REn)Q4^&L2iUZ=5MWe)*WL`EWf=n7hMdBRb z)c0XqT~RlGRgP7Mkbr;>n9Cu;c{!g5r?*>z=^rrmw7+nOc&vbwjG3JFc5QI^f`9#B z%l4E@-hWrf=#yObGF#>tCwA~8k9Z!p=bKOHm>_b>BsD!o2$nQ`j%)9$znoZwW~ZAESxK(gvBF}c*<(Y)0kSa596~!*U4^QV|{aj zZrDd7JuP{pBvIN+V7FAuiM|qSSxveLAH||t!#aEN_daKDKQW&_C)xIXU}%`M_k=r3 zrniI3z{z9h)D>UZ!y;0AZsT`b5wf-%yvr4R!#p)eId)1p7A98Dit5UMDlR<*>Sci{ zmkt`HvBF!GC~-(-LGxMmjF-;?L#68>4)#D8`c)=14VBDdB{RQMn66N<)0ShUU>E%D z>+R#X3-sI!W|Hs1)e$P9d{gfjPV@Y9eBdb+9qSq%>pGJI))})uhg(n}Gq64s@aNNF z_B5sXogcCjo|K@&EJ!&>iw9BQhc5UxV@q3LcwXBFt?WS5^fIWwZBVOu=I0+4zZGp- zAsxw63!REm{US6wQGy~;)NH4 z#VqKoEzp$4A_}`Y3sI8~$$EI#1;G$4hH<@4x?}6)S84N&UyZNn>Wj0H7tKeG3!B7(Crm%5M6~n# zYJRWyM@~lN+X~1YZ}B%Tl_LEF+P27UiR$GzD0|Nv{R;kv)=RFTU-7^pb4b z?{mQgB-@2MF4#LN{6vK=wXGNViQBcn>yYEZXp`1DSh?`-koiEgNz^jXU6I#W6241* zYUm-ozV%+ob7Xgv$18OdNjlWOS@@GZR3(ptrbQ+10dL~ZeFAxRNZBi7$|dGJwXY{( z>D^Gngj?sWCZ2EG!SfrGRs{RJP}g##R_ouCzZ-=4C>hW;fz%FA$MG;z;V@I;mF1Oq z0n};)A_J#9Znyi1{qxKgS~>F+7`FLm`2QtC2CP+2W z=|v(q)fWn8=j3owKl(@d@zi=UqMFh~4C){7!=m7NH_CV*tk9B09W$tq4%!T9PCl_l zGT8i6#c#CzQ$OEwU)W#cBcW;H*O|?Vn&3YOO{Ut$GCtkZKNQw%F;w!cK$53*rLs6> zsw(6jADm=mKdX?lOdGX7_z>E}F3L~RQDb`fZ z4PjPz7vqbklqeKJrcOeqx|@diwXEK;H*J)7v(A1 zx=8n7>Ir$>I)3+A*Y1K9-V2~aCw#;aLCKI8XSBrv@7%EBBHZUigDM4gSD^z%>X4!$ zEk2m^$n0hucdCG#5b>Cy1}s#JAgpmowJh6wdQgPAeFR{#Le(-6?eo*T)bwXLOi9Qo z!BHs{r+?t>Eo^qP#(b=UlQfaD_+Cbm{dJAuEPh*g^|LE|@QQNm$n!l5Qnq99gO0B{d% zPe_`cS~HwD^neiK7q-c`Kn0GCWs$HWl+;8fP=jw!Ntbyj#3%xG7#Tl`3jNiY1_m=j zg=4s2fXe#!n%QssWUykd7ap{EXZn(Qv1vsjvCI;z;WCX(=9oT1BMHxGLk4v~2{4^j zKa9o&5^geetmwyM36DlsC%o(DzSq$cqH~84Sxbk`i`dX1yTsN8a44sip~U< zcoK?uB6Gj+98Vj52Q&C0GPjroN$R2px}pc3qK9uq4`4+PBt;K*c?CndnY<#A;u)tT z_Bqt{bNaWe=6LdwD5LDiqix8e?kJ;eD5LJkqfd_z;-sKUwj6eng<3*9ye*NsFTz82 z#$!pJL0EoZ;D`K!FfVo9O7w;f%vlg;QY{cpOpt(C8I(ar2IP4&ObyL)P6%jJ00K!<49oQM5xP^_Qcor78=h@c zYSXhJwCyJTI3*iQPM2IdHIW%7iqzQT%;G??AOeln%eEaT%ygia0yZ}EK;&TR)_!k z;v(zCoHP5ImP^cfVVAW`-=)H~@-{mM8_ZI*6d$HDaC&%-Yj_PD`o=@`z-LjRu`Oz2 zIDAN4lbkTC$s|JFIyiCZivFB`DuoR-U**HVVoYaH!|qVBXjFT*JycZDua=5=mHJfr zH+;lp4wF1CSRrb^8TG6JE!ci$asch^;tvsn+(r~Os%+T} zUWjE`Mt1_(`xw<1JBvdZQZpOY%+`66b+H+Y{tV*eNltZ&Or7x$0;o5T(=_Zx^GIrm z!}OHm5m)7iiS<`}d0ymkkJ{hN z6ZaG(+d$7r?2O+i8JNf!n4R?EpW$u+p0n5)>?j#+$Qf<_oGH9Zqz4jmfZr2?-J^ir zJGM2Pq8=GwLy?luz1TLl4v7m~O7Bq=U3in{$V9#M@4{GW&~Pa4}_e zOM($k$U~l3hZUYc6@0{(GZ-qBd&8exa1%=n$3$87c5{jrc5{iwYX!vi#ErEj5iZSsRyR2b!l=Y@_w+d^YejJI)&7a0C(A67ShKMa||C}wUxGjzNYrv8E_ zK%pi+B_|+4YnA<3jIn(8!%#L#4LU*QT*4y>|2n6r^#gU4j_Jt0wd(%IL3Ixox~e%& z)y#vPcBC3s4YU~+nG?SSd46GPh$*W-))tR-+4QkylGSrglJ|>TWS7W$)qR>4gA2rg zRr@ltNEJp0A2jn)M?%d^u%H!Zi~=UnB<(J;D{;z?=mM>pz~UwHGH{l$4DJ*|h>;0@ z=yfgH!3=J)pS7&8jSH+cw9`t)hETKn5S|K-gf#C7nuA^HQO#js*w`K@ri%S}KP<)AblQZW+$}o)fqh(PtxM zz*a7Y4Q=4G0b16}0xTy1mJ!e-i_LlL9eaa81Knz^9PS z4Qd4pYDElc&)5va3Z62$K+99wwk*Nr{y^b1*@<}AIc)|c4=!v&@~ zv`NHq|BS^uNSU<_#6AE_`NB-S!%Ts1srpi&XNLOFj{x~e3^UT<(%01POewDTYWRYL z->)4i`~lEe;)T6Gal?MZZvb9ad@IB=fbqcaH4yZDDY-V$L?hV`$|E@*rKj%VRO)pr=PANd*M4=7=sRec3D z6qPixEfuVis+HU@tLBx%xxc;PS`TJ6JS!Ghow4Qx z_QcjzX#~TqTkjEl&M+k^>xiV^2||zZfdcP1cT4sL&9979N}mWUOZJ9wulRII{`D7q z>E>5`>65xN>w(wE%Iz50XxcVPHVu*u!%)K~>*Zk%)8|tI7yCn@Yf7+64smy-O^+#M z1-w*6mJFb;9b{vU<8kY#qH{&O6hWR8L6?^C2tkhPEc!1K#8#=tL~17Zi^K|iS!t96NipZKLM#ActYH_-&M1bzKc@wy$XqN@>+v=88S(I{fpV#s!m50E-}a#nTR0~{%Jg$TUZ?<&YZ9To}zFi9bIfVRAN{( z;j6~ciw2zEyIso!#{r?7>}*)8f?~s5QBgbm9mfI-HS4fWhzH)34Wwt!ZC;v24J`3( zd~vddbAreBBoBn7XY=2NFnPCr(PW5^!~3M>#wc4845QP_qPk1;oO{ZaFfC5P6~63K z74SD1rLA!3Tz>8<+RN6l)rzFnhhw}}hXmFkPt{Fg2AvuUV8nt3J!k9vf{CJq_8>+4 zaUAwT!?y6x5732m+o0sHY*fDpgA`v8GYUTO%Fd7mS>Ks5DzBA}F@sM@>PO3~Rp-l6 zy(%cC>s)T+P>${wZh7hHr%?u%)%Jp##X6zgLtSf4lfLyPe^Kcw@Aqs0M~WbJzJ1ka zUTy7Z)-j2(Kw6D!P;JMwi3zTnv;4ywVTD=r6H{?3yy8k+B|l8*9Ym*!A71s<*=qf7 z(EyX|l?y3a66%-W$r32_8546t?AQVn>-Moo+_Z~k?YvpCh){s2nPaCQ)3HcJ=0-qjVV(ML<=+^qoO?c0N zM@187*-@YaU&?^(UE#9OsaOv+?}eQ$gL4O>RlJzzgFgpBZV^GQkSCN36=YtC4Bz^E zzuE@68ivy6m?DPKiUFdh4CVLg(RP0u>?{WV_P7_cUvqkhWzI*)`K|Ixs3;%ePq+09^nSZ6OSm_NDd&g~; z<40gWHQz%#4kMoecV|IZ#|~7Tg162@q8&uVw~DwNyWs<`rTfWIV-`?C!ihNlggUBdPg zV@1lg8NYR&%(~p|MYUhGm!|!!?GiM72XUlB3GcCw12|iNGPS|UmzbODivwsz(s;0$ zvNx<((tQ8e)ag$e-*sK?K#DSnT$onpF#)bZj^V}N#VHL}lz)0jbWL4c|-bv9sd4P9Z}YKbBd zbWl}k5skc1IfdUMO88w0Og@>0EE|KwopIzw{DYzvKH)ovX>380C8jia2{o%Kn6sK& znZ+)KR$AK8<-FcH!m{xnJl&;*3B$+AiX=QU+wnTBX_s46_we@Ntrx7Tnci!JJpHy- zN>mh>TlNO)eiLV+%oYKfY}mDGbg@QFiK}x%X6s-tx8TP7Mng1N)J)Mzh0?foafB$E z*v7!J4MD{-XI+YlO#|2MB;1VhygQ?8(h90pY^4n;?y#l@is=Y0Y5O77%{6)s>9&2k z=}rs9f;LMt6@%?4q^Wr1j8K@VqM<;P=ICi=O{V9k_}dqEY_KN0KuyPnfcb4@zdol^ zXq(6fqwXf&u}nwZplj$S&`a>QWF%6ZARhRY5o6o%LY zus2`^S1GWjTl+j7iBt|;X*S>%SKZp*7j4JUXxv^t=p@vizYMAQF~qasVip5GXX zHeuegSp)Ye@G5zYi`W*PuzbjGANgl8BVQ!P8Yq%u{Nc#V6Sn|L%W6|s%%o#UvT0?B zEMJK%UWu%3g_%cMal^zxMU6s*8ifiqDivC^D)cH7^GNVzvhAKNv1I_dMV9RQJeZAzC_*wpYdE%!mr>##n) zadnJ0u8rc{Ex2}RkiX4DFme{R+hQA8#!$_@FXv%Uln6x-WQHn4%*R(I6UMh8`MuGd zR;}mqyAi?Hm|*I61~nd`WQ^>EP`%-gPHi(rKS1Euxa(uOe^*HSDxg`AMQ z)c#B4?k)U)oSa=GxjTwUa%7a&=FLbR3PJ6~^1#4n)HhOk*X{)hftzm=0XJ`iQU&*<1{Kic zLKCI(e<-5WehEr0EFD~V&ncj{#4 z#MNXDsTPZSG8(m1$ag}r({8IxOcItrs(zl@$*_=$7&HShoD%Hk$h}}0Qt-Q287j8M zL`1&|R;Pmgu~2NWK&_ByLk@f*Ctv2m8Q(~kjTY*v=1LITY`D2r*jERC!KOhhoH1dMus69Fc+Re! z6x{QRrPeq9Mkq35URDYsISY5}WaRR*&)?%Tim)iXjrfOq%sMWzOW^S+uqa~m`>yCE zxCm7Kt{m!rfPEG!&Z+o=oCGWgVE&|(Z+*sQVAE$~yC;9*#`@aNemZ_vIKY{U#m1yP z2ubmj9}`WIXthiL6=XIc8z)2bTty&VHqyj0ZvY@2iL%zQn+01o@6`gK-$rcbezl{h z4_ymKGGV%hXFG^?VN>AV7i?$LP067qod~2*1Z4&5*T%j8Wu~=wz+DoU1)zT7*A#J-p+`k!K_ z9XcD(ub5jo)e_l62gsvBq|sp0VfqirbcDd0brKu`gG0arIn+_yY02v#?#1qIczgSf zl?u<298H?%+$a{JJgOB_VXS##JouwL_`|AipFQitV%3GJi8r`K4P(b$ESig%Oq9S< z|HO1tIs8Tbc#kBEElkfjw*cUal}S0M^p+DinPwR8oH%hjn)Xs+n|Glp{*2P2$e%xn zh)>WWaJ_{nW)MR{K6t@mO8VFawHSpm&haUM5U6ZVPAhFav3}@>V)-LX0 zv9R1VP7+2_HMGF$g{qs6hMR`3sQ5tC+!cjX2pgOmL;B8|L>VrB;KC&&)Fib22x&M+ z1lfaWbxIk2LW03jN6ImZoO1v(kxdo(Sw{CE6Fz*sE5Y^cqMiu)BI*VfUsODtummQ$ zA>jw9yrF2+c;}eebzw$Ve8BrD52Df#j~wbb5u|0I@xGvsEeY}`I`Ib<@dsnbb25C0 z$1o>x4Omt&)EP`D`L@ThzBA*{5;Kb;u@^V4GV8UHUwZX+k^a8 zg!VbH!v$}(l(#0hF;Oz`aO5TwpJdsK1tB975!(#PBr`K^v7w9y|GfGcg_2icdHKqI zdAYSPp8)Z_rph&mMh0gFmYq^9V`)nK=C5#;W(XBP01d9NSJQ_eRMMDDF-kKdWlEhu z!&QPa>GA#>cZp3J$=lH`3!~sFZJ#}2sF3rjC!SKA5@ER7dU(pIhk26R5V2_^5sHkR zJaV#P#JI+g36BvoB2%S^Oceui@-1BQgtPG-sTTS@QI3kUUq+uGhch#YBVWbksFmw;+pc4{ulxVI*ZH}pE(`_MAAHot%rV}Qwhc!Dj%0J~$ws^6wS?-B{gXEdOIb`50dU6zL6KX*92cA)VODXhO$d)Wi;GlzbPh!=NP?8 z{8YSr%AQ%yJeyr?c?Rgw>mmCUf$XY_sNR{^rA7Rq_szR- z1f31NO9Y=yHs72B_rG+xZv!sPRk1!D___B5YUyioi*wC}SF0L@pcezp_fEM*5l6B15o{eq@$n-s(9S_X*db!0In9ZB3ueK*O6D ztr|%r8UN_7Pwq45Ci(C>>eQ(7$vz)ub;zH@37;(mbeR`$(7{&AOZZ>T-EH(sW(#JM zNBai)_cwW4d2ebK4~=^;x$Bl0WxqWFJxe<_#q~tL-&sI;@}m-m?M{XKnd5H!vOA524K44Zc~Iy%K=q9pc(s>3Nr>^gQqQB z3@9Z6l>%AmRPc6DEl~#lh}v_)PNi&vT7n#PjS~dqY&7)DzA>v@|;^-AFwn z=68pAeY6q8eiuAbGESm4F1)SK`sUVIrz_+ z{CBlRf3PduuN$zxI@&*X{(CD4r2abkPc>OVIY}{5WfcZlvHy%BDnhxHrW5o zQ~$)(zqNlnwf)6C`{mmIJGimEotdTi|CsK3`e)D%31Atg8l#3+SR~DQRVSh4G;rGzCsgdTAVrt9&_bc5 zyR<>%dc*9r9huH-r?aI+MHc}*I21oXBZ(!l3K+Z)VlR~Q(&8N`Vi7AJN<0L=;o_a% z)mT00-S6%0O#60cXI=}FG}}(w_xt_7|Nr+U8BOs^bq4Mjl4{rsQ&ubv4MNSI#b5Dj zfMWw@-!? z!zUSKf)bMQ8w_0#;qdl2bZIk6Cs;VtmBefpoLaoTSVp!>w07R|`;Rs)B;=QC(#Ujc zNlJYe?~-#RRni58z91P0_RKpj?fgbSgnbT+1I@Z3;g=reWbQ+l!R&DuPyEM1wNfk9 zRxS`=pcGmwf8pLk>B#+AxrE$fAyW}otmDL9jA~IBpdj!CM?u?^BX4%VM!AT@XgZGr zM#3kb=LAa-)GN{i6{Pc|u+Fa!t?! zroycoQDsoIM_t#&WnZo6UfT_Q`~-b0VwfCj;$)IvBgjgLP*=B7>tSP&aJK#7bHjFa zW)R|eCeijYcU%U13Mb!usbUe*+V(+&lrggY;pk<6c}&@%aLI77d}qhc=}W+2NK&9J zdY_YnzgpG zvQ`@}Hz7k-l8a8-($(R?SUC%h!q!WvZwt?>)6~Tj!d`$)KV(kYj$mj*K(emz4$7Tl zT{Z!khtc=!Ln;X80BVZ`-~CiruhK@3mnk3>BoRibP4 zG7@>NBBO)H&=8~H@l)B2RDb8{vI(y*6nxtsCQzvx^zP2OsAIOz74ymqe#nj+t!Vz`I8t zz)Zdhn+$BL^rsD+;8uoqlybN7+0HZ%AqqldN`j58SaCXN~YxwxkQ9mqy7nIHpGdr%jigTFhkh1S8yEBhVsPvw=j?snM$}oGK7F&2#y-w^u?~#=Wy(jeJ&B}_Fw*H*)lZ(N^P8>B)`te(hml3Fp)j;$w z?6t7(>89Yfz-~shVn^lkOE~dUSF2uwqEpeLVuM2TLSGWU=zKVPnF|LkWCTM-(nR?C z;K9Y?(OoxVBE+7(bw$GKIaiDya@Z^F^aB&8UjXCHP#U{^-X-%9E)p6+y}bxWeAHubjQ(UF=wrgZP@yfUbJH z51P#XN)ccYfMqiBje61r3?RDU$+lnjd`@1+C=}hPD7tJiYu)U!E{-|0 zkStQFYRSJ_Uq9%3kuF+5w8;&)Ziao zP@^7ZzbakGtSmU+j$bsBUO(pQp2vQWNMcVqC7%5!KIvqx5D6FB{y*PyPbKpQpi`g? PRv9^g4(G2}i;({VLb|?Z literal 0 HcmV?d00001 diff --git a/pluginInterfaceSupported.json b/pluginInterfaceSupported.json index e9d4c14..f9d5be7 100644 --- a/pluginInterfaceSupported.json +++ b/pluginInterfaceSupported.json @@ -1,6 +1,6 @@ { "_comment": "contains a list of plugin interfaces branch names that this core supports", "versions": [ - "5.0" + "6.0" ] } \ No newline at end of file diff --git a/src/main/java/io/supertokens/storage/mysql/Start.java b/src/main/java/io/supertokens/storage/mysql/Start.java index 15d8759..a90fe27 100644 --- a/src/main/java/io/supertokens/storage/mysql/Start.java +++ b/src/main/java/io/supertokens/storage/mysql/Start.java @@ -68,7 +68,7 @@ import io.supertokens.pluginInterface.totp.TOTPStorage; import io.supertokens.pluginInterface.totp.TOTPUsedCode; import io.supertokens.pluginInterface.totp.exception.DeviceAlreadyExistsException; -import io.supertokens.pluginInterface.totp.exception.TotpNotEnabledException; +import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UnknownDeviceException; import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; @@ -109,8 +109,8 @@ public class Start implements SessionSQLStorage, EmailPasswordSQLStorage, EmailVerificationSQLStorage, ThirdPartySQLStorage, JWTRecipeSQLStorage, PasswordlessSQLStorage, UserMetadataSQLStorage, UserRolesSQLStorage, UserIdMappingStorage, - UserIdMappingSQLStorage, MultitenancyStorage, MultitenancySQLStorage, DashboardSQLStorage, TOTPSQLStorage, ActiveUsersStorage, - AuthRecipeSQLStorage { + UserIdMappingSQLStorage, MultitenancyStorage, MultitenancySQLStorage, DashboardSQLStorage, TOTPSQLStorage, + ActiveUsersStorage, ActiveUsersSQLStorage, AuthRecipeSQLStorage { // these configs are protected from being modified / viewed by the dev using the SuperTokens // SaaS. If the core is not running in SuperTokens SaaS, this array has no effect. @@ -616,11 +616,11 @@ public SessionInfo getSessionInfo_Transaction(TenantIdentifier tenantIdentifier, @Override public void updateSessionInfo_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection con, String sessionHandle, String refreshTokenHash2, - long expiry) throws StorageQueryException { + long expiry, boolean useStaticKey) throws StorageQueryException { Connection sqlCon = (Connection) con.getConnection(); try { SessionQueries.updateSessionInfo_Transaction(this, sqlCon, tenantIdentifier, sessionHandle, - refreshTokenHash2, expiry); + refreshTokenHash2, expiry, useStaticKey); } catch (SQLException e) { throw new StorageQueryException(e); } @@ -800,13 +800,14 @@ public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifi } } else if (className.equals(TOTPStorage.class.getName())) { try { - TOTPDevice device = new TOTPDevice(userId, "testDevice", "secret", 0, 30, false); - TOTPQueries.createDevice(this, tenantIdentifier.toAppIdentifier(), device); + TOTPDevice device = new TOTPDevice(userId, "testDevice", "secret", 0, 30, false, System.currentTimeMillis()); this.startTransaction(con -> { try { long now = System.currentTimeMillis(); + Connection sqlCon = (Connection) con.getConnection(); + TOTPQueries.createDevice_Transaction(this, sqlCon, tenantIdentifier.toAppIdentifier(), device); TOTPQueries.insertUsedCode_Transaction(this, - (Connection) con.getConnection(), tenantIdentifier, new TOTPUsedCode(userId, "123456", true, 1000+now, now)); + sqlCon, tenantIdentifier, new TOTPUsedCode(userId, "123456", true, 1000+now, now)); } catch (SQLException e) { throw new StorageTransactionLogicException(e); } @@ -1288,26 +1289,7 @@ public int countUsersActiveSince(AppIdentifier appIdentifier, long time) throws } } - @Override - public int countUsersEnabledTotp(AppIdentifier appIdentifier) throws StorageQueryException { - try { - return ActiveUsersQueries.countUsersEnabledTotp(this, appIdentifier); - } catch (SQLException e) { - throw new StorageQueryException(e); - } - } - - @Override - public int countUsersEnabledTotpAndActiveSince(AppIdentifier appIdentifier, long time) - throws StorageQueryException { - try { - return ActiveUsersQueries.countUsersEnabledTotpAndActiveSince(this, appIdentifier, time); - } catch (SQLException e) { - throw new StorageQueryException(e); - } - } - - @Override + @Override public void deleteUserActive_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId) throws StorageQueryException { try { @@ -2193,10 +2175,11 @@ public boolean updateOrDeleteExternalUserIdInfo(AppIdentifier appIdentifier, Str } @Override - public HashMap getUserIdMappingForSuperTokensIds(ArrayList userIds) + public HashMap getUserIdMappingForSuperTokensIds(AppIdentifier appIdentifier, + ArrayList userIds) throws StorageQueryException { try { - return UserIdMappingQueries.getUserIdMappingWithUserIds(this, userIds); + return UserIdMappingQueries.getUserIdMappingWithUserIds(this, appIdentifier, userIds); } catch (SQLException e) { throw new StorageQueryException(e); } @@ -2562,24 +2545,59 @@ public void revokeExpiredSessions() throws StorageQueryException { } // TOTP recipe: + @TestOnly @Override public void createDevice(AppIdentifier appIdentifier, TOTPDevice device) throws StorageQueryException, DeviceAlreadyExistsException, TenantOrAppNotFoundException { try { - TOTPQueries.createDevice(this, appIdentifier, device); + startTransaction(con -> { + try { + createDevice_Transaction(con, new AppIdentifier(null, null), device); + } catch (DeviceAlreadyExistsException | TenantOrAppNotFoundException e) { + throw new StorageTransactionLogicException(e); + } + return null; + }); } catch (StorageTransactionLogicException e) { - if (e.actualException instanceof SQLIntegrityConstraintViolationException) { - String errMsg = e.actualException.getMessage(); + if (e.actualException instanceof DeviceAlreadyExistsException) { + throw (DeviceAlreadyExistsException) e.actualException; + } else if (e.actualException instanceof TenantOrAppNotFoundException) { + throw (TenantOrAppNotFoundException) e.actualException; + } else if (e.actualException instanceof StorageQueryException) { + throw (StorageQueryException) e.actualException; + } + } + } + + @Override + public TOTPDevice createDevice_Transaction(TransactionConnection con, AppIdentifier appIdentifier, TOTPDevice device) + throws DeviceAlreadyExistsException, TenantOrAppNotFoundException, StorageQueryException { + Connection sqlCon = (Connection) con.getConnection(); + try { + TOTPQueries.createDevice_Transaction(this, sqlCon, appIdentifier, device); + return device; + } catch (SQLException actualException) { + if (actualException instanceof SQLIntegrityConstraintViolationException) { + String errMsg = actualException.getMessage(); if (isPrimaryKeyError(errMsg, Config.getConfig(this).getTotpUserDevicesTable())) { throw new DeviceAlreadyExistsException(); } else if (isForeignKeyConstraintError(errMsg, Config.getConfig(this).getTotpUsersTable(), "app_id")) { throw new TenantOrAppNotFoundException(appIdentifier); } - } - throw new StorageQueryException(e.actualException); + throw new StorageQueryException(actualException); + } + } + + @Override + public TOTPDevice getDeviceByName_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId, String deviceName) throws StorageQueryException { + Connection sqlCon = (Connection) con.getConnection(); + try { + return TOTPQueries.getDeviceByName_Transaction(this, sqlCon, appIdentifier, userId, deviceName); + } catch (SQLException e) { + throw new StorageQueryException(e); } } @@ -2675,7 +2693,7 @@ public TOTPDevice[] getDevices_Transaction(TransactionConnection con, AppIdentif @Override public void insertUsedCode_Transaction(TransactionConnection con, TenantIdentifier tenantIdentifier, TOTPUsedCode usedCodeObj) - throws StorageQueryException, TotpNotEnabledException, UsedCodeAlreadyExistsException, + throws StorageQueryException, UnknownTotpUserIdException, UsedCodeAlreadyExistsException, TenantOrAppNotFoundException { Connection sqlCon = (Connection) con.getConnection(); try { @@ -2685,7 +2703,7 @@ public void insertUsedCode_Transaction(TransactionConnection con, TenantIdentifi throw new UsedCodeAlreadyExistsException(); } else if (isForeignKeyConstraintError(e.getMessage(), Config.getConfig(this).getTotpUsedCodesTable(), "user_id")) { - throw new TotpNotEnabledException(); + throw new UnknownTotpUserIdException(); } else if (isForeignKeyConstraintError(e.getMessage(), Config.getConfig(this).getTotpUsedCodesTable(), "tenant_id")) { throw new TenantOrAppNotFoundException(tenantIdentifier); } @@ -2933,6 +2951,24 @@ public UserIdMapping[] getUserIdMapping_Transaction(TransactionConnection con, A } } + @Override + public int getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(AppIdentifier appIdentifier) throws StorageQueryException { + try { + return GeneralQueries.getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(this, appIdentifier); + } catch (SQLException e) { + throw new StorageQueryException(e); + } + } + + @Override + public int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(AppIdentifier appIdentifier, long sinceTime) throws StorageQueryException { + try { + return ActiveUsersQueries.countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(this, appIdentifier, sinceTime); + } catch (SQLException e) { + throw new StorageQueryException(e); + } + } + public static boolean isEnabledForDeadlockTesting() { return enableForDeadlockTesting; } diff --git a/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java b/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java index 133dc0b..52bc3fe 100644 --- a/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java +++ b/src/main/java/io/supertokens/storage/mysql/config/MySQLConfig.java @@ -184,6 +184,14 @@ public String getTenantConfigsTable() { return addPrefixToTableName("tenant_configs"); } + public String getTenantFirstFactorsTable() { + return addPrefixToTableName("tenant_first_factors"); + } + + public String getTenantRequiredSecondaryFactorsTable() { + return addPrefixToTableName("tenant_required_secondary_factors"); + } + public String getTenantThirdPartyProvidersTable() { return addPrefixToTableName("tenant_thirdparty_providers"); } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java index 289980a..1905ec2 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/ActiveUsersQueries.java @@ -137,4 +137,41 @@ public static void deleteUserActive_Transaction(Connection con, Start start, App pst.setString(2, userId); }); } + + public static int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime) + throws SQLException, StorageQueryException { + // TODO: Active users are present only on public tenant and MFA users may be present on different storages + String QUERY = + "SELECT COUNT(user_id) as c FROM (" + + " " // users with more than one login method + + " SELECT primary_or_recipe_user_id AS user_id FROM (" + + " SELECT COUNT(user_id) as num_login_methods, app_id, primary_or_recipe_user_id" + + " FROM " + Config.getConfig(start).getAppIdToUserIdTable() + + " WHERE app_id = ? AND primary_or_recipe_user_id IN (" + + " SELECT user_id FROM " + Config.getConfig(start).getUserLastActiveTable() + + " WHERE app_id = ? AND last_active_time >= ?" + + " )" + + " GROUP BY app_id, primary_or_recipe_user_id" + + " ) AS nloginmethods" + + " WHERE num_login_methods > 1" + + " UNION" // TOTP users + + " SELECT user_id FROM " + Config.getConfig(start).getTotpUsersTable() + + " WHERE app_id = ? AND user_id IN (" + + " SELECT user_id FROM " + Config.getConfig(start).getUserLastActiveTable() + + " WHERE app_id = ? AND last_active_time >= ?" + + " )" + + " " + + ") AS all_users"; + + return execute(start, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, appIdentifier.getAppId()); + pst.setLong(3, sinceTime); + pst.setString(4, appIdentifier.getAppId()); + pst.setString(5, appIdentifier.getAppId()); + pst.setLong(6, sinceTime); + }, result -> { + return result.next() ? result.getInt("c") : 0; + }); + } } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java index eee5a00..5941063 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/EmailVerificationQueries.java @@ -284,7 +284,7 @@ public static List isEmailVerified_transaction(Start start, Connection s // calculating the verified emails HashMap supertokensUserIdToExternalUserIdMap = UserIdMappingQueries.getUserIdMappingWithUserIds_Transaction(start, - sqlCon, supertokensUserIds); + sqlCon, appIdentifier, supertokensUserIds); HashMap externalUserIdToSupertokensUserIdMap = new HashMap<>(); List supertokensOrExternalUserIdsToQuery = new ArrayList<>(); @@ -352,7 +352,7 @@ public static List isEmailVerified(Start start, AppIdentifier appIdentif // We have external user id stored in the email verification table, so we need to fetch the mapped userids for // calculating the verified emails HashMap supertokensUserIdToExternalUserIdMap = UserIdMappingQueries.getUserIdMappingWithUserIds(start, - supertokensUserIds); + appIdentifier, supertokensUserIds); HashMap externalUserIdToSupertokensUserIdMap = new HashMap<>(); List supertokensOrExternalUserIdsToQuery = new ArrayList<>(); for (String userId : supertokensUserIds) { diff --git a/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java index ba88f54..8e16b12 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/GeneralQueries.java @@ -263,6 +263,16 @@ public static void createTablesIfNotExists(Start start) throws SQLException, Sto update(start, MultitenancyQueries.getQueryToCreateTenantConfigsTable(start), NO_OP_SETTER); } + if (!doesTableExists(start, Config.getConfig(start).getTenantFirstFactorsTable())) { + getInstance(start).addState(CREATING_NEW_TABLE, null); + update(start, MultitenancyQueries.getQueryToCreateFirstFactorsTable(start), NO_OP_SETTER); + } + + if (!doesTableExists(start, Config.getConfig(start).getTenantRequiredSecondaryFactorsTable())) { + getInstance(start).addState(CREATING_NEW_TABLE, null); + update(start, MultitenancyQueries.getQueryToCreateRequiredSecondaryFactorsTable(start), NO_OP_SETTER); + } + if (!doesTableExists(start, Config.getConfig(start).getTenantThirdPartyProvidersTable())) { getInstance(start).addState(CREATING_NEW_TABLE, null); update(start, MultitenancyQueries.getQueryToCreateTenantThirdPartyProvidersTable(start), @@ -1561,6 +1571,32 @@ public static int getUsersCountWithMoreThanOneLoginMethod(Start start, AppIdenti }); } + public static int getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(Start start, AppIdentifier appIdentifier) + throws SQLException, StorageQueryException { + String QUERY = + "SELECT COUNT(user_id) as c FROM (" + + " " // Users with number of login methods > 1 + + " SELECT primary_or_recipe_user_id AS user_id FROM (" + + " SELECT COUNT(user_id) as num_login_methods, app_id, primary_or_recipe_user_id" + + " FROM " + Config.getConfig(start).getAppIdToUserIdTable() + + " WHERE app_id = ? " + + " GROUP BY app_id, primary_or_recipe_user_id" + + " ) AS nloginmethods" + + " WHERE num_login_methods > 1" + + " UNION" // TOTP users + + " SELECT user_id FROM " + Config.getConfig(start).getTotpUsersTable() + + " WHERE app_id = ?" + + " " + + ") AS all_users"; + + return execute(start, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, appIdentifier.getAppId()); + }, result -> { + return result.next() ? result.getInt("c") : 0; + }); + } + public static boolean checkIfUsesAccountLinking(Start start, AppIdentifier appIdentifier) throws SQLException, StorageQueryException { String QUERY = "SELECT 1 FROM " diff --git a/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java index edacff4..53923d1 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/MultitenancyQueries.java @@ -27,6 +27,7 @@ import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.storage.mysql.Start; import io.supertokens.storage.mysql.config.Config; +import io.supertokens.storage.mysql.queries.multitenancy.MfaSqlHelper; import io.supertokens.storage.mysql.queries.multitenancy.TenantConfigSQLHelper; import io.supertokens.storage.mysql.queries.multitenancy.ThirdPartyProviderClientSQLHelper; import io.supertokens.storage.mysql.queries.multitenancy.ThirdPartyProviderSQLHelper; @@ -107,8 +108,38 @@ static String getQueryToCreateTenantThirdPartyProviderClientsTable(Start start) + ");"; } + public static String getQueryToCreateFirstFactorsTable(Start start) { + String tableName = Config.getConfig(start).getTenantFirstFactorsTable(); + // @formatter:off + return "CREATE TABLE IF NOT EXISTS " + tableName + " (" + + "connection_uri_domain VARCHAR(256) DEFAULT ''," + + "app_id VARCHAR(64) DEFAULT 'public'," + + "tenant_id VARCHAR(64) DEFAULT 'public'," + + "factor_id VARCHAR(128)," + + "PRIMARY KEY (connection_uri_domain, app_id, tenant_id, factor_id)," + + "FOREIGN KEY (connection_uri_domain, app_id, tenant_id)" + + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE" + + ");"; + // @formatter:on + } + + public static String getQueryToCreateRequiredSecondaryFactorsTable(Start start) { + String tableName = Config.getConfig(start).getTenantRequiredSecondaryFactorsTable(); + // @formatter:off + return "CREATE TABLE IF NOT EXISTS " + tableName + " (" + + "connection_uri_domain VARCHAR(256) DEFAULT ''," + + "app_id VARCHAR(64) DEFAULT 'public'," + + "tenant_id VARCHAR(64) DEFAULT 'public'," + + "factor_id VARCHAR(128)," + + "PRIMARY KEY (connection_uri_domain, app_id, tenant_id, factor_id)," + + "FOREIGN KEY (connection_uri_domain, app_id, tenant_id)" + + " REFERENCES " + Config.getConfig(start).getTenantConfigsTable() + + " (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE);"; + // @formatter:on + } + private static void executeCreateTenantQueries(Start start, Connection sqlCon, TenantConfig tenantConfig) - throws SQLException, StorageTransactionLogicException { + throws SQLException, StorageTransactionLogicException, StorageQueryException { try { TenantConfigSQLHelper.create(start, sqlCon, tenantConfig); @@ -143,6 +174,9 @@ private static void executeCreateTenantQueries(Start start, Connection sqlCon, T } } } + + MfaSqlHelper.createFirstFactors(start, sqlCon, tenantConfig.tenantIdentifier, tenantConfig.firstFactors); + MfaSqlHelper.createRequiredSecondaryFactors(start, sqlCon, tenantConfig.tenantIdentifier, tenantConfig.requiredSecondaryFactors); } public static void createTenantConfig(Start start, TenantConfig tenantConfig) throws StorageQueryException, StorageTransactionLogicException { @@ -221,7 +255,13 @@ public static TenantConfig[] getAllTenants(Start start) throws StorageQueryExcep // Map (tenantIdentifier) -> thirdPartyId -> provider HashMap> providerMap = ThirdPartyProviderSQLHelper.selectAll(start, providerClientsMap); - return TenantConfigSQLHelper.selectAll(start, providerMap); + // Map (tenantIdentifier) -> firstFactors + HashMap firstFactorsMap = MfaSqlHelper.selectAllFirstFactors(start); + + // Map (tenantIdentifier) -> requiredSecondaryFactors + HashMap requiredSecondaryFactorsMap = MfaSqlHelper.selectAllRequiredSecondaryFactors(start); + + return TenantConfigSQLHelper.selectAll(start, providerMap, firstFactorsMap, requiredSecondaryFactorsMap); } catch (SQLException throwables) { throw new StorageQueryException(throwables); } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java index ae8090b..12e3cca 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/SessionQueries.java @@ -141,18 +141,19 @@ public static SessionInfo getSessionInfo_Transaction(Start start, Connection con public static void updateSessionInfo_Transaction(Start start, Connection con, TenantIdentifier tenantIdentifier, String sessionHandle, - String refreshTokenHash2, long expiry) + String refreshTokenHash2, long expiry, boolean useStaticKey) throws SQLException, StorageQueryException { String QUERY = "UPDATE " + Config.getConfig(start).getSessionInfoTable() - + " SET refresh_token_hash_2 = ?, expires_at = ?" + + " SET refresh_token_hash_2 = ?, expires_at = ?, use_static_key= ?" + " WHERE app_id = ? AND tenant_id = ? AND session_handle = ?"; update(con, QUERY, pst -> { pst.setString(1, refreshTokenHash2); pst.setLong(2, expiry); - pst.setString(3, tenantIdentifier.getAppId()); - pst.setString(4, tenantIdentifier.getTenantId()); - pst.setString(5, sessionHandle); + pst.setBoolean(3, useStaticKey); + pst.setString(4, tenantIdentifier.getAppId()); + pst.setString(5, tenantIdentifier.getTenantId()); + pst.setString(6, sessionHandle); }); } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java index dadbf0d..b3536dd 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/TOTPQueries.java @@ -39,6 +39,7 @@ public static String getQueryToCreateUserDevicesTable(Start start) { + "period INTEGER NOT NULL," + "skew INTEGER NOT NULL," + "verified BOOLEAN NOT NULL," + + "created_at BIGINT UNSIGNED NOT NULL," + "PRIMARY KEY (app_id, user_id, device_name)," + "FOREIGN KEY (app_id, user_id)" + " REFERENCES " + Config.getConfig(start).getTotpUsersTable() + "(app_id, user_id) ON DELETE CASCADE" @@ -88,7 +89,7 @@ private static int insertUser_Transaction(Start start, Connection con, AppIdenti private static int insertDevice_Transaction(Start start, Connection con, AppIdentifier appIdentifier, TOTPDevice device) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getTotpUserDevicesTable() - + " (app_id, user_id, device_name, secret_key, period, skew, verified) VALUES (?, ?, ?, ?, ?, ?, ?)"; + + " (app_id, user_id, device_name, secret_key, period, skew, verified, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; return update(con, QUERY, pst -> { pst.setString(1, appIdentifier.getAppId()); @@ -98,25 +99,31 @@ private static int insertDevice_Transaction(Start start, Connection con, AppIden pst.setInt(5, device.period); pst.setInt(6, device.skew); pst.setBoolean(7, device.verified); + pst.setLong(8, device.createdAt); }); } - public static void createDevice(Start start, AppIdentifier appIdentifier, TOTPDevice device) - throws StorageQueryException, StorageTransactionLogicException { - start.startTransaction(con -> { - Connection sqlCon = (Connection) con.getConnection(); - - try { - insertUser_Transaction(start, sqlCon, appIdentifier, device.userId); - insertDevice_Transaction(start, sqlCon, appIdentifier, device); - sqlCon.commit(); - } catch (SQLException e) { - throw new StorageTransactionLogicException(e); - } + public static void createDevice_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, TOTPDevice device) + throws SQLException, StorageQueryException { + insertUser_Transaction(start, sqlCon, appIdentifier, device.userId); + insertDevice_Transaction(start, sqlCon, appIdentifier, device); + } + + public static TOTPDevice getDeviceByName_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String userId, String deviceName) + throws SQLException, StorageQueryException { + String QUERY = "SELECT * FROM " + Config.getConfig(start).getTotpUserDevicesTable() + + " WHERE app_id = ? AND user_id = ? AND device_name = ? FOR UPDATE;"; + return execute(sqlCon, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, userId); + pst.setString(3, deviceName); + }, result -> { + if (result.next()) { + return TOTPDeviceRowMapper.getInstance().map(result); + } return null; }); - return; } public static int markDeviceAsVerified(Start start, AppIdentifier appIdentifier, String userId, String deviceName) @@ -288,7 +295,8 @@ public TOTPDevice map(ResultSet result) throws SQLException { result.getString("secret_key"), result.getInt("period"), result.getInt("skew"), - result.getBoolean("verified")); + result.getBoolean("verified"), + result.getLong("created_at")); } } diff --git a/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java b/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java index 973c030..355d29e 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/UserIdMappingQueries.java @@ -117,7 +117,8 @@ public static UserIdMapping[] getUserIdMappingWithEitherSuperTokensUserIdOrExter } - public static HashMap getUserIdMappingWithUserIds(Start start, List userIds) + public static HashMap getUserIdMappingWithUserIds(Start start, + AppIdentifier appIdentifier, List userIds) throws SQLException, StorageQueryException { if (userIds.size() == 0) { @@ -126,7 +127,8 @@ public static HashMap getUserIdMappingWithUserIds(Start start, L // No need to filter based on tenantId because the id list is already filtered for a tenant StringBuilder QUERY = new StringBuilder( - "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE supertokens_user_id IN ("); + "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND " + + "supertokens_user_id IN ("); for (int i = 0; i < userIds.size(); i++) { QUERY.append("?"); if (i != userIds.size() - 1) { @@ -136,9 +138,10 @@ public static HashMap getUserIdMappingWithUserIds(Start start, L } QUERY.append(")"); return execute(start, QUERY.toString(), pst -> { + pst.setString(1, appIdentifier.getAppId()); for (int i = 0; i < userIds.size(); i++) { - // i+1 cause this starts with 1 and not 0 - pst.setString(i + 1, userIds.get(i)); + // i+2 cause this starts with 1 and not 0, 1 is appId + pst.setString(i + 2, userIds.get(i)); } }, result -> { HashMap userIdMappings = new HashMap<>(); @@ -150,7 +153,9 @@ public static HashMap getUserIdMappingWithUserIds(Start start, L }); } - public static HashMap getUserIdMappingWithUserIds_Transaction(Start start, Connection sqlCon, List userIds) + public static HashMap getUserIdMappingWithUserIds_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, + List userIds) throws SQLException, StorageQueryException { if (userIds.size() == 0) { @@ -159,7 +164,8 @@ public static HashMap getUserIdMappingWithUserIds_Transaction(St // No need to filter based on tenantId because the id list is already filtered for a tenant StringBuilder QUERY = new StringBuilder( - "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE supertokens_user_id IN ("); + "SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE app_id = ? AND " + + "supertokens_user_id IN ("); for (int i = 0; i < userIds.size(); i++) { QUERY.append("?"); if (i != userIds.size() - 1) { @@ -169,9 +175,10 @@ public static HashMap getUserIdMappingWithUserIds_Transaction(St } QUERY.append(")"); return execute(sqlCon, QUERY.toString(), pst -> { + pst.setString(1, appIdentifier.getAppId()); for (int i = 0; i < userIds.size(); i++) { - // i+1 cause this starts with 1 and not 0 - pst.setString(i + 1, userIds.get(i)); + // i+2 cause this starts with 1 and not 0, 1 is appId + pst.setString(i + 2, userIds.get(i)); } }, result -> { HashMap userIdMappings = new HashMap<>(); diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java new file mode 100644 index 0000000..9da3eb5 --- /dev/null +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/MfaSqlHelper.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.supertokens.storage.mysql.queries.multitenancy; + +import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; +import io.supertokens.storage.mysql.Start; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.*; + +import static io.supertokens.storage.mysql.QueryExecutorTemplate.execute; +import static io.supertokens.storage.mysql.QueryExecutorTemplate.update; +import static io.supertokens.storage.mysql.config.Config.getConfig; + +public class MfaSqlHelper { + public static HashMap selectAllFirstFactors(Start start) + throws SQLException, StorageQueryException { + String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, factor_id FROM " + + getConfig(start).getTenantFirstFactorsTable() + ";"; + return execute(start, QUERY, pst -> {}, result -> { + HashMap> firstFactors = new HashMap<>(); + + while (result.next()) { + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), result.getString("app_id"), result.getString("tenant_id")); + if (!firstFactors.containsKey(tenantIdentifier)) { + firstFactors.put(tenantIdentifier, new ArrayList<>()); + } + + firstFactors.get(tenantIdentifier).add(result.getString("factor_id")); + } + + HashMap finalResult = new HashMap<>(); + for (TenantIdentifier tenantIdentifier : firstFactors.keySet()) { + finalResult.put(tenantIdentifier, firstFactors.get(tenantIdentifier).toArray(new String[0])); + } + + return finalResult; + }); + } + + public static HashMap selectAllRequiredSecondaryFactors(Start start) + throws SQLException, StorageQueryException { + String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, factor_id FROM " + + getConfig(start).getTenantRequiredSecondaryFactorsTable() + ";"; + return execute(start, QUERY, pst -> {}, result -> { + HashMap> defaultRequiredFactors = new HashMap<>(); + + while (result.next()) { + TenantIdentifier tenantIdentifier = new TenantIdentifier(result.getString("connection_uri_domain"), + result.getString("app_id"), result.getString("tenant_id")); + if (!defaultRequiredFactors.containsKey(tenantIdentifier)) { + defaultRequiredFactors.put(tenantIdentifier, new ArrayList<>()); + } + + defaultRequiredFactors.get(tenantIdentifier).add(result.getString("factor_id")); + } + + HashMap finalResult = new HashMap<>(); + for (TenantIdentifier tenantIdentifier : defaultRequiredFactors.keySet()) { + finalResult.put(tenantIdentifier, defaultRequiredFactors.get(tenantIdentifier).toArray(new String[0])); + } + + return finalResult; + }); + } + + public static void createFirstFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String[] firstFactors) + throws SQLException, StorageQueryException { + if (firstFactors == null || firstFactors.length == 0) { + return; + } + + String QUERY = "INSERT INTO " + getConfig(start).getTenantFirstFactorsTable() + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; + for (String factorId : new HashSet<>(Arrays.asList(firstFactors))) { + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getConnectionUriDomain()); + pst.setString(2, tenantIdentifier.getAppId()); + pst.setString(3, tenantIdentifier.getTenantId()); + pst.setString(4, factorId); + }); + } + } + + public static void createRequiredSecondaryFactors(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String[] requiredSecondaryFactors) + throws SQLException, StorageQueryException { + if (requiredSecondaryFactors == null || requiredSecondaryFactors.length == 0) { + return; + } + + String QUERY = "INSERT INTO " + getConfig(start).getTenantRequiredSecondaryFactorsTable() + "(connection_uri_domain, app_id, tenant_id, factor_id) VALUES (?, ?, ?, ?);"; + for (String factorId : requiredSecondaryFactors) { + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getConnectionUriDomain()); + pst.setString(2, tenantIdentifier.getAppId()); + pst.setString(3, tenantIdentifier.getTenantId()); + pst.setString(4, factorId); + }); + } + } +} diff --git a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java index 7c82f71..af3931c 100644 --- a/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java +++ b/src/main/java/io/supertokens/storage/mysql/queries/multitenancy/TenantConfigSQLHelper.java @@ -37,13 +37,17 @@ public class TenantConfigSQLHelper { public static class TenantConfigRowMapper implements RowMapper { ThirdPartyConfig.Provider[] providers; + String[] firstFactors; + String[] requiredSecondaryFactors; - private TenantConfigRowMapper(ThirdPartyConfig.Provider[] providers) { + private TenantConfigRowMapper(ThirdPartyConfig.Provider[] providers, String[] firstFactors, String[] requiredSecondaryFactors) { this.providers = providers; + this.firstFactors = firstFactors; + this.requiredSecondaryFactors = requiredSecondaryFactors; } - public static TenantConfigRowMapper getInstance(ThirdPartyConfig.Provider[] providers) { - return new TenantConfigRowMapper(providers); + public static TenantConfigRowMapper getInstance(ThirdPartyConfig.Provider[] providers, String[] firstFactors, String[] requiredSecondaryFactors) { + return new TenantConfigRowMapper(providers, firstFactors, requiredSecondaryFactors); } @Override @@ -54,6 +58,8 @@ public TenantConfig map(ResultSet result) throws StorageQueryException { new EmailPasswordConfig(result.getBoolean("email_password_enabled")), new ThirdPartyConfig(result.getBoolean("third_party_enabled"), this.providers), new PasswordlessConfig(result.getBoolean("passwordless_enabled")), + firstFactors.length == 0 ? null : firstFactors, + requiredSecondaryFactors.length == 0 ? null : requiredSecondaryFactors, JsonUtils.stringToJsonObject(result.getString("core_config")) ); } catch (Exception e) { @@ -62,9 +68,10 @@ public TenantConfig map(ResultSet result) throws StorageQueryException { } } - public static TenantConfig[] selectAll(Start start, HashMap> providerMap) + public static TenantConfig[] selectAll(Start start, HashMap> providerMap, HashMap firstFactorsMap, HashMap requiredSecondaryFactorsMap) throws SQLException, StorageQueryException { - String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, core_config, email_password_enabled, passwordless_enabled, third_party_enabled FROM " + String QUERY = "SELECT connection_uri_domain, app_id, tenant_id, core_config," + + " email_password_enabled, passwordless_enabled, third_party_enabled FROM " + getConfig(start).getTenantConfigsTable() + ";"; TenantConfig[] tenantConfigs = execute(start, QUERY, pst -> {}, result -> { @@ -75,7 +82,11 @@ public static TenantConfig[] selectAll(Start start, HashMap { diff --git a/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java b/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java index dfc72fb..ccfeb27 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/DbConnectionPoolTest.java @@ -79,7 +79,7 @@ public void testActiveConnectionsWithTenants() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(1000); // let the new tenant be ready @@ -94,7 +94,7 @@ public void testActiveConnectionsWithTenants() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(2000); // let the new tenant be ready @@ -137,7 +137,7 @@ public void testDownTimeWhenChangingConnectionPoolSize() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(5000); // let the new tenant be ready @@ -197,7 +197,7 @@ public void testDownTimeWhenChangingConnectionPoolSize() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(3000); // let the new tenant be ready @@ -280,7 +280,7 @@ public void testMinimumIdleConnectionForTenants() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(1000); // let the new tenant be ready @@ -296,7 +296,7 @@ public void testMinimumIdleConnectionForTenants() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(2000); // let the new tenant be ready @@ -339,7 +339,7 @@ public void testIdleConnectionTimeout() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config + null, null, config ), false); Thread.sleep(3000); // let the new tenant be ready diff --git a/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java b/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java index 9044c1a..db3633d 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/DeadlockTest.java @@ -33,7 +33,7 @@ import io.supertokens.pluginInterface.sqlStorage.SQLStorage; import io.supertokens.pluginInterface.totp.TOTPDevice; import io.supertokens.pluginInterface.totp.TOTPUsedCode; -import io.supertokens.pluginInterface.totp.exception.TotpNotEnabledException; +import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; import io.supertokens.pluginInterface.sqlStorage.SQLStorage.TransactionIsolationLevel; @@ -280,7 +280,7 @@ public void testConcurrentDeleteAndInsert() throws Exception { // Create a device as well as a user: TOTPSQLStorage totpStorage = (TOTPSQLStorage) StorageLayer.getStorage(process.getProcess()); - TOTPDevice device = new TOTPDevice("user", "d1", "secret", 30, 1, false); + TOTPDevice device = new TOTPDevice("user", "d1", "secret", 30, 1, false, System.currentTimeMillis()); totpStorage.createDevice(TenantIdentifier.BASE_TENANT.toAppIdentifier(), device); long now = System.currentTimeMillis(); @@ -290,7 +290,7 @@ public void testConcurrentDeleteAndInsert() throws Exception { try { totpStorage.insertUsedCode_Transaction(con, TenantIdentifier.BASE_TENANT, code); totpStorage.commitTransaction(con); - } catch (TotpNotEnabledException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { + } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { // This should not happen throw new StorageTransactionLogicException(e); } @@ -392,7 +392,7 @@ public void testConcurrentDeleteAndInsert() throws Exception { TOTPUsedCode code2 = new TOTPUsedCode("user", "1234", false, nextDay, now + 1); try { totpStorage.insertUsedCode_Transaction(con, TenantIdentifier.BASE_TENANT, code2); - } catch (TotpNotEnabledException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { + } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { // This should not happen throw new StorageTransactionLogicException(e); } @@ -405,7 +405,7 @@ public void testConcurrentDeleteAndInsert() throws Exception { } catch (StorageTransactionLogicException e) { Exception e2 = e.actualException; - if (e2 instanceof TotpNotEnabledException) { + if (e2 instanceof UnknownTotpUserIdException) { t2Failed.set(true); } } catch (StorageQueryException e) { @@ -445,7 +445,7 @@ public void testConcurrentDeleteAndUpdate() throws Exception { // Create a device as well as a user: TOTPSQLStorage totpStorage = (TOTPSQLStorage) StorageLayer.getStorage(process.getProcess()); - TOTPDevice device = new TOTPDevice("user", "d1", "secret", 30, 1, false); + TOTPDevice device = new TOTPDevice("user", "d1", "secret", 30, 1, false, System.currentTimeMillis()); totpStorage.createDevice(TenantIdentifier.BASE_TENANT.toAppIdentifier(), device); long now = System.currentTimeMillis(); @@ -455,7 +455,7 @@ public void testConcurrentDeleteAndUpdate() throws Exception { try { totpStorage.insertUsedCode_Transaction(con, TenantIdentifier.BASE_TENANT, code); totpStorage.commitTransaction(con); - } catch (TotpNotEnabledException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { + } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { // This should not happen throw new StorageTransactionLogicException(e); } @@ -573,7 +573,7 @@ public void testConcurrentDeleteAndUpdate() throws Exception { } catch (StorageTransactionLogicException e) { Exception e2 = e.actualException; - if (e2 instanceof TotpNotEnabledException) { + if (e2 instanceof UnknownTotpUserIdException) { t2Failed.set(true); } } catch (StorageQueryException e) { diff --git a/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java b/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java index 2a54c8e..96dbf2a 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/LoggingTest.java @@ -286,6 +286,7 @@ public void confirmHikariLoggerClosedOnlyWhenProcessEnds() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), + null, null, config ), false); @@ -520,8 +521,7 @@ public void testDBPasswordIsNotLoggedWhenTenantIsCreated() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - config - )); + null, null, config)); process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); @@ -565,7 +565,7 @@ public void testDBPasswordIsNotLoggedWhenTenantIsCreated() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), - new JsonObject())); + null, null, new JsonObject())); } catch (Exception e) { diff --git a/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java b/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java new file mode 100644 index 0000000..3714a37 --- /dev/null +++ b/src/test/java/io/supertokens/storage/mysql/test/OneMillionUsersTest.java @@ -0,0 +1,898 @@ +/* + * Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.supertokens.storage.mysql.test; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.supertokens.ActiveUsers; +import io.supertokens.Main; +import io.supertokens.ProcessState; +import io.supertokens.authRecipe.AuthRecipe; +import io.supertokens.authRecipe.UserPaginationContainer; +import io.supertokens.emailpassword.EmailPassword; +import io.supertokens.emailpassword.ParsedFirebaseSCryptResponse; +import io.supertokens.featureflag.EE_FEATURES; +import io.supertokens.featureflag.FeatureFlagTestContent; +import io.supertokens.passwordless.Passwordless; +import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; +import io.supertokens.pluginInterface.authRecipe.LoginMethod; +import io.supertokens.pluginInterface.authRecipe.sqlStorage.AuthRecipeSQLStorage; +import io.supertokens.pluginInterface.emailpassword.sqlStorage.EmailPasswordSQLStorage; +import io.supertokens.pluginInterface.multitenancy.AppIdentifier; +import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; +import io.supertokens.pluginInterface.passwordless.sqlStorage.PasswordlessSQLStorage; +import io.supertokens.pluginInterface.thirdparty.sqlStorage.ThirdPartySQLStorage; +import io.supertokens.session.Session; +import io.supertokens.session.info.SessionInformationHolder; +import io.supertokens.storage.mysql.test.httpRequest.HttpRequestForTesting; +import io.supertokens.storageLayer.StorageLayer; +import io.supertokens.thirdparty.ThirdParty; +import io.supertokens.useridmapping.UserIdMapping; +import io.supertokens.usermetadata.UserMetadata; +import io.supertokens.userroles.UserRoles; +import io.supertokens.utils.SemVer; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; + +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +public class OneMillionUsersTest { + @Rule + public TestRule watchman = Utils.getOnFailure(); + + @AfterClass + public static void afterTesting() { + Utils.afterTesting(); + } + + @Before + public void beforeEach() { + Utils.reset(); + } + + static int TOTAL_USERS = 1000000; + static int NUM_THREADS = 16; + + Object lock = new Object(); + Set allUserIds = new HashSet<>(); + Set allPrimaryUserIds = new HashSet<>(); + Map userIdMappings = new HashMap<>(); + Map primaryUserIdMappings = new HashMap<>(); + + private void createEmailPasswordUsers(Main main) throws Exception { + System.out.println("Creating emailpassword users..."); + + int firebaseMemCost = 14; + int firebaseRounds = 8; + String firebaseSaltSeparator = "Bw=="; + + String salt = "/cj0jC1br5o4+w=="; + String passwordHash = "qZM035es5AXYqavsKD6/rhtxg7t5PhcyRgv5blc3doYbChX8keMfQLq1ra96O2Pf2TP/eZrR5xtPCYN6mX3ESA" + + "=="; + String combinedPasswordHash = "$" + ParsedFirebaseSCryptResponse.FIREBASE_SCRYPT_PREFIX + "$" + passwordHash + + "$" + salt + "$m=" + firebaseMemCost + "$r=" + firebaseRounds + "$s=" + firebaseSaltSeparator; + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + + EmailPasswordSQLStorage storage = (EmailPasswordSQLStorage) StorageLayer.getBaseStorage(main); + + for (int i = 0; i < TOTAL_USERS / 4; i++) { + int finalI = i; + es.execute(() -> { + try { + String userId = io.supertokens.utils.Utils.getUUID(); + long timeJoined = System.currentTimeMillis(); + + storage.signUp(TenantIdentifier.BASE_TENANT, userId, "eptest" + finalI + "@example.com", combinedPasswordHash, + timeJoined); + synchronized (lock) { + allUserIds.add(userId); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + if (finalI % 10000 == 9999) { + System.out.println("Created " + ((finalI +1)) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private void createPasswordlessUsersWithEmail(Main main) throws Exception { + System.out.println("Creating passwordless (email) users..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + PasswordlessSQLStorage storage = (PasswordlessSQLStorage) StorageLayer.getBaseStorage(main); + + for (int i = 0; i < TOTAL_USERS / 4; i++) { + int finalI = i; + es.execute(() -> { + String userId = io.supertokens.utils.Utils.getUUID(); + long timeJoined = System.currentTimeMillis(); + try { + storage.createUser(TenantIdentifier.BASE_TENANT, userId, "pltest" + finalI + "@example.com", null, timeJoined); + synchronized (lock) { + allUserIds.add(userId); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (finalI % 10000 == 9999) { + System.out.println("Created " + ((finalI +1)) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private void createPasswordlessUsersWithPhone(Main main) throws Exception { + System.out.println("Creating passwordless (phone) users..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + PasswordlessSQLStorage storage = (PasswordlessSQLStorage) StorageLayer.getBaseStorage(main); + + for (int i = 0; i < TOTAL_USERS / 4; i++) { + int finalI = i; + es.execute(() -> { + String userId = io.supertokens.utils.Utils.getUUID(); + long timeJoined = System.currentTimeMillis(); + try { + storage.createUser(TenantIdentifier.BASE_TENANT, userId, null, "+91987654" + finalI, timeJoined); + synchronized (lock) { + allUserIds.add(userId); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (finalI % 10000 == 9999) { + System.out.println("Created " + ((finalI +1)) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private void createThirdpartyUsers(Main main) throws Exception { + System.out.println("Creating thirdparty users..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + ThirdPartySQLStorage storage = (ThirdPartySQLStorage) StorageLayer.getBaseStorage(main); + + for (int i = 0; i < TOTAL_USERS / 4; i++) { + int finalI = i; + es.execute(() -> { + String userId = io.supertokens.utils.Utils.getUUID(); + long timeJoined = System.currentTimeMillis(); + + try { + storage.signUp(TenantIdentifier.BASE_TENANT, userId, "tptest" + finalI + "@example.com", new LoginMethod.ThirdParty("google", "googleid" + finalI), timeJoined ); + synchronized (lock) { + allUserIds.add(userId); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (finalI % 10000 == 9999) { + System.out.println("Created " + (finalI +1) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private void createOneMillionUsers(Main main) throws Exception { + Thread.sleep(5000); + + createEmailPasswordUsers(main); + createPasswordlessUsersWithEmail(main); + createPasswordlessUsersWithPhone(main); + createThirdpartyUsers(main); + } + + private void createUserIdMappings(Main main) throws Exception { + System.out.println("Creating user id mappings..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + AtomicLong usersUpdated = new AtomicLong(0); + + for (String userId : allUserIds) { + es.execute(() -> { + String extUserId = "ext" + UUID.randomUUID().toString(); + try { + UserIdMapping.createUserIdMapping(main, userId, extUserId, null, false); + synchronized (lock) { + userIdMappings.put(userId, extUserId); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + long count = usersUpdated.incrementAndGet(); + if (count % 10000 == 9999) { + System.out.println("Updated " + (count) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private void createUserData(Main main) throws Exception { + System.out.println("Creating user data..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS / 2); + + for (String userId : allPrimaryUserIds) { + es.execute(() -> { + Random random = new Random(); + + // User Metadata + JsonObject metadata = new JsonObject(); + metadata.addProperty("random", random.nextDouble()); + + try { + UserMetadata.updateUserMetadata(main, userIdMappings.get(userId), metadata); + + // User Roles + if (random.nextBoolean()) { + UserRoles.addRoleToUser(main, userIdMappings.get(userId), "admin"); + } else { + UserRoles.addRoleToUser(main, userIdMappings.get(userId), "user"); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + es.shutdown(); + es.awaitTermination(1, TimeUnit.MINUTES); + } + + private void doAccountLinking(Main main) throws Exception { + Set userIds = new HashSet<>(); + userIds.addAll(allUserIds); + + assertEquals(TOTAL_USERS, userIds.size()); + + AtomicLong accountsLinked = new AtomicLong(0); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + + while (userIds.size() > 0) { + int numberOfItemsToPick = Math.min(new Random().nextInt(4) + 1, userIds.size()); + String[] userIdsArray = new String[numberOfItemsToPick]; + + Iterator iterator = userIds.iterator(); + for (int i = 0; i < numberOfItemsToPick; i++) { + userIdsArray[i] = iterator.next(); + iterator.remove(); + } + + AuthRecipeSQLStorage storage = (AuthRecipeSQLStorage) StorageLayer.getBaseStorage(main); + + es.execute(() -> { + try { + storage.startTransaction(con -> { + storage.makePrimaryUser_Transaction(new AppIdentifier(null, null), con, userIdsArray[0]); + storage.commitTransaction(con); + return null; + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + + try { + for (int i = 1; i < userIdsArray.length; i++) { + int finalI = i; + storage.startTransaction(con -> { + storage.linkAccounts_Transaction(new AppIdentifier(null, null), con, userIdsArray[finalI], + userIdsArray[0]); + storage.commitTransaction(con); + return null; + }); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + synchronized (lock) { + allPrimaryUserIds.add(userIdsArray[0]); + for (String userId : userIdsArray) { + primaryUserIdMappings.put(userId, userIdsArray[0]); + } + } + + long total = accountsLinked.addAndGet(userIdsArray.length); + if (total % 10000 > 9996) { + System.out.println("Linked " + (accountsLinked) + " users"); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + private static String accessToken; + private static String sessionUserId; + + private void createSessions(Main main) throws Exception { + System.out.println("Creating sessions..."); + + ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS); + + for (String userId : allUserIds) { + String finalUserId = userId; + es.execute(() -> { + try { + SessionInformationHolder session = Session.createNewSession(main, + userIdMappings.get(finalUserId), new JsonObject(), new JsonObject()); + + if (new Random().nextFloat() < 0.05) { + synchronized (lock) { + accessToken = session.accessToken.token; + sessionUserId = userIdMappings.get(primaryUserIdMappings.get(finalUserId)); + } + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + es.shutdown(); + es.awaitTermination(10, TimeUnit.MINUTES); + } + + @Test + public void testCreatingOneMillionUsers() throws Exception { + if (System.getenv("ONE_MILLION_USERS_TEST") == null) { + return; + } + + String[] args = {"../"}; + TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false); + Utils.setValueInConfig("firebase_password_hashing_signer_key", + "gRhC3eDeQOdyEn4bMd9c6kxguWVmcIVq/SKa0JDPFeM6TcEevkaW56sIWfx88OHbJKnCXdWscZx0l2WbCJ1wbg=="); + Utils.setValueInConfig("postgresql_connection_pool_size", "500"); + + FeatureFlagTestContent.getInstance(process.getProcess()) + .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{ + EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY}); + process.startProcess(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); + + AtomicBoolean memoryCheckRunning = new AtomicBoolean(true); + AtomicLong maxMemory = new AtomicLong(0); + + { + long st = System.currentTimeMillis(); + createOneMillionUsers(process.getProcess()); + long en = System.currentTimeMillis(); + System.out.println("Time taken to create " + TOTAL_USERS + " users: " + ((en - st) / 1000) + " sec"); + assertEquals(TOTAL_USERS, AuthRecipe.getUsersCount(process.getProcess(), null)); + } + + { + long st = System.currentTimeMillis(); + doAccountLinking(process.getProcess()); + long en = System.currentTimeMillis(); + System.out.println("Time taken to link accounts: " + ((en - st) / 1000) + " sec"); + } + + { + long st = System.currentTimeMillis(); + createUserIdMappings(process.getProcess()); + long en = System.currentTimeMillis(); + System.out.println("Time taken to create user id mappings: " + ((en - st) / 1000) + " sec"); + } + + { + UserRoles.createNewRoleOrModifyItsPermissions(process.getProcess(), "admin", new String[]{"p1"}); + UserRoles.createNewRoleOrModifyItsPermissions(process.getProcess(), "user", new String[]{"p2"}); + long st = System.currentTimeMillis(); + createUserData(process.getProcess()); + long en = System.currentTimeMillis(); + System.out.println("Time taken to create user data: " + ((en - st) / 1000) + " sec"); + } + + { + long st = System.currentTimeMillis(); + createSessions(process.getProcess()); + long en = System.currentTimeMillis(); + System.out.println("Time taken to create sessions: " + ((en - st) / 1000) + " sec"); + } + + sanityCheckAPIs(process.getProcess()); + allUserIds.clear(); + allPrimaryUserIds.clear(); + userIdMappings.clear(); + primaryUserIdMappings.clear(); + + process.kill(false); + + Runtime.getRuntime().gc(); + System.gc(); + System.runFinalization(); + Thread.sleep(10000); + + + process = TestingProcessManager.start(args, false); + Utils.setValueInConfig("firebase_password_hashing_signer_key", + "gRhC3eDeQOdyEn4bMd9c6kxguWVmcIVq/SKa0JDPFeM6TcEevkaW56sIWfx88OHbJKnCXdWscZx0l2WbCJ1wbg=="); + Utils.setValueInConfig("postgresql_connection_pool_size", "500"); + + FeatureFlagTestContent.getInstance(process.getProcess()) + .setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{ + EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY}); + process.startProcess(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); + + Thread memoryChecker = new Thread(() -> { + while (memoryCheckRunning.get()) { + Runtime rt = Runtime.getRuntime(); + long total_mem = rt.totalMemory(); + long free_mem = rt.freeMemory(); + long used_mem = total_mem - free_mem; + + if (used_mem > maxMemory.get()) { + maxMemory.set(used_mem); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }); + memoryChecker.start(); + + measureOperations(process.getProcess()); + + memoryCheckRunning.set(false); + memoryChecker.join(); + + System.out.println("Max memory used: " + (maxMemory.get() / (1024 * 1024)) + " MB"); + assert maxMemory.get() < 256 * 1024 * 1024; // must be less than 256 mb + + process.kill(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); + } + + private void sanityCheckAPIs(Main main) throws Exception { + { // Email password sign in + JsonObject responseBody = new JsonObject(); + responseBody.addProperty("email", "eptest10@example.com"); + responseBody.addProperty("password", "testPass123"); + + Thread.sleep(1); // add a small delay to ensure a unique timestamp + long beforeSignIn = System.currentTimeMillis(); + + JsonObject signInResponse = HttpRequestForTesting.sendJsonPOSTRequest(main, "", + "http://localhost:3567/recipe/signin", responseBody, 1000, 1000, null, SemVer.v4_0.get(), + "emailpassword"); + + assertEquals(signInResponse.get("status").getAsString(), "OK"); + assertEquals(signInResponse.entrySet().size(), 3); + + JsonObject jsonUser = signInResponse.get("user").getAsJsonObject(); + JsonArray emails = jsonUser.get("emails").getAsJsonArray(); + boolean found = false; + + for (JsonElement elem : emails) { + if (elem.getAsString().equals("eptest10@example.com")) { + found = true; + break; + } + } + + assertTrue(found); + + int activeUsers = ActiveUsers.countUsersActiveSince(main, beforeSignIn); + assert (activeUsers == 1); + } + + { // passwordless sign in + long startTs = System.currentTimeMillis(); + + String email = "pltest10@example.com"; + Passwordless.CreateCodeResponse createResp = Passwordless.createCode(main, email, null, null, null); + + JsonObject consumeCodeRequestBody = new JsonObject(); + consumeCodeRequestBody.addProperty("deviceId", createResp.deviceId); + consumeCodeRequestBody.addProperty("preAuthSessionId", createResp.deviceIdHash); + consumeCodeRequestBody.addProperty("userInputCode", createResp.userInputCode); + + JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(main, "", + "http://localhost:3567/recipe/signinup/code/consume", consumeCodeRequestBody, 1000, 1000, null, + SemVer.v5_0.get(), "passwordless"); + + assertEquals("OK", response.get("status").getAsString()); + assertEquals(false, response.get("createdNewUser").getAsBoolean()); + assert (response.has("user")); + + JsonObject jsonUser = response.get("user").getAsJsonObject(); + JsonArray emails = jsonUser.get("emails").getAsJsonArray(); + boolean found = false; + + for (JsonElement elem : emails) { + if (elem.getAsString().equals("pltest10@example.com")) { + found = true; + break; + } + } + + assertTrue(found); + + int activeUsers = ActiveUsers.countUsersActiveSince(main, startTs); + assert (activeUsers == 1); + } + + { // thirdparty sign in + long startTs = System.currentTimeMillis(); + JsonObject emailObject = new JsonObject(); + emailObject.addProperty("id", "tptest10@example.com"); + emailObject.addProperty("isVerified", true); + + JsonObject signUpRequestBody = new JsonObject(); + signUpRequestBody.addProperty("thirdPartyId", "google"); + signUpRequestBody.addProperty("thirdPartyUserId", "googleid10"); + signUpRequestBody.add("email", emailObject); + + JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(main, "", + "http://localhost:3567/recipe/signinup", signUpRequestBody, 1000, 1000, null, + SemVer.v4_0.get(), "thirdparty"); + + assertEquals("OK", response.get("status").getAsString()); + assertEquals(false, response.get("createdNewUser").getAsBoolean()); + assert (response.has("user")); + + JsonObject jsonUser = response.get("user").getAsJsonObject(); + JsonArray emails = jsonUser.get("emails").getAsJsonArray(); + boolean found = false; + + for (JsonElement elem : emails) { + if (elem.getAsString().equals("tptest10@example.com")) { + found = true; + break; + } + } + + assertTrue(found); + + int activeUsers = ActiveUsers.countUsersActiveSince(main, startTs); + assert (activeUsers == 1); + } + + { // session for user + JsonObject request = new JsonObject(); + request.addProperty("accessToken", accessToken); + request.addProperty("doAntiCsrfCheck", false); + request.addProperty("enableAntiCsrf", false); + request.addProperty("checkDatabase", false); + JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(main, "", + "http://localhost:3567/recipe/session/verify", request, 1000, 1000, null, + SemVer.v5_0.get(), "session"); + assertEquals("OK", response.get("status").getAsString()); + assertEquals(sessionUserId, response.get("session").getAsJsonObject().get("userId").getAsString()); + } + + { // check user roles + JsonObject responseBody = new JsonObject(); + responseBody.addProperty("email", "eptest10@example.com"); + responseBody.addProperty("password", "testPass123"); + + Thread.sleep(1); // add a small delay to ensure a unique timestamp + JsonObject signInResponse = HttpRequestForTesting.sendJsonPOSTRequest(main, "", + "http://localhost:3567/recipe/signin", responseBody, 1000, 1000, null, SemVer.v4_0.get(), + "emailpassword"); + + HashMap QUERY_PARAMS = new HashMap<>(); + QUERY_PARAMS.put("userId", signInResponse.get("user").getAsJsonObject().get("id").getAsString()); + JsonObject response = HttpRequestForTesting.sendGETRequest(main, "", + "http://localhost:3567/recipe/user/roles", QUERY_PARAMS, 1000, 1000, null, + SemVer.v2_14.get(), "userroles"); + + assertEquals(2, response.entrySet().size()); + assertEquals("OK", response.get("status").getAsString()); + + JsonArray userRolesArr = response.getAsJsonArray("roles"); + assertEquals(1, userRolesArr.size()); + assertTrue( + userRolesArr.get(0).getAsString().equals("admin") || userRolesArr.get(0).getAsString().equals("user") + ); + } + + { // check user metadata + HashMap QueryParams = new HashMap(); + QueryParams.put("userId", sessionUserId); + JsonObject resp = HttpRequestForTesting.sendGETRequest(main, "", + "http://localhost:3567/recipe/user/metadata", QueryParams, 1000, 1000, null, + SemVer.v2_13.get(), "usermetadata"); + + assertEquals(2, resp.entrySet().size()); + assertEquals("OK", resp.get("status").getAsString()); + assert (resp.has("metadata")); + JsonObject respMetadata = resp.getAsJsonObject("metadata"); + assertEquals(1, respMetadata.entrySet().size()); + } + } + + private void measureOperations(Main main) throws Exception { + AtomicLong errorCount = new AtomicLong(0); + { // Emailpassword sign up + System.out.println("Measure email password sign-ups"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + EmailPassword.signUp(main, "ep" + finalI + "@example.com", "password" + finalI); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("EP sign up " + time); + assert time < 15000; + } + { // Emailpassword sign in + System.out.println("Measure email password sign-ins"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + EmailPassword.signIn(main, "ep" + finalI + "@example.com", "password" + finalI); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("EP sign in " + time); + assert time < 15000; + } + { // Passwordless sign-ups + System.out.println("Measure passwordless sign-ups"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + Passwordless.CreateCodeResponse code = Passwordless.createCode(main, + "pl" + finalI + "@example.com", null, null, null); + Passwordless.consumeCode(main, code.deviceId, code.deviceIdHash, code.userInputCode, null); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("PL sign up " + time); + assert time < 5000; + } + { // Passwordless sign-ins + System.out.println("Measure passwordless sign-ins"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + Passwordless.CreateCodeResponse code = Passwordless.createCode(main, + "pl" + finalI + "@example.com", null, null, null); + Passwordless.consumeCode(main, code.deviceId, code.deviceIdHash, code.userInputCode, null); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("PL sign in " + time); + assert time < 5000; + } + { // Thirdparty sign-ups + System.out.println("Measure thirdparty sign-ups"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, "twitter" + finalI + "@example.com"); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return null; + }); + System.out.println("Thirdparty sign up " + time); + assert time < 5000; + } + { // Thirdparty sign-ins + System.out.println("Measure thirdparty sign-ins"); + long time = measureTime(() -> { + ExecutorService es = Executors.newFixedThreadPool(100); + for (int i = 0; i < 500; i++) { + int finalI = i; + es.execute(() -> { + try { + ThirdParty.signInUp(main, "twitter", "twitterid" + finalI, "twitter" + finalI + "@example.com"); + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + }); + } + es.shutdown(); + try { + es.awaitTermination(5, TimeUnit.MINUTES); + } catch (InterruptedException e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("Thirdparty sign in " + time); + assert time < 5000; + } + { // Measure user pagination + long time = measureTime(() -> { + try { + long count = 0; + UserPaginationContainer users = AuthRecipe.getUsers(main, 500, "ASC", null, null, null); + while (true) { + for (AuthRecipeUserInfo user : users.users) { + count += user.loginMethods.length; + } + if (users.nextPaginationToken == null) { + break; + } + users = AuthRecipe.getUsers(main, 500, "ASC", users.nextPaginationToken, null, null); + if (count >= 500) { + break; + } + } + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("User pagination " + time); + assert time < 2000; + } + { // Measure update user metadata + long time = measureTime(() -> { + try { + UserPaginationContainer users = AuthRecipe.getUsers(main, 1, "ASC", null, null, null); + UserIdMapping.populateExternalUserIdForUsers( + new AppIdentifier(null, null), + (StorageLayer.getBaseStorage(main)), + users.users); + + AuthRecipeUserInfo user = users.users[0]; + for (int i = 0; i < 500; i++) { + UserMetadata.updateUserMetadata(main, user.getSupertokensOrExternalUserId(), new JsonObject()); + } + } catch (Exception e) { + errorCount.incrementAndGet(); + throw new RuntimeException(e); + } + return null; + }); + System.out.println("Update user metadata " + time); + } + + assertEquals(0, errorCount.get()); + } + + private static long measureTime(Supplier function) { + long startTime = System.nanoTime(); + + // Call the function + function.get(); + + long endTime = System.nanoTime(); + + // Calculate elapsed time in milliseconds + return (endTime - startTime) / 1000000; // Convert to milliseconds + } +} + diff --git a/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java b/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java index 2eae408..02d6a74 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/StorageLayerTest.java @@ -16,7 +16,7 @@ import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.totp.TOTPDevice; import io.supertokens.pluginInterface.totp.TOTPUsedCode; -import io.supertokens.pluginInterface.totp.exception.TotpNotEnabledException; +import io.supertokens.pluginInterface.totp.exception.UnknownTotpUserIdException; import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; import io.supertokens.storageLayer.StorageLayer; @@ -54,13 +54,13 @@ public static void insertUsedCodeUtil(TOTPSQLStorage storage, TOTPUsedCode usedC storage.insertUsedCode_Transaction(con, TenantIdentifier.BASE_TENANT, usedCode); storage.commitTransaction(con); return null; - } catch (TotpNotEnabledException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { + } catch (UnknownTotpUserIdException | UsedCodeAlreadyExistsException | TenantOrAppNotFoundException e) { throw new StorageTransactionLogicException(e); } }); } catch (StorageTransactionLogicException e) { Exception actual = e.actualException; - if (actual instanceof TotpNotEnabledException || actual instanceof UsedCodeAlreadyExistsException) { + if (actual instanceof UnknownTotpUserIdException || actual instanceof UsedCodeAlreadyExistsException) { throw actual; } else { throw e; @@ -82,7 +82,7 @@ public void totpCodeLengthTest() throws Exception { long now = System.currentTimeMillis(); long nextDay = now + 1000 * 60 * 60 * 24; // 1 day from now - TOTPDevice d1 = new TOTPDevice("user", "d1", "secret", 30, 1, false); + TOTPDevice d1 = new TOTPDevice("user", "d1", "secret", 30, 1, false, System.currentTimeMillis()); storage.createDevice(TenantIdentifier.BASE_TENANT.toAppIdentifier(), d1); // Try code with length > 8 diff --git a/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java b/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java index 5e052e9..b551c44 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/SuperTokensSaaSSecretTest.java @@ -105,7 +105,7 @@ public void testThatTenantCannotSetProtectedConfigIfSuperTokensSaaSSecretIsSet() Multitenancy.addNewOrUpdateAppOrTenant(process.main, new TenantConfig(new TenantIdentifier(null, null, "t1"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), - j), true); + null, null, j), true); fail(); } catch (BadPermissionException e) { assertEquals(e.getMessage(), "Not allowed to modify DB related configs."); @@ -191,7 +191,7 @@ public void testThatTenantCannotGetProtectedConfigIfSuperTokensSaaSSecretIsSet() new TenantConfig(new TenantIdentifier(null, null, "t" + i), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), - j)); + null, null, j)); { JsonObject response = HttpRequestForTesting.sendJsonRequest(process.getProcess(), "", diff --git a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java index 6f583ca..a01b71b 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java +++ b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/StorageLayerTest.java @@ -112,6 +112,7 @@ public void mergingTenantWithBaseConfigWorks() new TenantConfig(new TenantIdentifier("abc", null, null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -156,6 +157,7 @@ public void storageInstanceIsReusedAcrossTenants() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -203,14 +205,17 @@ public void storageInstanceIsReusedAcrossTenantsComplex() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig), new TenantConfig(new TenantIdentifier(null, "abc", "t1"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig1), new TenantConfig(new TenantIdentifier(null, null, "t2"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig1)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -275,6 +280,7 @@ public void mergingTenantWithBaseConfigWithInvalidConfigThrowsErrorWorks() new TenantConfig(new TenantIdentifier("abc", null, null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -308,6 +314,7 @@ public void mergingTenantWithBaseConfigWithConflictingConfigsThrowsError() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -342,6 +349,7 @@ public void mergingDifferentConnectionPoolIdTenantWithBaseConfigWithConflictingC new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -377,6 +385,7 @@ public void mergingDifferentUserPoolIdTenantWithBaseConfigWithConflictingConfigs new TenantConfig(new TenantIdentifier("abc", null, null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -421,6 +430,7 @@ public void newStorageIsNotCreatedWhenSameTenantIsAdded() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -468,6 +478,7 @@ public void testDifferentWaysToGetConfigBasedOnConnectionURIAndTenantId() tenants[0] = new TenantConfig(new TenantIdentifier("c1", null, null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig); } @@ -479,6 +490,7 @@ public void testDifferentWaysToGetConfigBasedOnConnectionURIAndTenantId() tenants[1] = new TenantConfig(new TenantIdentifier("c1", null, "t1"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig); } @@ -488,6 +500,7 @@ public void testDifferentWaysToGetConfigBasedOnConnectionURIAndTenantId() tenants[2] = new TenantConfig(new TenantIdentifier(null, null, "t2"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig); } @@ -497,6 +510,7 @@ public void testDifferentWaysToGetConfigBasedOnConnectionURIAndTenantId() tenants[3] = new TenantConfig(new TenantIdentifier(null, null, "t1"), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig); } @@ -558,6 +572,7 @@ public void multipleTenantsSameUserPoolAndConnectionPoolShouldWork() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -593,6 +608,7 @@ public void multipleTenantsSameUserPoolAndDifferentConnectionPoolShouldWork() new TenantConfig(new TenantIdentifier(null, "abc", null), new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfig)}; Config.loadAllTenantConfig(process.getProcess(), tenants); @@ -632,6 +648,7 @@ public void testCreating50StorageLayersUsage() new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, config); try { Multitenancy.addNewOrUpdateAppOrTenant(process.getProcess(), new TenantIdentifier(null, null, null), @@ -685,6 +702,7 @@ public void testCantCreateTenantWithUnknownDb() new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfigJson); try { @@ -723,6 +741,7 @@ public void testTenantCreationAndThenDbDownDbThrowsErrorInRecipesAndDoesntAffect new EmailPasswordConfig(true), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfigJson); StorageLayer.getMultitenancyStorage(process.getProcess()).createTenant(tenantConfig); @@ -794,6 +813,7 @@ public void testBadPortWithNewTenantShouldNotCauseItToWaitInput() throws Excepti new EmailPasswordConfig(false), new ThirdPartyConfig(false, new ThirdPartyConfig.Provider[0]), new PasswordlessConfig(false), + null, null, tenantConfigJson); try { diff --git a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java index c13d875..77d1ad3 100644 --- a/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java +++ b/src/test/java/io/supertokens/storage/mysql/test/multitenancy/TestUserPoolIdChangeBehaviour.java @@ -83,6 +83,7 @@ public void testUsersWorkAfterUserPoolIdChanges() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), + null, null, coreConfig ), false); @@ -100,6 +101,7 @@ public void testUsersWorkAfterUserPoolIdChanges() throws Exception { new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), + null, null, coreConfig ), false); @@ -125,6 +127,7 @@ public void testUsersWorkAfterUserPoolIdChangesAndServerRestart() throws Excepti new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), + null, null, coreConfig ), false); @@ -142,6 +145,7 @@ public void testUsersWorkAfterUserPoolIdChangesAndServerRestart() throws Excepti new EmailPasswordConfig(true), new ThirdPartyConfig(true, null), new PasswordlessConfig(true), + null, null, coreConfig ), false);