From e47c019ab1752496feb84859f57408ae253acdf1 Mon Sep 17 00:00:00 2001 From: leninner Date: Sun, 30 Nov 2025 21:28:14 -0500 Subject: [PATCH 1/5] feat: add subs --- bun.lockb | Bin 0 -> 262898 bytes package.json | 1 + .../adapters/openrouter-llm.adapter.ts | 147 ++++++++++++++++++ .../controllers/voice-command.controller.ts | 5 +- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100755 bun.lockb create mode 100644 src/features/ai-agents/infrastructure/adapters/openrouter-llm.adapter.ts diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..57a05babafffdc5120e5d0cbf7a82546b9af7dc5 GIT binary patch literal 262898 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

&t2DCcIvdAI%q)>r(1B5;#^cF0!Zb(Y~j8 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%0DFkAYVCp}np=i+}NLREw5QE%r!j zUi0rQQ@F8Nqs~u*vPX}9XKnq|E5Ac&^wo9poqnXVxINk2ajn0|Hsx2$(Ee_?p+vAP zWOLUSd0t*lEmNik#cg{%eOd^=LDQjW*(;BKYGymEYx983jbEQhJZa_r-6H#t%cc43 z>pc9;@85^a@@G9lRINV0O>FgHi-X2jw~*wGyTXlU^f69yi8J^nH~+%=A9{Un=pLK< z%*XMy;Psbc&0Fdh?)*r#Y~U1ntNEJ8tay96n%ZCVxY&(mrk9JR9;$mc$Hd#v0>nbzWvQbS1;?iqdZB4OVuVJW@Giz~h`|Pi@BJty6zG>P@F#r{mu@ zPVAOzs37Z@EET{RIEytdobnopkd6M9W z%$}&7M;AG&tgv@q-NEYXf(9E^2QGZ?60-Q#zWvTy^R`t^cenW3s_^F6@A_?G6_%Q@ zxb*kIh?hCibzlD-qlZ~tk5&np(dcxOrET1{%AGIkT;?Cf=dZoqn7SUuxkJ8eiNNr2M@S>8kW+#$${-9VR{4D*CBH@_rcdJxp6}`Jk-chZnM3w zm!69C#vz7zeU|)q)UUC`fs`pxx22`_KBw-q^e0bNsoov!@n4)!C`+ z@{tv<1)ICcV2f74rZs(Mk9ny4f2g|4s34y2Vc;~IEH_|QL z($do1CEXZ!QScod^N12LaIi?O**A-#udVt{{@j!f zK03_FdwpFN!AEZHMr7zHk+6GiN*cKdf(o^&<{Nap4o!ph)rC`U&n@aBkgp)B z<2P=%ndtI6L9qQSE44K9E~08(Amf$0T@L&dMBujyfs~tM`0 zauaSQA+6qafa@$F(4~dy84xEei20fn{1V=j(7@^L`j!4J%4-@`e?vL~iUn%G=!r`& z=(E~yCzWctk+Kb6yka|qU&rBi9ljB)4}Z@-{(HU&gRc5r$v`aa$DS{aPB*hRZ@Vr9 z=MG#Z4i8FQO2%{d#6+A8<@eX1-R3z0tJ-N{)R8{7-v?_+^DhsQBl4UG%&`Ej2#v1hX!ik{va6`h3uaj21F39_w0VJzSvXp&gEp zA>Xp1XD^qxj6n^!qM*Bp*>(2VG?GlbGs^BdbD5h~rS@`xH?KO4@5#ySU#5G%>>9qb z!K(V)KVT|9^44hTR zjnCTai*shbL;d*U)?VZwaWMp&qd)0OGO{9`;G(WWu_E+1p0$=3YW4GfXQBW1ybuT7 zAh|1;N=b#aqgD}`YjqQqG8|au;2~_iQeLWQjRmg2bAckL9?7vK)R|@1yJqiS<8V@Q zWvj!>fs>xCQs2FdfpL%k-K0YUtbnTw)th_gHG}%l)hsdr-&{4vXtR`+J_ncnDsSmG zk6wFml;p#sP%2zl@9ephEmX-#@)fIoKHpy;n*y#R=q3^)>#{}p3x7IUK)-1wT=WQJ zcM=|yfBCN{GTt4J-}^I+AyXtC5wECdnOUK^fqn9>^!96Ry(Hh_VNIt2D=FYgfvyzl z&?uhQtw5^w6vPxaUdLzkK;M!6%}b6Pgoo#53TM2#{pr038;@#k9q*r7EfLxVa+_W} z_|{z+_fV_zE*5|*4Z5y15x#9QXrH;f5l%J4IUQj4KHRrppa{wE^Ga2Gxz@WIQR%cr zNF~n*J%4MsFYiOSoTcBaOy7mfKiR!hC#D3rGN2n@@YXk9vS~a%9@ZUM6IuZeC0sbp(Uin16|8e?saaCDg`6k#vRGU6J|!C9Z$T7M?~j%gqh0wOD!DB zkOPwD(S4l{eX3_hc^g90@5px5`u|9S&x?!i<2%eI&Aeo=$>nB*{~ z#IzZTAQ=ZIqcwx}nTuA*rC_tr?6kq8;sztTNEScijnF-n1+y`-;pzu@AYUcWr5xul z={-bTeWzl0V#LSciQMCfG^lCo>lG#fiyWXH+no?qxYJ3^uoe2DmHXQDNW3?sNG=Z| zZNg$|0{??M_+G6Hy1`mM>fm=L?e1r@AXRbEe)*N{)#P#@zE>H|Bw#LS49^gkiW=d< zDJ$~FWFxyT*oy5uNBzFHn+x z(HOsx3*hf19%6y<{d>;gU%~8>^GwVQuo*$B#ZK#Xm@uJ;tbIn zPQ{t}be>s^fy;ijQ!(@B>O+M>&itt$I>K>Qg!&UBwDp}4U>vkSmpRsF*Vp^S&@DLs zL%6Ag*9_P6zP@m|hbawql2lv#d%hPmINItr*cT?xt39s-Pre-aLGahUVtoA}$EjAt z9ITgUgKlL=ua%#rK@6Mu=o-;3`gLZ}>v?_73&mThV)`e3N5V@j!B5=SHd*fohKZfeA3ALF%+_O?@H z8j8fbkjZc+qvarYj*o>@oz7v`kWjt=3!4T3C1K zI`v|8LY?_aZ>m#IuvT+smwU5*FNWOC`K1dlg?iWiFdyMO;`EB~HA!SraT(>+**Y7tp6 zo}Xv`%0bqU2C2^EHD!kUQtn}`7SBL0xNgz=hyM2y2AY?nUC)^)$Jw0mn!0L52RR?R z1XFTqkv}x``mVV+4w;x9+E}vnJ-lKUT}uT$T7A@b%filb`<}l!*XOY+8(=1Qs1c zyldkQ8&S@l&nn;=fbLZ@x%{i?kkYB$ERi~SD>)xO+BY%YwH)Y3W(hJnuMuzFNvw6# z=9C<#Ye1~u{>F%2(@)NYa?$rOR_Mknei6e@)%7jqEj z7O^~JcOozBuuzMdkb5k{q?yv1*h_}UK+o{F>KJ_QV@g*4O|Azc028cN8-eca3XOk! zqeml#qEQ$m^Ffa=KAAetr~BFUK{43ztHT@@mM~7165`4)G9~n_VV){G^Oze3`D8*= zTHbcK5HQ(5zQ&+?MEEGGLwSg|cf1Pm_^82D59QUKai^uTbmzB3DUx{ffvVjAC~1#w9kpQYgd|BH(o0W)PCjMoJ_!xTn_ z6zK!s-vzuRGJO|Pf1c9remf}&>Hl)l4HZ>F)~O{9TWF6i;n?R-0l221>l?I1UnbUU zK>ABX3VOz0=yw=X?3QmLDk}v?-%@Yc(*u3zuW1bN=KFFaCWg)Y*i`=`lK|pDf?6`8 z$d*j5TEH~}T|3^?nN!}Lsrt}KZF;AIw!lM;v+b?CdTSf#6-SzmQ=8cP^YS$cMbS+h zh2L?8N&a54do%;kI+IP7(N>eiV1J1@=r-%bavS~0v_2X(jV$W>8rEcZz2JoVbv+~@ z#GK?~7+c`L+fB-h>dB+#8Q7IU(_;uHTdSbK5#bCgr&>A**B?N>7N8sJX|?pu!f?*C ze8m!#=TPs@=L#ZY!p`%11Ud%ACO5ZA-Cxx9at3nxY6h~~6@{#GkEun4%qY}(R<2V85=g{k5CsH3dy zbeh~owMO4)^qu^!oUY5g91jO4PCBx|WzN4A`hoW0J9b^%26R8WmVrYahON0@sr1_} z#J2;R)_`jRx}u)4%-JRxIekR<>(`J5q7;Ps@YsdkZ8gThjumTbd4D##fKlC>24ha|;C{8!XTFx_zpJmMI%{dLwh{fNG#J(+9gg9Ps_o$XR%r?`T zZm1%r8Ruu&_be)3E+7ANF?q~*bz>6b_lRxMNcVki z5FXE9rkqXeIP;`VhZ={~!V?1LNe9r?wSU!yM$EAfwO@eLU(PJdh+X4(6fx(j{bpua zOHEdv^Gdg2R+h-N^9@$PI-Ssh*01)|=v)?UczNtVEXE4(`gH`|)xa!;+``$uRIOEUYpB(5botYRY*XdBqp-NrhnH)v|M`W@r3|W*`bnG3CZ*d;h!9p_Q zpDayqZVJoG?)LetzH$6kfCt9c8FU|1jibh|1Tn{QCd#NJN-e7&RiIb|*9YugdFjUA z$m^iv1NnXd-O^13U6n}%!#|8ZN{a5h z>PUE-Lj+lPw0pHm>7y{yRi9oDbA6DdbD?w^ByoC5l44iJ>F_>yzw=ZuX~HIihz+=I zpxapL9dyU&3U?3Ns~9k~NuP>mv!Zl*aBhX^2BlpX=gkwD-=J}c zHZ7eveKL3ypEXetpqb4yyq5&a+f4e}_8Z#0*K?a>_E-z{tFBtT_3=T0}X-TLkYO>N_3 zHY~vkGKT6JCtzX%`Feq_7zPyoz(e@yxm_Bf!7wZly#?07QOvUox5@-vJBL6TjUKGn z8mDP04~qS6AJY0))a0S3kDeQsq-%W=2su=Afa?vq&PVObNJ%RdRh$hHR$2RFQ`}aYs`-r%Y>e^P#~m@v8)7{Os(4M79@OqGD}+Eq+{& zAjBdPZ$O(I0^s_BZus{sRVAKHXLLCn`uQ@^05g~7kHeT6$}~vu8<7J<>12Hx_-SKj zWTV*M-o8$-8)#EvfXS)bqhH9%r0-}l2K(ClK=;Twc>{)Uoq^7gd|%}gyV%Lo2TyCV z*d9hvmsueUkv4Pldm`L{;Zs{d-*{Na;Jt6*#R+K`%v-!O^twvY#^8I2Kj;!Wjv^49 zM)mR99H21IQJ7`#_Iagw8^IiCSfMti=SoLfW+&Th|Hz)6%Rd_}nF!x0dbJvOg_l2j z2+@i@kXQ_iLjdSfjJ-BU%((uNLWK4H#g+T}`!#>b4Hl|~q>a#^jX<$lg}t2*gS_dM z&Lt==T9?c-3NIQdTzFQyHDw_LC*%jbPPt+rVPrPTjB_b zZt~T4?tin9E;lomIW@9Y{P?(orl^a^RVyy%r}<^!eMpgu4bRKW5Rh*W=vuEnT|nvy z`BX-rOq|m9X%ZBbuM~?5Q7XOPUXM3hmxt@e*{ZYYwXJ?d7PWnOYt<$D>I=19L?AOa z$1SV$47kr547!M)(tgL0$2@oM*C{U9Rb-efIR!~4Q4dLJ{0a4#aq~80vpt$2M^7qi zxtTP6&n`ud=Tji_gGGLZnS{+-;h71@Hw1Los-hOOKeb$ZBa-2L5Wj9p4y>*&I#m2h z!q0QX@hat&-)jL5oJ_@)Ipv(FjzKGjI8@>CD zOF&lCRWRn7ZA7u5a_D)O?7O8Qk56;9Y}i4KFu7N3ZE0ie^C{XDSNITntbJvOU)BcC zJ8uCu5_FliWsT8QhY!&065O#ky?B&_9rUN~Nilm>Gxa59wA_vw>qCi)0pwC)mY@*rdrkXfxqB&T8JTRY2-XF?Q6pk7B z<{Z*P4es~;Nsugz+*z@7KdH8s561Xsep^po3wl^yetNKO6b-uWZEe5VW7K**7x|5Q z6!RL_p`owmiTm=BM>6oH;TDdH`DNCXu%9#7+1)>FkeM!3JKbCfEmM@Z)knO;4o}em z#vulD`!?y1yHOkE75Okf|A9B$==d7C)Po(;OzHE@cd4t`vP8(0q19COWyKrY+V^2pKc=eEzt|x*Ojj&98MR~W zImXiv4xn5nup~AM805IxPsQO$^ZAv2nRykGmcbDW=>xc5L3a&aJZ#pnEWT@M6qix7 z`D1*XD9TxsJr$V|S&L1+*zn7iO3}i8?8I`0kS()`<7y04Wk3#NTce3eN07b*6PRxt z=u#VF8idO$72MI#U8lNy?cCLx{muL4SsGGc4~4vYbVbMjPeECJ19b^XoiSfi{qDJm|*Mb51i$=+a`h96GpFYqmx?D%W z<@km<4KKh7yW{QjG;7TIdHL>}7}S0Z*)x0xKjsIx380I?s?`$7DetZEWGWj+&lgSc z)-1#5ja%4;Tb}Vjee#X^n48t&PqWMB!C@PWmbADKMVEAkem;6nX-qW1w83S-O$6PI zv;5O##=w3j_RKPpkEL2QqMP(o#ZAHrKGETuq{^pX;pN-b7erV_wCYa!^s;Of%Chog z9NsM1y(Z^DtIy;B+$7L7NaJD{i9@S19Abi*7DdZtzdVuFEp(2hm}KXx?hjC%(>Yw) zo|HUUbmY>9{%MA8?anpL`8#}}d;s5qo0XG?R*_zQs^y5QcQ$g$Ryd>j2OebN9 zcoy-F>N1xljH>rl;FUCLZ6~n*>HV<%y>(fU&$t4=y5-&|CFbDNEN*Un5pYvL_nU1) zs1!d!gqtp3N^!J$#Il;=jsbEEMHGVnPT+=$w-g@bIyujSBe}>g=3nsdh+eKMC6wb+ zo)y-9@=9YdsQ_*&=*o1+IZHwdt&QMO*X*+vt8-4qv@?Fik)%zgqh@VRIB49Ub{dF| zES=BQ3Qg1svXbk{<6LhFPuiGKf=^2B1sG%@M-uv?n6-NBm%B9u5#POnS!#9akjyZO#9|&Ak z))K1qr**3VHv@EULZ!#Qc$VMCCR?jJIUJc2pnfWF8UMM*FM-!PTh)Rd!h3aMfoF1v!c3%zdbL}dnqH~4Wc05=PCd1C5Bg;aOf z4#&QbP)^2%;@f+=#9`2VF6gR(z+%jDB+=Ng*^4*YfhZ0z;bCp?dGt#`+wZ(^Sc5+RtUQcoQ>Na2L~XnP5%N zBjw?OI5wh{1OB7UY>!qNzBA#?BjA1m-F@SQ$4FtLt9uxzJ!6-^jbV!${C2ZcyyuL0 zbFvBSqr~9Q^Q7kXt@4&Ld!FF7*G`a(HIZ_mY*p!1Y>XLm2s0zP6zW6di35`@cQuR%Q|BSo;ldxiPlBF z9VD=?-7$Z0f8I9M9&T+U0Ng^*4O+tL+gC?qR+0_zxVTc)ml1*DX}j|ERg#gB`#oRP z^7?h5=Vzuj7l~0wZ-~CjYj`FXTfh6X5aoG*{<57w3a;miKo_mvllRozihoSQaOoAq zcM7dQo}pHSqT$?SA0$EI#;7#}L7%Rx4=5p}i-A5h=Ti8-{rqi@lJ>9NieF6qL%{y^ zV$jv0`{@C@BXYPZ@I!rJx>+PL73#8SqEl|ZH=m~J<)F6-6}3wLwLOQbRW_ekpts=X z&4EO*35vOfOFj)#=4(!197;gEETHxp7QNti2CnS(0 z1e>*|oP2edfiTnK0^44dDdfR)DUW)XIOy6-i0FYLUjj zp*GvvW!G4_E6j<1@paBax4ttM44QX7hj_c5xKGit1iyH7dH36n0Wpud?fdvov49kC zzxzAr$}|PPiy$r{QM8zOTnsH#k~th_@E~W`#%O(?lKi@F*t5mXjm87oKu!@xq|)W2 zm_;=!-Y9?~rHK`p|8rIbB#>_<=x#I5SPe*f>CSF{{I*iarfVUelPK6F!hQuEKA@AW zwxhKmcvF(HzT1IXUT1T5gTke}?WPv-l6|2MGr}Sar3|=LplgUUE%!)2I6AGP%mDv8 zG_6-d+IaHZ=UBQ`hco_F%2?6q@7Lcc)d#;6PU>69Iq8;hij5Zp`#P;gP#I!rjezU7 zYS6u1VpkNzN44ZJP`qS$VCrRPY@EfMr87!mY=k8}{FJ>C=Ot~hP+`2@N5H=9G&Ag{ zYC+;(9%%2WYpTzVJCd(Ah3Jp9NXmJT zr+=A?v*E;5`7g`JL}V+gmb1wsJm=QfW5Y8Pi+sKZ+*;7>MrgytcZp6e74STJX)azB zmB7i8MSpJzxy(Lu)fa2enk5viHbB?*O6H8%Y_>#uN@Hf#XNf{w&os+K1I2g?aO*&q zi(H*J*q&03T&XiaZcyDvZT3yVQ4OJ4QHBavj!RoiG-LX`s~L)u@814JRGiV&HzK&v zkhNaCFH;G`epEEa zLm!(k|J6?%vIJ4JN!KtoV~2$i_KiU2NlRqm@Bdo(H$OChu4RCd9ij1;>*>S>p}UgF z>6UV;IVQr?8$}I0<>=>ET=wkD-#J-jap%z-V9ZKiDYzPlkNjdKRj_JOW{XDG?FQUN z(7j(3F)N9Ff;2eo=^7ZS_cZox?pXA#(L})=6zz|e9Iv<-(@;~{O0kp_fZk|x?o;qL zzO&*;mx$?1pi;LwDjl?YLhNVw;oW8Fp! zB~*4Qa)O{zOwMibyY;GoIA)6i(U9~>HT9Tnh;qPf2Hg}{jsi&r7RrLQb$bkjU-Tb^ zb{jSr|IoJKjzQYr`Jz3Y9hgm41;jX1ut3@&p5KX9+VYaIDgM{OJm1rOpWhF-EuhO$ zC8(Zn;>2uwZ(Gcdj)nuJ{OeV*-m~90uj3DH^FMn0@@~U)Ez6@QNldb}uF*2*1lbC| zf(5wpt%v948;!y7Z3W%wS@~PTCj1BA4yOb9M+H$1iqDjq(QfodMH>l=-ES8(r)be} zlGDAL*Rm>SkMC77kel?C(ImA&Sl;2?Q*H~7IcZVR5pyd~=bE;ww{6nN8zeYi<+WB*>@D}4nXfrhfvvS9 zQVW&h|DBR`^at{72VJomw`cAk`zc|2PPe?d_zcX!M-L879kf%Ih7BO?!pyy=OvSc@&Rg$4{pQ6A_+%~}N0NrzB4LQ~6xT982f7_N(4TO?n9e;s9urg(r)oCsDOQ9ouGS9WD;AG zWBhYII+RmITI#Lsh;d>@^GE=y{6S5Aycl}4F8P)liq70aW`$5r@h=r$1bf<9XNRZn zB_(%wt#R`}zFnYugI6auT}TraW5C*Y^I1xOPpPQ;0*U04l3NGM^cy=@*bf5~@?lX+ zB2QRI#8yKAMAILb=TOd-HWoy0k7=Zl0Jj@-*{J8uPK^0VeEer{*L&*AIim#!;hrpc zT5Gg_z@;RJ(|utO6gwNH7V5#`2@p^vaVEu6J5qY)5@53*9G()j5a@02r&|!^+r+E5hxYV$AEp~-xcNn(8 z_T8J8;5y(Z=xUlt_GRQ@`UC|*DG0x43Bpkk2dKKTb0||rscXP1oK1d?a~({5$cG>l z>h*xnifljSovjoz(W_G@sz!>&2J6bbpv&3s+(Fsk<`5kYm~CRdB+k>7|rC{ne@COO&XLR_Jn1w;XAqD|r3(fi4tk$}Iia%X+3{ zOCUPJ{j~rB9E5T(ziE%m36_7BK$D-T$Mv9jblj{i+No>{f`HQ(MJ`?GAvguE*xxiX1#z_$c}<3I zOfEWg`_s}%$$bnx24Iaf=G1-x?f~en61LX~;Ej;?HK{T2;oM%_7|;&X(ZRaa_!;D*diZRs$L3{{@<4cO^7UyAJsba0fxxuM@=_VPyeg0mq;h zed9}fYsPf;y;b=Qay-!!GR!dM9<6yvU4nhss^?<+IC+-|RyY0%-MJUDi%h8LJlpSP zz#RhJ(sa+)NZ(-f&lUz?7VJ7!BZY7CSI4aWJJgJzJk7PwIR>Ghmd7=&H0sq6dW)x} zCRhG8qFB&`VKnVnYH}+O?Ef7G-PG6PAB?YsVD0A=Kio+OQ=d#8s)wms(2QDmRWTWS zfj64vHJP}Mgr}Emoc(BDt#_sgceARAR%fR6v7e+Z+YHF}7wER{UNJpUeRvZqD)fNI zj;hc-c_RDlKSsVsk`mD`eAw4eOG8FbJw+8t#)^I)-iayj^`1h!LO(~|ELouJsg)-m1qH{BfCxYwvYwp~@m9{-)lMnb~)6P)0BTY3O zZK$+&sSoXXoRG@bFS-L^t$PV6rMh2nYD(ZBYPUAPzRWSu^_Df~-w^M3Q%15CJ4X3i z&u|)}qzpH7LE72~YHI9_L-fRAxyZ0GJ@k?(SlLwS6r$`T=OOq(|fq*Mo?dJp#9WrcQ2J`5&cEgwnqlB%W}bSK{FV`A&hZ zX~rys;s8#0(Ce&B-D2EFZfLP&r~A53(f*WASXk>pSKXwQvwE1vX>-V~P)>(wJ}1Se zC>x79>wBhf+w4)`_)ddvECljY5y3j+Mmsyc^OhjXS|oFt+VXea&JD+zcPADGYL8na z$=$XeVe8;*-cb^%Q5wHs@MV>hUD2^2rW53o0{PB>Zf2yGRL8FdmC)P7j4rnEehO2~ z?J`A2sYhF?(3U>JjtZHG&avFyH7xbw>ifH@2S4@TO zWFAZB_8kE7T?Ac4adDI~p8}a`{W^n1urCoKXv;#k za)bwK7G&$ihEbR{8Slww7=*?qJU zN43rf$ae*FQL@;%vCb;$wq9!S4J)c1{)jn8N1NR|Nh(e}wCR(n;s^dlBjFTgPM^rQ zWj7zv(|%+85)jo^(I>LU0BZ9!&+wp3jt{_5rJ&h3kjT0Oa*F|Tm6QsVOxG=dE|+5vYBbghxCB|25T`Rh%yH#8cT1@-k0sWHuZ|SwL1U!7$wDtZVyFs>%bI47ij2ghy!mLy%nxI z?gF^$pu4QOWw@KuvA~mi8E8jQ-c=-we0^O=njNG^<7mqCX75A*xj@y5G>Cogq#-?$ zX`(+vWZnM!+@ikE3HF%T60G-afNq;sq6u>LisAVJt^>L{`Q%cS+7fbnF-cnB4;};Z-2`3haOyfXH(E=bTm&T7 z8SBDxr})Y2BF5lE7CdY5`rnCn3wfzQN77uvwC<`42dc9tir9l!uaejR(%Bgwzl9bexhKzUA z_n)S_Ifl~>em_)Fjra7G!)qh@^>QZ(dc0ryHr3~M35>%w=vFW2GO2e*66$|QMu|iT zQ6-#(iG{C?Jac#P=k1Y#NPIi6Y%wbEmON#YoG!mm`Z*0>@ScEmCk?$})m4C&5UeBa zfG&Y$*@xb+>7`m4{lihRSBudek>9Y%p!LoxJhk1r4dnWdF4c-j6XiDUAE#k%>_d~3 zNQGEDzc(j-4SlUQ*GmQDy9>IK;)Cj~=E0dg5Ku_gB4|2gU6BaCxMWnbi21MV$b)pz z${gl#=RF1IYHzp^ru~0+OfNm$VVPU`ICz9GO3c}M7h>v?M(Psdqcz1{Bruf#b!TA61AGO$JC|_a1TKDqI=5>s!n3lq)+Y5$8EDgzRG(-3zw#z_hpgx+d76H+~%7+ zgN!wb(B;3C`vr2sG!mdJ#n)dYdE5|{M@RG?tk*^)JeB}|7InlTe6^D zKK1ywc<(pl7d5~=2HjD|p_1i#W1%R9&q99$CVp9`KR!WHwXG4P|Fm|57(mCZNq?8D zPJB)!;oaqn)$CO}@?ri_%R7Jf82v{V-8k5nc>=l^9!_GZ{&#+b1PZ-2j@7~x_*@VX z=qG*On;Cf_K4ZKmZz~+TcdcLt|S<>K4R`P z{5vP=?3y`PS3U#XDI@dQLuP75-mRw1wrE^iOm*g!A3RV?wSf~p%PWh`5z2D=!)tJb zbZe*73W2T8(Ioy9JEso9hn@SEdUm>>fPBwE*CCiMo!+=Q21UFW8eX+$1}}`o>#^h6 zZT3q|hDzVp_~`lS6L_OS?nn``)8o1|K@!9Rm;L&+3b>ULoe4W*M8LfO-K?CRr$8p8 zM;Y<5N*unVMZ&4KP&m@V2(J7pj8x8%kbZsK3g%aBwOw-LA=sN8}YSbrNoL{Drp?6_RM>^fpixoB8S30Vz_Inafd%rt0^O!wLcNS4<=et$H^WGZ#RlBMAtq51ZDXsc zpEkMl{t(~M-)A%h6q!PBwZ~UZ#DvXBB7M$M zVjUEeipMq*}jmq_C|&j_0<8%~dueiuGa6x>m^vlD%Ja=84Oq-m1bGXmlm*Fp_01IY}t z2ypK}7yr*W8Mnq}z3%cwf^s=z)TNwL&_>>*-ISAa_3}Y*jKssdV}{0NXPTadHHiwY zO}N2x>=n-L&{u^arp7blA;7%{-NcY4LgI1xEkyjPBj_FPpwrp<-77doXda~wT|ukQ z4`f%_TfEmxdNQInB%hLPr_xUJ1DvsJq{j^^FK+Wf_yG3-bWa_4t@ElPoEUq4)5hf( z1eT{`Yn)nH21jo|w;Wpz5~3&V>eU2AoKi3KpG(jWVC&@dy~FW3i|<2NnbQK7p<@nYqP%4PKR6&NQ^ldMcu&1^sT7>~++mPv&Qzhkj#- z3T3$1-T?tf8;Ig`9=as-wZp;z_Zf6KziYusc_RjdIcHS0!!`XG zB4G@iILCUJ@vk?fBd-fgU46-xFlNr<Qh_1!@?thzPk&>L$Mf+c45q2134}<+#Pp z=$E#2&i=R30=by*fcxLZ%l``)JyE^R0bE{*@_@WCkTbT6eZUjB3MrEcQirVoW( zBfVT^`SlAJJYA0!D+kVcy4c^4x1Gg)mYdiv`*?ZR1GsnDYz(hkQz8eV1~l}9ASO$ z2Dnh53ynO%{y~b9W7OaFygArouFY+1&E_HUYbM>~C{(k1%iTS0N<`$Zmb((gA}ty_ zep;$-;TWhW=^>#6HOaeD@SG(y=w9Y=4!h_I-)nwN&J(1;ybX@i;ucY0i57jLbE84u z+`z)3_Ouqo9;-E>bg!uiB0NO7MCAR#UitW9ED`t%9$aU^fUf6y@PURoZDD@*i~nAc zHIGB3pWBY#e>+>&xhst*-Fyc=(4D=QN&g+D`ynKD+@C_h-#+_R^MRI`QGr@v>L)m# z{hj0g1f+UQ32XmZ|MuVDKvx&7O#bxlqn_z*A;O=k;AB2v_VW>zVJLQIqoM0hXkxjz{cdmj?e=vgNtL>V zM%-5a9k&VytRPnF`f80wSJy>PnFLzPy&?N)HV42(23=cPve?>DprT_41^gtn1{XUw#UOFhaZV zfu@(Bq+JH(J`8w0pn~q0al7`+!zwzKl4LvAsiu{MP}2V6&HHa3$jYkAz3D`GIt!Xi zgGw-bjR~+QI$v!e)8X{tyj95|i~q%8RP6??FaGux{0o>qowro!v`3kvmIu=!hs5%h zUunEi@e}8v&QfALMv$DlZsRjP_uCC;9uGE964F|Lm3tOK6|>^s51^6QG0c zxf?_w22vIGPlBp*g^jKij7mNJc=sJlJaHkO56X3S4au*>;n>$du=m4P3@Dm)4Uai83RFh4 zJ1f~{277?P%owR%0jTdeiVt5 zI`iD^t^aMGnB~qF5Nt%I2G)15Kvx3N!mcgj5l?|pY``q8!DF4wcgB=#uP^aEIs6od znMB*Nv0X{li8K>Y8-~Y|BQDC8aYaS;TYCq2iXKABk|-eGzkkDj0ds*A0vlUJ?_gjs zak#|5EM~wU|H_=p9bzsov)VL|K+mr6?0^Go94~3^4)(e zV;O?-sbaeAn97-ac~d zE~Z7pb?czglYTPxx;;FT0NlT|seb|Unhrt!ij)5BtmC4EuP><=MO|Hit%>A@@6h#$ zbbN~u)gJumvM^@i_J@*0jvV`5S;#45W)vR34l`^n%sW}|eVqt&PY{FGy4Z=4V`f-d z9|)*%CZCNbmg%1ZI%oY&4Ndd3*V*^jahsH?mw3VbWb(@t65Z)B@v!Js2Y)_$KsLN$iuImD2`=i zlT=XPX)s)Dob`>RNfwo+X@{zFyiJ#aJjJ4*V=m>pakeuxF9BRq&~;&d-->3HBuKbJ zK~`4{{eY=!%_T^xR`eW$f{uWYKZe4NkzmW{}Ku_+${q;zK}v7j(&GI*)u# zQaa$0f$kkdq9w}Ue1Fi-TD0hQc=@b;bj@W9RWH4erT0{R1o27%PrU7(9{Ey~!Q_89 z*(8annNQIk&~2uP&`94`E?WXFIq3G4_Y=XBZSykzzCo0*wl+3->YF3GO@JNCSegqF zFV!YX)9=K>5Y;jZEqFdtD@c4m{h7wUC60hXRl-gy$7BGwfA5ih0mBu{B;{}Ek8Qh2 zlfRJ2V!w7}nRERW{p4Nw@?htA;5J=Ab>@$T23-4fnR35(m^8spWiPpJaWrX;=p!!o z2f+H--#wCl0aJ80XNwi+c)V|dYpkuDO-*2}HdF7niesg|D>SCTOt}WdeYK{O#adiw zGl@RBV{%>C)+>}IuKXl_7WVqa5L|cvt)2V}nC=YC+9~tiq%aI}ak7L9Wbu?j9auV2 zek>9#YR0UTV%ct4g@B5U4L)gVSUBQ@16~eAM~f8ZJqB@h6S$d5QD7XXLHF`htz>5j zmq-2Tx3}i^=%v|m@=#*YU&{pJuQ(TF-+1~4=#We$#bGOG+e-)gT+a0@r?mzcqrHXA&+ksE z#C!Q!Eb|2D1k--h8DuTQH(^*BSE+#SCA6SBw$1u{aWY(t?$J+Tt{QNX$*T53Lano7 z$GNfQtn?s_vxGEVN~s=(+U8py$D9JW`&_Pka1W<~G2SW3RAdRRhyI>v{TDFG^*ZHW z&8QLI_wn=>@SaT3_wyQ3y9@^0B$@aH23oSx%*WNDqEGSK8N+gAr|b+bq3!zZn1yTd zbL$Bcx_T%8<3JC(KRQI!d`@roH1Et9_fE)ZDKV8P* zvoV$gSk7o(ZSM0)S$tHp_M(X)^-WY>09*#pg%~t*pX0lw^0MsaykXn<4%49-fujsj zv_L#Dsy3*>-+R5CqR3VQXTq14cb_ z@+zXpT#dQb#sepy77P1_BGWGzhiV9Z#rOOXHr2htE`MQLcIte!FAb zWIgqM{6h-%hxMAgHBR;{dueVmGw^%>Gw7y>La|#Tw0e2uFg_x|OL8xhti2}p(Y6U4 zL;ART>GXx?D@hyQapS=<(goju0iW2B*@Ukd&R%czNXjs|OvvB4=HL9w0=hcGc62$& zmVA;Ci_koUvoA&Uer_~U(WFng-KaFEy5B_CM`*+>uv$f?icS-Fm-n!vTwo@Cd5_Il zOoqyon1K6wtf2en^eBt8%*g&ua|uS&v;VbUgFe;4H(N2;&*ZO|G09r)b-EW|qqqkv zMd{xW$4@o?TxX56Y@bdRhkO?6`ZkY-CX}ywyI`dQc6t{2Z@u(uMJ@Q-|0sBq6hBk>!5B|EA zwuX29I)KXoy73Qv7TyAe|NS=~-blo&ac&o4Qjdf8WoE^=wj*r&qY3!GkSJ*fH0LV= zGw|X#miwgrVZRKiGvG9R4oM|L%<2N%zrCve;{T|+%djfC?{WCVp`^PT=?;)PqT|FZ=ScHgvS{kJ)F+kkBd9crG00~*675wg#PLf?zHW< zKd^q|0lL(kT;x!^Ek-+iu9SCZD)uX5!wCDkUFYrE494uArpB;4ZhZ5^yFN0qf(mh> z4a*Q1j7lPH^Ct?*TO z)Advj{yw05gJ*5__=IRJ;~((&YaC;z!Te6R>Bmz59q?<*b8 zM5|^{E5GdZ!fR2hhNCpAgVx2aUO9_|&!s zr~d6^xuUgy;iA8o;V}%P%s>q4Ai?1lmYx`YA~8gT&7HuC%qQi18TEiKlFDL?`-|XL zwI87m$QS%94iX>UlR`Let-E?s&e?)nLK@x!v1_rpJYTptZ7ap(|8 ziRk0qvOHd=>xLEeo@KIXVj`&EY*gVRyW!M*a4zGB|f9bJHj04v*QJ@Ao%gQc0>HlQq%55VNP3(d%6HXZ=^nTMV}Y99RG>N(A{F1YIxEd4BUsnV*&|KoAruy{;M@1WjWmsQ+`va1*Z~T z0YtMQP3mUSyA3fHw+Lj0)G@S3 zlkMt112SYt=n*p~4ix&yO{GRPWP3mpwc$5Eki(NEXkfKXlzs}cY9cirXt%69xIc2C z8%s;)Dm>7<0`BwRvn3=z(3)p!;_luHe-5K&ZP-LJWqx_TU%p5gF5^B*_gJQ)X877I zk@VJx<}fPuN6u}EiaI-vSM3ItiXi)atalR(a6U)@-M7aKd64?1>_Qxz(uA_BIOw^G{5Ap7-a`z~7sZ2D)_Z zUh6ofFoHbX9P9%c9Z`ON5vZ8>%-Ret{&1=b{jW>G!8Rc0g?`HJ;aI+@Pb!7bS zs1SBIVWRjarqSwxz%>wL9OQv6df@d$LRx=!*Y45g0;(!laLi5cz25 zKgwhl5sq>Ak~Nb%g04k>yY_ZYyxu8`$mu6C+IC=Jc!>@axOWK2 zR}tu*rsMhAd9jPfAWv%RhrcW2&65ffY5bAfTl~3VPtTs0gO515x=~nGY+rY5Thm`l zD13SwDO)={IPovRn`}GqnE~R0YYj+%K37sC$|{Js))C}xWN{i@f-bkS%c*QGBC+|% z$d8Dwc$xgxgxSt622EUNIgC-?_v(}E8gEf#bPGt@cR9+t0bKC!8bSi}6I-qLh`lyG z_WQ$d?Lnf$G7kQZIWF~E1*$nT6!M>=;W}?Bc;!?T*+PH59RJQyjd932OqQa6V!e#7 z?CfW40JthZ_kzai0NR7Pm*#X#3A!fC-B6JxPI322Ci46P2QD7PqG9JU_e}LSBb;X8 zQQhA9L@yr4&)ctsP1{V>P7cvn&j2pCHi865aatSxDd;lH3EOMackle2bsT+bQT@zA zV#6HKdaZAV7XD}*MZz~WH|;T_%loug)*&aD{s3Hkykx7)pRoiJ0QVixg<)KLBlM{a z3x)kI@2fZ+LPQI-J{C^w00UIK2Me*b=1J@Vrr-Z!Sf zb%OW0IN;h9a^2K`E`qRSdsefY<}|6K*zJ(03wj0_8Jm=$tl*L?i)f_)w`Cn)f`s8O zsz0TL2qjInWMK+Ugd2u`@kR}6eCD22!L>HTeGhaC`FT@LkwWkOq6m%U&fkWwtFDAE!YU*JUeTn#l;I*H*KiN4lkOj|ptfDy~yArcJiYp4U=_U!0y zRrkNrYc*Xc6}d?L0-N~%9Kb&EwM-+W!#&L{hOe@{z16N>9vKhi-4dToI~_-VLy$p| z%%F0sjsnH<6_Bq6(DgwU_xnptiyksOztzbAQzoAN7)kS#L^G!w%!qXlV&7MA+%kaiY#4e>BZytVornC@C4gfWA%N(pem?+8Hx)JBYKs=!!OyQ@=J{Ov-&^_3dt z@zZ00syQxmD@wF^dHA3&#UcVyP=8YA+5+-~VPAP@G&TxR8$ude;)x1!C%^^2+XV>_ zhof8M)Y0XJzoQ6s=q>@ag>MfT}j9UI@mZEtVIL~x|?$DX80fKK0ov*ukaJTp9tlqg# zy@fHni{a-aGtTiQnJ?m(vAb#I&~{+gdZB}E zoGT{eX~d^Y0oN3e`Kt$XZz}GpRk!n#H#e2L5)UWIxRegv;W$q1&BxbLE=peUiAz}p z!B3(K4*c*Z&oA!9t591cJ-Lz^UM8KDD`L$X1GwO`B_u%T-qB>=vz~9!e%QG^b#Kof z->M%DY@(a^!c0Gw)Ou_>5Z_^3hEZ;ZA7f#V#!yqhqrkK69~CD(z7Do2C_n)BW+C~4 zYfngk4tDK-ckt@Y@7&l`$%6KS zGR39e2)nULaywX+8H?Tvu0s`CQf!r~NGw zOdQmKv1X)D3#rzy`fPc5vrPxBGFg5zGW2YBeD(Oo5AKy^Dh|?fKUo}GPfqd(Z#4vP z?+}u&G0;^%m1%h?Tch@tEh=|z1%2bll%mpBA&*-~nn6}%(#<=ceUPgvXcc@e5?>@;c2kNAinIS>zU!D|pCKn&XCTdufOZ@0#5>JBChw@9qBF23J<9vt2q zU3lv-aEY;r;YBqpu?u=)t*L(b^Df?I`6b_)EG;fFtQ_a>yJ>)H3Upl}#g^!#E3M4f zi;-b>wk5eb%p|^xwe=9c6)YY7E9zf{t4go@)gC^vF>m%3j~^Y;di=KBt9;<^*efd5 z;6PxX)(q(8y}q=uFGKA6Eyyy}iAf~ramConmvMRc_6|c^fH-*UF~8aUR)QPexaSK< zXZsdupSw4V|41%^w9aAZu1^^R$k!a`A}6|AIc|P+u9#^k>$#JE1(WU2tkYLAT0K(P zbyAcm@RJhn9bvJ5YN6nxMF&seUn|%aA00Jh_J&IKP}kI-+W;5bqk{y_oZ~w~2s<-t+9$w~-n+tsBCQQj(%{K{*3Szr?!n$-DiSJOARvkX`B^5-4R|gH% z66H7x0$lK!3KF1lK^0~XkD9o>y6+jz1<~)z^`0xnrj~pgHEzbO>CKfo;H?)cS9>Oc z_HAj_p?kip!#qJh$Pq2)7~Onb)=C5JLsmf7VI4l=`wTDZXCD6JJ+yz%KsGoV%ned* z8Teq#Q*N~Mbuo+!=hjZ+vkMZvZESwsZd~T;v!!&_hz`kQX8*Nv0OV^8blZ8$Ka2#x zqo7z}B7Ic~M~w+iaU*w zmXJDJ7kitSXSYjDPqIb&(hlLN>EH7U*so9w&w0DbVjrD}dkwY@0j?d;#qi*y zI8)uk2}`-_TP)*aghE=Wji_}OS&Fkn!Z9p}<-BR+^%MJ3hebx>Ep z4Kv9ipNtz&^$D+oLSItbEQpx!8I3%zO0Gjyr8D z#H_0Nb-4x4JW{N_(&*pc^T0)AiHswCLHsoztvP0=u8;srn;3R!D&JxP1wP|I+>byv zsS@`^^RVz^F`Sr8Q}>jbohXR*MkmEG(;hWqlP?7RNn<8qlXR_dsJ?3)_wxulv_t<} zNi+Qp*U4uW0}1y(02e&xAOQ-SNkY?i9;KQLEZ`mTSRu-3Lo1uh5XXqZ@1PO3 z)1fymJONF9=S8ajaIx7LH|ZgN&BAwgr-U7q+x#!t|1V!hpldJwGA8}vGiS;pkTkvi zY$Z+cyC-V0Q<_eM@R`KUuV@n3A!AW1q((FF?apBgByuf2Kq^7%oq2>t-q z3F!W=HJRtLKc99Aus&ORHQ6hJv!BW&^ zyOx@^^)a>FCGDMYo-%NqbOySw(+B8lpub}T4}62;ndzlUk-y9QJa8z$CPJ6cFCZJ0 zv?eu1JEq=DO!cr6_%66sP#^F3k!rcqm!%XZ6OMZud0zG99&sqq4ZJ(h>#ASWA~YMXE@p;m&>XWy_A6K zB)A6(3DCRJXgb~$>36KL?5qO``|&XfJA0^NVe)?V=~vxnDDE#MsZ|V>T451l&Yj$t zVHbA}Q?S`JQq-Qj{sx1Nh<$*3!8I2oKn5P$t%Fc7NUA71X#z7sKO%ei#3e_IEK1X5uoeF7epNRj zSrfWMcp<9;_mUy52hhD+VE%~^t;ZIo{XQgf)hZ{iA1(X!F_grKjn8BgE#0YyM55Hp zG6`1OSv()U`g>C&|BXV{3|}_b(4NidMsF{G3+|;s0+b#1n7I@r$Z9;BLhDp%9T=1w zNHA6+iFN%JfObTpNf=ht=3FsbG znIFgA)1gaj4enGr-=^bC1bYz$X>M=n^-+FKfSF@6m1XQcL~m~HaQ<}6PS;eU1?_@j zk|akSv8cZC$z~bgf^&xi$di(H^h&f|e1G0n@oMV;w?JTaMiOl(uaEqS%Q137Kvcib zSA1%@E?u8y>vcppjyyVi$EzJP8B620w3(G{!0YA>bXoG_KSp&1tzmKpyj&9@-ep&G zc|%KH;-2J$Bz;l|9So4FjYSP7AhzRCjPCWdyECEZG|SZeJm2tb>N;uO19<-R0lJn} z3d>8h6gt-yiA|gcAM#3WU(J*d(GZ6gyZz98 z_t;!IKWCr55(BPXA@ji(=&H##7QoLK;q|)iY1}QdNk)p5{3Z4y@3gf8 z{zNp$8vcgWWfpv~km36HU7;J=mSSGK{+NLzfnsTy@$e1rmp}OzjBfoG(UvuUe8FoQ zBtSA}1|ki07$a}D4MIlJ)%3j(4cOgj8gw^U;wY(zYjSX&!{^F^*x13jV z>%=-`sYNRaS}9+E(mDWc0MKnrIIqk%5wI(?%DM`sUs~kaS|ji|lYJIxovKO;=a3q) zId<-h$C&*cgkr4SO<)!3@W#w5!$q5aErqur`Ut$yjwQ?0+-k;xAm`YEAi$eF!>!z(qJV z&4wFRI0eqbNtY=D;06O-TGeQQy*yX(SLN@V67$J518_90xsHbfCPlWc-CZkqOY10i zRg;ycXxO?!(sVw->9a-n)F)8hZuKbOTK@4W1i0YbApz12XisXIFrn}gz&IJ}(Dpv@ z$DHTp@*NN!ql+O%qq6m5E2KLNPVcPb^zY(buS3v%C@(=CL|Fd2^2QTCKQ9m9h63Gt z7NZoV>Ai9HcFM`Ec|MC=;uS?=je)CdgJ%X?+%NQ}B!X_FcA`Y+vDQ4_kqB-kzhO+` z=Wc)2t&eF`{?HD-7a;dV7|{KL5PrSyAn^$Qg3CGK(U?kIyNZ{#`>iDBLoFExQs_9b zyG1>Yq^m$#2ec9)ZwU4mt)9TBA)5VPd)Y;QJ5Ut>ZaC2OiBuiQ3o179O^y6)IPfRl zNBLwT+G!#R>dlt*VBx1v^H{8eR9fAszfI>v!bqSQXob9ShT~jMtghZ;y&d961i0W{ zFeE@{258i&HrfGv6eexlZWK2Yy67k`=1)4!=gIy`W+&%=6lh(m@|GTZh#GgCq>CR{ zU$Gc{sMgZeYVjnHpO6NhO(Em(8R(i!2a26yb%%~DR`ZG-U4P5}o?gpWN%gmmq40pm zxG2;xQpT}l5JHUnaLE5U`T zwn_Mp?o@B%ej*2Bx?}Go{j%E(%bq&mV6)0|jjldX@m3xdqr27SN}Cii(Fw*_?U2nR ziUGJ$K-d1~JCx16l7?rzDG&3T0*phq)erc6&N&R2lNhRHp~!F%LfQ|jT%@J13uh>K zMs}u1B_yDiZY|a3itkvsRww~(G|;8)zwq5Q>e30?#r|bwN)_8^=1piUi}NU&nQay1 zz`V# zM+I=d09|zEe;;Q_A=*9&ST5pTysB5_atZj{y))?$xY=a86w zs<-EkRJM>paArs#0HR+QjVA`Uu|Rh`gMC!cMuV0i-s@TW@kS6{ym6`Q$HYAYPopeT zh2hI{#2@`ie-+yzP>KR023grFqHqFkaa_R)%XfKM4btE_3z-jbKo@Rdf8xNq5%nA4 z$Iw_x8C{8c)=lSF_1_!Lzs9SGMwr(UH(p-TH+OhU&x49R)MEOpliwD@Cn0wp(N}6R zK8OHZa4!N9AP3@gtx%ty6yj|UI3=M&A$mg4AMpg<@i|s{4Gp>8s9<#*MO3fpF;|7# zX{w!a-^_)*Q88+r`!-!s%ck22@E#1wHv#A}2q1CV5~sHhu^dmJk)k7;XcY~n(QZt# z@|lOfC}4exG;T~w7rDZ8kkf`W^9nDH+_lSyV2M)D{7vsyI!}NOaKZO9BtZSC!Ym&7 zGwe2s;o2zh$)}jak*~LBGkJx6S0wSff5nJA}na zonBsY$OqoXNkA7hVGt`%Q&hX2sq~X^czsr-H?3a3iRqQ&=NviQpErhB!B#nO?-EqIgPcFhWm6xBCw4_ay_}Tc0J@KCI^{iNn?Oh}^zdDfjJ%m`U>A zxd!d@HyHs4YpXAJfpR9Rf|a`wP)u7KQ9n4psXmQ73tFz9QIx=fYaqz@rT|?;T5*)j z>{fDRH8FEDQ;On59Zr@aI7Hax$}_`%FPj)<1s<10z7etU?AoVNEZ>~W`84MKe*OoV zd}Ta--^J7vz)c0Zy0)kn#St)H7L-CWp)Z=t}$K#T-0|0J1&^@xXe|D=+ zumAlMW{D}-rEs9al#9|eTB|kc;wO|nvvSdwKctMe=DO3XB~)^&uVppkulQMHx>2pW z8n{@#i@^h2@SYC|5K=gZrzW&%=oPEANd+BC(U^TjBizQgd`$ci!BT>#q1~pQH9b#; zz3R?7$ucG^n~K^9HWT~qDh2C3rT@Cf@_q6Y@5k38vUjR=|NvGJcnNdvd*2+{7TKsF7 znHLc?*9!G1c#NdVCB2CIMFIs^%GkNj*ZNy`5!SCYdml&Zbjz!c#ng7>asW36=;j*x zy(cu*8O2CIp+B<%5hE1maeP=+L%S|swkOOWh8xYrO20F|m`%LCOj##Fn@FMe=b@a{ zvgmElvHIpkA`ftLfo^wID}2>OX8fS|hZuUs+cC$pm~W@beb}KGdkNXWOv`TV`QPt2 zPO2TI`1rZ$KaLo?33z45TMA8%7qhbCKLG12@L3HKAZb|@;p~R$++I=io9HF0Z;R+K zdJkJ3CRAUSPrrD=X0TD$eoQ1_IU0IwTZQWI+5ExFAf&`J?WQqLmr;K6_70G5KG5AY z#2riW*>Cnw64X&5D=6)O!cj_?2~=QzZij9?Vo`-1^e{oVcw~8gcb31ldU$We^eHS6wWu-Z8@d zdh?1%N8AzSf}CnA-W-k%e}||L1+(|0o6<{Y{0iWL&%%%Z5yQ+)5W*PptPJNj-2M+^Tv4{l?!xjCv^+EkA@{ditLleLS-y@I!DUpu*HU3lznno!75%c85 zZlvjCJHocYy2F*p6lQJ;WuRT~4KJirG+eSxApX+UvIX;|J~`}$>}w0c;X*=R8Ne+C zxXFj5|t7W&>GR9B1f?Tov-hP+qf?Gnrg^Yg)W@fGM1iORT2H;iz zT^Q^(F&XL$9XtCELZ7Ww-W$8m1-T8oth0?_r0X)tPj<_{y{=cGpr-e7k|!ZDxnq-J z4S{ifz*3Y%qYXf##Ra&PK$qwAD|Y17-`6FDC=!?14XfxeGsK@HH(uUwI!di2<2cdQ zFmw249$9L8%9NQ78wNh2yqs?o+i(ZOtw~Xd^RfWkDxe$I`<_QWPEn9XcahXMCV#G2 zBwJLn_B$+1>4G~wa@RiRh3E+lsI!gGCP4JTczHk`y0rCa+A|L^(uCc#MH1QXQ2@{YoBDA1ueY+55zQdr^oQ+J560kE; z(C>H3Xj-;%BjA2r+=TL3q?YRFtyKeC-rd>NT$_9Dd4C{M;p!X&%$GIXOJ?Z1;t<(L>w9&*cr64`x!@X>HHf*`J3>%Vp&h8uxhGNku_Mj`9ucRL}#NPxa zgb{Wpa=f)rEQAlH0Nxk%KsN>7zt<=#aRb3Jq`z6i&f423Jb5XSliF5eHL-(8Z6za{ z;(~e7iVPF52Gb&PK(_2{d$8UU+w=J3gw-M-` z)F(}_+)C(Y-HxmNV5enW#a~pBI_4zT)o3zV7SuH`jZ*(gM)x&bY{cg_>gOdsQ{`2| zNEYL?Q6*Cp?fn|?90gw6AOY%%@>Ug6zqaOI^k)v~P~g86?Kp+4W!p~DlT`OWctpu| zVpPKZ0Od=a-S#&+9#c1@Tgt5II!}3zK~t*fp%V{~Z!^&4Gm|*qZ_%6+zag7Hl+W>Z zP0p)3yj>4cLF8y_=S>KgnTclm_7kyzms9|c%djG_|Ih+- zan~uJ@cxeV1*Da;p8q0mWGa(qyiX>v^$!dFd+X{bRPGWuG1pLlbQsRrgIN$z%25(T z&+hsp8px+npaRDx1jx4)=+2azmAPtkH*>xkx^4jZ8*nyuRVRx}qU;Y?A3da;);dQc zT0>(9Vm?g&SQlngD>x5nv=FV55?NB)cQzI%0M^}YK-cxq{m03U;;01I&T|?WywT>* zs!Va!#EBOqedS8$8Zz0=V?@(gWcTG6!dHG5ermHQSej-zS3j7d2XcMkEvNwbwgX-E z5mD(KNr|^HO4|}=Z&Avv9c2u}q|jGEFJ-I?q;h;4tNm!_=Y|o%k{^5@EaohHRUTm% zZvz$IUj6%W#>5%$`~dDLLIT8SHO}V#K>S;)^96O`;a0iIob3Sy59x*{bg;SL>8b00 zpAPmF#dRwzwccsnGH)+%^a|P>jb(+B#37cc^Zg#C8fb^$1Afv z{Qluy(0&ba%AZKjJjZ52+ME|%;`L2_RX=v|_ z2}pp34%F-@M>dL$v70r+v^$DE+=VPmr4AJIBqV2uOKf8ppnIE~^ZvfMA*yW$!?%4SDy*>6ZKGOJ}P3+@~;rfjvS{SCowYdR2F@uJSP@Y zRqfi|>u@~*zXm_d&j--3g}btNqQ_sWc}s%eXDpC>!FvZJK=+L|t$v{2bs;DJ{?zK>s=^~iQgVM`q}R9u zn)X*it(x{D0mjseWgFo?G#D()of~;I_oA4A;TYQ^T8b?;7z_ZnALtrtCFMJ+FGvb5bx*2Na1FQkR=@0R1~;=?n%tnB=;NRX~DlIxltw?V4# z%y?g}HdHpck`{10FT=P*%DlJ>a0h`dXssC`HG{ohNOi)j(&|%iYLM}RxF8SbjGESm zC?b`trC|~@~)Ga}xy}1A1@1qX^-Q3{Igt5fn*vV@8 z3}dtIe5nDI&f}aXUaU-qmwhbCIa0=c>)8_+-(V@4r|vDP=vKzC0eg-t^d!kq-j?B> z4}g4!fv(5uG6zl~MeaoCgbTSrbd&cO15HwB-fE0dv(;AQofyHfbD2n1{4esDHFgqG zUe?>HJ*u8Wj^4~oc5xG5mji%10(7xvYjaNu2dSR5Pn;st!j;n1CJ8&V8y{90{~$jm zORXU=+II5zeEsO6J;)Co)yZ=Hd!b5xT%S7GTDNONhXS}hi~`*;wzyrEEx5nK@G_qC z4n)VBN<3!LEN?;v;PKSxM~%N-R%^m?iAw2v{t~j$v{E-dmdMr~5b)NQ@(Si-7S8(QI6~3|03uHRnwM;RZV}iO#YlhOs zd{*-~PfgG0b(-=PzOwKfe*o?{&^?`=HV|@5svigx9BBCW=D?E6w8A3#(cWVxXQ521 zuPetZE6cL;N{lOx42lHNnB`~<-}xrB`pXZMNv3*b!{AyQa=%RgU0W5^i6nuTup2!D zvWa+`Zq&$J1QGKH1=)rKcyr5f*dt;jT+KCdiz>$IIj)C~Rj=6*e3Jz6J_T;}wX)cE zya3!upc`=`f3QpKfb(&E)AQNV1FH{_JzlZ&6@9V6_eX*9@3N~f4wC};L4BK>LYKE* z>X*$yv8xqU>OSvt%w*sw=HCNcaBm6{AeI8NCfp>r*zQR(E9^^0r*f2W_1MJU-R3T0 z^MY&k{farP+2dZKMC*%xfBK6>wkU>&{PB?~PT60otIw!w69Ks2fUZ(-M%L6BF|2f5 zqPvs&lHjYeUtc-0J@3mcLg(w~p}z?`sqClLC5N|@dfgrTcrW9=wYplY=&1E^NLkCJ z;G)L9Vog| zNrT1_Tk6(jRAV!+xSyu=O88vC5JO(I#?|sX|0Cs>E-a;w zd}d}H0_`>T#wXAMyabIIAw#RaH+5dt2y`--yG~-O(-j!tvngagdSq`hA=-7yhH$bQCJ5 zPIHA=Vx)DsgK7lcEKj_8Yeut+u)!y_{^1e|%$IPEXxalsa4!Qg4nKe{F03a9{>kgD zjpJTDP`{KRRsvd0a~u>CyiPp)EgO!q7{a@s4Bl!upy1G-F1K810|Y)vyjI<2Xx=Yv zPRk&7fIAO#t!RRe7N6(y`@WMXZ01$aJ8GrYkv6FIrpf5%Y1SG#4;)i$6)v%~2EDOH zqByReQHU`cyh>ke_tf}a!v2XD_}p{>=pw@J)fBpH(qhCl<1|rg4Z;2(w|;g0ysdMj zkuo;vDH8TY597Nx=lnqGgPDi>s&>A)^NMP|0FR&=3BLf+DkdP`MWD-b;rX6j+zC1g zO`Y+?>74w~VO=qO7IUW5P)s1-yK&Y~B-MIBN2O*&=aOST`%bh&Vg!1QMn1N)K#?Q( zr;Z-LT>`oyma}hrNuEcergJZYcq|AKpYMpqbWhY#Ogm;+^7}U1M6t+lp9u|!hofb0 z+9H_D%xItx?d41cbl-izY9|D`;CloTAg^gpu1|B6k04^3SjrD6j zuYy$tj~zHn7Xp1o&6@wFp&Mx_Lo0hz;i0NM+XVe;(LSX28Rc` zUS#d7gdfYtXT-A?7X%i6EBmJ4LfAe-4ZjyVJJHr}j6*GJ*y{K>e|y)UazWShmhk9v z&sDuW@Eir+J0JnFNJvOy2jT1&U}7jFSd!Bn?k4&OpI}EBbD2vr#kclLW7(#0Q!9*O zNcEW}bK;*_i+O18xmxNA9;hrJzm%B$vmo<#73eN!N4`#)EkhsO*joH$!eG4Hoa*s} z)$zn(S~+1V)b^JhwlkDU>bvg^X#+X`MCDzlx5mZE=0oC6&GcRVCI`4ChPZ1$w`@z+ zaPE$Sk!pYTkAOjnUoNJOT@WKne9nsrO&x6`nX}^ZGg_WzT#~rIZ9=I1v?nZP);>&i z6?5=KR8KtCEx=s|x(seZxHH7K?r#IPWc#CInD*|iG#?uf7NPJbj@>Z` zXDJm<4+kAKKd4+-`Im)q8a(e5963g%`b_zILLbyz`rk%cO>0|IJ?Q5m499BSuXtaO}Atw*VhlGW{SlF zv#8`KE*EQXF$u=cZG7U@vz?C%>r*`&qFJD;od1^3OH)97w|cEP(Fi<0`~tdB`D6M;jV_$a%Bl#t1Pk^=B1owueoHdBxJnvvzRNA?+1u@mzEFUV z{7qe3rn#W>&w|Xe-$2)eg6|JSGzsD-q}5+EVXd|ia$~=mOgfRHob@*nX{D6Q^4sB} z1JkDzPYSK$1@||}(BHG3@D8;*8Y;W5U2@O^+#R6%)%-?9&LXDMKrHpBcx?ZMfQi_R zswTg3r)0bSV{>t|E$CY%nhU7)zCpPLpI0KJKR=3P$t?zkw}O&?e{}^sw;=g~&+d=_ z@t1v^uG}K@CmF*_6o02Eg3kScN`u(m-%<0){7#*sE|*NYOMaXNkvc9YbKUc{qMS~L zzwvsT(bgyBk)j0;oFl~D1G=%|QO0+chrAgspIz32JPN99yFoCHkC{=7ES61wF!NeN z7IJxlJIj8mSNS>gS3KtveO0;fh^?vDQ|=hE$OfLH_JJP`Hy)s zK?|lo+!|xC*r-$^S$v3+5WX3%L@&%vW zAp!cTcJ%%&?SjmN!RrmFM3Nu*z3m8|Vfiws0;|gyqkSy9<_MEmzldFwX4|>o?o3FE zieAdv$;Kx6BTkX}^lpItN$^=15}?;XBzayexZsumQG^n zt){>{!x32UjSv3&a#(1*QRIk7JZqJ`EtKnQpJ+kSYzBBwgN*MX(DgksQGKVPXyG$f z%OV??sa1*=&-A4BLl1?pceIgx3wAsK)}q!oaP+*2Lq1zqp7|gkKJ8U<6e3||sz^G< zr3Jt}0=njJgzfL!rnrahBgHG>gtDq|0s_*6gfN_0Nn+(aRf8gwY=DQ z^czp=y6=~Ik|P}kt28aJ747(c%GQ`Dl52Sbw(gX+DzA!AUhm0~{bTezWUQ>+mZ%w&w;L~_T};Ig;4uM zVcTZqgwE08M>RNys7m;2EMH0)PNa2T6Lhy9XL7~Z!S9B@X|$*L<2Uv1l0Vh^2vtPO zAfx;RxEDZodjW2oZW;GH!#U#1M^3|_&*puv-wwe_f6&H>SipUcH?u-oq}JzP7NHTS zKO7O>uH6t@L5HW0#+~|Wp@G;0cpqN^T|fS6$&N8@1o8-~HBCw)JW{3f$uF2Nhr|oK9EL1rF8)nn}>8QF*l32q3^ZjLv25kDc zNU(dyz$PB=`Yv4*jog;FtPNFwKfnc_sUQKWz#YXRV?eYTp`gD`gHc_1PSr@KM&w?_ zLfDr>(SN?7>XLR+mJ?ue9{?qlzNzEVkMYivXhX{uNLUW}UAYRbT_N)fd`5u;$S~1t z-*{$fap9pW<*VQMXA06|F5Xx^4njw1<@w0A*QblPxc8OkFb>pimP&Jl*y1Y9ycT^o z+!6^lyW&=u%>eff=z7e!)6EoL&-p%w`n8zoWjt$S{q8&KZjXmI zCWFem*0L`*#;yk6Kd3S93_ZQ5->j`3NdxPwd!QTAo@$vL_IZ-uCn z-Q!swv|YyP7kszmTY^4d9PjF z**EzsObh5;Jh4)pr2sB??|=kIh=G_zp5v{$%j<|=gU%mriS~~~@*}lTjLy1}E4egx zsVEnz!pJ2IElln4J5#LSst9_t_*9}v^myAxRw6r}0WNsXK>{Sh-S%dG2bnis&_I!? z0iTr;u2>x3b42x_!Glrh7$w$h)=sac!Lq%&qd6Vz^(*6120eZ~asAN=OFAU7zWY}I z7yL6I0irb~RMB9uj6|DV)?PJtj$nJzYY}fyR_Cv=^Bckmkd}0>32t@X)x|!l5^z<1 z-Jug6^%wWRT1fypJN}jO+c1C&zV{#j>RJok3gyIf4s)#AulPMUN`Kz=`zx7~(**rg z$rNX>)cp1}WfpJ6U%k_m0ukHVPaj-Se^>RaN0f}xIFAh8AOYMLpz9POv|&I|UHS2o z<<7lbglbs+yWG{-rY{w#^C5C(JldE(JCtUN7c1PSevv8l9+}~TMW<3~j+&#dF07by zUHJhn6bvL=C@9b|?kitUEcP+3mg0|wwi$(o70hPSeuxjLEAdus?}$D-Bq}zKhm&k1 zthrzX{k|e}_YLMOErmvn$+KcoEGq`~xuAiro5>|BPi+G?n?V~CTNeU{-MJz|w%F=&-2WzyFU0MN8J_zlW$P6}ra0fUTZb-|cqp2sWX)Pu zL;O!HX5k$sfC~?FOTs*_w!(HC7C_Xq3b!)r+yd*O56#rHs?(Xy67u^Q_cSi>>neJ| zXATVHuNmz$KxJPdcXYMvnJ=cT2Ecv==C`Q7fyM&!7pS5`qRh6bVir&W7Sx=`Vefb)(lHXlMRARmt zW8s6=TdK~q8|MaxZ#yfHcD?ZQgM554m&$=EWI`g?{?AUuJW8tig_q7@oC+}vx0o0wQ z4gLA0C2;tiTvq##LpO|C%RyBlp3SS6Aw z_k2Ce;XLq}7wm%mEs^LzcaI3x*FT4?Wf_`pImjZmsP02Q`S;VNV)pTJ67%-oET^5M z1Z1snccj|s*>}J66l2pL)|K8YT1@3;ai!pINc^)P`Ci#)cA4~1?21tw4=eGxFOi&G?k{em*bd%YiO~8g^Gyh$yvq98%DkMmPk1-*?$?f+cx zRfB@U0lNHqQP9>*Jk-O`^Q2VVDMskkFG_(@ymbEPD!efg%MU%TDbcgi=UWNb7l+Jw zCrLcQf2mCu;J7JnZ}`RG#Qe8kKp|rMb8&&LSBP>LFUh|9PsEJB&DZbG{mAwF?}M)k zi5_Ll4eB%gH@^S5ctCemRx0Y9 z`a#eWDG!oWwrQHFCZ_+3EjPMfQ53bKYDLISr%$Vq1X@i-3%aGX|2@(7bt#^?GmB3x zX7riQVx<4o^H7M0|MJBLx=ABL=YBJxKe+0C@f#Ffb+zp;f7nW;l?q3obHipozv(3u zi&`^Lgqv*)ZGxthCczw_RBykQ4J$@HjDmNY1)oj-{X-1+=Mn&2HJr7J<7+qf>>dgF z66jp+O`CV>$~Z;I;!qU7*CZ7v8qSad9mk6|krTgkQi$dS`vrcSRtjkylo5><@oP(C z0Jwxem+l8_#5Q4a!kTl`CmtuVLO$l^aGK^&v-td^=E}`)neJoO!^zE5OpLC(O|^-i zFN&IR-UNz%`%V!>glt2Jo$!Ayct#KbUDO=ZO_~@#Bd^~Ku?e$2xr7_0T|?(T=D2Za zq_sA(r7P%cDcgR)E_M*YRS6yCaD<|^!y?MirPsWt!8>1k|6e~93I;qMh=Hy~6dY$V zGOUPz#m7L6XkO|HJg>g8+81S^$w=>Ua(8qEa-2-b5$|tJb~Rb1FP~5>mo?d*VD80{ zv{P`6G7}m9mu~A(d14fj(tMk<^IKVOTt4KS9vMX@!vT7&m{%AhhuModm6i^s;`(OTGCkz z_%<7`>Wdo{^ouVhgy&+W5(T4iOEQop47i=%z8(Br&3tg&VX*YN-T z{m&%>y4%w!|33Rd;Wi@d2(k}wH8FNLrq~awwEjpR3;Rx1CqwHI-Flf7*;{br=_j0; z5wg^1&&8g8R0(p${+PJ7-z>l-2fDOOkqbC-Or_diq5N` zR2$#y_w_SF_606q_4kKr$TOU@nL@peymwm{Xf$Rxdy`6=c9_4NsotLd;dSVOPNV!# zI$5j!H}`+}!u)R>D1mMlmjz=@%sy4mxg1M<-A9+x$2ac?vKw277@+&!ndklF6 z4)%#WP4$Pyru;EqE5iCT(Cp#sY)+Z1ic$WnFaC3>fNtV4>|!Q8^2Of4T1wA_GS1Ua z{QyLqb}xkerp;0(==(pX#RV;5lqTP_g?1kF^yT6ZWSfTG-=)c?suPBP5vlmUe8Crw z8tA6ulX(hI?qw4EBH{ zIE?@LzaS{^I!Oz3M+XmI)pz~OtB0u|w6{%65nvtRZ7rwR=(SX_~@&vLoX< zvq+YDxTQnqdTn<=;9^rhb*ia3wAcF++*5~!0{w5E(E(k8t&fbE95PRo4R3~?J1^XJ zCq6qP$RmT)zDCa^2)fyA-=FKwvp<-?x7yIkG^gjSJO-qQ3``vCIcG!B{0DFbcd0eed(XNyYBmoXd3#Y;-J)GC0#2(3 zg=>E=aQL>@cW%_dBaiQI7&rT5x3Sx{R_F_Iuh$j1_0}$_yH%}xy3?;>%g?sGme(Yr#3uhFFIdmn+_{u50eHS#$cX!esF{W40e! zMCh4&6t`a6=oN}$RcGury$kDRcSFQY@{WB&Ud)I$b_Y&1JxO{$yywXy*1LOr>?u90 zrkkBgai7TJ7YmaXNR>_bSl4OnKsQq^y`#DHmX$BPSMlV~Nvme3+};&Q=dyRk&HtXE z?Jb&6FM6uxd`(1br_c?DS00$M!K7yF>ZS+B&40>Ut(aAhe+^`YOyPM4F1c?a?dTj?LD4W-EEW<n#ZBKjYH6i397i z&Tr`7`|hbzy+Y%4T~3~g(QmG~yl+g)-3-amIp1BzNqUH^ymD-E)0+r+XRjhP=l4gY zo_>xowPgE&Ghe83>rELRq+$QDvSzWWdZX(+&p{IpHO;Zyd|jgG;`80Bx9!~hz*oQF zuJ85MFSD;pELpF0uFHbg<`wZW@y>4hGCO@);>gz9nI#K*)wuP>yT#h%@BB_Kk&=TyN_J>fzPT(Dm53c?mFR{wnOoUts3rojOX0jk$p(`ev&}N z;WT=Oh5y*&nL4*#-;JFIrB{Pn@6y&*<&!g-k8EoBHGbgEn^L-! zPc&4f;-8Y8g4O7tt49+AQofJYEQ(s8al!Jc^U9yw%%Q=F#W_}XYXZUw7;x89-ZUzTT=`2F&a*lO3p>Mql!7e3bJ)>{@Y zZC%iHvADs=YQupo&fE5uFP1np_FBp`KXsSzwf6wunxCgo%mH?Jb4;Pv;% zy<2+j^|NeLw7p?jQF}xDn221)?)CafyKd*nUsWx?7QaX)^!huSeHPVY!c_LwWruZg zjQ)7Q&U^m`kWlx7w>c{gQbs8C!mU$>B?cIP1sXQ6`mNkuv zlgn?ZD6Y_*+&J;v)rvYvoo|bVFTLRUrRN^`{tB<;$Fl9^tW)*5^{SuU9sWYr>V9p> zP_f9bcZ-|dKGaHY_z|;U@rL(XLW2j~G!XV~NblBX(&Nrg?US9JZC$)uNWHOcPo%M# zOY$|1p=`aJb*cfk-e$iQEe?+7FCI0LQxuIdJLGiUTNE>UtH_GAAI6;8Bsl2Gn@q>W z{;#avMH12uEV!*W=Ip%D(?{toI#A{_-e?ME{N>E^hTM8ToREC8zso`~*@D+DWhV#P z`F2v?qTpt|Z=j6D9?c)YgHM>>-nqVNm(2Gv>FAQ-omTsdf3eci(&~tQpV7so`?Li( zeqcWj8FA~i@~yhROZC2#&{ZjC2iqhUQHyE^QwsmpaZ4iP&hK5|)`iha{lb`A?{n?@Km0v<#?Rd)A$mvp!~m_Ns`<-4 zTc+K%D@+K2D?sho?D<0dQG_X zI&8^P{Al{q!$A1L=E&-8K_#yyRWx03{Rn(sX?$SvxxIAwtIs4-3c z4!%8%jJ0NZ#IK7>dirqvVyDb|^W~oj9@R*3+8+{s|L~P1%2M>rB>tmi6l)B(UZsZt z)-G2oXR8i)p{xJo$<3|l!ctW;Ykv0b>=kc#D(6*t&bNX|T3fP)x_@(?kviCH(*!lm zcVn&u40|19eZyWdjj@-Whs?P3URSZqzv&lzPP^s935Cy^Ve$?-Pr7uEFa2>*`?`Ps zy~EShm)|cOS-EoT$-I$6->%hk5>>kTy8F*2RT--fYvpIq-}aEbG(OOtOxv&XAQA7N zg+=#gEOqPQGuhl(er;m5$D!o(C(+)|wdSn8{Nm+5yO-91|QE?#!Uy)u`s zhbvOfOnek@*AW#WuvFsznZ3JbL2ve*xtLsv)68B^qNAiIk(%xy)yV=%(9CE7-e2yKEXRlQ1&7|B*%AHtQESk5Dl!@m|EXm-F0W!L4`Q`wJJ9CK~E1H;vg` z*;Uhh;l~+H9$EcsxBa@2eo4{OyHw0g>-~X8!#C&{ML+hAE$=3n_bY47+)ZOgoU|&i z3Nc{oO=Q2in82-9Wni*2`H>PUP0B&{_1$usDk?tMG|SO_coV zkiDm4#n*RL%$Ou?lstU%YYAb$`qnL{yJ(1}>^INbsW6yfzT-|}^vYG1((mOa zSFQcIZf1{W#q*KjoPNyFJDFSW2+{Gq?BYt?D~4X%<|$~_zj*zsy3!LrJzW=fQ4u^B z`DpU`0J-F8b*7u;BW{Hpp4oE#veAvxJAR1{+_GIlW@|lt1KzejY0a&7#W?vM!iGyn zGz)C5ldXHwJJ`&ZOawi>;I-QzhUOViqfGX=ieMhT)kXhR6t?Smej*9V5SsMO2f7uDv2#sdLTNe8( zue>*Tns@ls+k*~wbp3T=rU%pC1ho0rj$5ycyNT9|!V~d@Nm)r+;a?O#7HG64->pfJ z`#Cj!L8DaHT=~T1St`kKp5JZH@3TB^HT=K~8?zBNdwjK;`Y2%Cwn{F&_S||UMSBi4 zv&>!^(aAnj*s^nJiRhXoK1$hxemyHYUgPn8#F?(0zKQwH%Kubzu~u>C>^UbIUT?N` zik5UK@agON%s7fmuLHN-=*`Dqn{|Qd~McK($=Jj zGyZboVH&qyJKcf1Uae0r9+KK$!=_|-rnSXwM(S59}Su-Dd$&I%ca4PH>Z z@2z}V`GySn^7k_oj(EE1ry2+z34c>^apL&hUJEk~`zKX=o8sn?ekub9sO0r>wfx=Ut?Df?9-?(aOaWCw#&KiS34fd ziR&ucvuF9QEiThFZaj82i?2FXFyz$fw^z=LXlZDBZlQ&g3%A}&TdM~v_ZigiO0{dz z5;0Zxk19861Wz|y+~J;)YP$Plul0SS>&3gD*%F?uxn%V6l7!`HePjJwzFs-z9Mj8U z<9zOYqnX@#b&N;Jl@IA}FivZxjOxx_K{=oA8#Z6=bNg8T)@i!YAJuY&RtcmO3#iG} zFML(8P}8Hk=c-kaZ+)|ShHX#Iy)LB0_Csg(PJt`8-mtzF&KW}X2^y0EY^**WI6nOO zH?g?Y==SNKXFMsFhg z;Kr>t`c@Z<93{{01NWtT9pT-_Ur?|3=&P#RHy?M?*FNGI5F%O-xna)$*)wZi&U1LS z&vC|7&0b5c>E(=Edvcu3yv&E3eIw3umOHoJxD7` z<;BIR8CB<~6;0|AbTD>=^~gheL|%te{ny72wBux-h3HH_^Ju)MO?#fSp2C(4Es)4=Y!w_x5@cH!nc^)V*yQUF7pFM&6wiHe}tdfK4Cvvr@!U8l3yI zcz8Ti8#ZV`7-#(Dym#{E)?3mg&G1KRQEkmeiSWRp^g-)X4(pun{Q9AG<2coAE-|V1 zde2)OEbVss@UZ&l+1bnDB5pninY+q#`A_LpyM#yUsj=-5B0kaapMSn`ITQ!XMMd1#a~J{6IOY`|jc1 zVznEV#f46=IQ%2ZskPYP(Z{pLI-Te=Lx20xNo>8G=PW;Ny)#;>yDD82`Cg-EWH^Ck zKk0CKUBBknWiyX$t(yGC>V(%Yt=jV|8o!2}co-)p+TgKP)@)yV`X!ZXWo6p3YeyDv z#&ynfmOr=NWp7-5JhN%&Ctw#4GAOg>LAgQ3)2|Mw_TQ8<%3ztg{0DOfv7D_7M@&l= zeY#pFOQ-PJ*o_5~AIolZ_8lx)zv3W$ODq7j6b}L1dQFz*J9j@e^t`Lh7%ll|-J0Uv zm(RQ$Tzb!SORU6I@gc^=pW;qP?LRmns<2rprzr5;z1bh`iw$s>@)d_k{?7|Dir3N6)rPa^)||&SVmxrbe-ij zxpT{gd)R)@n|*s&bhn*Chc_Pj~sLlC##G#xkd^EtgfNeBHbHC;Y((d5h%TUHA1 zP{}LbzW#KKxzx8po1pPa7Z@gG`mQOGHv4EH5uyAsq}aasO~`x4cd~OCdrhG?m|JhE zcGh1`7}%CmueQHm;4*Tt=Bd=XYZ@MNgH|<+Kx`E`m(b3nPy$pm4VlSM$b5- zyv||T_!)()607<$#ogN~%-s6rCkWPFvDt6Ep_k`Czxue9ND#x|dBkuNxi`CGh$1=~8W@5uVS-1i0tEI%psp=94%)r6yeO zm=!#yoZbQedYzfH+c3uZ%11fR%XyY^oEWRj)d0^z`` zTzY45>%BVf;)bJhqxRfL^yy)}HQ2PTYQ&f)PrF_`-hXD{im|;%m|hm&=lwRfd6~46 z^3k-(Kko=NW$8TDew7}6ZP<~NOz!>l2yVTD!>%=cI}uc!a_eQlr-u5og&t3Te5g)P zbZDG>yevEBmO*Yytm==zuO2Hthz0E1Bj=v+YsRIZrbdGe*`b#du5drUMRM!)?;N;r z|ER4~ysl?=FYW#W~<}o^hoT`<`v|yLY#bj=E&{z$?=# zTbn9fmuzh5-|aEQ09?WD$5GsR<0qazW;}I(_U`yBgL%JXb$c%}u556KxEYqy6yv1* z>qYF_#aeS*DzBZIrcx4Fbh_o|!<^ci1sgrI?B)+{6yCyoPr%k2&8_!NWp>x2Hm0NX zqU|Q`6msws${nU!y{K1piLB5RWlUpYe%oEwbNSK`)qaJWTER>$2%{7S7YCO z-*~ma<(&Orj=i(F^(xENy7U_TAUSQk-m!ew4FT@r6VE2Ps_R-TeA(N%>Rn^%9!H=3 zQ)ZOs=UE8%D-|1cCO+)Y0wL*DgEnOi6PT+^PN4S}w2q45*85~fSl`9ZPYZPt5-~mc zxcct$3!985y!lEyq~7$(AYV5PsMzz%I{9R<)@$2e$-;4Bw#RwanH6}6p?jlNea?%F49)j@UP`uv72v-Y1dlQ)+BzGY*Q{FfWy-X3KS!`Sw6)=}}? zdcS_%dE@>UJHNcTkkj6|iFfxtO4^vdv3g_bmm#O^Cihu8ckF<*#m>c*%Hk*88-&H} z?{p8Jm|OQ|jcneRb>)i(^k(bjtfS^}>&;qddjFG1vU|1updbamEX@~(2YfL!+I6Eb z>dW%ze68^{SE5S4e-)^9x|e&Z)#X<0$AE?Bh>KzG;eUlS=YHey63z%T*&b+dmWX?t@okz-EHQ_#_m#F zd}l)7{#$-U@4IG{b)8yzJ#9u^m7>$;9L<;FH?QaRmNPYV5g2?#z&!KwTfv5PQ_?QG zVk72K99u6G;<$iYZ>~t?>gfd!Mow9$)_Hm0vmQ$`jj}AO9&{a99Xs;fcd2(@<9be9 zbVPA=dAdi?z3tO(7i`OM4s7g_X6F`Ll3sR@{&tGiB^194x%GZqoAf$;xN4o-rU47Q zCr&nyY1Yi05cHu;_e}Be^4C`c=dKa@9-y`_eEs6WJL#(Pg%#Hh-97Z=+sPyEnqPUd zzkl2JMo`OI#I5(Cv)9<8pSKIT_dC9@!G8OXXHO369mq_~Nvd(Tsp>1}>34p^^STRy z%ZFZ{xoO;W^J$)IFMC|gFmsPBJD4?XkgyYDFU|8w+k?U2yL&*L^c@3+Nz@&mTLobS1oaO<^kP&bl2d$H`EL2P8#G4o#9sHsm# z^ElMmn^k-N#sNd$P5Z?AExR`~rQT)K;q}7>+ zmsC1pea>v#NHv4^Ib8s4yS9Md#-fgPHZs*M!+hbkpz7Nr{bed>({IaA;>CR8*G%ss@yz+8~qvB%m zordmR=C#yBte)h_nKwE6)ydp?Ljwi9rK92y7psA zl-l@a?_t-EOj23?VAkfxuJYS|Wt(=pKH*wa$j^wPH}?lmd^@#4aP6Cm<4RT>3@PVc zpRMB7+hy3;tP>f+QALR&hZ55J-U%pNvQRU?IzprGc!SefeJ%Rm>D%SYfK!c^lCzR~ z-ijEzwxUY&=AyMXvn~BrOY|MIfy>_2+NE$MPIT<2~{jpa0d_x0HickKE+ zD%rij>_cq-*K3Z5EdFpz_gxR^qk{wYO6}6H%`Q23yX?JSX@u$2CE;9pQ@QnayFF)> zLg_gBr+P)#R@y$BcEW#Zmyd7v6>83id?TTiGj?*uTcht~5z7s(k6%)!N?7Bzafo%6Q$Hw>b;XUP#rt^u@D+^F0A4&em}2ebu~XiG}&GPE)#_ zP>#@e;FT)6EyOPUXoIibk_~2~3U(Ln`Wd!(XnC@Gde!cNDTSM)EUHfxzFF(CC^+Q9 zsY9+gT=uTz*4z2&^(C?IpX-&R=A3_C=k1!CRMxM5%e@|hZXJ6zr;AnJGLOxBb{^Q? z`mv^ zo0IOe%r@V^cT3IPTU~BVTd&xo>k7Lljib5C2L`D>*;iJ5(AU{3+38W!EUybQ6TXf+ z9keMl`+R=-OC7gu_ebWP=hC~LTW^m7pHsUR?2ouA=P~_W57kRW86N|@HYW^Dx7BL3vw14;Cwt^8N!^|L!vQH+Jj+@_l$f zXc$TPzVFya{8YXN{yRND`vvrCJ94i6_x>-9Igvggvwb31tOEmCtX>%R{~5KVa+gZ8 zSlv-x8jd~xN#*{t>gE?5=1FDw3})}eCH^zY{d>#c_WkQ2|9b|*pMLafQWDw%T|lU68{&@Z)8hon75CT-`sF%9sK?Ef6^9?zVImWyS^^xS&`2F zH~gq>9ub~l5do1=zx4mL>k_gh+`}s@%7?{jvxU+=8sTqm(S~hl{~P@N?^Xx$b6fvy zG2^UL|J`i-tM*XcydoogBE9gps^fXrjqbDP#~CjU4Lm>1X@TdxrfpoBmy8c zQi;7S9XpN1>dj*;;oKJ%s_qpzyBYWWXV)r!r+NI_{s(w~Vk06TB*Md&#Zp$`?~wlw zXtIAh6DfwgBD^%zag0M8{j>Hv|Lq*{ztkXVU;bL)e`({QTGYNik--6>*nOzNYwiDw z{g-BJ-`;#4H?J$Y-%?^n2iNu;gA?-h}ufsz4i5+@?e18Bwr}tmjFZzeRCv0msQtZF+ zzvn#@l@SpZ92|}JbcGrG{U-AD|HU80L8wP)80{ik@8s-HQkqYsXLLZYH!BTk^iAyl zMc?r2{O|1niqoh_udq;Gub{3)yvH!QZxm?zw%hBU^l>-8AN_mB&%e?-er)_Jz0WWE z-_ZmA4Sy2!?^sQ~O?(gVJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7md=KzF!1n;(1AGtg zJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7md=KzF!1n;(1AGtgJ;3(>-vfLP@IAoy0N(?A z5AZ#}_W<7md=KzF!1n;(1AGtgJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7md=KzF!1n;( z1AGtgJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7md=KzF!1n;(1AGtgJ;3(>-vfLP@IAoy z0N(?A5AZ#}_W<7md=KzF!1n;(1AGtgJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7md=KzF z!1n;(1AGtgJ;3(>-vfLP@IAoy0N(?A5AZ#}_W<7mj0cYF6l9-u&gC4t8wP|%MtKAW zD+h;p1^EU9`zSj^`1lyhs;kOI2E_V=`Hq&=l=TP>@Cyy|?aoos(#rYKRjvSwh5uOH zIHJE@lXhVyZ69+_CtQm&X?aXqXIu|p((;+KF1Q}Zq!l2o2f+0lzh^I+1*4qq||KTjr&suIYgdErQ>J%9|8=7S@Z(Gx5HWE1J2v|eBbljg^y z^~UvLCe5Eo6Tx*flNNw9GOG`m0q7UZ+$V~2OF(rDK^pl)3~15`ezTbS$ajySgz6oE zG)Wx$f-yL!-*V=@emG~EnU&0>Ng!=6b6*ORM)~(KX)Bnt{z%)vq^)GqsD0KmX{(qt zYM*;JC*Q8dk;GCUl1}hT!;yR?4d&pS{JjQ85>q=~1mx3o%zZLAABPN-md>ON#l=!gGn2L^NUC$e{W{;4#jynla|G#4MUncpkFqVHXP^v>=YJj3zH^? zYc2Sm+F&cv$af<^70&5b!rV6!=QnXq{yvN&iRHm1oKT*lIKl*$0$7N1^3O3G@gGYO z9063{6U=?1aQ=)*D`nC~8RKn}w143nmU^HVq{+s`t2 zRdN0TP+8}h`_ypW1gNYsCQTjZpO~}@OqvF+n*o(u&gj#``4=Xwg1Ju%*MhK*?k8W6 z541riCasc5Q_aN*e(r}j$L@yF8tTRvZg>nlq=)XLYEsuAJE+f4f1rL(u}E=7{g`5g z`YFW;#Rc^{>SxrZ)Q_m&P`gn(Q9q!#r#Pp$rgoyZr8uRyq&SoXLqIeNjsig-0H^_V zpaN8ZA{YfmgTpZN1ULeYfurC!C;^LQ;brKQM}24+3q0~Ui=5C@V#1c(Roz-UfF8%~Lclg@Rik3WS5XfW~{8pQ1qwa0D*E9qr)(Jb@SR z20p+S_yHPorvY7{10vx!ZD0c)z_waY4Tj=+Bv1goKyM%denIvXd;wi?{T)YP99wW~ z1wX(~Ab_;aKoE2ST|jrx1M~#na1RY8LZBO1g6rL2E7%5>gJobT*afzO9Y6!9fl**E zPzRb|G*AV@fHY76BY-mK3nYLfPy+qIa4-N20{ws-7zpHn77zs^fecUtvS0`p3hdzL zDZmDF!gXhG8Rs-lT?N&k23!Nz!3{w310NcQJum#))^FS;}1T?bM2m|3j9qC;r4SY_Jw&fhdpz7J-8x9i)I2U?o@zR)LLRJy;Dgz;>_< zB!L|u5-bKWpa^UOdq6hW3D$wVU>Ar72_O$F0b9TvkO=mJxnMJh2B{zyEC&a`JP-xH z%?2@G4u}QwKmu3*7J?OEC0GSkgSFrS@?HcbI6n-=16n7VgU_HD)I4FrRMG#CJ+z+2q!jH3(i0=IG92glwZ8*~RfKse|Iguyv*9+ZLWxPLbt z!DUbdu7V>-KZ4^?U=1dMUr1{K6qnDybMOJY2Yq29JrmJ0(0)(^Mgt|F3{=1fKnoLpUVPTlhYdf0-$xb3-U|>w!jY916ot}0RzA=Fc1s@{lIV_ z1w?@~kN|Q(9t;8_fD8}=l3*|p2eP0)=nHIN&rLvU&OERYWP^AxA1vfLKMH$>!cH4t z2khIOSKzu51miweFb4W9ff<+xjKCx?7U+R-z!+EoYhVs0gYiHgm;ei4044xaUsWCK8dAPFQuKhPJ512NDC^aMSCFz5!lgWjMQ za}>c*6j1sQ(3VdY=YxR^kOqSQ>5yWsm2srC=LjGNhJ#^%>>Z8cD4+-wz(^nusD4z| z7@z~Rff`T+T0k9W0u5jSjDZm_1O|ZSR+8xgx>t|uXo~akz#NPNW0@nJZv$R{#tCmg zv2+d;0E(F|faaj-pcGUA>Yuy72SD)@h9iw(Zh*#za2zWDjsGp+7x)QiEc*s1_GoO` z2TlSSYiP`&*u4Wjf+p}D90W9W*#cMa7L#nQO{Rb$0}9I!Gt^mHgHwr~K}K zY$aPrHUp5H>PB|EFxPE)NFUkh2|NJ#Iuei#p}-gT0Ds^IfhzFETX>*uk9FDZ+mdi_KsM$BDwFh5d{YdQZF|6OKsJ(mFUV!isVyn3 z7#v{E$rnYSkh!KJx7O#dKTwuW(N7R05s>YM-ZoVzM5P4=4`FCW>7uk79cT zr~=gQ$kr?1GN=TX0NFymtN<5*3!oUO1(ePm2iI}!2*}Shz#X)eLv~SFZN8#ZEZ_-(Y@3jG*P$W zKt61{pW3;t99oOex`fuvw3hA+nH-LyKm_yz!@)2x1jqu4@&D|P)+lXd_Qg4sN9%nV zK;_b!z89eKX&0~R0xvI#iSJtDvg=aax>Fb&Wedn#}M_JG#gwqOdN^yz?PPJq%K0m;Ha7;pzv z=MdlzoPh_RG#5Z}S1=P$nj3Q@yUBh(9DRWg@CIJM6SUn=bq)l*aBl#PRBzG~#C1+F z5{&CmFbn5@k8aW%0iwV-X|0|J62L;R2rLE^drNU#0+xei zfMT{Q(pTU}avc74{DO-bunMdOMc@peKC~7072uc;szC*~1onYaKx4s0P!1@TE`U>j z#;UKtADqB7ji*O(JOT~_16-HjxC?9n8DK5g2sVKAU>#Tk(m*O8IoY=rd8w>)kO{KD zX0QoRTV{hDU@OQ0+rW0P6HwhKe_NfX9#jX?w;ObWY%h*`KrYAwgO1yq5nfOIv3&)^gI2%5kL@E*Jc zji3RjgIC}scmbY)r{EU20j`5<;3jwg?tt6iKDfu6-{m^j$9X+?4C=rW@CZBvl&==7 zNB!xV?xAx^C+M7f{2Y*7uL1docmv)6vYYI(7Ub+@x8U3g=bZrU?@R)gU?S)Pen8$E zN7@7G0>0zAGme7b7tVizZ{Y9gcchE*(~%xjsch2mx4bwPKswn%I!R9Fl&3q6LZB<4 z{FIOG5yo{l&K z5FiWa{SLk7p?5pdKne^50|34EkpvQe_BCn0N(qbxqre1U0mcJ!Fb<3bW?&331@vCR z7#IOVU;y-i9?%6kfZkha0ZpI*)PWjM1u9@Gnt=9srhqngMB+RG%mVfx3^)MVpPCBj zoy0T{3g|sXFbD#HAOO(2FhAf6e1JFb0-nGFxC1xf3T6Tq;0$Jf=^z}CU1UcxSPqtf zrCnwqkj>L^H{F>zQ;VMy{cKTmcZ4P;~Qjfg|ixptg?=W@}PkZ38ZDQm(50i5!T zYBZOsnTrKNqN$85n(SvCtTz(t)tB^mk=0v7P{37PSzTF`^CT_`iBGSk>&w-glp#S5 zU1bgSGc@IS-*V9DRqKsPwnRf&M~D4XOp>HyvC{9{OonjsD68wRpLwt@OFX+S?WlUx z%P_VC)@iG6LwzXEgRdex66`yjg+vRs>2RI_sixn)J8fF#IQ0u8YN`;avb-X~LXnL% zSuD0{N_NozNHmo-$ZBtRR>?Os(rC@9algi#{Kb~2u_a+qKB2P_Aw@2065?*YC2iWu zn#x-2XGCfRiEiG3OA5Y`57giSc$8M`WWnkY+v1mJ+a7~NRarw4;RWNM(=TlL=(k8;vW_oMpnm!$emKiw{&1jw3XG=*-u8) z+M8~yJ918SQz2WM4&@1;4EQ}6{OI6;L6u%?34D#77Z&M5l7Mp;47c0tRfj}NSx;FT zlE|=7b+5?TZo3063_P2%Q&8Xq?!(G5@iUH8PWR7^5y$l=ZeX-&XtF}XLr58`=j7HW znz1=|Awjf}OT)c=m4X92SzDxz$qsgFE+UDtnhv}JNl*ZySfuCttQ%XL=Cidyf;@g~ zWvpjo>rPHxDkcUAqF00R1aN$i(NA5{-oj!%BznqdZ_bVwdGyz%&iTcn-rcAiln+s4 zR9KJ?7RbHE)XOZ|oG_du@TfX^dYCu6ASLbk28(eCXCTo~R@YG0W$z<#M{i#NV^JV8PNa<^*PiuFl??D^{tORW+%z^{kDd!jh!bXAT%H(ATlbWc3p|>lIN6Sn0%n*=-A6SUH=p$)IO+>9wby#oBW!XH@639 zv9+g?h33&&5KsjE!?Vy0aw|qO8q$*rxGdq`;2x zv4@PC*b?>_(qSI9Z7~rZ;o;aUIKTOB)yVkSKLiD!i2aKU4-SYzYn<0s7W|yDI}h5( zYFNPAwogKwc)PlK_oo}xCmWFmmXU3L#n-LS)))2BcszLvK5`x;h&HOvI7s?I^1ZPo zw0Yl|3P{v3gurUvEjJx`$k)b-b>fYCzRMsFr_=vQIpKcc9+8oVZ~0dmo4sQx@sL;8+#muBx-KBPvnTK!o9m+D+aP{W4GyQgcN&>*Lo+> z6xp-_5;bLZo=ix{Z(f;sFHOU|AG7nYB?XX>)wv}PXnWh62ZXbTVZQ^Iu0`h06k z52MmWAK4PNcXF9Lj&_?_E$_Zx5)?o(#(q2@LP9ZmF>Ap(1CMhv84F08M-Y1szN#Q~ z|K)_t=a5kJYGEbJ-%=*)NjAbk?X_JRyl3`m1{Q^y0PczRNkTs&M{hds}6{HBI- zs5cI{m?m7ixNslxP_IXyGlc}rns`F$nv-6`u%B!R+Xph+dF^sDB>F7`)3~QFb}(?QIWK6z!<-!HaAD|_*b?M*kN@KhS9uWP*&7$#l8C) zkT7xm0TPPq{Pgh-bEZ9_*^DF@Lpo?VwnUB9K{@D))E#-{!3yP%aX{KIn}s0O=(pqG z`J0DsubyD`x0b^M$d**hUlU&3?a6FNm{~K*BZ4j2qo3hB)2wDKB-&_GSnU@aMlN9a zI<9;>aJscQBv`}Jsxve!Jc=YoyU#aQtn|1I3D!vD>j)nY_OixYW5q1he(rN1p_Kz9 zk&zK>6I{oxKYL#F@I=za87e#?y!>gedV6>MZLf}*kNY$b&$}wbLZE$i^tVh&4f0_>Me|<;mwA1L0^IeA)%Tg zc5)esuH~h->YD~~q8EKZjdh5TXbsxcKPmmhXXHUEQ0G1k360mvuWkhSh_CrY5|{>O zUuGl{#x_dx_X_GjLiIr_+<}BfiYB+sQ$CemYGf>c5q^YOppkl35EHKYhrW=S3295>4#PGLo7l^P;;Lms7+u z?Q@Kgthq68>`?8@G)S0;uY^Pl7BpOMEtMO7`#mIjoKdWnk(@N#ozNWE90>{2Pv0?; zy9+;^SSum2h037@QfCQZF-qDh7p|;bv{!UANjNi;I3(hb7>xJ3aj{73EL#H4X|qN! zk}2B+>@uSQbs=G*R}T_2c;bWuXZ;6GGWCH3&*3yuOojwTB$|J_((P8FEsYc$16ZDn zM1Q~4%omf#ME%wl0}1|16wUqB>u0z6K8ysdy^@jquy-AB_hIrwNT{Ep6}Ce%0D0DJ zdw+HOYM~%Vn3g*M$skCiN^cK7nHb**5?Drg?lKaCUv{FdmWG8FMb zCc(+aWKViSLhBvmnFvWANJdl+KYHr%%lO}Ucx&UGCls4VwCa3+eqQ+I+n29H8#@x! z{xH*WB-qUQ!*~q|GlsN}14x)wFp*+^CzW_7c=NDf62_AtVdA>|jQ+cv4qHKs#>Dos z4Dv85hj%E4M%V{Oc8|^!@W}dY!Cz^)_7MVYOvJZeyZpAG{apWB(qVnrQN_DHyxT`r znloNk8%@6*6&$S<2AYn$A_Pr4jCVF{W9T4d=hgRNuMmyfK7khmhd6;Ks z-t}oeDw73doGPpRSOp184CZlp!X2YC}!I4(MJ7K-R42U2?LfF zB(&P-{>pKX$<`I$*?HKubr5e%o{Gxu z6u#Rbp)vkfus~t>&~f*WhgQ*O(+fdStC=UG4s2ukLIJdq)iVS(-yi>FOE|lx zY^!FjI^5>Ti=Y1lpMP8375c9Q1VqWlTC1 z3qYd9el+{TdIu6F4*uA)*pUdUNfL`~hs|$wj|)tFP5p=32R`6EXJw7z*p}#dc#@@1 zE_T`2YfI#5zxHRep?!8C4@G?Xu~MrNX<_T%w(*`z+ONE+98QJWKi89lGl;Z*LM90f zv1)&K+J%JT06ySd(^gnbkr>e>==n?2RN9eY#t`Aroahxab{eWbxxXS-sKlv{WEas@X7dX-GW9_opHR%R0ik|L zE7KhwFHSqk8Da6RizTAW@pZ+1<73_qhO)?m8H?J-2ND{4zx5h=sGsT9_ksdbkwW8i z2evUa?LflJ&K=Js6d`^p91DDY?b9Emm+%=DFl(1tkWhK*l6fOy)#8`3C2YSffJ79M z9o}y9a;(Da83|fp4I_CVHQVUtf^f_W>{$jr;86~0>h0qh?T6LIszof#Cj&2CKpuKe zi}gVy{-uOSNRC8akr)_b{~8i?WqP^H8jRjWG1{m1+igWzqPCDwz|*q~B;+^a$JV1J z9s5pJGkZdTk)EMY#?qTR;PB(BER=)5p<$F&#AsVPZMVRLodPG2heRl+{XQSt0=DEI zsSm2c{_)6z(s}!!{jMP_(810ed9>ZGAz4j>ulgT$07=3bDcbMmv9+A{V>n|V{M9^|GT`hYkmCsB5t?ecxeIR*0Oy}YD6IZuG!pxey zM+)BciG=TH<>0U@wm>Fceh0KM&sirJiHb-!&%tTM6mRGv6p4SLt=+yQ@-R=;yz_KJ zoQlJO2nF-}XK5$OkcaV`mw#AHXav6CDZ4$(w3AW}B>!RGrgA!-%|e2_10url&EF5- zW3x|g*~e%@KkZ;lWPHHGYWSdowK9{Z{mv=MVei@fapx2gCeLN8%c)I8cYZM5U6v;b z3F8Ca&)dA8^t^RAvvcN@nx+|5>$^i6^My(XB;@PI+6gBPZ*r=Ign80yzX!>-fc>tT z*Bq?zhy8fuVV*U4&!@bf=Xm$+L|9GZn?}^}zBLjf={*y5ZM;q5-3q>FY#L^+Sm@Rl z*3?@e4}H3VmMdqxGu6GZ^?RyEGrOkjUf*8Q7v7PLkC%1TY`=$(JWM2Z*gouml=rFz z-U*5Ii14o4{;~4VMNyjPI0Moj-eWMfVNB%hH{QEayq|V8^*OzM)ap&F{GsXR{vHe3 z@3J8eGiC4|`6lAyQ#`;W8jPubk-9Y-@A%vN)_w<&sVRD65b|J)C-Fz?xG%nY8_XbK z_MUj}F#W^*2jwh5IrKDjCceR=^G=Hr#sc`7_ZqhS4lQFFw5^3U+GUe?{-A%7h|x(% zn7++>J-Qir`XW!nfveAx^^E8Vnbwxj#(M{&5P7HvtC}Z`o%10vfSrduDtA0H{mE_~ z`a=6RYS6~?VBWhpyyKepu2lP7YO->dLu>_-p?iN-*hqMzyd)-&MGbBqI&1U6R$}9E{FGy8Sj0|4#rXT zPQBWn*v2bHRe8FYpdwB)^a%X^LV!ieLYw{b1@ zYp=W0Y{u+$@_x?xD>2HWZ=-#9MXxHW!_l7|RlH|s-eck{W6r3&B2Y_I{jZ^BuJlnN}o5;xw2_MT{c0LcnSdZRCxT1=mQ zDE|k|!OWbM2?<_*BradMOJx22Rv}2}bv^PNVDdN}k?I$GPuu*rw)Sr#e@jj?78E>*jBSg3ez#1xn$U&hNw$3Dlz&q zLkO>D8QO=%W}hhh*7jBr+Sq#=YOH0@24P~Rm&31?f@d~@0*tG9wH#K^|Fu5gWt;k+ z^m^XCv4eFyQ=tyl_e?o!9KF z_J?l?e#bTMJb$Ge-u2;CPKR%kXlD*1Uk7h1n0FE$D9FZ2p>P6Ig2)5KP54}ncj&rb7RMU z$AV8s)T5&VyvYYrZ>=U)%gIzC5A(dx;a{GxtqzP-VhdN@O%eIFJx`Fa0IL8pfZqRW zSsG>Omf0Q_6oAXvzpj%xPyD(IA8W44GLu9etX!0}byy;h(4MM*-T3;U!$p>n1?Y3w zuNufmI@t*=*ZH0>0}`qa{3ZuUFXRza@e zQfTgV!;x0r7k`=PwMu`(3g4EIc+3e1i-eWBg}+kED>ABA~R+2rtvIOv)_^`NNA@-+NoEq+#T!a-;yVcr1pOK zoAc#8Km3+_f`oQtG*)=VADuYp_-{!!YmP)(ZSd$;DF@s8_|X#C6E2nOH%#$Mw66bg`sd1q7tOK6X4X_qzf z_YLmf7Zku_4Ex8sFPuUiijWHJ)@{n(K3epi36mCbb?_#i>D#>fPX)BmUXAV>{fwDH zOKG1Re>*_a=6y)$nW?m5O#GS*JNgR>8m}?Wwf7t6Z^!6!?he1h$2T2+`gfG=z71!W z!~P0n?-Y&&j@3ri^NXDVAwdVG;pMNiLWk=r_Fu2@9^X#F0`iV?VK*nAfTZBxQB@5I zK2AvVx^Fz$+vmxr-;%G8(6^Ie zvbg@fAeQ)(qGACHh@ztIr56?OTEK#$5;0cDmgnBP+`YTYKD*p|5wU?{!`QL+Xf&GG zYs4TXiWS>0mMEyP#~3S#LErE9%sg%P*=Kgi`^WqFyw`-CdCr_OXJ*cvIdi7{-P$?6 z>w&uEpk`NSoK@fMw6xzz&$R$TJqny({#^BmCCC17*T?5(Cu;~=E<~#IewXsS$H38R zyRC6M)|`pAT>N(HBR!9KYlY?j`Baz0%6{5BUGY>Mr@ThHcjJ+mFc}30kZX=+mHFJS z^XZ_1$KQrM4nFyz#p9oa?!{>ccvUMTUUa;i@r)O65UgNZ-FtuW+R@A2;p#FiNYvY; zUntq>HS)}RKG>@pR~1py+%NVEK-lYF@3m)kvn{3^3fmF;?)&$hv+ew= zx`a33Afzu~MV!2);$1uf)i8C%Bcnb$=h97pGn}jCqj1)DZaNRh4GpP3Z+*eX=K=!J zWhL10PK!AGUL3l~4uALsB~g#gJS&pMiHvt=t^D$XlXvHSKCP>o<90EIlfyk1-+XJo zwVl%e;d(u4w3J0Yd8=^R^e4VJdIz zY%9j#qP^*rpKi7FyRTB>**+t&<_er%sOv{x{xETyecxGtaP#js z^1XhK{Up@jjUHQZ<^d3nGLW6cz~P>SCAZ#r(zH4K;SZV5UJre6B_PxkC#^c~wGC!0 z{ilY2gUTA6&vTTJ-dlmg(Ruf;uix{^hW;059M-iRFBIZk4V%An^3qq5dv4}~RI~!9 zNh^fbsIfQC>((6 zDjWb(SqCCJsL@I<8&7tR9yqL_kZv!;F=P16nz@;87f+c9+Y<86ze-7TI0#)SmJu*y z4+c9hq&M^wu*e&ZEa8=p*5Veo?6K^#_g>=OR^8f_95}p%_^;`uM!o%NhLX4SKe}{G zcFA3;*UN};6(D_3qfb5i>HYI(9y(j+gL(_uKg#wQ8?}G*o|)RJIe%WSt-8O~sm@V? zfrye;Kktn5W_S)I-qG-jZC;MYFS!q`&He-45~b#5t6(?W`PJF;mR>s-{x^XjqhcWr zePmm`x4nJ!;71N!*}dD#zf=-96&?cGi_h)9YWC)j-n$QGEUGIsoCpZ(VDdeQ?;o5# z>N^D)4X*D1g#Glwp~s!S^ZgU{WbIHZ4{vw?5cbB#hgT0@_5C>o>8Dbo%K)K9YVGR2 z&%-NMpC}M$Mclrm^J!iGhwH|CQgU`$Kn_*`vMF%3Ik)S82@}2>0UXXg_QY*LfNW04 zDNp{-@r$RNF4RP-s`K^^Jd@;l-s^qtUVG!1?L7{vbNvZ$$aUkP|62Un!Czb^IHG&2 z^Y%S(HUrKP4_&* z=#Dpb7HYDeZ#&?yt{;2mRcm$2FtpqZSg@4qkiM-)j3F9l&hkqv*thD8{B_v|7D5;vDQBUgzYnLgA=csaNaFh@J0?$Z`C@Hy>Oky+P#g$$=zg)WsB6e*sD2Y_`(k4rYjn=ldtNzYd5QaOsjEP3 z3LxxrCvEc6gzXQ12s^W7Gy~)~Kq&EB?z&sIi&ky>cY#PRX#<2Mz5K1qmaJazv)>Cu zcske~Y;W!6{kjOwl@%Pkj zhduw|8$)PqP#vIlLT`EyE1(2ZmAswv%UzE8{`FD4fTL@tQj^Qb1Zp81Xics(A2>Mp zfb({p`$vr1u(+h&s!*#Yqf(=xGd;1=(w1e79X+aH!SvFP(*_)%_V=O(jSO3B<9>g% zX~>AddP6_0G6I6P{|}^!b%5IGY|mgoE7)`1eEj4=58TK-7+UXS(&*gyd!=|#_m+9@ z!!rj9QmlZ=v*q(CJLuDu)}TlgWVBLt=4+d8Ge|FIEZ>~l+~e7q!ycA=M6N4+0qU-a zVHNilarOa$N8d`dBQH=}zvYm&cmHSi)p9?Dlw%$s{V4HEAMW$k+wU(V1Wk>s!p%VEGAnf&nj@as(wU2k7p&)cnJ_ra$z@0bm@t14wX!*SdSpf(+ zIJkGiMMvy>_iPXH9w6jk$N^6_ZTi%0{~`pHhQCT*0P0Qp=?}o!0ywA6JmG>3Z+dAk zaUi<*>yuTyeKl+9MFY=z{|Rr#zdazt>2ui3%l|p;+PyuVUJ|*?>^@{^7a%CvSAcLl)VJx^%(+mI_JdpK=fww1wbs^_5t zKPWAGdvg!c-eu3upg~5>yx^%dpM9_esj2oUzdwW!se*=l&MvkTEPK$1f8OzzeFq&% z2vjBhFfmIO@%yWf{_;-0UoF2xcoQV#(#Yv<$Ljw~dE|`s3IY)vKyZ`U$c7sh|8f6f z>@s+DCr&`;!C$KC?OvHur(71+@98xU9Ui~x8RO|nM zO_#R3dDV*#pADZk2q;&M&Vz1y7y?T7CcybTLD+K;pzT3~ZlZdi*(n=sGCBRRa*| zS5^1>Lk=uEk7prqc4(_fv$lL}5$6lIuZ=azmm$gZr_=uQ%wMcu)7z?j8)%Xl4BMi&FO3^R?0W@`Y_$A|NTeWLQU#` zBYGS-jgLRnxZj9fUnVuF>|wZ7Lx%f~1iuGd0rkV~2ge@p%u>-XYf*Ppiy!!F502&>r1#{bRSAy4@M*r{fw&Ll$wz zriKihbI9)teGhp8)G*7U#8+QkKBupu=Gq7(wr)+R9frgC8-23&47h78Zf!TWbqC6OkaEQi)v;hQnefqdZq5^H(<&iH{WqXoe%2zEkHP;uU_<4@$RWBxKDMI zlK5``*#?jaQ}bQhEnGGp5adtusdq_fB>S=Hcih#zH~eD2k(P^T$X>&z9M%7{cYiDS z2-i~p84PMi_djUmfPdZ#*+K0X%2Tcn`gA)RYJfadIkAJ<36);4#rEq^w<%0qbmWcy znwgmg4%iz}Z|`E9rCk4c$jnnaRyX$sgsnXad&8|RQ9M6>Jm{P6i(9}Sf|80Ruk>UI z4x|d6{bJEdHLSe;-B<5=V8HD{Z3KM|RjhSzuoR;?<+^>y_KDjsNx=U`22h*^`g>>N zcg}lD_z4K{MuFbO>j9m{YTt6s(e+ZtiO6z0;(l z_PKPA69gi)Q(Y@pX&+FlqG2J4)irE&omgG-h01|=3C7_9d)Cf758Tl^IqjC~Q68*) zu(GS)QMdp&v=i^x;g}o$z3``&pA`Lme#JK-$1R`DN4J% zv1sQXCmz4(XTr5u8-oBL)dl;!y3HXkJ$)b`>{%#jzLdpfl__h;#KhTSd#z9DrH}$L z<1|&C__7_II&ew9Z-oOYmxdNV*c;m>T(W5PD{uc95IxdXhg2CG(X);}T~XWkn$>SE z*zo<4ngf*QuNrdiGpAg%U(0U?144-hBxPCoSlVuQW5?$QFF5G)CP2^`sVP1J4oA%= zdVTbp1Mf|-eTah&^rfaY?y}e=J3P4=^&9OFl&89d@^9eu0kzJDza6{&UI*U+9M&6F z5vuc6na_NkPjwv2u4advyin<#qmO)cYP`>VtZR-k;ChjU95`?D8xk{Q%+hk5$7Nhe z+~NDbJC5IQVb@ud9awzC0R;Dt78|}j@rd)*+ADSgglY^jdh(enpP{!-eB#4}iIV|g zjRGgMO$9RBMn}NkR-I=ww_o!$*7W9&f$jyhc!v$$jPd)nMW2t{Y4>A5jcaY77P3Ca z89()ozFKiY-)V=AS$HRU{d~<^GLG4lW!vX`HTIhICMEv}2zcXgmbTU6RP3(L6EjcS z`eFqkwUK8jIr#ZcN36GR&+Q>0z@eeqFkVA0xZ=RpueP~;C?NC_0A~^)lJdqJTU#(t-hYn`wv2mhIh#73+h_5*s;K&7Mpk2=h@3P{MXw;O)PIq zL$=-V>lbbwel*s^QP(nOnhglGSfAy0zWC(Y%hyUiV%^TykTcJ^YRSbP=HNY^&wL>9 z=W56sZ%%D}f3qQH0K#z_ye$EQHq!N@FTC@<7dM$N5LR2muK}SYba=;Z*NtBJyB{?U z$gb$IY330!r%WgXMs14xDWs?>XV`-^^bo9LNxO_abeJbrr|VZ;?Qvk+ zt@$>{!HxNkuO7b18d}l%UeH;vQ+$krN1+pACY`IbI*|)DhXALZTR1FK-P)SW!PQwd2pD%yt zxNh9S9DMk?n>JKZ6CDC_mDB(c4k}ms2!K$*yPt)|!v3eZKRfi8((Tv*4oMWha^;C@ z$~D<;v5Im%YviYQWj>T-6tznYz)SCsy>q$V3QLU-k0z0S={ilkWHYrEvVO>5JAStvq=z zIuS*!%!gdl@U33bP-;>K)p@H9siY=77&ThW5*pbs=zJwRBd0%-es%e9YCb(SR<5jy z9z~7j?F^f=;gy?@O@6cW=Le})XdE%F+IUKwu#r|g&h6=TE0#($Jo(hk|6Kbgu5iFg zlzu8JL%0U^g*&YgH^m-52l;3rt<+W0Pq8Xr*|(+T(6?JJRK33G`ph%^)?_%M>)zM_ z2(8;y2cCV>cB{tGBIc-xHa#5>%E4t1Ou1>JvCBD^fkh4h9-dRz5;R=@`PA(n&io!; z9K``jio1a@5pQTb)$*xH8%+80b-#V{A18T`>aAV9eX8R;aWv5JCoqPAu z8J_G^?*RA zQO|R>3sphuw%etOw}~^lKlbWBHp0A7dOb8>_1;)rLaLXiI<@LGI_5If7jAm);HSr4 z{+nYx-lhOTy>razYu{M4Vif&voJowp=^N~TVC~F2W#RG(M}J5QU*85?y?v_Jb@h_| z0UXd0`f2t9|5?3cEOrd+#%%HToQAA7v)|XR_WtbzaKLe4ICNFIMefx-<=B1Jd;an- zf2AR)>wjFX`oabi&$cdFf7jmHe+_DuohYR=C%4wNX(!O(jN#7?ZP zEx96qlUNNW#9vtP`Jo$~25NBhab8l$WioJEHXM<8>!9AZ?0X>~*nvl7Rb3}G+twT_ zTeKhg)#+O;{9@5NJ(NWZomkoHZ(5?-a#p%1?Q{0kum7UQ(VJjp2x~?d74S9$EOpl3 zmE&Ljcty|kzLXu{Vk12ST#hC4A1c{Tk9%zdAPNQh>=e$lkM=uf(+gWW1u~XM%Yj2J zw$){Obp7?twV!$ryV#W}A*X$=jgRa#aiMSkH`1uaadxQ%tBrQU!_OyQUAq3$cL7Jw ze~R27Q@}2b(~tY<)*ZX;D-b?tf%~uFV#41h2lrjF_|x?s2LzPZ+T~{i0AW9cjIK+| zmA5IV=^G^~doT^Iap0*+`+$RQu2A~m(Y{-5cH#wBoZbU^bTsBukm)OxFYW%HKL2Xt z{woH1klg_pfEqpW$}hfXx_;%49^?>>^ZJNKe>(rGUv%>z&45tXZ%}+Wm3iUo?jB@; zrgrb(9w!d_c;V(AYi3+A zf7I10e)1q2UZptraNofjeY^hw%RR_oKn4P*&jmYu(R$v#KHes2$k<)(95>>JmnM5S z79cwSXK?d^8E3rpk3V~mGj%>!JoCZE0J(KbvZvnC`Ag50{c;(+7UpCT%d=ChBS#LM@@NR#b_u8o*r0>;gY&?C+b#0&h zX5&LWNFyMm*89Dc!}s{lv;XlRhX6uqiwalm^4CQN_w*nwfUtJ4$Gt zJ<8K49+_8fQ6tnl?<~FMjuC&@vj=8VP;anDKh%))!{cuowL$xb9%PM%d~{jys~h(D z?oki2@vjxNKmP5)+cw|o!0$cCwi+_#(B~ew;iCKIdXPpyHV1FR_PcWCgB$dQ95@{8 zt06c3X8x=%HX8i02RTYZ7WMdT>}>hvHj8nV%*6L){8+a=F=khy^LMLth&c*NzC zKW<;Je8*YmU%AMGY;ddQ`nyvH%)5E|#U7+T zAhcAk-DcP$uY8g`&VvlqkUiSA+VJZqXQBT%HF^LbTLNd=#Fuv8cDqe)^&rP-NYAYf z_~hEV=AdUeIC%}ZV{-b$!aloP?Lp4ekjyV{{OR=zAI1%v4$jpYGGfz{k6!)Aw1fw_ z2N2qcD{ttt-SS;OIoyLh14w^B9AyIgGbz>M%pcU9eiA}^?&yQgr~4zp_~8+ai%_g&pvZb`4MXp((6&uO5Wz9 z4)9Lbu*ZP28E`J^bLze$PrPfAZ~!}Pc*8dLD*J80PxoK@!`55Se$!rpodKau{=w&u z^nYUD+LeMMKCUo*AlWp8=>r7`(+3I?rVkV(Odlvnm_AUDFnypPVfsKp!t{ZHgy{nX z3DXA(5~dFnBupPDNSHoQkT89qAYuAILBjNbf`s*Y1qti*3KG`q6(p?JD@a)1R*=?5 zR4>_nB?BbWEj^1x@>Q;IU zIVxc0iYYaHLcX`KxRNqF^erqxFfN3=g{9X4L*ByDIE%pn^BJ-9*82{6Zs%Fj8)ZC& zZ?GARG#vi?gR7QbvB$NtA|T^w`Ha%5gYq4C;@xi?ITjY@Q>wq-^z4$Z>t?+SFWY?1 zc83qEn4bcIRa&^i$5qd#Y5aO*tznh^-FUn@S=l%V3s8k@Jo9sI$Z08yP8>Mgdz*Be z_cm$yn~xvE1ZACEzxNkk9=_L-@3MI{uk5ktlYaN?cImF)X?WAK15er_vB#W6=craZ zcm6T^T)g8gg^Lg;{!drG(D;vE_50`b8ot!}{SF&E`@xsDYxw)C;)@@i*nIaxh;vT; z{{J5J*b&X=WtJmOJK~lBm#)8H$fS-w6I5xB>)u03z43UyvpT%mGppS96vv}}F}%dr zB#*rfO_Z`aq~5A@A}y&xdhXne6@!18wopu&N@+YF2mi0#gf$F4bCeq@|2A>++EDCM zi^-YCe7Y$U&$h@pm!Vivx0?95kSn1HhT5sNCOa9=#0x`-1zyrPbB|*$xG31t**ouZ z>L`~L)%L}h)tQfHQx0=DrS1fgxscC>01?hSkiF%D7?n{Lne6bi0UJf&`M&Aa|_!Gm`o-lc%iz1B}Q>`MKkVY5~ zqKl|&(JOO|`@T#}`x*%Ze6g5%>y#`da~TK~cllr)yct3eFRF8yxqO!d?0B;kL%X7< zW9v*V3$aNTV;L*n7Hh@^L!lZ^AVEA?jN#v`ozE4Dwv{XuEG)ADL5|HLkWR)Dxm-JG z$peCW$@9zRhhhpO7HRKf1`9UG%tCZKI4_%$& z&`3hRcmf+y=bl~ysuw|f;YtTX8C>NCR5vWr0plmSqA6Oy5($$xqnTbxQGlvU76rhy zSh&g4@l1Ly9Ok?d2|oQ;N4$`Qx}04~C!r)or^ZTI+y)oVTPbwO3)}-flHmXd0ay8> zX_mDLh?RX2Dkjdt+MA@Pfy%@HW3yTP_(Tb0d@;0~xt{VZ%)2F~-Z^IlAcA5Qa}aX` z;fl*zNg7L9uJ|pJE2Xfbw_qWXjTdn#LqxX=AgIhd0#H@vu{MkiO{knZ$VLq#omWCd z#wjnjsR>(I=~8bJM6O!KopVDmxz@mqCAwgBx-se=H-f_*R$)#&6IFxyFjCA(ORmem ziPAU8p6vGnw)~2;nuZrQA2RLFmvQ9D9e##h<8UgK;3pv;gocT4mkX&@KMnaHir7d) zJ!DN}6_T7y!wu5%X>NtZ5PDTDGQz!Ng2aI2G}=^8sb);;h$8{$&EYzuWT7h$gMF4g z3m1pcM!;);U7=$}fsqnSaK23o13aqh z`;&p9Kk79Zw-iCLc|stHmOmM2`J+-a(+JMft*i|E$dI(Bp*h^L0?7>n6YIkUOt+PQ z>4v2eO#_U6fgE@`B()@1O?F38tS(pwqT^*hHU|HA2BUwmP)ZgtO>$}&3JsUu6w_AJ zgs3txGOqjx&at80P-eG=0=31BGA2wP_rUeVYO?9ds)9AgyMVmP5%a|)8+h9snD`fE zH5)7PMmo~VFIvcKqpSDUfuaJ)h0DItYSZ7~z@)*AriTEcN=+(PUKR(E{DMP1&>fwd zt72F#N8Mn6FxLjO6?V8MfTu&0be_dThD{C-m)T`gcx(eUEGFsh=Mq#?ga!*117yu| z=`DndeAcQWWEXa&!!Q?p(=AR+&5i6*UVK30C0A&LC1IsvE$|v~ zGnlXd{^Kq1ofcYV7u1ks6~Jyh;}D7$61f8A$4nhBrGN{w6@DcYsR)OXLZ^4BJ>F); znl032tQD?UE9;axmQUwV$gCw9awgUu&!(H9b@`!$X9^4cn2J5sZKg+p($-9l1gqQlbTMptoHnp>ExPpSV-L zm{ftTv~0ZHYQhCx@uUrzr&~`B!C(doZyeaQJfB^R<%lKd9W2D;NI}%V6p4qv5DBko z4i?F_bm5TVP_e1*7tvd*))c5#g~jB2kwM{vw+vN7Xp?z!$IxscM3Af~gDVQHT46L* z8M?)65y``1LjiNhh*}F3P_{#u;0kq7&l;Sx^5V^xsKY`!6(wTjNu9iW*vkGe4FhE? zICQK|hbaud=2^H<(beRT&{42q9)!y@BS@5e;rw0?9feX1H~qIpHGRfO143>%hNA(z z#09F8e#GvJmqKi{~&?tfqZl6P~r>)PwgW#v^Ia718!C8b66) zTD*QbSX0wELL)+l%mZBu4k-B7D_V+6B$nMi z6td9R9x2z{nFw_LD4i#sn^~x7I}eu&m)c?6l?sI}c;u}Xte|6&3|G@;Qh^RHs)*S} zh+a4Xt5>(Hm^v<{nkFXYOo3YYCv-h_K1fQkkb`?l8Hu=S01FCSl#SpRHocPygncn| z2(xwM%MRGSm{==g$dTP@C9q9_HYCjKR1_=0lw>FPMPx;Ew*!!O3~C@L>3jqwUeiz@ z(t#T?fb0Z4Mb}8_gS`gNnJCQ&PJ+s{mYy9{uEa16TRus4*i~{(OIK?owT)ID;N$=_ zLPGRQ4vS#knK^-~6BHe1Qcg^aZ3D?xjVR$54#UBOf@mZ-{p36bTLUnSiC~~CCCHV1 z@iZ1L7UJ%k6ee}ZIErQ4NZ&LS&{ZNpcf*hmZC5$d5|{_2bW^^qWtI&o!lWM4 z+o+MaJSnKVXwM>lX^GBjWcCL1G(wIzZ(|CA{~LOU=6DahovHjczl717ZK}A zG^UU-=@BmxsCW?>j!feuGll+>y4E~6QRrBnf<;%b+Ha4KAhRlvnlzt}B~bFkM2t+j$k#efm8rHunYGhPd_eSoz;P5+yg)h-3&g#S zuRhb>kEkjykxNKs2-J=yZ@w#oKy}03L@Xj#Pws%~MMQ_zRFTg3hm zAfZkPZXht#Z-@^M^g_ORvx`}H2qs1!t{dP!(M;4{$+DElq3jFPkl7{S;so%;1~AlH zi1QLOLcS_J~3th_h3R;yPV>tStr&2V)rGZ>S zMqI=Zc~tn3kwwL~nB43xsyu78~_Ti<^i%xDiMI6?L?d;N3;Q;*X>^jjM7J4G8j!GMabcw{vq&yDc(p;>Hsk z;CKsq6HEa-(-$rQh>zri=-yx|0Hxwy~G=CK*5Vh&otGuejyl$IuyeRJ-t+p zjU%}7H^v2FTF9;0A$L(cteH;*qKt){sUhsj~H=0 zw_>`zRKWl6cv+O|z?TYyd@)h`rXka}01s?mOmv$`0v)Z`Oo<0_O?E1rA#xUgzamwp zT=+II=<`SUp-rNM$4ikO|AKs(_rq7hh}Nz&2x!wvw&LrBuVAQMNQ%EVQcWFi=LTr9rgfq*Y2O=HU0X->620t8e59GDfmYs&)74Wr|0UvL!f zu#vfD98k0&X%sIlP~2-LD9kTgw*wyf>!iul!NOh1IL%H72I=% z4GlOW2k&7HJ2_x*XJQFB*>la!oJ-KzpNN`Nd5MsL7m-P8{%a}ALXrPt(rh$nb_5Ev>@Q-|>F3<9DrhQh&aG)Z+x ztAI?%S1@BXLfytD4X5ETgwTMEHas{L3~cBDg^F)A^>)~>!Rre6Yip3KV=X8Ba|rnoE3hv1t#ePOv6CR+xXM74XYHi91#DrwHTTf2%WE zh8<<$?B)VZCn$EQbRQ>?UR{Mx-&sb(l&Z+%fli8c3wxSMnJnhWnPdqYue`~(yjuXS zFayiB;U<#yc5Im93IUFi7DR{0nw)Z#;T&TOTcIu14|iK}mlyUu!QP2+JG1i{xn$He zz|x8iS3-z>k&bw#4KE)E^$0EOPlgKcM?H-hf$#1S1hN~hNt(mi2AOa`P25yg4(L^W z6#h)w(LpP#e;>gzh?u*ko(HOUr&|$0pr)Ea+u}(V;z%II>)Di5!al&3#|B7@AF?Ab zL_#B)&k^40$jG)j&|{yR;D~uD6X~V!r2<`FtftoWmsX=Yh4*dOP}kezm|G_5B!e#% zODKLxE`MrL$sUWUn7~y5uO@2BH&_jz68r#b$h<|{ z;|1G-K?48Q#0AsArdJ4fA_8a0ML%5uS}FjB9IPr6hZ}^Bra)#PKSL+{Tx*- zD&Jsw&<%d5vwbK~puwNoYQ>#L)v~1Fn{6NyU#uqi3v$fR>?@{ebNL*NGXayX2pQVJbjVk6OBp!`F&;oJ%%-SmJaVlP5OKqvFG9v*RAtO= zO}BU81#9JviK#mUA_Tc2E$CN#^Gvn~N&yx?B@p*GjiBK0&wA2DsY%N_gQJ*lK$c$_ zsYFNc03mK~#o`H_QDVsPTG9wcs$hV06$seWDx42X;0O{H4*4WRL>|F}ARYW5LLsJ) zbQ0Uf!S4uaC?68A;v^u7%_Q(nwS^eOAQbXdtZkvHHZzr-x`^(^Wr>kP*%$i5%zljE zsSr>Je(>2B5w+!%oF^*MT#8WvBAYo#rei#TLM#=6q?xe-$6kONh|3azskszJUY(+G zDd;%Q2boozBB4&`xD-^>Yuku=Q~2t%kBhIOwN<=WhU(-H@O?4GzsV?v8wz_sMBuACSvG^`e&u|xCl*OjW2m#r1XmH;^ zO$KR$hl+1C=|xosym`v$rU=*6(%3?kOsD9p(;*Cdy4v_%?b(W`KrazUco9gqdEE?) zbwx`E^6eIehqW|AsRF#aPLO4$cyhnGuwa170E z#qQz^_8J##UkbdUHEeDeG1rK8puAEYr)w%>nb1`9zE zV(4SWKiOn^jg{laNi6bZ_)Js^Rt|#L^T4a-MUZt3_KDL4f$DZg>7rwWX;?_OIS;o!$TdT2L+1PQpDJvW7>qm)8tNNDRSXmp`?cA5@WK6n4A{L7+Hw zh79P74Fw*Nr9T39PvDbnVCp z#slfVc_1$4lj&jsH%qBLojrSznpx+u{EyQik-HP!G(tkBuW1Ac6+ci3{Z5C5?%H;` zJrAkvNZO_yt7R!cyX*`2G%r8NC`!I$H04-ovbcit7iJqc_YSMg+l>Z|gF5I0;+#+_ z+2qiNCBWfz4SmX<08teHHEg4ny%1_79aF)2CJ%HeJ2#E1OgI~Lf@nofa#d=%`o6lvsu-Px_-nuFn zV5SO0%m7nwD{ER%EBk_)(KkfP`k44s)9#g;Spxkhz4*nXsfzzKHS%rP}bXtUn z2Bim-f*-`NFlh^))Q~_xhRjBWzcPUCkJeQ0xap-(h|_S^A;B_@0Ra&LZXhlcjHUJo zB#Z5f3chJuwNJKz?u!8%Zzr3?&Fv#VcEjvM#s#QErer13vVX=2LJ#p#m}oWK4AFqT zLw-7>s>#GC-u5lT>2*^9NTvC*4gXPh8ku6+G~12HKf~>EazYq>EZmIDE7POaGRl*J zk@8P9HMcK!sR5T4!8VB-*B50I9&p_-YTevD$_@wvzw8V0$A2QNm~mibhnr&~dc2ni zw7dvJhr$yr0=y0}jjhSRbb?ZR(+IDeo#b74Lg}tCRhiPo99ncpgxkcSJR@MoJ6JZn z8<|B=@FX{79E$^PR74HIApqx;*f35IG)BUbiLM=PnTo**MBYviR)ao6)Z~0p=jyzu zx;{CAo${n4udZAsaZxjRvc$cn+D1&Eje-b*Tt>Z2osXRXw`G8WH z4=cJf&=`IShytHIE?S~|?Fw|+O3cd!$2E>IaqkI@Gu4q_PaZXEJWHU1yfGx7=yG|+ zx{L)sNaSX$%EbO+x)h|sOUJOrUO7A zjaX}mP>o0v8#zLeK>%Zs*@fY6Ibiyu(DIn`n7UR_5I`dML25xS9nI}hvY^Eh{V86` z;QCOdm$`nZUb4|2c-Jr{Hadp60ajYFxdiv^>TeL`$h}|wWZ=vnMeWwye*#&1bON8H zwM+xQW7bi;s(*~gcOJIzW0ZbS?rlaBM$ z18}_vjAETH_P)_?jC*M#AC2)R10{b{_%PLJg2PdQgOJ%>rg{j|E1id>CbOYvS=QLm zqkxoFA?cc?+VLw=p!%c0H@g;H%NodT7#f@ts%ROD+g(|1E0ACGV7`E4z|dnwOojuZ z20oxg%{6PsJ1rWx@(VuA26$(C24-!6NKVj`od`ua%f{dWB>6@8WY0u&0W)bj@$fH_ zYir$gz(nNarU9}W7M*CS(Nw%k9B%T<_QwBAy4b(WHqIHTBe*NdTSE9(RK1D1@3}CP z#uo#&S(iHLVXOPF5#wY6kEv3?ny|1R!wMre3}LY>R!G^rXcr6A?pqc^)k-yXA9Up{ zyGb?*7WjhG>MB|z-E~Pk zDx<@Iz_;E6HsED--;8MLL{5$AoX#Og1^dEP4RGC7vl-FQffwLd{W$%ABUeDi_6l_r z)TE6RiieBG;W@}e_Zn0dwzuL1H)N@UH7Qx#Imi9g{6Tu%-*jzdN}Z8|zCRggNOJTz z?OBefBuN>-Fx839imNtU?*Oh76!m3tA!&3@WPmF38TCk`^7~@GkjBPE5uymT{mDSa z9|ad9;5;)lQuQYVK~B~c0`Cl>zhVp-qdKg9jnKrSlZEOK80*=2K?oM6qEmwF90%z1 zeiThLu)G#g0}k~-dhi~IBR4*D5G}7w0X{%NF;t`aohxO)%!R))5Scvxt+`wq7f+<3 zRS<2)NtS_67R`GUl8j}8(m+Z=8KUk#}cY% zH>JLH8kfCSe+)7twWjQ1gEmbrLs^6GWrBvhn_1I9U$8px>=sZ|088}R%fKm>g?sR` zhEusJ4G5?J_7;xT<{nPZ=COGSTWfS0bbYztn#UA5_r)ykX=@3$ z7hPH3WY=q1l05h1ez| z=Xs*fXVrv{HmfNe`nK87j4ltdDl1`aM0JgEFlN!Y^$c0*T74<@^cf%(` z6DRO0tf-xWArj){;FlW=mHMWK$i7`wFhJEWCsZHK_#KocHIvs{5NppXfQHNhaVQ1t zGl?QtQSVyZK~0Bfq?p%xt8^!jDeqyB2VDsfe1-K`&<*uawP#;<)37ShDa4% z5K5OsaOfo>Ef)hKWA+m$9|v~<>JYH_U$pWsUoK-Uip3DYCA1$+G5(;QxKA2+h%Qi5 z_6Ss8Dp2snz-$d#qD)J(tV&;_{qyeq^#S@FtgyF^5G^A)=whqlL44lm@y|E%3v#VMOrMpvSk94VMpb zY*fiW$B!i)MM|J7ikKQ~KrolVOEkQ9JVK=X$)tQ9R!v$YkS7QP;;1IwEqHkXjE~4$ zd)+i3b4}Bpif1^D)FHlTjZNXwLYz$C+P}yv+}$)F;f66bVZLQjC+Z|S@KgZy zIn`aXWLVh9V$tqY0UQR>gEy`lC}d&cbVjt8n+Eu9*vmF-{GTDiKaE;JFcEhNl7Etg< zQ3GbTing|70t9@26!S5?LS@-FhFiie19W38P7y-mB@%)ThV&7WP`Eh>s?HS!G23Up zNgZ%~F|nddDgiZ56kzI*XkV#(e86@$LLS-7WO-6#SN;hMoA=BjH~RnhQ&Z3Mm<5&>5nPi% zcx4B!7eW6r&j8%o0;(GpOq1m#Z(pXxF^a=xF|;lRQj@>Pu{cBvVY|2Ij)-U!*HZx| z-Ed9nBb7_ieL&^q1Vv?-s?@TbWgs1rMmH%M?5;@RekEk4L+HigrbSBU@L$|@B?UQ4*}jM#TnRG zo;Q70_Z|CEftD{;6Em}Tkug^pRRB2pbch@*M(Y=G6OnuRHG&OaDxv1$)HJYoxdGXW zfE}}~0l_cixbsQ{fP*z^X$0GD&9|YuWarS__hKr<4&{AkOnnC#NW2G8@ra@e8uC}@ z$euF{OnQnPmQ~EglbM7(Kpe{_+EUFCbo|Lc&L5SwG?`6qen57^)Mw_!M=P0xxh{89 zJ3&!|rY!yUT60h~^=zJ7;{U;+6J&dt=LT5V&=1h-kg#W3HH_QY;mC?VNN?Vn5zv-E z48)}kjGf!Bd_e(QE<9xn<>#!cakHQ4>^N~%B27rIuu(mj_y~*$Ko7)G7kZ8zA&vg= z1qA$2!8dW>AFGJ(8@iyr&0DVWHg_7~UkZphxi?4x%Zq?jUg#a|g7Ah~;Cc}mWk#B; zQ%Rpvcl%?+PT`3?p20BX$+1?(d1UE^k)zqqD?5$a#Q1T7D5ZIV>zWwI(G3IBd;~7d zx3AOz4krjaj#JU~%F7hETLc+8LE@P!2P1$b7rm%}7}AniBhLZUbAp~LG^VCNWpKY4 ze<*8am(^^RXtoUt*S!4f9Fzfu6GU-1nMd8tp%<`dc)d|20=^1}RSt~_bnFYzi)nJ` z4a<5Uhik2Wqcv0HO)oD{Iws|ncoE+^QIXCyp;TK=?BczoRvlyUZcB#gBqwikO;(m%^JaluL(iG7n3exnl(C%sAd2G z74T(EZ;^$Y1+Z>z70QJq7PV;V&_-*6F#h#XjVO>`P|1)_ZlNkhV$c?oqG?tk4LRws zG8w!@Qo`mh-s4YaVbuL`5m@9gNQY`0|3x=tpngCj5ck?Z?^aUKh|&krdF0%ANffH? zU8=7ER|RUTbx!id&B|X4IyEc=JDpi~b=IE_)|RCsA4;9DtV&x^Ju7X7qvKfP!}Z*b z(Zic*bq(=ERzzhG43hkTQa1add{iAY9$J?EqhaE7vSw%0gbI7-V=~Q%V4^G~2$y}4 ziZ)ruW!Zy@!->?hX~+$&L=a(JLc-04W5`GV^pLM&tH{ubc1yPL>4AvKanq0&Cp~(& zc})ouGkr6m4oNji#huk2uj~=;ScNr(V>K5DYZ5O5}th$3EOQX`}IC zR(rxqr6SKUHQRFO42J|KC^ci!#njz&V<)ICy$GrVyqMIG`_ck%-LS}qDcj(y3)-x9 zuO=$s#;;P;(LI#_xvBuN9IXx3CJoX6^y3a(IUg^yj~P`4LMJceaJf+!3^+K9Bam3T zJttX)ij`q2VTYq)>sYB%qqbyAWte^_?q$i8fqgv1tau__26nMypiFpcbJY~29-2gz zEgeSzLyD%d$mDX_mNBE4O=t$#N1dEg13aXNDuaAJ8G&w(+;doGNangVJ1g2!l?mTN zkUUsOah;Z|B&qleC+WdL3dk*)m@?ya1H6JpxrPdJ7$S3o)XAorEqaOVJ zUy_EI&rOJP!}CGmPflBvQFfE4L62vHEj?EKCcsDze(xQ^?$96 ztiJ6YB%FKiu{8h=am@T_OUnc4wsH>0Yk`sH$OGv>G7!gv%RCqL@+3zt1Hk2fV2ZPx zES~U4ryB7DV1&(~5`l^ez#W0TQ!WV$HxHyUQ8$n36d<5OoQ%lje&7PzDFlCLJlz?S zA;kUS_Oh}swCx-$yOhn@G5;4OZ2m9anChY_(p04GC!8+i6u^(@X;n9sPuwcL`B9zj z=T%deC&g zI-G`4Xiw+uF{7|M+G)NDD>y<7t0O_ODhT;ytQMlGFb;#D82nH#xj-#w{@fX6y~F|) z?Xu=rE56QDdqH(uy2KpIq)uW1aRISFyxw94Bof2|@p_5*WgfKr(RxYw`xHp|qxF*V zjf9}&i`7fWkuT^M5c0+9C8T6alnn^^V(UgoG?`0CO$q9hDaC`R50{X{>gC80MpZ|? zSiOWCK~#i%v2`Vc;-F{_A;jt>S|3 zyhy#=sOnH{<%a7e;@TBp#SPa>MAeJp#0{?-5hXEh*Ql3>Yh0l?Zn#DwbRz3FPMjbx z&8yi=EbGI_(+$IiZQeIw7gIP{%M%Ye1e4R*dlfOndhZyqpjSC^uBd%p!s5A zUz=7$$`;8Qr@a8iMy6J$-Q zISH5Z?PMXHk2;&im4t%T2?9EVmN)OuaPApVn@M~z$_)v??sujFIPJ;1a|=yQGI=%# z%kQ{5#Ig8dBxKp`*vT7@zKggDhBS_Y4%yHbGGNPB%&GeTrhDaU)U>Dy2J-UIWv(QW z06hW7m$51nOmCsjhgTI zXM@<;h;=haMFhuAb(b0D;6Q0b$8@KJ)=y3w(=Ij7xLyZh)s5@Ah&dLE7(d`F5U;nG zK4U{n#z4GYVtx}CjQOMWl2RkIQ$$~^UP3+_7%cf>^%7Fz6mAjM)qaXlxJA4Ugq%8Z zjQ}_w>y&jzg2F7~x;S#AC(I&VCql};amXT8Z_$+GXdBdv)Jw)Qf+0j+q+T+rjlwMA zx@yNWg1ugbDzBFtRUN9W+;F`_Tq_u?xZ!$9v$G|Ais%`dPeH{$wiFR^%IL2sp}!;=v7BW2jXnKdWiXyVE9N~ z4>AAH41w@R>*Y&n4yTB|SiOXNV>4Lt#p)%bI)9asx}I86gsP0x^%HXH$W=~CW!FQ< zkszfieX)A$$dM*R$QN5zLQ3yCgb=HjkdmCxk-DB5@&;!Jkr%0#8`VakBXvF8M2yt+ zka0(6l*tX(TO@aM1`#)0FA-HQAtQA?#c?|TIB~=Ea^m`{K*SB#N<_RIxRn&Rc|J?a zD_l)8O(axkf+IoL26_MnFk8ayap@#id0Q~p#|n52GU^a(Fd;b!V9Ko7bn4ti;p0OE z9K-dKalT=AH(MGmCEf<=ry{q5(r;$0ABX)!7o0VI67r!YF5sl&3oQJp$!p+p?L4g$ z{2+On>=Li($g|syVxO6C_4es}s#!U;RDe=weuYEh;=Wkq%Ufe*3EtG=?)9=7Ny#Bm fN6PU;O|>J+I(5^42CntxegyCf3%B9_(ZBx#Kmz-C literal 0 HcmV?d00001 diff --git a/package.json b/package.json index ecdf1b8..456ee08 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@getbrevo/brevo": "^2.2.0", "@hono/zod-openapi": "^0.18.3", "@langchain/core": "^0.3.77", + "@openrouter/sdk": "^0.1.27", "@scalar/hono-api-reference": "^0.5.162", "@types/json2csv": "^5.0.7", "@types/uuid": "^10.0.0", diff --git a/src/features/ai-agents/infrastructure/adapters/openrouter-llm.adapter.ts b/src/features/ai-agents/infrastructure/adapters/openrouter-llm.adapter.ts new file mode 100644 index 0000000..5441774 --- /dev/null +++ b/src/features/ai-agents/infrastructure/adapters/openrouter-llm.adapter.ts @@ -0,0 +1,147 @@ +import { ILLMService } from "../../domain/ports/transcription.port"; + +export class OpenRouterLLMAdapter implements ILLMService { + private apiKey: string; + private apiUrl = 'https://openrouter.ai/api/v1/chat/completions'; + + constructor(apiKey: string) { + this.apiKey = apiKey; + } + + async classifyIntent(transcription: string): Promise<{ intent: string; confidence: number }> { + const prompt = ` +Analiza el siguiente texto y determina la intención del usuario. Las opciones son: +- CREATE_TRANSACTION: Para crear gastos o ingresos +- CREATE_GOAL: Para crear metas de ahorro +- CREATE_BUDGET: Para crear presupuestos +- UNKNOWN: Si no es claro + +Texto: "${transcription}" + +Responde SOLO con un JSON en este formato: +{"intent": "CREATE_TRANSACTION", "confidence": 0.95} +`; + + try { + const response = await this.callOpenRouter(prompt); + const result = JSON.parse(response); + return { + intent: result.intent || 'UNKNOWN', + confidence: result.confidence || 0.5 + }; + } catch (error) { + console.error('Error classifying intent:', error); + return { intent: 'UNKNOWN', confidence: 0 }; + } + } + + async extractData(transcription: string, intent: string): Promise<{ data: Record; confidence: number }> { + let prompt = 'category_id=1,comida;2,viajes;3,education;4,otro\n'; + + switch (intent) { + case 'CREATE_TRANSACTION': + prompt = ` +Extrae los datos de transacción del siguiente texto: +"${transcription}" + +Responde SOLO con un JSON con estos campos: +{ + "amount": número, + "type": "INCOME" o "EXPENSE", + "description": "descripción", + "category_id": "nombre de categoría si se menciona", + "payment_method": "método de pago si se menciona", + "confidence": 0.0-1.0 +} +`; + break; + + case 'CREATE_GOAL': + prompt = ` +Extrae los datos de meta de ahorro del siguiente texto: +"${transcription}" + +Responde SOLO con un JSON con estos campos: +{ + "name": "nombre de la meta", + "target_amount": número, + "end_date": "fecha en formato ISO si se menciona", + "contribution_amount": número si se menciona, + "confidence": 0.0-1.0 +} +`; + break; + + case 'CREATE_BUDGET': + prompt = ` +Extrae los datos de presupuesto del siguiente texto: +"${transcription}" + +Responde SOLO con un JSON con estos campos: +{ + "limit_amount": número, + "category": "nombre de categoría", + "month": "mes/año si se menciona", + "confidence": 0.0-1.0, + "category_id": id de la categoria segun corresponda +} +`; + break; + + default: + return { data: {}, confidence: 0 }; + } + + try { + const response = await this.callOpenRouter(prompt); + const result = JSON.parse(response); + const confidence = result.confidence || 0.8; + delete result.confidence; + + return { + data: result, + confidence + }; + } catch (error) { + console.error('Error extracting data:', error); + return { data: {}, confidence: 0 }; + } + } + + private async callOpenRouter(prompt: string): Promise { + const systemPrompt = 'Eres un asistente especializado en finanzas personales. Responde siempre con JSON válido.'; + + const response = await fetch(this.apiUrl, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.apiKey}`, + 'Content-Type': 'application/json', + 'HTTP-Referer': 'https://foppy.app', // Optional: your app URL + 'X-Title': 'Foppy Finance Assistant', // Optional: your app name + }, + body: JSON.stringify({ + model: 'x-ai/grok-4.1-fast:free', // Free Grok model from X.AI + messages: [ + { + role: 'system', + content: systemPrompt + }, + { + role: 'user', + content: prompt + } + ], + temperature: 0.3, + max_tokens: 400 + }), + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`OpenRouter API error: ${response.status} ${response.statusText} - ${errorText}`); + } + + const result = await response.json(); + return result.choices[0]?.message?.content?.trim() || '{}'; + } +} diff --git a/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts b/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts index 97b6eb1..2a9a168 100644 --- a/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts +++ b/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts @@ -6,15 +6,16 @@ import { GoalAgentService } from "../../application/services/goal-agent.service" import { BudgetAgentService } from "../../application/services/budget-agent.service"; import { ValidationAgentService } from "../../application/services/validation-agent.service"; import { OpenAITranscriptionAdapter } from "../adapters/openai-transcription.adapter"; -import { OpenAILLMAdapter } from "../adapters/openai-llm.adapter"; +import { OpenRouterLLMAdapter } from "../adapters/openrouter-llm.adapter"; import { verifyToken } from "@/shared/utils/jwt.util"; const app = new Hono(); const OPENAI_API_KEY = process.env.OPENAI_API_KEY || ''; +const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || ''; const transcriptionService = new OpenAITranscriptionAdapter(OPENAI_API_KEY); -const llmService = new OpenAILLMAdapter(OPENAI_API_KEY); +const llmService = new OpenRouterLLMAdapter(OPENROUTER_API_KEY); const transactionAgent = new TransactionAgentService(); const goalAgent = new GoalAgentService(); const budgetAgent = new BudgetAgentService(); From 5a8fc826e0767b6c205db74e6a83580fde959da4 Mon Sep 17 00:00:00 2001 From: leninner Date: Sun, 30 Nov 2025 21:41:01 -0500 Subject: [PATCH 2/5] chore: update drizzle config --- drizzle.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drizzle.config.ts b/drizzle.config.ts index b62f4f7..0147787 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -35,7 +35,7 @@ if (process.env.DATABASE_URL) { const isTestEnv = process.env.NODE_ENV === "test"; const connectionString = - (isTestEnv && process.env.TEST_DATABASE_URL) || env.DATABASE_URL; + (isTestEnv && process.env.TEST_DATABASE_URL) || process.env.DATABASE_URL; if (isTestEnv && !process.env.TEST_DATABASE_URL) { console.warn( From 819fb9c990233573a10c3e32e812299058f81f22 Mon Sep 17 00:00:00 2001 From: leninner Date: Sun, 30 Nov 2025 21:51:31 -0500 Subject: [PATCH 3/5] chore: update --- src/core/infrastructure/scripts/plans.seed.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/infrastructure/scripts/plans.seed.ts b/src/core/infrastructure/scripts/plans.seed.ts index 8eb560f..87b8302 100644 --- a/src/core/infrastructure/scripts/plans.seed.ts +++ b/src/core/infrastructure/scripts/plans.seed.ts @@ -33,7 +33,6 @@ async function seedPlans() { "Entrada de voz", "Acceso ilimitado a IA", "Soporte básico", - "Acceso a la app móvil", "Informes exportables" ] }, @@ -47,7 +46,6 @@ async function seedPlans() { "Entrada de voz", "Acceso ilimitado a IA", "Soporte básico", - "Acceso a la app móvil", "Informes exportables" ] }, From 6285c9e6d32658497e969f0bcee85ca9a895e9dc Mon Sep 17 00:00:00 2001 From: leninner Date: Sun, 30 Nov 2025 22:03:07 -0500 Subject: [PATCH 4/5] chore: update --- .../controllers/voice-command.controller.ts | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts b/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts index 2a9a168..ea3e9ac 100644 --- a/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts +++ b/src/features/ai-agents/infrastructure/controllers/voice-command.controller.ts @@ -53,52 +53,52 @@ app.post("/voice-command", async (c) => { }, 401); } - return c.json({ - "success": true, - "intent": "CREATE_GOAL", - "extractedData": { - "user_id": 1, - "name": "meta de ahorro para comida", - "target_amount": 600, - "current_amount": 0, - "end_date": "2026-10-09T21:58:33.460Z", - "category_id": null, - "contribution_frequency": null, - "contribution_amount": null - }, - "confidence": 0.95, - "message": "He identificado una meta de ahorro: \"meta de ahorro para comida\" con objetivo de $600" -}); +// return c.json({ +// "success": true, +// "intent": "CREATE_GOAL", +// "extractedData": { +// "user_id": 1, +// "name": "meta de ahorro para comida", +// "target_amount": 600, +// "current_amount": 0, +// "end_date": "2026-10-09T21:58:33.460Z", +// "category_id": null, +// "contribution_frequency": null, +// "contribution_amount": null +// }, +// "confidence": 0.95, +// "message": "He identificado una meta de ahorro: \"meta de ahorro para comida\" con objetivo de $600" +// }); + + const user = payload as { id: number; email: string }; + const body = await c.req?.formData(); + const audioFile = body?.get("audio") as File; + + if (!audioFile) { + return c.json({ + success: false, + message: "No se recibió archivo de audio" + }, 400); + } - // const user = payload as { id: number; email: string }; - // const body = await c.req?.formData(); - // const audioFile = body?.get("audio") as File; - - // if (!audioFile) { - // return c.json({ - // success: false, - // message: "No se recibió archivo de audio" - // }, 400); - // } - - // const audioBlob = new Blob([await audioFile.arrayBuffer()], { - // type: audioFile.type || 'audio/wav' - // }); - - // const result = await processVoiceCommandUseCase.execute({ - // audioBlob, - // userId: user.id - // }); - - // return c.json({ - // success: result.success, - // intent: result.intent, - // extractedData: result.extractedData, - // confidence: result.confidence, - // message: result.message, - // validationErrors: result.validationErrors, - // suggestedCorrections: result.suggestedCorrections - // }); + const audioBlob = new Blob([await audioFile.arrayBuffer()], { + type: audioFile.type || 'audio/wav' + }); + + const result = await processVoiceCommandUseCase.execute({ + audioBlob, + userId: user.id + }); + + return c.json({ + success: result.success, + intent: result.intent, + extractedData: result.extractedData, + confidence: result.confidence, + message: result.message, + validationErrors: result.validationErrors, + suggestedCorrections: result.suggestedCorrections + }); } catch (error) { console.error("Error processing voice command:", error); From 7ec74c2b879b16d736dfdceb7eb1fabe0e6886c5 Mon Sep 17 00:00:00 2001 From: devjaes Date: Sun, 30 Nov 2025 23:23:45 -0500 Subject: [PATCH 5/5] refactor: enhance recommendation services and logging - Updated daily recommendations job schedule for testing purposes. - Improved logging in various services (BudgetSuggestion, DebtReminder, GoalOptimization, SpendingAnalysis) to provide better insights into user activities and system behavior. - Added duplicate recommendation checks in RecommendationOrchestratorService to prevent redundant entries. - Adjusted OpenAI model usage across services for consistency and performance. - Enhanced repository methods to include status checks for recommendations. --- .../cron/daily-recommendations.cron.ts | 3 +- .../adapters/openai-llm.adapter.ts | 53 +++++++------ .../services/budget-suggestion.service.ts | 57 ++++++++++---- .../services/debt-reminder.service.ts | 70 ++++++++++++++--- .../services/goal-optimization.service.ts | 75 ++++++++++++++++--- .../recommendation-orchestrator.service.ts | 60 ++++++++++++++- .../services/spending-analysis.service.ts | 49 +++++++++--- .../adapters/pg-recommendation.repository.ts | 9 ++- .../infrastructure/clients/openai.client.ts | 2 +- 9 files changed, 299 insertions(+), 79 deletions(-) diff --git a/src/core/infrastructure/cron/daily-recommendations.cron.ts b/src/core/infrastructure/cron/daily-recommendations.cron.ts index 4011ae9..56a9e54 100644 --- a/src/core/infrastructure/cron/daily-recommendations.cron.ts +++ b/src/core/infrastructure/cron/daily-recommendations.cron.ts @@ -11,7 +11,8 @@ const orchestrator = RecommendationOrchestratorService.getInstance( ); const dailyRecommendationsJob = new cron.CronJob( - "0 6 * * *", + // "0 6 * * *", + "*/5 * * * *", // TODO: Change back to "0 6 * * *" for production (runs every 5 minutes for testing) async () => { console.log("Running daily recommendations job..."); diff --git a/src/features/ai-agents/infrastructure/adapters/openai-llm.adapter.ts b/src/features/ai-agents/infrastructure/adapters/openai-llm.adapter.ts index 0b74053..aa028a5 100644 --- a/src/features/ai-agents/infrastructure/adapters/openai-llm.adapter.ts +++ b/src/features/ai-agents/infrastructure/adapters/openai-llm.adapter.ts @@ -2,13 +2,15 @@ import { ILLMService } from "../../domain/ports/transcription.port"; export class OpenAILLMAdapter implements ILLMService { private apiKey: string; - private apiUrl = 'https://api.openai.com/v1/completions'; + private apiUrl = "https://api.openai.com/v1/completions"; constructor(apiKey: string) { this.apiKey = apiKey; } - async classifyIntent(transcription: string): Promise<{ intent: string; confidence: number }> { + async classifyIntent( + transcription: string + ): Promise<{ intent: string; confidence: number }> { const prompt = ` Analiza el siguiente texto y determina la intención del usuario. Las opciones son: - CREATE_TRANSACTION: Para crear gastos o ingresos @@ -26,20 +28,23 @@ Responde SOLO con un JSON en este formato: const response = await this.callOpenAI(prompt); const result = JSON.parse(response); return { - intent: result.intent || 'UNKNOWN', - confidence: result.confidence || 0.5 + intent: result.intent || "UNKNOWN", + confidence: result.confidence || 0.5, }; } catch (error) { - console.error('Error classifying intent:', error); - return { intent: 'UNKNOWN', confidence: 0 }; + console.error("Error classifying intent:", error); + return { intent: "UNKNOWN", confidence: 0 }; } } - async extractData(transcription: string, intent: string): Promise<{ data: Record; confidence: number }> { - let prompt = 'category_id=1,comida;2,viajes;3,education;4,otro\n'; + async extractData( + transcription: string, + intent: string + ): Promise<{ data: Record; confidence: number }> { + let prompt = "category_id=1,comida;2,viajes;3,education;4,otro\n"; switch (intent) { - case 'CREATE_TRANSACTION': + case "CREATE_TRANSACTION": prompt = ` Extrae los datos de transacción del siguiente texto: "${transcription}" @@ -56,7 +61,7 @@ Responde SOLO con un JSON con estos campos: `; break; - case 'CREATE_GOAL': + case "CREATE_GOAL": prompt = ` Extrae los datos de meta de ahorro del siguiente texto: "${transcription}" @@ -72,7 +77,7 @@ Responde SOLO con un JSON con estos campos: `; break; - case 'CREATE_BUDGET': + case "CREATE_BUDGET": prompt = ` Extrae los datos de presupuesto del siguiente texto: "${transcription}" @@ -97,39 +102,41 @@ Responde SOLO con un JSON con estos campos: const result = JSON.parse(response); const confidence = result.confidence || 0.8; delete result.confidence; - + return { data: result, - confidence + confidence, }; } catch (error) { - console.error('Error extracting data:', error); + console.error("Error extracting data:", error); return { data: {}, confidence: 0 }; } } private async callOpenAI(prompt: string): Promise { const fullPrompt = `Eres un asistente especializado en finanzas personales. Responde siempre con JSON válido.\n\n${prompt}`; - + const response = await fetch(this.apiUrl, { - method: 'POST', + method: "POST", headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', + Authorization: `Bearer ${this.apiKey}`, + "Content-Type": "application/json", }, body: JSON.stringify({ - model: 'gpt-3.5-turbo-instruct', + model: "gpt-4.1-nano", prompt: fullPrompt, temperature: 0.3, - max_tokens: 400 + max_tokens: 400, }), }); if (!response.ok) { - throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`); + throw new Error( + `OpenAI API error: ${response.status} ${response.statusText}` + ); } const result = await response.json(); - return result.choices[0]?.text?.trim() || '{}'; + return result.choices[0]?.text?.trim() || "{}"; } -} \ No newline at end of file +} diff --git a/src/features/recommendations/application/services/budget-suggestion.service.ts b/src/features/recommendations/application/services/budget-suggestion.service.ts index edb0384..67e786b 100644 --- a/src/features/recommendations/application/services/budget-suggestion.service.ts +++ b/src/features/recommendations/application/services/budget-suggestion.service.ts @@ -108,6 +108,10 @@ export class BudgetSuggestionService implements IAnalysisService { new Date(this.getCurrentMonthString()) ); + console.log( + `[BudgetSuggestion] User ${userId}: Found ${recentExpenses.length} expenses in last 3 months, ${currentMonthBudgets.length} budgets this month` + ); + const budgetedCategoryIds = new Set( currentMonthBudgets.map((b) => b.categoryId).filter((id) => id !== null) ); @@ -146,6 +150,9 @@ export class BudgetSuggestionService implements IAnalysisService { } if (categoriesNeedingBudget.length === 0) { + console.log( + `[BudgetSuggestion] User ${userId}: No categories needing budget (all categories either have budgets or spend <$${this.MIN_AVERAGE_SPENDING}/month)` + ); return null; } @@ -153,12 +160,24 @@ export class BudgetSuggestionService implements IAnalysisService { (a, b) => b.averageMonthlySpending - a.averageMonthlySpending ); + console.log( + `[BudgetSuggestion] User ${userId}: Category "${categoriesNeedingBudget[0].categoryName}" needs budget (avg: $${categoriesNeedingBudget[0].averageMonthlySpending}/month)` + ); + return categoriesNeedingBudget[0]; } private async getAISuggestion( category: CategoryWithoutBudget ): Promise<{ suggestedBudget: number; reasoning: string }> { + // Use fallback logic if no API key is configured + if (!this.OPENAI_API_KEY || this.OPENAI_API_KEY === "") { + console.log( + "OpenAI API key not configured, using fallback logic for budget suggestion" + ); + return this.getFallbackSuggestion(category); + } + const prompt = `El usuario gasta en promedio $${category.averageMonthlySpending.toFixed( 2 )}/mes en "${ @@ -188,7 +207,7 @@ Responde SOLO con un JSON válido en este formato: "Content-Type": "application/json", }, body: JSON.stringify({ - model: "gpt-4", + model: "gpt-4.1-nano", messages: [ { role: "system", @@ -208,6 +227,8 @@ Responde SOLO con un JSON válido en este formato: ); if (!response.ok) { + const errorBody = await response.text(); + console.error(`OpenAI API error: ${response.status} - ${errorBody}`); throw new Error(`OpenAI API error: ${response.status}`); } @@ -220,23 +241,29 @@ Responde SOLO con un JSON válido en este formato: return JSON.parse(content); } catch (error) { - console.error("Error calling OpenAI API:", error); - - const suggestedBudget = Math.ceil(category.averageMonthlySpending * 1.15); - - return { - suggestedBudget, - reasoning: `Basado en tu gasto promedio de $${category.averageMonthlySpending.toFixed( - 2 - )}, te sugerimos un presupuesto de $${suggestedBudget.toFixed( - 2 - )} mensual que incluye un 15% de flexibilidad para imprevistos en ${ - category.categoryName - }.`, - }; + console.error("Error calling OpenAI API, using fallback:", error); + return this.getFallbackSuggestion(category); } } + private getFallbackSuggestion(category: CategoryWithoutBudget): { + suggestedBudget: number; + reasoning: string; + } { + const suggestedBudget = Math.ceil(category.averageMonthlySpending * 1.15); + + return { + suggestedBudget, + reasoning: `Basado en tu gasto promedio de $${category.averageMonthlySpending.toFixed( + 2 + )}, te sugerimos un presupuesto de $${suggestedBudget.toFixed( + 2 + )} mensual que incluye un 15% de flexibilidad para imprevistos en ${ + category.categoryName + }.`, + }; + } + private calculatePriority(averageSpending: number): RecommendationPriority { if (averageSpending >= 500) { return RecommendationPriority.HIGH; diff --git a/src/features/recommendations/application/services/debt-reminder.service.ts b/src/features/recommendations/application/services/debt-reminder.service.ts index c8e099d..71ba9c8 100644 --- a/src/features/recommendations/application/services/debt-reminder.service.ts +++ b/src/features/recommendations/application/services/debt-reminder.service.ts @@ -94,6 +94,7 @@ export class DebtReminderService implements IAnalysisService { ); if (activeDebts.length === 0) { + console.log(`[DebtReminder] User ${userId}: No active debts found`); return null; } @@ -106,12 +107,18 @@ export class DebtReminderService implements IAnalysisService { }); if (upcomingDebts.length === 0) { + console.log( + `[DebtReminder] User ${userId}: No debts due within ${this.DAYS_AHEAD_THRESHOLD} days` + ); return null; } const availableBalance = await this.calculateAvailableBalance(userId); if (availableBalance <= 0) { + console.log( + `[DebtReminder] User ${userId}: No available balance to pay debts` + ); return null; } @@ -126,10 +133,7 @@ export class DebtReminderService implements IAnalysisService { const suggestedPayment = canPayFull ? debt.pendingAmount - : Math.min( - Math.floor(availableBalance * 0.5), - debt.pendingAmount - ); + : Math.min(Math.floor(availableBalance * 0.5), debt.pendingAmount); if (suggestedPayment > 0) { opportunities.push({ @@ -143,11 +147,18 @@ export class DebtReminderService implements IAnalysisService { } if (opportunities.length === 0) { + console.log( + `[DebtReminder] User ${userId}: No suitable payment opportunities found` + ); return null; } opportunities.sort((a, b) => a.daysUntilDue - b.daysUntilDue); + console.log( + `[DebtReminder] User ${userId}: Found payment opportunity for "${opportunities[0].debt.description}" (due in ${opportunities[0].daysUntilDue} days)` + ); + return opportunities[0]; } @@ -166,7 +177,13 @@ export class DebtReminderService implements IAnalysisService { private async getAISuggestion( opportunity: DebtOpportunity ): Promise<{ suggestedPayment: number; reasoning: string }> { - const prompt = `El usuario tiene disponible $${opportunity.availableBalance.toFixed(2)} este mes. La deuda "${opportunity.debt.description}" de $${opportunity.debt.pendingAmount.toFixed(2)} vence en ${opportunity.daysUntilDue} días. + const prompt = `El usuario tiene disponible $${opportunity.availableBalance.toFixed( + 2 + )} este mes. La deuda "${ + opportunity.debt.description + }" de $${opportunity.debt.pendingAmount.toFixed(2)} vence en ${ + opportunity.daysUntilDue + } días. ${ opportunity.canPayFull @@ -178,7 +195,11 @@ Sugiere cuánto debería pagar ahora considerando: 1. El monto disponible 2. Los días restantes hasta el vencimiento 3. Mantener un colchón de emergencia (no usar todo el balance disponible) -4. ${opportunity.canPayFull ? "Beneficios de liquidar la deuda completa" : "Reducir el saldo pendiente para evitar intereses"} +4. ${ + opportunity.canPayFull + ? "Beneficios de liquidar la deuda completa" + : "Reducir el saldo pendiente para evitar intereses" + } Proporciona un razonamiento motivador (2-3 oraciones) sobre por qué es importante hacer este pago ahora. @@ -188,6 +209,29 @@ Responde SOLO con un JSON válido en este formato: "reasoning": "explicación breve y motivadora" }`; + // Use fallback logic if no API key is configured + if (!this.OPENAI_API_KEY || this.OPENAI_API_KEY === "") { + console.log("OpenAI API key not configured, using fallback logic"); + const suggestedPayment = opportunity.canPayFull + ? opportunity.debt.pendingAmount + : Math.floor(opportunity.availableBalance * 0.4); + + return { + suggestedPayment, + reasoning: opportunity.canPayFull + ? `Tienes suficiente saldo para liquidar esta deuda de $${opportunity.debt.pendingAmount.toFixed( + 2 + )}. Pagarla ahora te liberará de esta obligación y evitará posibles cargos por intereses.` + : `Tienes disponible $${opportunity.availableBalance.toFixed( + 2 + )}. Considera hacer un pago de $${suggestedPayment.toFixed( + 2 + )} para reducir tu deuda de $${opportunity.debt.pendingAmount.toFixed( + 2 + )} que vence en ${opportunity.daysUntilDue} días.`, + }; + } + try { const response = await fetch( "https://api.openai.com/v1/chat/completions", @@ -198,7 +242,7 @@ Responde SOLO con un JSON válido en este formato: "Content-Type": "application/json", }, body: JSON.stringify({ - model: "gpt-4", + model: "gpt-3.5-turbo", messages: [ { role: "system", @@ -218,6 +262,8 @@ Responde SOLO con un JSON válido en este formato: ); if (!response.ok) { + const errorBody = await response.text(); + console.error(`OpenAI API error: ${response.status} - ${errorBody}`); throw new Error(`OpenAI API error: ${response.status}`); } @@ -230,7 +276,7 @@ Responde SOLO con un JSON válido en este formato: return JSON.parse(content); } catch (error) { - console.error("Error calling OpenAI API:", error); + console.error("Error calling OpenAI API, using fallback:", error); const suggestedPayment = opportunity.canPayFull ? opportunity.debt.pendingAmount @@ -239,8 +285,12 @@ Responde SOLO con un JSON válido en este formato: return { suggestedPayment, reasoning: opportunity.canPayFull - ? `Tienes suficiente saldo para liquidar esta deuda de $${opportunity.debt.pendingAmount.toFixed(2)}. Pagarla ahora te liberará de esta obligación y evitará posibles cargos por intereses.` - : `Con tu saldo actual, puedes hacer un pago de $${suggestedPayment.toFixed(2)} que reducirá significativamente tu deuda. Esto te acercará a liquidarla y minimizará los intereses acumulados.`, + ? `Tienes suficiente saldo para liquidar esta deuda de $${opportunity.debt.pendingAmount.toFixed( + 2 + )}. Pagarla ahora te liberará de esta obligación y evitará posibles cargos por intereses.` + : `Con tu saldo actual, puedes hacer un pago de $${suggestedPayment.toFixed( + 2 + )} que reducirá significativamente tu deuda. Esto te acercará a liquidarla y minimizará los intereses acumulados.`, }; } } diff --git a/src/features/recommendations/application/services/goal-optimization.service.ts b/src/features/recommendations/application/services/goal-optimization.service.ts index 9ed0f4c..4955337 100644 --- a/src/features/recommendations/application/services/goal-optimization.service.ts +++ b/src/features/recommendations/application/services/goal-optimization.service.ts @@ -104,9 +104,14 @@ export class GoalOptimizationService implements IAnalysisService { ); if (userGoals.length === 0) { + console.log(`[GoalOptimization] User ${userId}: No active goals found`); return null; } + console.log( + `[GoalOptimization] User ${userId}: Analyzing ${userGoals.length} active goal(s)` + ); + const goalAnalyses: GoalAnalysis[] = []; for (const goal of userGoals) { @@ -160,20 +165,41 @@ export class GoalOptimizationService implements IAnalysisService { } if (goalAnalyses.length === 0) { + console.log( + `[GoalOptimization] User ${userId}: No unrealistic goals found (all goals have realismRatio <= ${this.UNREALISTIC_THRESHOLD})` + ); return null; } goalAnalyses.sort((a, b) => b.realismRatio - a.realismRatio); + console.log( + `[GoalOptimization] User ${userId}: Found unrealistic goal "${ + goalAnalyses[0].goal.name + }" (realismRatio: ${goalAnalyses[0].realismRatio.toFixed(2)})` + ); + return goalAnalyses[0]; } - private async getAISuggestion( - analysis: GoalAnalysis - ): Promise<{ suggestion: "extend" | "reduce"; newValue: number; reasoning: string }> { - const prompt = `La meta "${analysis.goal.name}" del usuario requiere ahorrar $${analysis.dailyRequiredContribution.toFixed(2)}/día durante los próximos ${analysis.daysRemaining} días para alcanzar $${analysis.amountRemaining.toFixed(2)} faltantes. - -Su contribución promedio histórica es de $${analysis.averageContribution.toFixed(2)}/día, lo cual hace esta meta ${Math.round(analysis.realismRatio)}x más exigente de lo que ha logrado mantener. + private async getAISuggestion(analysis: GoalAnalysis): Promise<{ + suggestion: "extend" | "reduce"; + newValue: number; + reasoning: string; + }> { + const prompt = `La meta "${ + analysis.goal.name + }" del usuario requiere ahorrar $${analysis.dailyRequiredContribution.toFixed( + 2 + )}/día durante los próximos ${ + analysis.daysRemaining + } días para alcanzar $${analysis.amountRemaining.toFixed(2)} faltantes. + +Su contribución promedio histórica es de $${analysis.averageContribution.toFixed( + 2 + )}/día, lo cual hace esta meta ${Math.round( + analysis.realismRatio + )}x más exigente de lo que ha logrado mantener. Sugiere: 1. Extender la fecha límite (¿cuántos días más necesitaría manteniendo su ritmo actual?) @@ -188,6 +214,29 @@ Responde SOLO con un JSON válido en este formato: "reasoning": "explicación breve y motivadora" }`; + // Use fallback logic if no API key is configured + if (!this.OPENAI_API_KEY || this.OPENAI_API_KEY === "") { + console.log("OpenAI API key not configured, using fallback logic"); + const daysNeeded = Math.ceil( + analysis.amountRemaining / analysis.averageContribution + ); + const additionalDays = daysNeeded - analysis.daysRemaining; + + return { + suggestion: additionalDays > 0 ? "extend" : "reduce", + newValue: + additionalDays > 0 + ? additionalDays + : Math.ceil( + analysis.goal.currentAmount / analysis.averageContribution + ), + reasoning: + additionalDays > 0 + ? `Basado en tu ritmo actual de ahorro, necesitarías ${daysNeeded} días más para alcanzar tu meta. Considera extender la fecha límite para que sea más alcanzable.` + : `Con tu ritmo actual, estás en excelente camino. Podrías considerar reducir el monto objetivo para cumplirlo antes de la fecha límite.`, + }; + } + try { const response = await fetch( "https://api.openai.com/v1/chat/completions", @@ -198,7 +247,7 @@ Responde SOLO con un JSON válido en este formato: "Content-Type": "application/json", }, body: JSON.stringify({ - model: "gpt-4", + model: "gpt-4.1-nano", messages: [ { role: "system", @@ -218,6 +267,8 @@ Responde SOLO con un JSON válido en este formato: ); if (!response.ok) { + const errorBody = await response.text(); + console.error(`OpenAI API error: ${response.status} - ${errorBody}`); throw new Error(`OpenAI API error: ${response.status}`); } @@ -230,7 +281,7 @@ Responde SOLO con un JSON válido en este formato: return JSON.parse(content); } catch (error) { - console.error("Error calling OpenAI API:", error); + console.error("Error calling OpenAI API, using fallback:", error); const daysNeeded = Math.ceil( analysis.amountRemaining / analysis.averageContribution @@ -242,9 +293,7 @@ Responde SOLO con un JSON válido en este formato: newValue: additionalDays > 0 ? additionalDays - : Math.floor( - analysis.averageContribution * analysis.daysRemaining - ), + : Math.floor(analysis.averageContribution * analysis.daysRemaining), reasoning: "Tu ritmo de ahorro actual sugiere que necesitas ajustar tu meta para hacerla más alcanzable. Esto te ayudará a mantener la motivación y el progreso constante.", }; @@ -265,7 +314,9 @@ Responde SOLO con un JSON válido en este formato: ); const extendedDate = new Date(analysis.goal.endDate); - extendedDate.setDate(extendedDate.getDate() + (daysNeeded - analysis.daysRemaining)); + extendedDate.setDate( + extendedDate.getDate() + (daysNeeded - analysis.daysRemaining) + ); return { targetAmount: realisticAmount, diff --git a/src/features/recommendations/application/services/recommendation-orchestrator.service.ts b/src/features/recommendations/application/services/recommendation-orchestrator.service.ts index c971192..5c807ee 100644 --- a/src/features/recommendations/application/services/recommendation-orchestrator.service.ts +++ b/src/features/recommendations/application/services/recommendation-orchestrator.service.ts @@ -93,6 +93,26 @@ export class RecommendationOrchestratorService return null; } + // Additional check: verify if there's already a recommendation with the same title/type in the last 23 hours + const recentThreshold = new Date(); + recentThreshold.setHours(recentThreshold.getHours() - 23); + + const pendingRecommendations = + await this.recommendationRepository.findPendingByUserId(userId); + const duplicateExists = pendingRecommendations.some( + (rec) => + rec.type === randomType && + rec.title === analysisResult.title && + rec.createdAt >= recentThreshold + ); + + if (duplicateExists) { + console.log( + `Duplicate recommendation detected for user ${userId} with type ${randomType} and title "${analysisResult.title}". Skipping creation.` + ); + return null; + } + const recommendation = await this.recommendationRepository.create({ userId, type: randomType, @@ -144,16 +164,27 @@ export class RecommendationOrchestratorService private async checkRecentRecommendation(userId: number): Promise { try { - const todayStart = new Date(); - todayStart.setHours(0, 0, 0, 0); + // Check for recommendations in the last 23 hours (to prevent duplicates even if running frequently) + const recentThreshold = new Date(); + recentThreshold.setHours(recentThreshold.getHours() - 23); const pendingRecommendations = await this.recommendationRepository.findPendingByUserId(userId); const hasRecentRecommendation = pendingRecommendations.some( - (rec) => rec.createdAt >= todayStart + (rec) => rec.createdAt >= recentThreshold ); + if (hasRecentRecommendation) { + console.log( + `User ${userId} has ${ + pendingRecommendations.filter( + (rec) => rec.createdAt >= recentThreshold + ).length + } recommendation(s) from the last 23 hours` + ); + } + return hasRecentRecommendation; } catch (error) { console.error( @@ -174,6 +205,25 @@ export class RecommendationOrchestratorService recommendation: Recommendation ): Promise { try { + // Check if there's already a similar notification in the last 23 hours to prevent duplicates + const recentThreshold = new Date(); + recentThreshold.setHours(recentThreshold.getHours() - 23); + + const existingNotifications = + await this.notificationRepository.findRecentByUserTypeAndTitle( + recommendation.userId, + NotificationType.SUGGESTION, + recommendation.title, + recentThreshold + ); + + if (existingNotifications.length > 0) { + console.log( + `Skipping notification creation for recommendation ${recommendation.id} - similar notification already exists` + ); + return; + } + await this.notificationRepository.create({ userId: recommendation.userId, title: recommendation.title, @@ -182,6 +232,10 @@ export class RecommendationOrchestratorService type: NotificationType.SUGGESTION, expiresAt: recommendation.expiresAt || undefined, }); + + console.log( + `Created notification for recommendation ${recommendation.id}` + ); } catch (error) { console.error( `Error creating notification for recommendation ${recommendation.id}:`, diff --git a/src/features/recommendations/application/services/spending-analysis.service.ts b/src/features/recommendations/application/services/spending-analysis.service.ts index d031f50..c266a9d 100644 --- a/src/features/recommendations/application/services/spending-analysis.service.ts +++ b/src/features/recommendations/application/services/spending-analysis.service.ts @@ -89,11 +89,7 @@ export class SpendingAnalysisService implements IAnalysisService { ): Promise { const now = new Date(); const currentMonthStart = new Date(now.getFullYear(), now.getMonth(), 1); - const threeMonthsAgo = new Date( - now.getFullYear(), - now.getMonth() - 3, - 1 - ); + const threeMonthsAgo = new Date(now.getFullYear(), now.getMonth() - 3, 1); const previousMonthStart = new Date( now.getFullYear(), now.getMonth() - 1, @@ -116,6 +112,10 @@ export class SpendingAnalysisService implements IAnalysisService { endDate: previousMonthStart.toISOString(), }); + console.log( + `[SpendingAnalysis] User ${userId}: Found ${currentMonthExpenses.length} expenses this month, ${previousThreeMonthsExpenses.length} in previous 3 months` + ); + const currentMonthByCategory = this.groupByCategory(currentMonthExpenses); const previousMonthsByCategory = this.groupByCategory( previousThreeMonthsExpenses @@ -147,6 +147,9 @@ export class SpendingAnalysisService implements IAnalysisService { } if (categoryAnalysis.length === 0) { + console.log( + `[SpendingAnalysis] User ${userId}: No unusual spending patterns detected (no category with >${this.THRESHOLD_PERCENTAGE}% increase)` + ); return null; } @@ -154,14 +157,18 @@ export class SpendingAnalysisService implements IAnalysisService { (a, b) => b.percentageIncrease - a.percentageIncrease ); + console.log( + `[SpendingAnalysis] User ${userId}: Found unusual spending in ${categoryAnalysis[0].categoryName} (+${categoryAnalysis[0].percentageIncrease}%)` + ); + return categoryAnalysis[0]; } - private groupByCategory( - transactions: any[] - ): Record { + private groupByCategory(transactions: any[]): Record { return transactions.reduce((acc, tx) => { - const key = `${tx.categoryId || "null"}|${tx.category?.name || "Sin categoría"}`; + const key = `${tx.categoryId || "null"}|${ + tx.category?.name || "Sin categoría" + }`; acc[key] = (acc[key] || 0) + tx.amount; return acc; }, {} as Record); @@ -170,7 +177,13 @@ export class SpendingAnalysisService implements IAnalysisService { private async getAIInsight( spending: CategorySpending ): Promise<{ insight: string; suggestion: string }> { - const prompt = `El usuario ha gastado $${spending.currentMonthTotal.toFixed(2)} en "${spending.categoryName}" este mes, lo cual es ${spending.percentageIncrease}% más que su promedio de 3 meses de $${spending.threeMonthAverage.toFixed(2)}. + const prompt = `El usuario ha gastado $${spending.currentMonthTotal.toFixed( + 2 + )} en "${spending.categoryName}" este mes, lo cual es ${ + spending.percentageIncrease + }% más que su promedio de 3 meses de $${spending.threeMonthAverage.toFixed( + 2 + )}. Proporciona: 1. Un análisis breve (2-3 oraciones) sobre este patrón de gasto @@ -182,6 +195,16 @@ Responde SOLO con un JSON válido en este formato: "suggestion": "sugerencia accionable" }`; + // Use fallback logic if no API key is configured + if (!this.OPENAI_API_KEY || this.OPENAI_API_KEY === "") { + console.log("OpenAI API key not configured, using fallback logic"); + return { + insight: `Has incrementado tu gasto en ${spending.categoryName} en un ${spending.percentageIncrease}% comparado con tu promedio mensual. Este cambio significativo merece atención.`, + suggestion: + "Revisa tus transacciones recientes en esta categoría para identificar gastos innecesarios y considera establecer un presupuesto mensual.", + }; + } + try { const response = await fetch( "https://api.openai.com/v1/chat/completions", @@ -192,7 +215,7 @@ Responde SOLO con un JSON válido en este formato: "Content-Type": "application/json", }, body: JSON.stringify({ - model: "gpt-4", + model: "gpt-4.1-nano", messages: [ { role: "system", @@ -212,6 +235,8 @@ Responde SOLO con un JSON válido en este formato: ); if (!response.ok) { + const errorBody = await response.text(); + console.error(`OpenAI API error: ${response.status} - ${errorBody}`); throw new Error(`OpenAI API error: ${response.status}`); } @@ -224,7 +249,7 @@ Responde SOLO con un JSON válido en este formato: return JSON.parse(content); } catch (error) { - console.error("Error calling OpenAI API:", error); + console.error("Error calling OpenAI API, using fallback:", error); return { insight: `Has incrementado tu gasto en ${spending.categoryName} en un ${spending.percentageIncrease}% comparado con tu promedio mensual. Este cambio significativo merece atención.`, diff --git a/src/features/recommendations/infrastructure/adapters/pg-recommendation.repository.ts b/src/features/recommendations/infrastructure/adapters/pg-recommendation.repository.ts index 58c9e26..ab45c9a 100644 --- a/src/features/recommendations/infrastructure/adapters/pg-recommendation.repository.ts +++ b/src/features/recommendations/infrastructure/adapters/pg-recommendation.repository.ts @@ -1,6 +1,6 @@ import { db } from "@/db"; import { recommendations } from "@/schema"; -import { eq, and, gt, lt } from "drizzle-orm"; +import { eq, and, gt, lt, inArray } from "drizzle-orm"; import { IRecommendationRepository } from "../../domain/ports/recommendation.repository.interface"; import { Recommendation, @@ -65,13 +65,18 @@ export class PgRecommendationRepository implements IRecommendationRepository { async findPendingByUserId(userId: number): Promise { const now = new Date(); + // Return recommendations that are PENDING or VIEWED (exclude DISMISSED and ACTED) + // This allows users to see recommendations they've already viewed until they dismiss or act on them const results = await db .select() .from(recommendations) .where( and( eq(recommendations.user_id, userId), - eq(recommendations.status, RecommendationStatus.PENDING), + inArray(recommendations.status, [ + RecommendationStatus.PENDING, + RecommendationStatus.VIEWED, + ]), gt(recommendations.expires_at, now) ) ) diff --git a/src/features/recommendations/infrastructure/clients/openai.client.ts b/src/features/recommendations/infrastructure/clients/openai.client.ts index ce2e2d9..5bf5c7a 100644 --- a/src/features/recommendations/infrastructure/clients/openai.client.ts +++ b/src/features/recommendations/infrastructure/clients/openai.client.ts @@ -21,7 +21,7 @@ export class OpenAIClient { try { const response = await this.client.chat.completions.create( { - model: "gpt-4", + model: "gpt-4.1-nano", messages: [ { role: "system",