From d95ce5732f03963a55018f1afc05c3fb160ca8b7 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Tue, 12 Mar 2024 16:10:14 +0000 Subject: [PATCH] docs: add readme --- README.md | 135 ++++++++++++++++++++++++++++++++ assets/logo-rounded@421x128.png | Bin 0 -> 16978 bytes 2 files changed, 135 insertions(+) create mode 100644 README.md create mode 100644 assets/logo-rounded@421x128.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..e6ea31e --- /dev/null +++ b/README.md @@ -0,0 +1,135 @@ +

+ Plutus icon - rounded edges +

+ +

+ Plutus +

+ +

+ A Gateway to Effortless Blockchain Fee Management +

+ +

+ Plutus is a RESTful fee aggregator for scraping on-chain fee collection events. +

+ +

+ + GitHub release + + + GitHub release date - published at + +

+ +

+ + GitHub license + +

+ +#### Table of contents + +* [1. Overview](#-1-overview) + - [1.1. Project structure](#11-project-structure) +* [2. Development](#-2-development) + - [2.1. Requirements](#21-requirements) + - [2.2. Setting up environment variables (optional)](#22-setting-up-environment-variables-optional) + - [2.3. Running locally](#23-running-locally) +* [3. Appendix](#-3-appendix) + - [3.1. Useful commands](#31-useful-commands) + - [3.2. Docker Compose service directory](#32-docker-compose-service-directory) +* [4. How To Contribute](#-4-how-to-contribute) +* [5. License](#-5-license) + +## 🗂️ 1. Overview + +### 1.1. Project structure + +The project structure is, for the most part, self documenting, but below is an expansion on each directory: + +* `images`: contains the [Docker][docker] images used by the both the API and the MongoDB database. +* `scripts`: contains various scripts used to setup, run and test. + +[Back to top ^][table-of-contents] + +## 🛠️ 2. Development + +### 2.1. Requirements + +* [Docker][docker] +* [Docker Compose v2.5.0+][docker-compose] +* [Node v20.9.0+][node] +* [Yarn v1.22.5+][yarn] + +[Back to top ^][table-of-contents] + +### 2.2. Setting up environment variables (optional) + +1. Create a `.env` file into the `.config/` directory: +```shell script +yarn setup +``` + +2. Go to the `.config/` directory and edit the values in the `.env` file. + +[Back to top ^][table-of-contents] + +### 2.3. Running locally + +1. Simply run: +```shell script +yarn start +``` + +> ⚠️ **NOTE:** The `yarn start` command will run/re-run the setup script, but will not overwrite the file `.env` that was created and edited in section [1.2.](#22-setting-up-environment-variables-optional) + +2. Navigate to [http://localhost:3000/versions](http://localhost:3000/versions) to make sure everything is runnning. + +[Back to top ^][table-of-contents] + +## 📑 3. Appendix + +### 3.1. Useful commands + +| Command | Description | +|-------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `yarn setup` | Creates an `.env` file to the `.config/` directory. | +| `yarn start` | Runs setup and starts Docker Compose. Intended for development purposes only. | + +[Back to top ^][table-of-contents] + +### 3.2. Docker Compose service directory + +Here is a list of all the localhost port mappings for each of the apps + +| Port | URL | Docker Compose Service | Description | +|---------|----------------------------------------------------|------------------------|----------------------------------------------------------------------| +| `3000` | [http://localhost:3000](http://localhost:3000) | `api` | The core application that scrapes the blockchain for emitted events. | +| `27017` | [http://localhost:27017](http://localhost:27017) | `database` | The MongoDB database that stores the collected fees. | + +[Back to top ^][table-of-contents] + +## 👏 4. How To Contribute + +Please read the [**Contributing Guide**][contribute] to learn about the development process. + +[Back to top ^][table-of-contents] + +## 📄 5. License + +Please refer to the [COPYING][copying] file. + +[Back to top ^][table-of-contents] + + +[contribute]: ./CONTRIBUTING.md +[copying]: ./COPYING +[docker]: https://docs.docker.com/get-docker/ +[docker-compose]: https://docs.docker.com/compose/install/ +[make]: https://www.gnu.org/software/make/ +[nextjs-project-structure]: https://nextjs.org/docs/getting-started/project-structure +[node]: https://nodejs.org/en/ +[table-of-contents]: #table-of-contents +[yarn]: https://yarnpkg.com/ diff --git a/assets/logo-rounded@421x128.png b/assets/logo-rounded@421x128.png new file mode 100644 index 0000000000000000000000000000000000000000..d347e2f6d20fca482dc192afaa3cb64752797fca GIT binary patch literal 16978 zcmeIZbyQVd7dHwhiVBJ}BHi6x(%lUL9^la3jewNW-3UmRNJ)1i-QC?G4R_)5yfyAO z#vSh%_xtbNV~FSMz4lyl%{Av-GkzyXURDh0`J3l3Ffd3G;=+nBFtAzR^GAdy;BP^j zV;cCc%~e_5UJ>F%U~Ow8KX@LafPgIy&xOK;I2y!NQ zJI7df==kty!saqv(OnJo8p#vCHQXX7aHQh?x)4u~6_k!>Lfd4-FfQBUYT;Y7#K@7x z5_=il-sm*t?k0BT6>rSI#KC07(sUxev=7Ujf$7p(NUk5+7OU3~?&YSb+7N}LiHM)Z zG5{9%$wWvoj_wp~|ABtr5jcOZvwt}I5|XAV>J&+>$$&x^R? z-(SJYyop4^6l<RTUFnOK)8 zmvi&CqUjBIRXMF}#;I7xYskGI6eT4zb}8!&k?L(IB!TksLfGh&fkXLGdW169&+zZV zcjCIT!V3^ZL*bRv1srb|y$)-&3Xs!IBL$y*y>7SR6ZKBj{;J`We4yWHk_yvov?ytH zU4ZmqJ?hj|>kA(2lEvb3O%bJA)7ndh3xlrgT}gpN!E~6qv?2DjkKS5et$ytkRfLT^ zB@oiivi#^P^r29EYKQM&e{Xkhfw}0;6DEAawk&q;8BjbVXA_`b>N3(?`c@Wn5Cbbc zD4nx~HBdYl7#@CSYlyxX)Sf^OYGh)`OLS1%NJL;_z)PgYD#IXSEd(_-5qGtPD!Ixk z>${ria~crw^F8Nr<^lvPp!N^~XA5&nJ1%ElqCa%Gz~_hC^h5-IhS;0&5~<6`69`$^ zLJ3&tSm+pNMVw6>nTYtF6Y$s?7;-5Ji~daleB&iDwzs$DqNjIqa-wr$rn9m&qG#mf z-nnnNwXP&+Uy<9|#kCLtsL&o>@KU}R!p{pT$p z?Ee^PZ({f_Vf_bh4^RFq=ieCtum6+oe~kXe+W!m&qhw^bgst=)9@vu*<|TTVpUc2X z-^76H&qq#neO5y~23A@_R#qlj78XN8S`J2bPFhw&1`Z~O0jD7&6Z5~3lCZS1hgj-E zA4mb>bS8if1CxQF9-{#REdR0dYlmEKa}+iSoB!*m<|8p#z3D-)XLTZ0=Cn{ z0%8QEx3)C;GslC#xdh}Tc!`+k82)uf-W+0Y2wvbNk~Xn)aQ@c=WfKdil0D=>nvCp> z41izomzkB3m5KddgH)lmc0dy!XfiU;F|+-7@~|yjU@<_jkOw^l1peFyYvB^Ig+lDD zY?ZC7%z23(SR#0M^Pi7pfH@gJ>>o1E^g4+D`?XR!qCVxzcfZ&f&a6$C{T7n(K z5o+*&nA%vEbRgZ&KUyqf6 zg^``zfP?cdvHp{~ot2@z6T}uOU9_%j))PG`F=3deFi0>O3W&Jo;LbB^aSb~dn8dJ$f3R@h2wcF;r}h#uB2PCTAtEE- zp^Gf@z`zi|NC*okJ5TSW7`;Om!}L#+iXqc>Re1cm+2=#&yw+|9Mr~=EItpqC<(o!h zJr=SzTD$e4`t*#SSvv%2aw!OKg|}{p_s<^*k+fuqS7UBmX4RIJ_3qBPocASjiV0$0 zUYqy`lSNg-?RjIo<86Aw@R$V|;W3 zxUtA$G#{Q6c}IOrG8O|Ak)u)1y;H$-OQaZCaX$92xzy8g57gGAVFuF~AdzT9;#W;j z2;nop+*co3GJ2<{t!-+r@^8e#Ntz4^#UI$p{V@CS7rjG{wF1$=oE8V`!$Q6?VI3+u z9Y@sZktV=;e)Kjbf0#`f<=MxwT3^Vi7i|{(CxSmjBN?6Z`0q6(>4l#1iU^zjk=I%j z?5K?sL-19nVj{(3i3f&MghS%EKCNbLw4%19lKdft3yTueCIP=m@b?I5?F8xd>?iKj z(;2Ja3XcyLm$ZGpwYBvvCksWE>8Ng_-Z?&!3%P!R}kES0a*A+# zvG!Gzw$=bDT5_ycor|4P&2MvWB@eMei^AOWES2K(n6(~fjI-duMS07GpPiu=UYH#G zddm8VY<4SsLA|3^@;Fr;belMvQ4xfsL^P2jo%AC)UQad4ExmLOHNj*bo?^5k}qMjYo|u6 zbVTotq-3GG_Hc2YIzc)(OPWP4K1X|se)CUwGZxMl%-?^K^JqkD@C*<>%+Mq8p z7|Odj88NEJl)F#8)Nu>L;~`?92)3-R{hSK;`$R$c=&00Ycm6juchyGG%+H!_W`}j; zH`VNl6joKaffSV%vz=mTGD6zgy!RI;MngA_i;uO~=HQyT72-7P0!F&(Uq7=s+MRX{ zf5n$b;`#$v9Y(H-(N5QSF}?1 z8%ihgg;wHfm0ksC&(`4fMjtgY>Ihn>a3q*b!flT|Bg5y z#_(te`nt#>Ei-z#pVJLANcYsx``y=5Lu^E4B`=NdV z+FV)4e=~iQ*1#_=D=S+%G2v7+Fp$KTX=kLR(`LYE*+yk~jT+YC%>%O_TbjE2ciVVJYcm->#%1ml65Q_QpvefglPNC-p}44=L>Sud|dR@*bO zc%c>+6!6_^v7wf+&(@-1<8=q0Hx4*Oe$)!az5f)1AMCLbQZYR}eY&^NHnfn6#xdVe zk6z?w?Q7nNUZ8HXTW3I%3|TDJ{Rfcnb?U;0OQVopG^7Lt<#ppM984}nC3EAbFHWX35^qhn zh9t6{EvU!8-JV|Fa0}bqM1)CBIlFMab4El&k~G@R&s|(zmzJqVEWXF?Ykv`DV?Wy3 z5Sp?%2ef2M-dQXFm|v$Cw}i1Z+M|WNkdTyL)T&BMUmD*BRXIH_F1~UO#`FvzNm>&M&?<7-0dqNVxe!?ir@+i{Y-W>WrxR)*miHj zp|h8?xV!zy!=l#q)vD%OP#WExu?bh<*J&Gk7gC|c*HT>h{b7rbzkVNaN=Qg3d|&C! z_o!yLEz<_}1vunwj2B+B-5q0QlWo)J@FAIL?by~gRurLcbuaNa9}?+?H{34qzTH`a zhN>wk32ABJC^0LUa!;-dwWP>u&wMQ^5NTR@$5uQi_rA}ryqtxRfh9K@ri6-$iet=) zgqGB2rYd#G?HmucmPL)@KnMsxo=a+Lv!s)eVKm1=tYo5puHGZAdu8I$ciTA*9xZ3( zE@lHGBUB6&QAItJ@yc-#tb#bh!yW^#UB+t|B1@8_S9ED8Lkmpvlz()Bl z54HAZgN!Bv{iRb_(dAO@ve5U!qh->Do}=FB znNO(QiF2~DZ6-G8I$!F3HCm{2W;y@ruiE}uNm!l3_loAphofOa`^{;cQ^!AhN3%Oy z7l2X3o2xZY+H?fW*Hh>2g`4ACrUkcDgAUhI8JV?N1k*}L8VaAq(XtG{}WQyoi5 zVGf)Ud-2@r`dMvmLBVjPz7)9Mpt?VN+3U{b_9`(E#S!-gks7Dq`8|%Et*y9(Eae23 zii(QV8kH^z3M$H4>crTH$DVI)U3X6pm7{KAgSRKVJ4se#OpNxb3oR`uy|O;%jf+V2 zR;DV7TnMYH?CR+eOiUG!eO*ex%EB@@On1*Z-?J_D<2^QgDnB_HS#10Uf9p? zf|8uDG*TXx#0dST5XIhdiBHGez$(IcVR+!BRHX@_P(_VtJn> zlFAOe=4N$T&uzoC(_PPJs27@x=WT2^i}~>PLA$tq-Q|%fw}MqCyS3l>L{Bfc*{zP& zK8@9dqtWr`(z)i$o*%5Ot`25z*;hkDlkf8TUaB)C1n1m&&(__sdnKPWPq3G^P1Mxl z3}uNi&+_8v>l-QMNk}cA`Dqy+o}c7+Y^?jeTrG&*8`$}vd#<7>aJ8{xGWZ?#)02SX zlUG`s^EtS`G+kr6OeJL{4bS9CUQyImzV(oaR#s8LX5P~Fvkva_#DPj;aTM|+&1qjix;6Fm_10q9S(v^#;G9f^ zI_->=H}Ms#naow9r>2r!T$0+gUz=9E31qYS**u%D02~0B=vvjhqT;@MDs0$o0?#_m z%Uv&Z!n1?P-|WofUSAs18j-V5obn54elV2{4O0B1#S& zNO>TG)fcv4Nx;HUzKKbu&^*Y*PdO}H3bW-Xh zA63Qo=5Nis`mby7*=o`Rvl!^D%y-S>FSj16mQ3p8GISd-$>Q_-##C^+h0#C{mgG3C z?eXj|`zXe_iz3{Fz{Ul-#&*YinaJ0k5#jAM_&tgbBH{PJgI0u`)lAW>e4fDnrS)B8 z4e!S#N4DnaV|K@`cvA{*k>*k685?6rKlR+YK_{?+)K&`ZnclB3v9Ut#Ch&il?WDuC zL`Oxnrdqg!;>}kfMbs-1RJpP7#CT2t26P8mWyDa=ADkc&u7)!Cb-+twhH!YnFa zih~NEe^!(&R^)S1H6&{+oEC8xTzl4*J0x>qz9c<5if$)VFKBf#0M4?B@fR?NSkpzC zS`sCSN{wVud|2(nB4(F|D~wo4iPj$`2&JV%fR$(^@EXs)sb1PG3`o;uI=^d>J5l|W zzj`n-LObVUZ>VaS-jC~NbJoL5mwc98E54v0ATD`xCwV+CsT9X!YZo&jTXVD_)1UH! z*5-2DqVLFD2VaR96)^-+UQLahSV$5i5DKq{-dAt-*1L&t-vuX41`nYIG*$`|3Fjf) zUANya-U+o3f8*fZSz2B{R=qt9kqN$BJ?W;oUEm6qF&!>edXZRh>P{RdizI_28ob|w zdE&X&W`&tA9L?oa2_5=Topr|%6dbs`-QK8PwryLwhUsbZcpw%}vff)>!DMFWOPSxN zJE~xyIEXm%r+kG@0qh1HyZd_x z3HjD4zLrC?O2y`NvKI#Yk{^LBaA&Ra4WYc59j}Z!@1`#E9Qjffv?(7;ED1}<$b_`D zDH||hgGA>ocj89PrcOuQI}l_TKn?M4m8|-O!b(ty*cc*&6{Z( z{p9&*8`ipWqha_q9QQ4*dY$_d|0l;GHw!OyNXW^>g5BZ#)|Pnrt2bC#N!=@)seU`` z_9}a6=hV>LSd#Usg??LDY>+IwNtc()%gFF4wnSoLVsbvFkP8PXXLDc1DTJ$7x4J*q zJ8igfN_xHj#(!`TIm?+a=vh$VtqHMB=~3V1&7)wMVBla_OBtW>xE|)d-ybU0*J(pM zuw#!oHXCp0iKNFsiqcvK_O6%O85kk=_519R3(fgWUsw&q;@U96Oj=sTc&su;vEoaM zL{6EM#j@V=Pdje<9kZEG87b|~6|t~{vt~yhpA#Q#of@p}n=nr@QW2X>?A7&k+mkEW zhD$wCZ8wL-6akN8Up+}>k~(fv0xhr0n9=A__69ZHIM>U)52wd;oG4tdrCjPmlKeX(93mwB@B^Vm7|a9 z2B+@E>Cs7UUfyt>3bAaev*y>}vNAl`e%a?o>>ceLOSjjgc-QdEhjXbMT$~u#Rr@L= zD9?mM8(QzQ#S&PZwsClcv~##%-q%>CMd(9GYZ^1si;Dc-$>T~$_LI@FB3a;C5K5}t zz1udm-&}3G^LUlJW1wb!2`qPa?g-~)XeA={(aZH%3>d7WH>K;Hk9geUg~L)S5>A`D zs63iowuXd`_?-N@0x^LFMR^KI9=z6v>WApaSlry+*w{O|KcXh4PmU_FA_@u$!oqq( zp}j$C=_*^5O$X;q1YBhH?1^GtFnL(&;ACbgGN}l`rU^?pdyE>INnYMtPG_H=lfv^j z{Hqlv4cWgEe?W{-zbWR;QkE)yktz;OPJT;56^Y_^E)giVc$7(=%(E<`O>Q>r^t+{F zd_9CF3eTg)`sOf!9fg!wU;orzMMAclkd953QewOafl$&|;+Qwl#>NlpBt-Oi84;XY4C;2)BF^h+!HnkuE8-JdAGS`+p8 zvt;#iMR9qAvTT~B-V-6Rki>z7syjNxK+E^F%^(BSxV(J=d&e|ILJEp4pn$FphY>2Uey2(IHe0WzOB{euf6BZ!Z zvXf24zWDm)deXw`kJFnW?;Bk)iB}SxD~;Q}LOdARSo6X+wuUoty|im37QE|w-v?BS z%$K!yc2KM2$jHeVoz!@=$5IzX1;3L|U~zPM^s<}QZbOzQN|bhKW#GwBhQmo!%ca1Q zFeT&C0?#QQ`+YyYx~;7(N8LSwM#7YI+6kYjY0UNJUD%^z_$?K_r20gRqMhaOpLh;$ z%|Q_hnr|a49n3i#+oVV zi^pp+w06wd?t@(Xta1uB3e*ek_R;0qM*aJG#T$Enwa!?*QB(?^`YVTxDqr>&w~M#*ade`#Tgz;wGiJ;m zjH!7NYk~5s>@E9HB~#oo$0(O&vsrMv+Ftv=I(FC<^hb7WMAW z%%e<~KzHqAu^9hUTXhhp5q($6<_kwne=J~N0Oys=scYLyL7Ore|F~G!qbr4*G|BKS zQ@KDoPB=WANb6)2|Vfw2ady zlamQUZDr3!$Z0Yx+|)$n-Y7tQ9)I{?+;lv~JXyH}V%=JkQA91-l(h! zQk;q1tb?!f(C3x8XSQhrC!0NG(Rh5)%O`TLR5y9&JxaV{exrMTWdXTIc-nX{q+_%w ztAP!$p+Zduhv{ACE@3gvnqygCBWWf;X&>1*8m)|i`t2vHjY1$oRRykT+2V}c#p)O3 z^78Tm_tw1ZY_f5-Y?3ze4+iGS+dJr-LuwkAkTEyX=STF&6ezzmS@p+URrs!rskciDNFg2p z0qG6bYji@mu$Eq7V;x#yA%tj@uyvWKx@%M}`*P2fn*BMc5Bp+n2`t-E#m>5f)YMXe z!%07&D>8}BKNpwBKjL}R{j}Nh->mTaU<06G5or}m_A?;IheR`KyT3G>U zjtsk8aPpN*rqaQK_0H={s7`{ni+c^Cc;PJ>GA3OY-=_qFa(P2{knMQTi#o4|0!OJ-a4 zQ=Cr1_NE>E&SvJ7^z2fxx{UnY)&cc7Swml~zR~*#9@%?Vx&}E}-?T*oIg1nw9 z=Ap^_;u%pPiePYd=J!A4oSS)wzQj-!?zY8HRVY~Q_;tsY8ZiEtOd>U?Ml zw|qPA6b;D?K&!nzmQ)Xs(_~T3M=`XJV3{c24VJst7gLb;y>{pvf>1?$}+#ZhHNn4}A^~*-B@~E>J zvrMb6>ez5-rZN&#F(`)|Z(p3$-7@=SAzF@>za9>j-oKiq^@J&}q#5;X@2(CVcIpBJ zqlWmhH&zFMJOvDbJ$-pvM{bL1%UpL2DRFr7-+X*JoaW@6xBq;N^yn&gGcl{@u8@4+m?1LLg z(99PIBk?wPaLfq~oF36D)qH$zoWF8ioNUO_q zT)&*NUTOJL&{pvWa#ltlVpv9KCU5B3E-Zqx;!m{%P^MYQLEP9_(-N1Hiqpz5dhv>F z@9I-({Whr0@Q}&ie{ppPG&uBkbJFD*=uI~;{_5X=LUw_Q@K_{MO({%bq?5tq$4ygP zHzg;J=c#(2;*jor1gQGxo26}BIiC&t5@}-=nHOU5)RE7y?UHeGYgyK7PHVE*I(2mP zXHT~Y7ij0OA>lO8kpcHaJ9PG%UVEkX%s$Ui!9Qlbpi(r1s@lr^{j%1?xDBI96mub! z&<&`0G27nM+HaYXSIrXZdJ#&Bync)3?HvIdJFfapCpUO9ev+uSmesMfxjQto5ihRR zi;|KtZyJ7cba;HZfE0hQR&E}TSWXUg+%j1>rG`|CzINjT`J;bGiXWG9424P00$M_J zvW%(eCHLCw(X(i``6l_x;jSH=(P%e5mTxy@RUMreX#vtjpZPCF$HuT(3Ip5~T#-qH z^C*Z~^@j!rf#QDzNhPfFHocd=ac41ZSG1wc-L4-|FU1I7^6&=}X!ngs+2u+98&%7T z#12yFOpq}5-_<)E(-hbI7R1d*@YSnJ1s+3Tt!|2&kF9tTjUXoC+mE`T0!rQJ(7WHC zfXBD3H&XuQo^Ccd_>K@oMpIp*i#IKnN+s7RPd-Drw~xS!Do;O-XJS2RV$E$TFF&8j zxeZ3pm*}VCmgW*a6E3b|WI+IqvkNlDTYqJ$)=^hz0+mm~B7*nc$FyTO6COQh zspkh*J@`$1tPC_lZI}5SlcQKNGM8n9VffJp(?RFeX0`)W<|`S<7MbRZbm(mA@mecS zVBXGpRjD5!gNmbn7;eiR&iNO#?4OfWR(SOk`&X+jn@HI6f`#NNj3J3#m|42x@2SRn z%fEfg$tlx6p{$11oSO#b=jRVsWL8$PY1eRd(UuuqAL&h`NlA*!ADZEu+)HUxrHW@M zDk}9H5ZC;qft%(^e11lUE*TveHQd$R-Ak%xVi8nZ`&uy%u`!_CYsuKul*!}@3pD2j z)?TPRcgF?2xRra3_rV|EiMn!KJL$qU)oT!gwFlch%F%m5f$dg>PZg&QCHLYEDJi)L zV?H-Tim9Zn=jsaccD}Sl!}L7&T)7r!{VIwzhl1j0gL){h(KAfS7C!j*;)WPtur@gBSejdPID_4OQ=@%Y5erM zMpI6Wy|ns}V(%{nUxq8QwDha=at<4kodN^S@uM&CrlzKL=WN1JJJ-0soZ@dv)7q8k z?YM!?=z?5|en(pg7N;{O|I-ihjxaE<4<4`pbdB$vKShH`sP!Oy0jH{4SM7dzuvyHu zcU0lK1JnStNei0%v^}CK%dw)boQ)4k z85|!{ovvhIVKV5uh;5He;)LRY0*~7E6?0YssF}w(6qI0SRXW}G+YXSEk^H#mMXwvN zfYt5iZY!E8al;-+t$DIg+W^%;tvQ>ZUH7Ofo3sr*dyBTio-Y1M-^{4}%O>XKeF;?c z3xxPM8Dlw8i&B7O*JKg-N}zio zGiy9kd=a>@K+oCRleH7*iJ_h0y0Wr7^~3WiIN+%&3;n8}>~U8qT~+Rmm1vbhBb98O zy>_`??(!+?#a$l`GBjMflI~2P@xMF+yHS62wi-J$HbTlN(ZK$}U62h`tOPO(ZggofV~FMZhD4Tz;pDOH6r{hoK3LM&vB<*|_7uyyf|XIhc}-mU2z zM^f9IuYDn!b%lnsxeia~R^Z3Keq@WjZ^KryNu4{I;P<}v3dkMQDSKA0|9tVfjS zdRmsSw^w^Jo0^K;j{=95zyPI)qbsJUEWW+Qd*~#Q$(hM~8OMv)h=&|X3Wtu4DraP7 zRC}zvEbzL@oD|r?=exD#U_CRVx^-hNg7&mnU7d{Gw6@3ILbfPzIYnB2gw8NxqHE-L9Jw*P~x8kwv&gS{@a`BjTixK8{z36^Dgv2gO2hju*48 z@)`CoL5S*p-Kf-*XIp(fjNV#G14%7;f`r4cs;&0>;EYz`k`~7b#K6C7&2kd(o!S~g z>s#vi{Sq5ShK8Dldp^ZuGQu}d_=ogMiB>>{oKrw;0drvdYcr@dJXbj_kbL{i8|gc1L_8U4 z_Ve*mjXmSJ;??F<6=h{Cb{Ei#jKLSklv3lK$DWiTTu1{I6Vt7=<~ow=53M;Gj99`K=e>h=W3M=V2Ah4VvEc4!?~&9(goq z@D&Vl#G?Df#le?t)R%le&|VVm21>XwFb~ikw1*;$#?HDhm6i?dnNP!dl&ij&dBEMY zCNSSW0{P|T@=DfhqaD6Raq#wM7NMT?v!^iejJ3Xji(eN<2Z!~hcaMT`4;0eRx26hS z+F`nX1Rbsl3n_h6eGIx3iLiaPT$Qg39vlU{D>)4TqS*BsW(i|@L+8vUWBJPyF75tR#Q!)yeW@@B138pp+sE-YZA+%!WvWk)MqACi~8WcacKrq&l@&ylm&sKuD! zz#W=zHCK;Jh)Yxaysq2ep0lwXZSN!x1>V(y86s6;cw@6p6dq@10QySO@oYZS^An(o z!gYgp71O)#A_CeMpV~oW8*Vs&d!>pfI0g@nAlK8q{`uCl;i6iP>d~pXYRV)>Y5mPy zfziSIqw(@A!;m+KILyHnS~-iVvODa)0Y9xb+cwHgXYxmt97WQLGJ*aPPgXjSrEt&0 z&MX{k=MP-bMqx9Xd{cZpqax1E;^5%W(ZK(ye#Q&B{8ax~wp(J@^`v9WyI99?`|7 z-&3anH&3}EP$A@~P;_3!3e~Y<@8ZU*44dJUkUTVbW7A4bQd?}sG4>Q^6#Lvz=Ce$k zf_8*B$xl|xt{x=W*{dCl#(nP2Gkz(2C2P>{wci`V>vRo8#~>c;o(h6r_yzg7fZCr@ zqih~rpK*Bn%2W%knU-0W4e0>r@9$it zn5%oG)V$=nsWaibdJ?1mgS?I0`bvFh$=q~%XZR!qPi0;djNCx_bF0aSfGs zMPrm1F75I1Im1V@IQ-XG@i)^tB-~oGT=tgl=3IY+?jFPhszN&NFpwrye zcx$vsKc?;;B$-4lM9!y8VP8Ko$l}#@eu*#i!HCWNlr3YnG@bjB&hjjGNByb3Qk10E zIDkRH-KL>z;sA_P>|8-4Tg6Z3~P&sAh3B_&~V$U*PLubif=tV}{q3Z%^e<)ii>I|eDRB=3{w z3RJ`z2?^#JjZv{Wsqh($Z9HDhg_Kgy5Tw`Y8TYe(dj^FBLC1c`fK#JDcnb$W;Q|r9 zG#xbSgNPv{JpvCYX|#2G{t0j@ptS$oJ!W^ZJc+fS7%f-7`$sxDUe8+bfHql})~lur ztEa=&Zsd&900l@Wxkf9^UA3E89K~BSQ_+uq^C4puziLvPCs5kXo;eRcv`j^F|ukWuk`1_+Br)sBAE zFWLcds$Fmapwti#PjZ0GWmPhO ziv0HW_U7jH2TPOwFGhDfzp1f8J!jh-FR>kZqsTqw;+Z|r6$Y5L_y-fV@MV;#tZ)Fv z;^JwR-LLNzRnY#MSD>$Fw3VUq{$>S*uJ}x&)RhH>I`+2Ne{80!t1Dbf4rBr#pAIN` zg&<8Em;4(wJM^pCf!9g2vx~+D1I0T$YbVP&$Z0J<1~Lh)1?^B7z>q3tu#7l~XmGze z;9Wg^W`&4!hTx3Syw>Z&8CBy@Wz>=U468@Nq15<}>7nbesDAI=?|$4Ku=YFHrql*x zv6<<4%`Gmy8sAq}Y;9ik|N6Byo5z1FbXsL$)a^rx|4aY{z?(vbr5Dhz4)gQlwGv0N zwO{P+On!hseNs}`f^2MN>n?p}*e!>fe&OjywPeC`bIzb%T);*sxKxWJva>^{cNy1W z#h$*C(s}`E0stU6I2w(Nj_n5kN;qQ)k&!K-GHw@3*L5^Mlycl&Va7;H~+yf?&fIR`I6cvx2Z(`ybF0So|B&bIAWmXLvF|n_Hfb8MWDXy?+ z*2-#b@8^nk|tk2DbAE}|bTk@^m-ExHD zHhlK>d^ujJx`y#Pt2|ySzRYVwVY`+qBQsOU+y%rEPtWlV_gWm@PR7Ndnw(B%_uZOO zffyS8F+CR*9JSULlrd_6ockLeRutA;MB+xg95^uq77kw}z^lj)3C^0S1TdqJ0CF ziK*m;wIgQD?_HXSXDe4@jSQ@;7#Spg;FT}1v9V|GcG!|8@K=^vNnk+#CgBQ#naF14 zQ&HrQRoD#>!Qc0DewFWxqD+VuemUHYp9ADbgtURT}~(T zf3iAefxz>R>LZgv(Q@i%AYg39<4qmmzHohfh|$!{IDrbkk0 z&bB{TnE3?-NhGwMgNkEYM+XXkh2-2d-+1g0c80;DQLJp42sSq38c!EWS2qmgKrVK0qOkVK1_dySml6mfa4hn1P=wNVgXo8;kXAp#liu#La z>Pbj+3ybiOQ!)ATmprbI6-GQ(L_gnJ`26(zk;(WELfl$MinCLQrsf-d8lB#6TbYt6 zhYvVuv_P65xeqtYP15Be0*aAJ2uROJDG1_c*zv5_6e&PW%<6p!z&u)Tv$S=St!9Ezt4XC^kALC zT5TENR{*|LY#9~np71cr_(eMjJ9`}FfNpqfVyu_+!aIBbH+(HC4zTX*hPklw8MtVe z4`}PY_Qz*SE_eM#1>u|Kni-x?l1z*Ix!05($JJH<5>41=85Tf_@8p9>>PGRO2Sx&f zJ&>kF)syLcDG=9rEHW*UO-ntHL~rwG z>IHKgjro?qL)c4 zYM=6u^g{k1_19Vnzse~1kf=rLJXb