From da2eec8cf94ab52c2cf147a03c0522e9d8ca12ed Mon Sep 17 00:00:00 2001 From: Stephan van Stekelenburg Date: Wed, 28 Oct 2026 23:51:08 +0100 Subject: [PATCH] feat(archeoids): wasm based webgpu renderer --- Archevolt.slnx | 1 + .../Archeoids.Browser.csproj | 18 +++ samples/Archeoids.Browser/Program.cs | 61 ++++++++ .../wwwroot/fonts/Barlow-Regular.ttf | Bin 0 -> 104068 bytes .../wwwroot/fonts/Barlow-SemiBold.ttf | Bin 0 -> 108348 bytes .../Archeoids.Browser/wwwroot/fonts/OFL.txt | 93 ++++++++++++ samples/Archeoids.Browser/wwwroot/index.html | 22 +++ samples/Archeoids.Browser/wwwroot/main.js | 68 +++++++++ samples/Archeoids.Browser/wwwroot/renderer.js | 140 ++++++++++++++++++ samples/Archeoids.Browser/wwwroot/style.css | 20 +++ samples/Archeoids/FrameGeometry.cs | 131 ++++++++++++++++ samples/Archeoids/README.md | 35 ++++- samples/Archeoids/VectorRenderer.cs | 124 +--------------- 13 files changed, 592 insertions(+), 121 deletions(-) create mode 100644 samples/Archeoids.Browser/Archeoids.Browser.csproj create mode 100644 samples/Archeoids.Browser/Program.cs create mode 100644 samples/Archeoids.Browser/wwwroot/fonts/Barlow-Regular.ttf create mode 100644 samples/Archeoids.Browser/wwwroot/fonts/Barlow-SemiBold.ttf create mode 100644 samples/Archeoids.Browser/wwwroot/fonts/OFL.txt create mode 100644 samples/Archeoids.Browser/wwwroot/index.html create mode 100644 samples/Archeoids.Browser/wwwroot/main.js create mode 100644 samples/Archeoids.Browser/wwwroot/renderer.js create mode 100644 samples/Archeoids.Browser/wwwroot/style.css create mode 100644 samples/Archeoids/FrameGeometry.cs diff --git a/Archevolt.slnx b/Archevolt.slnx index 84c5461..cb4bcc6 100644 --- a/Archevolt.slnx +++ b/Archevolt.slnx @@ -3,6 +3,7 @@ + diff --git a/samples/Archeoids.Browser/Archeoids.Browser.csproj b/samples/Archeoids.Browser/Archeoids.Browser.csproj new file mode 100644 index 0000000..147efc4 --- /dev/null +++ b/samples/Archeoids.Browser/Archeoids.Browser.csproj @@ -0,0 +1,18 @@ + + + Exe + browser-wasm + true + false + false + false + + + + + + + + + + diff --git a/samples/Archeoids.Browser/Program.cs b/samples/Archeoids.Browser/Program.cs new file mode 100644 index 0000000..60b8b72 --- /dev/null +++ b/samples/Archeoids.Browser/Program.cs @@ -0,0 +1,61 @@ +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.JavaScript; +using System.Runtime.Versioning; + +namespace Archeoids; + +[SupportedOSPlatform("browser")] +internal static partial class Program +{ + private static readonly Game Game = new(); + private static readonly FrameGeometry Geometry = new(); + private static double _accumulator; + private static double _seconds; + private static bool _paused; + + public static void Main() { } + + [JSExport] + public static void Frame(double deltaSeconds, int turn, bool thrust, bool fire) + { + if (!_paused) + { + _accumulator += Math.Clamp(deltaSeconds, 0, 0.1); + while (_accumulator >= Game.TickSeconds) + { + Game.Step(new Controls(turn, thrust, fire)); + _seconds += Game.TickSeconds; + _accumulator -= Game.TickSeconds; + } + } + + Game.Capture(); + Session state = Game.State; + Geometry.Build(Game.Frame, state, _seconds, _paused); + Render(MemoryMarshal.AsBytes(Geometry.Vertices), state.Score, state.Wave, state.Lives, + Game.Frame.Sprites.Count, Game.UpdateMilliseconds, _paused); + } + + [JSExport] + public static void TogglePause() + { + _paused = !_paused; + ResetClock(); + } + + [JSExport] + public static void Restart() + { + Game.Restart(); + _paused = false; + _seconds = 0; + ResetClock(); + } + + [JSExport] + public static void ResetClock() => _accumulator = 0; + + [JSImport("render", "archeoids")] + private static partial void Render([JSMarshalAs] Span vertices, + int score, int wave, int lives, int entities, double milliseconds, bool paused); +} diff --git a/samples/Archeoids.Browser/wwwroot/fonts/Barlow-Regular.ttf b/samples/Archeoids.Browser/wwwroot/fonts/Barlow-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bb3faec4e243e812b288fbfb9235b12ea781eee4 GIT binary patch literal 104068 zcmd3P34ByV@_%=~H`hx@$TgFYkPJykLINRoLI`1UkOWA$qUZtraIBog|haT_M&Z-5_p8 zdaHOA=^pWCq%Ywk#Vg_?qz9#2NNLDCq(!m}X@wk*^dvb2=`^_j>1px|q2w}oKJW|W zwMeg%cObn}-jDP_`2^A(67rL8$h}DSNytL}UH)B2HByZfO0}zY;A7NSq?6Pnq)XLO zq*th43r+n-{RZj7YP---9|x!#aL*0u22gKQw}6j0By%X#n(A+edsLoK%`NQ{Mcm@f z6-z}XkOQcx1Q^X0cg}X$&@QKvZ=Ph3<)^mC*r+0C>iPJ|o zeUj5%oW8K6bNT7wHBR5<^dP5SaQZ!^Qs*>|)6^xWFF9Rib6U)4EvGGWQU9^HLZ1^AJz;R@k5Saa=no?F1JXXBLzD{iVBp_z`kK(>vCv0KiCE=;ZYmWJ z9@Pj9SA*A3Ny~PZy~M34LhnQR_zQiDYv=Q|U1cv=*S@r_y^d@1t@~cYHRKTbICRXs z3j9kU2ah4DXc0Gx+r(Ys0kK(Z7f*_vusJV^*Ti1&KJ3k>;tTPO_yO{F%Q%@V`$)gc zlLKX$tdaGyS&ow9&%aIGr5;e5oqL_{J3n%M>ioi`TyFPD_XX}t+-uy| zxHq_Ob#HXv=YGiji2DimGw$8)7u>J7-*mt0{?Ppo_vap1HnEyy`@bT+C3FNOIZ;|q zEhlb)O(CAIEY8tF4}C2h04Kl&a05I50}um<1@r>M0pbC@0SSOaKoTGskOJ@me1KFy z8lVp#9dIG!vkGt#;Ci&<2EYw~8v!=~ZU)=}xHa^)_!Zzbz^?(f1MUE91l$SOg!>-~ zeJ_`VzLsZ(zLd)WX8~3K&IYUmoC7!)a30`%z%KxQ#65cee*!!QcpmUN=x+f23V0Ln z7GN)6U+8W54&YtDdw};tZ>#LkcPa;PQ?&d{DO$4plx5i^l?LRx1#;a2xo&}6w?M92 zAlEIB>lVm$3*@>5a@_*CZh>64K(1RL*Da9i7RYrAEPx-74afn#KOi4a02lx$1QY=V0tNw!0fPZ0fKosipd3&Es0362 zssS~CA%I%sI}|Vs&<@)&3AAZ|>G*vzUD$7z;3`EJm*h<=K#+G{tS2#@E5>K zfR_QU0A2;W26!Ft2H>xNHvw+}_5$7p>;t?5co*;<;C;Xcfc=02fR96e69+>(#NR_Z zq$l*6GypMxSU@j8d}x>K4M+qe0g?eJ058A?NCl(;`T)`a8GyckOh6XE59kNT2IK&8 z0eOIYKmqa}04T(>i|{=VFbGf_`a})}lmJQr&<$A;`kSl-Q~|01HGrXjI>0bMJzzK> z0B8U-0-6BLfDwQeKr5gP&l-hij0UvhcL(wxgYU6`ae(oF384?L?SRJsj{|-Sz??w*4)7%4DFDqOo(4Pv_&s1J;17UZ zfM)@_0ekR_KLMTtJP-IY;6=b+051Vv2D}1z74RD1b-){dzXIL_yam_`cpI<}@DAWz zzc2!`w_BW1zcC8~&$prP;LnKAH<$rN{e?oH zTk?t`Ga9Zlqzm~WhtH!qAd_RE_d-XbX4NzedM*TuVYVl}zr*h@A-k7Df5opqhh8JDNKO&Vy50JMw*cLW=InO; z5LzJ8o^OU;1~2~(eGKewlxR1!?`Y_Ci%N1to=91%!nuY1Nm@YK5dI^6ZgI3a{hg?d z_}b^t06~%_uF${nM5|1ZdUd%!jj8TY0{X*TN*atwtI zn7M{6Mp%D(Du4KiVIKSU39JpS4-dUz+Ee1ivpz)nDd1~Z@ltNPE_xJtE%d6Lt7(U+ zuXV8*;p?0uB9P{vX@{vjeo`Y&(3atxx_^fy(}k}3nL0V6;8H|a67bYR_*sE_%%gm$4TM=&LY}&v#L*$>>f3Qf0xQCNR!GEF0 zLob-t!TJrKB?R9FRyNGB2V)XiEG(zc^S}u#n*!|jp=a0{nEL7rJ*~v*bZ2a3F%>ztn##xMRgC=%|F(CgGt;cw-WtmlV$d zC~Eo!U>{&V;2;2T7(rgdQ9uxp8bkpR~IXLCAJB3cw$ zDCyo?m@<#k^C%5I!}x`q-p!N%aRx^-K9cEMD3wk`wxo*CJK!Dw`P)BF@(R)xh^q;)8gMxPv3rhpQ;S4H zxOGrcZl(2T8$9oSkwlM^Q)YH%4dS7(s8^<2&( z6Hwy>)D$sHnGh5*Q5RZbHdaHRhY8Tb1n6M``bA=aP>C79A>~BqU>ATsCVImlA5Ykx z@MP-w^Z~Zh#v-&m7VX7^*X*l%ZR~v;`^d&3_kL>AzOb+t6C$*4?5jV7u|yTd>{7jG zW7`wm;j4*pVJvdBCoD19s*O<22;=4R? zZ4cP`?ljzUd*aO&HG)7Cw>HbCTTbBdjarF(knLh zrj4O2*3~fIyHR(1XkYz@jfMFl`TfKlWC^=HBdSzX_U>21ci_tBc72c7*!MPOUriP! zE!mkIYh#HvmTF_+tC>-Jx%SmU8!Iuf)bo?8Y^=_@+89N%t|mtMzTJDG`a-1jBdrx_ zbDNgjmORFKMq9X5qiM+#t*g_MXNUQc=iAs~8(VH;c7Dm{+O$;`Ha&`VseSb-8(U{% z;asLi%9nhjef2gQ3-h&^6i6?sM#*@^#+X(omF_S#pi5jOdw5_#v*(c zmNF+QmxVUpQX5-gW08Bg)rg+5+P-@E@mP3_N?B`PvoYMe-lpDcW4GH_(ZIg+m zY)yIG#&+0PgciXpIj8JOc@9r}39u{W4IA5MWBYCFpoJYyiO{~XuO79rppAudJ{)<5 zR}WwH8expCdVAv+mw++8!=%w27KS@4%p1lcIfpTCh8Lr*w*ZjgEjF=~UET`wY2I3I zz?2KH78?uG+PxDjT6@_3d826NHRRduooeyT^v*pV3wxH{MO>C;xMPubB~lZ+z{aSg zOrzdoT@BMNiMn@aoa6&qXbfZnW>d&&D3IvB=d&Oq%xz?=v>G+s0n7vGCPbqWIpl zufA(zADS3S@DCgN+`4)sie_DnShFxU*%$Bk;a@&sV@?~3wXw+6#2#p=J6vMXpA$tA6yV#h0=x%oV|W>wGtwRA9G- zulw$@Y2m96_%>U#?Y<{%Y^RMyXgy(jOg_~1MH_p~#`fA+~kO*he}s=Rw>K*DeX)t=d_wB=W^P>C8=Y45?`(3 z^xyoH1}@L7{H$&Ktl|8u1dEfN6=1xKV~k~-PnotF^froQ%8}}6N;T}06&KU9#KpuT zZl$}##b!!R5tA(n@)RqXb0u?L#`*8$e0EYkGQee~)e0#a`H91ree?#(jiQFho4fzITteC#Pl4N zMix`5nUcwAma4?Pw7x23Dqn43yqR#df+?pkXEWlS@$uf!KICDNz;wV)C6K7qG z;j1}J@o@Sa=N}geAfJW&l#BQ&z4$5bGmpVf>1E<92ba>ouXAq6oF>s#algt2-C)in zZ3!r=xz?+RM{qP={1tcKj zr}t6HYY$S!Gk*b7u=WFbZ>F5fX)e=asSGlP@fTPQv8)e^SPrXM4)H99{T4r!?Q+gR zshxB$=WH;AS07|Q=8UJ5_EaN%o34s4neq+ooDp9#<^bxi85bgxq#BV68%t7oVdq-&^M#2K76bBf&!d=;g_RVr1s zq7vpa{Z7VnSdy7)6zJ7jEb(yKi=UFmCG171IKX&sPH*OWJ)BRFaUa+22P&aB%J(Ml zUEeUz5#~wZXQlA7iuozYl%jU@+zXiJ1}^6XoQ~%_zf%ERP0$qO%;{e^JxFH+L`aK6 zN`KO^$3d%YvDn4!!0${zE`WA|lmM!*hLp$qt$%7Q=QdSG<2ASboz%XLOC1|H=lQg2 zAN#X=T1o1@hG*{NdK|nv0J{Lsbpu*KeZz)W5#IAn>rMAyZEGv9@9jca{@<+Eu|*HD z)d|fe?G7zen~}2Z2|h!%EwqERelDkXaypGt8B42qVhiE=CHf^Stwf}B@L&bB;QfNW)f6=qYtlZfQ1?OIGw|_= z9B6u~Xuu~!jKQa`I1_81nK;#RD^9uGkIw+{AU=iIdHAp>5`V#Gp!gV{L9$$yi()xd zP8EZ3hG&^5kr&7dM5(+)UM9-qP4XsDg_AsYiE8;f`8zR0J|%aHTAbn8Cz@5EDikA7 znhd)%ev~F#BP!*zVygmq5xxPZ%8gt=0aw9GEX$h0$D1Wa5kz+bin@{BgV-I zI3YC!C!}VJQ{)1ilbR=&%B5nys#euvfw}=< zXTf}Y7Ob4lf_3m&u+#V~*cv_yb~T>``z@aZdz#OJJ;P_gUgxu5-_ThwjDk1|Ce!IG zm>fc9!Ei<(Uk2nosUypL-0|M>QK;!;p2qv*W;WSX@3m&OC1`15=JZP0~-3kG^Eqf6P(-= zoY3$y;q@%XM~buXaiU#T3b!~1z1f2vasl>`T_`SseO-;-5`*5d9_jViu@H-XL#IRT z!^g=zUgsX~MjzS)e(FUA_o6uNMRDAVV!0Q^aW9hcO!*5D%e|k@@m-8vtYib|G~Wi` zWCL`0H_r4qxOX|ZcR9ItxzM|w0?!Wld*PNlVIe&7kMen8$QN+#FGjwObAPe&ZS=ri zkkEKoi*(3^q?yLjq*IF7xRQfU8tg@Xr1_9$8cS2LG!@HHvK-S{f@v(lG?t)(1eYNP zl3*IkPO;Q9mYRp9rn96R(C<4Tqr1etkTuCmv5a(_`mTXCGUW7}+W3id6Krg}8UITmnwA zEN-^my}1<~+j_EX$u3T^fT`UJI>;&#%wopf#?2m0juXvGiYhr-4EBT?n5 z{@BMp03%WctkYl-$M(yk0xEzW*{B*tFYZGITeKLqXbIe(5+T=YjNi|qwf~5Z&N7v3 zaV5*tV3}%cadnn#FSfWbY;j}R;>NP9b(Xb*W$l2h^PqzyYn^4Sv8iP9wl(C;<#20u2llpDwb>F z;F`p7O&nYkCu@qq^>MPM#IU9$u%t?lL3PUO~(k7{kD z8dL*xf!f?<*-aY7oGhIrZgV$eJWXTxDZ=}w*RbeMO7Zzx*<5BL9g?*H-J z+vB;n$8&Fw<-Q%yeLJ3ebv*a#IBo~Uz1qpW+QqHm=KdVdZQ|rMadMmV;?_{ypB3w# z#;t+b7{+shWv^Jf6!&Ds+GVhI(YfbA;Gv!z!|kAPAJ(}K>)a-i`>?@nqH&wVaGPk{ zhjnfl2e(XbZW#x+3C-r0V636uE4lZ2xc9oa_r`O-jpu$F&;2%@`)xe;+c<7RC-++y zx1^ifO0mW|xJ~Fp$^(!z#yx5mw(JVC^vlur*U5EAH_DCRc@Q3kVmnT}G=92RzH}b^ zdE84@km3f||HU$rEF;O!BaffGei?9%>T=$?1nrAI>=35d1f91|#kg63QM4YXK*xy5 zIQ<$vf!)F$$K4|4)p1@9ncQ!y&i{YXbqv;eei?7nSLT9r3 zK$8m5PisT~XKcsejO}dex_M4J9V1MUD8<;)AVy*&nkG7}>*m?*49p?vjBYK?=#Iip z#_3{?b=^GA-4|oiAW;tOZ4#p~mY*z6wXU0Iyffhs6n8sSOfu*NnbNuMER1V|MJ056 zgy_I1c8ZuM=67~3UZKo%DdQ_SUB&6;oLZwbXsW&-&pVNb!e$MGPoCYb?oSeqZU3$h6&C6*9r`enqa9Yf11*f%~2IepC zJXLGqbR4JCIi1VtQcln1^b$_jE&dUL{J?R`!^T6*@9<=Us5e!=NCoc=(mt~hmb8pmn!8O!G`)%$Sj=QNMgft;3c zTEl5Qr_IZ7n?8!uahy)(bOxt$I96N>2sXE#OWI=s66{P-OuSkP7ibX6{klz4N~f$zDRwW`s#o8 zThe0BY|=F8c!DLaa60l89)HZ;__!kd zCa27_zBA0Wk$tS+G>;>`TtXQkileC=}U?P*yO1G-VDb z8*CowxGIFGx?>b-pd4$&V)#gB%H{Gbxk8>TSITqbx$->37JdQG=0dqjUL;o|#&C)J zFL|lF41UfPa*e!FUL}7i*UGEqHHb;9lh?`ha)Z1<-iXN7&GHs`tNfL`P2P@3#YW6< z@0Rz-d*ywISRm>mH_6|~hvjB?U|Z!j`G|Z}ZkLbA$H^CixAY{uu^sYh`3(HAKgeD3 zS$Jf7g{zbkdUzV@PR}t}e9TAVe$~Wa(hqz6 z=TWXZ0eizY3&5wE2o2EX>CoSH)=l!+{BkjLq#O4XA}~v_K;!!sDJT79s+60qp)d%gE?wd!f~8Zyt$~isKh)uQPjgXNEO5J79&_bnJsfg17^;pq8U+y8Zi#> zgE}z@G4pz?6SN>6I2F-?agg@}IYZ2lGv!RNfFn2y(GCvC>|^Ns7i94u7kV3(*#?T+ zK<74aa2rr;x(N1`+Mo}&0Z!GT4f=8$WN{m0a~t&MHYnsaDB?C4gf^Il8SKeuiCS)n zI&O(!+!FQN5*>&;Uy8XgwZuejiAmfN)3_z(a!btPmN*T4cZ*oWt+1F|VJWx58QcoX zxE0RlR=AW~;c{+;E4US|LeEdNa`|HoPWPqF-;X8AwE^54nw-^KF(3(Nl{?jNslM2p_2=Ryx4 z?|wQy5_$%YinT;zZJ=0XJmQm|pufOh!i+=*-@`JV*Y`ZIH!-j;yVZq(nz360YrMe%Q?{Ud~ZK>AeionOf7iA8>oby)#D zWsQ=wX12<9X2)kIW~XHL$a3_JlQH`0!o=?mvSzbQlgZS z-YURC)r;JM(H!SQr4^t8ouap?TeS)nsS^Md1p z!-7S@0-}Fd^datGOnlhz;m8kT54?F`TvjaeRjHy?;cU^F_=T$-W+@aTZoZLu8oZ!Uc!{ z7a{grfqpRoE1gpjzwK1z>Oxha=Bd%pv34~DpCN{lWPooq$)u?Z{Vxv<4^ z*%qH6=BVkI4_}UvkgV^o#Bx~uaJ;e1ehu?-)fs758ENDj@!e@#r%|Lyut``M3BN#`7OAzJCb|-2sKW zA8Rn-c!$a#qzBCf;Od5vrl>*QE*qnw11 z;AD6Qcgs2AUaXhhBTp6cWrkQIv2KO&=r>qrdkCv+h1f568Qv&(m)fZAQ1_?@@kYT- zSXDOHn%Al8u-?1|KG%A6t@@?9THGwBh#TZYag&@3i~2NX-oJ;1|1Cz_--!h5Qc1)+ zn&J_qaA7x(2k&$;@J^=~>|k+Y??JhE7m?rh5t}{$&*85aW#5A3-3zPsHe$+eB3}I+ zeBf`zsWJ__1=7VSGD*ymDPp$ticaYhGi5S7g1+K3nI#rUzc^j?6AKZ~xJ(Yi?uX&x zO4%TODVxMv*(|P>Bg9p*QQU!%h6*Bwun)POcYKt;*N(vR#@yq7_Ij_*YF9Xr8JV?LE!Y?9twr zo~qzO$QF|#1TS=XiF=i%t#Zex2i@*tQ*_rJ4Hs`#D!7nW8n}$wD)dt-mrGrR)%IP& zy-mrjyS7#qMe&?!^W1^>S&ux}=^f7JVf8s|2=Y-|ciZ`d+Ekr(w#g%M)Qxf}Kl2*7 zhj}#_#Y?h_%5QT|`7uwO{md;V;?a)SJX=r5bAioswR{zpjAgLXE;~IdN=|F#OFhd# zBb#T+a+~^_$)loV$uh9y9VLTsevm;oxqoHn_lWxV`21J~={C=!C*sk5uz9whkmr{+ z&lQqJ0dBuYd8q8rXRaT{Rc=3cD&2MHN@#hH`k~!z=f7SpI{{Ct&2vBY>>Za+s70L= zRfY!;@1hkkvkdRq_g*V+IKKSchLLt&hkLu^k3O3VqcscplW*7%sIQWk)>8ZxlYOD@+->w>HZN{zljTZWw>pbvel}f{P6Os8WrZr`7>O zvOx359mcVhj<t76p+BJw+VC#EOtl-MY+YbT zEOzKq%OLV2_0@6>&5v1H#h6*}!K3g<&=%SXEMMIr>xiNjzsObboxdEc5dS0VUYM5JHH7DS3 zY96h1(&U!lKUyYFYE>T1({O4P>m`?&?M7eAzM48GqxyMwo{hrPU7LsNK7#8$LY((l zGX-SYM{g|{H#JaSJZz|V0n~^ zX`mAr<+^eBIx4Gvj$xdm>suPy)ef`FhHTaizoE+l)BMgt<;nW8)pZ&fw$%+= zTCz-GoLYl$m16|g!LTYA)*!x@;d`uM$ZbY9Q;HTb3M1vu;l7-2_2t*P>WNjyXr7H& zY3!nJRHx7wu2VoP7`@epPFxUGG50Ltc3Ty5(YVsJ`}Vh4t$vHmFx~HqjI4C;3GEmUQ$-#Pyg`m`iu-wSCj1{&Wvw)KpPvTvTWE`Md*@5xg>m+k@QJ z%6GfU&ElzH|H_pAHuaUs6XjpcgpXp&pZ%-V+*aZIqWxOdEu4{~9p>cwKBE40e14>V zI{8;7&!Z>eVgJhH*?vME@~=#uE9473KT9J!Wb&+$=N>Nusvr6T^RN$w`t=~cE9La# z@1?r14`$}S9>YZ!-L&%|AI#*rAG6UeJW=}FB+d#LS<;~wN+))W|14d0IGmjrj~bj9 ziXys*f9w^7SiFO z7;wv(-u04c+qb7xHSQsae6I^HVsbHjL{>f=+_&@8^%SayQ}9m$YgS* zI*0W#jM%1$rYAM7>16h1FFyTT%a=mAwRw&b?R@*#l59(c0Wlk2{A}lvU)UP|}OW0c#o(E?{(F?e?-; zjS3!a!SZq^@URN1WyWBthE*GVuwng1orpa6e7b@fsuFStf{Bqj%Fo#?SY;Tibe+>} z`q?`Ep~_ajDc3GS+tgcj`x8VYxs9LYxwzRj;$FxlMx+J2xUH@OQ4}+b0-C2>i@06f z6f;fH(_jN>o6nhyueW$CZ{X)#g@{-eJBP9;@EnWcSu6W>=b^WJ%6N_Jx|z=vSgqlF zqQ<0=$me%#*G--^i1c-TRtL@t{uXuOe8{fDGa`9p;of_r%5WuC#k${15&eB^*UkLb z%V)du&^uuz<|uYK?+2xOKDnV5vDqvGmL4>m4cba&pf}0N4EEd1{MRA!+2vleN#D>> z#Hx3|J1&4-hel%gcQwbjFtgA)b-1QY8kv!F(WfG}(g8=5Y)DwWc&@;XGFl9Ch#d=R z&}frdTPEXc$bu$!#jN^v!)R|DKfY0Z0vqS6pH)Hf!E+IpA$@7*c3i7w_oOd~`|p4y z&I{!9>zm|8&%x$uNt%Osqe2LiN|rDB56Ca4l36}GisGe-IVOrO&FPaAfy?ILo68I% zl48N+*6HqAr>1|6iGZOzwQl`0%wlFKTqKnXK8z>G=?=FZJf!sCIS!Xo&QNlm(*8-h zXxW-%lrKSK1u{T^>Br=D7Cc?6WC>>NEi8*3cY<{Pk|o9>+%YV1P4NnS{0r8gF{T`U(xfr66kG%rjL&BH00 ziFv5t=mBOzn(+7aI7PXJa(j!+;6^gc2UmEJUt;~E z((rO*)21&)T?dek_D_k?NDa`-F{_ZPyV&-en*8z-9(1EkI~SZw?u<6^z9es1b&?w3 zs$c^z?{>KQxEyy&w(}KkeFwDRNz2l!ftu33cR6tsSv&R?56aHq-(bDyBp9_t3(A)z zG6U)9*gt~ekxXs-mQ#~cq8ojRC`x3OAYbM=Q(mH^Rc)2`L1IKA!Cuu)EO=V>&zreXXyRFUFXZ)c{XBYq6-hzC3Gs+h5KAi zQg6(cO<6mukLA)yyN^CONY`GwZkxJ8im_U$KwWA3hTLB+vJ4ugC#QCOc`q-z3K* zVk2r|R$^wF4~)I@X})h-H7mNrK_o0j(1ahW5foqg=i;G57q_-989H=HYx|5D?W1SR z811e-ZNv{FPOG)PhRtY~qWzRp+C!p!2Fgo54ZYza8!M1zjQ&L~Z}eQIJI`AAW{*6j zJbyCt*`~~TBSvq>c-t_)u%E^Ar*v%XvJ{Wj4<``5abZ z-P^$P=kR()cYXOKc51Oqy2z9Cj(i4FCilZ1=pr}7lgseG*bGp$C@O!4G?2+P*h z6c>7xQ&YVVnbc@-kewLPcuFHWQRgNxreSz_sXwz&N0&jwih>Z_Sr9zLFANSC4KPAr znT`ep8XKy7J_Mf2Fd*lfok`?l8BF3%4ymc3juI*TbxT@LZh$p&xbxk5nNnFp7q^@O zLY{K#dBIZ&8>h8Tn`YjZO@kMO#IRB-%-LF9 zhv8AQD&a6!C9LcQ_QZ+SvG_U+>G4GF3E+(bR;r>A^QK5ux)V~%)uQ-r*P`9OxP1DM-*DOB&^}z*)>e0)uHUD!PMjXFIIlXc`==jCSg1z*}w z2laQXyTHqL(Q+6S3-ijb0#FFr8Yn63JomIA3#Rala>~LXr#0U(wY7CBf!aM}epB$s z^p&ytEW?>77Gw| z%9=e6EX>OWcVEoxT@arizCH;rJX?lZ@=})*9v_vw%aWJ;OuJrco6H8*CNFAl&@lkH zD}!6~Cu`fz}z*gktn68KuVTNgd<*ceIQ?sr>BuXRJ2L zjFZQ=w)Y>=Hga0^1xwxYCuJE%dTnb%RZiK!zL|qst0tbZaI)7h5^G1*R_6}R$;hl2 zT{Uqo$%5;^vN*?*#dfY|^x92#o{gv_$-?G=9jm~aG09?_SpFEA8ag_9YaT3Y5mvqw zBA2US>74Z1IUJqVAReca7tXl1W7Dd@)E?2wf)jAV@JbBE;hUTYz8fUPx`INN(YGiU zdVb;vd-o~uPfA%OF79+_W!>WL=@fULv+T#EKWC21QB>M>$&8}#?zv-rPMbguJ+#SM z`Aj!?E75>;T1;JGwJOD+Kq0IFElr*VG3gkS7Vye)C$fVVke{DlnO{*o0LsNH%Vz&_ znn7D02r3c2&C79O>kc^u>{t5~cKB3tFv?58Uikx}$BAc-pS~ggcSyEs)QXQVE z;p19^*AByCn63}$T|OM8#*!)a*Y3dnHpBukE5i-}if4pJ1JuMPQW`6AD0FaKgw34K z^iy%hZZ>2)5DI%4)084ZKXx6A!5KPGWD)h8!L-)pp!dG<(C)+&BfAYKB;1sPr#1O` zO_mH)*A+W5sn`u=J{U`Tyw4y!s&YB>rG~MTOS9N87VA2f$xs*Sujxhx!gaqw8Rszy zLXlxW0Mzy@2c9<}7J&7VtMT3kTE9bIGxy1$4wGSb=$GXD@?BtgP4lo*8Rg<+&HUG^%X;M5&hrqH=LYr16Yx-7)^w3c^n8ZOY32i-Zspw0@-*)am$U1=M{zHe z)8q-4^LQTeg-xDy@&hhscOH7nXSlw;BO;E6~}2Sz`w6MkKT2FsobUjgx$a9kqHBw@)txx)qwNRE#3 z!<_%vDwDa_!Bk^&Vj>SggICVcR7$GU(;~}DS*31O=x|P7V(B?-LNIUkc}|sBfCy#u z(vmA~P@$$`&N(@{1K7Gkd!9_WTq`%7Kz7syCQrBxqQ^(9#`E3=FZEfEq^Ot~9L2=K zia>fra&-koAmJ0`lUra0y(l({&}dE$M%8`TdFas|ht+yq^Hj!Y?`ocEw|Y=_xsN@L z;b4?I=GYWB^i0Aw2#xk|718r@lQ5sb6DeX$@mLsEm^h3I)fE(gD?9Faktb7B7G}=e z4hif7ZKpIUJ?dr*@mDL9M!_S)UPn(kn)GSq!KL*eTq}(-6imZ@$ahh&9FOPNd-%?E zI~^#Y2b;Oou~$5hFPD>b6Q@XF@2*mly6RmIJZs@pcF|3nhirzK&lRfUxOVFPtSjYv zUGst5D6UR#94!+5K;PW7IP9bC-c$vJ1p_ETSeA!vqYwRPO1-As zH7>^^XufR@S2bQe`Kpw!DtEQZu?@6G94=hNn`ZG25?wi69JB0;EoQ;3nihP7NHPO+ z;g4KgPKjOWJ4B|)3HVcS=Iyv*LJcxSMt%)x6ixGbE-5?SN98Njl-dI*#e=%L%BgFw zAf$=y^aYq*oXdrI8PkkXD$E+G2lpB@CSYw@C21Ez=C@k*ZyR={^H}wVa15k7&svOU zJ@e37p_$JWc)JPnsI8HFU`MIG%)@pRbN?R7aHSk_g8c8Y^Ixw{IRVcvY@T)U@vc0O z`5@Ht3zQ*C3=RxTMC6!UE`>D_Ga`>s7#5G+7W6JqG0T}$KFM6{Kpb9Td7Oju=DGsH zDzwv>=4br|;kYd906PU+;2d0!A960n-|!5?=SB=3=&_d=MdqkGmxue#U6%as z>Z;E@@NC41gzkOE%!l?wnE9;18G-IRZJ}CT&knB(--Q3S`Ka)~FL@$#lo}h)qV)_~ z1IngdQD~!^`GVOv148^a)4B-quRs}S zj**SiA!I9V!v7!Ly$nToR`k6$;YtC=lca z3nnVqbxP41+7mRQgBE*5Cs}E1^GXlo_P~OyhcO=yc?ecd3#1ej;6D$oC@3FXgoowz z&&{v!&~gGz$6-j}Bj%am7@Fp>=SUMg+w(@yfPG2qv4GP(Z4L%5Y?>HX+B$nl=L&sD zT}hpbcA_iy!ZBHs_0t;14a4?{8STNXhA{vJHZ!Yj)aWUCUir}e{jh&cIcr*i=5A{K)WO^?URL-m@&jeY`l-2H8Gh z-AjAU>$!cd!MR@IMNBk`7wr(0-{v0kBcAi@XKpzmPpQqb^+Y`CNt@?tc^CdqQV(L% zPlSS&&UTl_T1#h%{=Me5>ZGY{cte9J52|ZeepX$fqtW+0rIpzCJ)$1B<@lmD&89yZ zMSn`GwdvcV>FRl#euca`>iNp1v#i7IWS2`*SIWNjbDvTNZ2tACA&O4%YtjRy?mrJ- z+)r9C7%0pe$B8Qf$$97}HQsnly6SKc2n%Hn-I~}JfY}KJGkXle9n@i5F0&(aAo9aO zXr9&gw^P>^mZQgQMnBP!5JpOf zaw7A(^sC+G?jv#!hoaZWp8A*}jRhUk=Qz^)nJ(pBR(HE9yc@|CS5*va+*7ynR5znf z-seau_OhF~)9!+iK1KW8%szOn#5#lBhL*lUr`Ab~hnU$z7vY8|(TKNS%@pecF?~E3 z?a?4QnXfdMue@Gvyj(=;*k6PV^jO&LB)4)zM_i1e&0w);C)#0@9w))6Oh z;>W&cTEIVH!iXjzCd{00%Ct!xqnpN$7>}Yf6y)XQ4d|a6kNAt1kNO;M%*qftu)+zn z4V-qiSUbnC(BL)AAT2OpE}BTTkajV%F?2bjn``~t#dB8ZLx&aD!}gUUh`wOd&`AkO zOPW;Cd|Gd(ZUp}Xm$qZb$=SLm$E_uw+B9TJG6v_AdBfk=zteS3b4h8VTT{QDq%Ue3 zQ(xw8ZW}dGFRB=x=O-J9#wyKsI{H_P9-cB}NQ|DBR#r9AqbE7srGesnB@2pWp+HlPcT8-r+Je05Si|G- z^r|W-9ESH7j-4>5zRi#Dj6%SI_FWtX+Sflau)lI}X|=as!GP?Ps?w6ml$^rCT(T!p z1R$fgp}VCNU5|riB03D40?%nR>c}<%l@BkGH0k6yl!}sq+=2ophD|R@O&bfVus_7- zrOk#e-W*`6iKR_d)s@w(P^3tIT9DMMSK`99k*D`|NKYA#aBH5Hva%-B!)PiiZAJHp zDMeR_Up&%1IxuitTUq_+QPqjDV03xnu^KioZ+K(wpvv+B9b3iS%9C8%hQ4XmgW7rz z^+}xJx`+F0SGrOgmxb%y!u1{_&IrU*Nlni-XnUJwJaZ8(rlWb-5r|G3i55c?&;dIf z+OIns^n>D{R&03$Z9OF1!7cc&C%pK@#Uk2MC_ z$F8!bF?VxR8|<;$W(`iM(pc62-FwyQpQi+jOmxi{{Erl2pAXYP+6ENe1!bqT%Z<8V zx2skcR20>3QrrcL3$TTy+wMerSc;Y|teHAd7rY8C9(#G-hJuz^iE*)svs?2Uy--`X z+lZ~sE2!-i8v|@uVL=uC-wNK$SjhdZt$xsilLiDvX7$C-L&rX@Dk-T>$sSP9&s$wO zxH2WTunXXOm|H;sbS+#RYwxQXzUHNf@*}9&Z()r8nAl0TmohV&Tro z<|q|fr@_SHJ3&~ItK5qd5bEA#W>RrX*- z`;q8}IcvtH;mRD|X?@!3b4CUMyLZc1bZ6rH)|PpRPF;8Q>Zt0S)UPfX!*MC8jy|_0;Y5BRD=5!RMD(N%#A16qyWZB54Mve3pRaO@HMz&G4FgGFgamW11WBP(<%r3i2y*VlYB?4Vj-vN4o^HF(7l$`$USX z(v3QbZ)3>lrnveYhH(dnzU$WYq{EAibOh#K#q#j+YP?*hi;afSs0WLBRA}ng-^#rh zJo;lUhncu_+LzZn!tx^*$n2-^QY!Mws|O6o%i+}zo^NNTK=F743_BvGH6)ECea(X! zyXZiRxiTX68o{S^rN^|@6b2HVwCy2nZbR$rltj&$uwdlLb7H@5FyK)a`v87 zX^uMnWInj&bi~G_^r@D5?YN|$EB(SsY%?gb53*sv)qJUi1C={a@w3}xE#kgrU;kF& zc&go2+c57m>BG?u;Wo_29Jm8oN@Eo6v*w)NT60crZ=NHX?fr=QLpX1_m*Ch)GV^3wX>p}BKgfrO2QJ zH9CrZr%k_3UT4|97S_uE_PnkP7$tE0a;?PzS{CMGW^e?1R8B)>s&ub;p2h7= z_7}Uga)+~aEY=o&o@pqoa;kv?QhjvFMd8Rnx<59i6gya5Cs0niEiAhLX{?j?vdo8J zoPR@Uwq3N=g3-?{vlzW99JY)2Htk|$=r-3eP16?@n!@PZeNp(0a3ys^HuYp6uVA}~ z!^NguoD?>J89f=u;I?SPC`Em!4)0$49=qPKv!oo3avaSZDBg-_w?^kN9dtqw&I)`1 za$6eYnDUeR7v%ZLCrgAOr=@PVBWTp>iYjvx8&>~uBAkfqpjl^@co`f+gUj`%Yx45S z*7Ms(G`f|`(KvkCl7fl#C3Q-3VDQ#IL$u&)tlUmEoG-}Oz=GkU7gZ)}o+4~?Nt$@l z;PIusr86D8`YxPP8e|xQoX-2WpKx6`7WFsFmfz2|oZ_b(i-MkKA+ATP5;bcJ11&O4RC5vo}OcPv-XG`D9~{p zbD56KBYKlzH0c>5>iZgoPpv8)nyjPjdJqTVC3Y+UO|5V3hX^$K-muUREUhc7k2Hwi z2jYwJ72YK$H7DMTuQd3QG3eZWj{aCBbvjx3csVfKNZ2md>jZq5=0+OR+E(||`5`#V zVsSXEz!Lna;~zT>yXTC8K?Cxua!Y92h_%H#q98u(hhpEz+#6vT0(h_8-1mrQx&{u= z#b^3r4dv9+PnoEx;zrLilMDIAnqOx_Y-HXjHZ&(;cof85$v~YAr6rh zW5rC49NQmGP+d!4!1#f6sdXbM9F-q@Vqjr;PJCf?Rgu4WWCp$q$p)LUCtG`v`n$U0 z7x=R2WDh`RKjHDNeuB+I;}hLWdD(s(}DpRf4MscC? z=$JGZy}7Xw+aQV~LP2bU+J7M4go3pyVK}jUF1+J$L`N*n%^lw;mM;9%Jw55gPu|s#bUETWrGztQPD_W(rd8)p=N5$l(8Kx%?-mKkBTZNP=6ft!XapKCV6kj&(a}l zs~3)W(FkL28KJ-zO_(_HWvZ4cH74pmrdLoqed3|v2x{pU8pegXrbTI)OeG)sjh|35 zoD0-Hs4DE$FOyyFtUhrOeS-?X9zhd${@jmt7-i628EiZ>x8#_+SV!Pcm~{wV^b`Ja z>};c;jlI@kZ^Zd@-Wv0X~6*BVAGPjEIG#zy@FrT4R3#~a3YM&@x%sK2sYd5_OwtH1t6 zblKx$^DIHXG#M!|XQwbtjp#H;=$4>S` zzXV3{Hhkfn+&}U4F|Rd&4qJB(Rmqe~c#R2fwHEmQA<5R6_pX&F7w&xz^rP%AoAfL2 zUP@|@GSKg0f7zt3!F$Vzj&m9;-)y{Lj>>Q&y%P|0=%TnfD*r2K?+xe)pg+q#vYF3% z`H+=QiM)sN=X~(a$!~}r`Uw1AV(*bzPOQNYfuGxgcbt(;{<1`f9JK~-9i!*pLjM;b z?t2F{cd##EK4+c83{R-gd!Z7XEhK%&5K~Qk$iNU|>w~7T=b-bubQ*L_{rU(5ASGsr zr=eqay*Mq9%$kuAo9;_aFm=OqoNl1gL{67EU8k@*_)~8&PDh(goEcG(ANJwAkeshF za6a^-Nn_BOlFNGw^rSbR$>XRKs?kYH7nqo$O1(vVc@FJgpmVWZ9+YD};Fa#Vl6*)G z^gohjixA6gt@PsCv}bRDo+kqs}SjiQFE}DZ&n*SGX{}p#Y$UhpHW-@1MohMC|-k2$=h_dTjuK83Z-r0 zy%b~<-XfcT<}%0dJG$Bgv;5*Flt0|B>@#bqLQiLMsZ99S@xe0eLjiGGJ@nsJkYxhc&{JnWv@^pKR-;r32)^i`gm~tfzIAa4X>5Q!8ehmYR$a? zs+NtF#D;kxhat}*(Kpa1J1rKwrAhXDV1t(nhlHUMMOn9I^8b3fdEqtT8A_D1N7mk2VHgIDi+vA*cYb- zdP5}DqAH(;#9V9ufU|jmp@)Y3$nJM@FSr$j!njjau6{KIF8c8D$_7-mzM^ut*{F!R zjVP=bm83N9xN;nQ9TVJ!iZ)a?1gf~o5e$a8fZ}X@3kw{M0Ryal@G9!tPqaUVVV(DC zQ&p4D99kz<70DJ@BYS$lXPO2K|9slT9$lvedZCj2{`12=jRQqISVFf*7deJcHk`)+ z%yo~WW8LLUT&B8(PLi*q?1RL~fw)|}xvDp!4tS3h&hwb2W$}0+TFhFJ$^)IJLH~S2j8(<>Y&7UxR2=W^+h^F8_6lld< zYLb)@k4Kk9Cy$%;(wh^;D=>kA*>lEXTVE8)G;nDZZi zP9|Zq3B5B3XeaI%!2`d2hB6sZ;pF_}JiMeRNhD%rjm}W={MU?kVx)IrqD`@%VA0oO?;_2?Oqq=qIWQ$yiq7z%8)qfL zejx?|^fKtJq_786G_oX9P+VQmpN~~XmW8bqR0KfK!aNJ1z5ZBF?QyjQYr+fK+N@?z z!|sRld<|RHwaipqD^DI0-S|)jIfh$3tOeLQm5Y-O{*pLN%MCo;MG-0op;}$!Kqv8| zb%EM#G~{5?kC&TCKVEJoo#kfd|BRUrbc*&-=%!BTJRI3P5uN&_d^f6W@X4&UxL;gO zWfWDR{qh~<$M`iA@6E+pcBWLaxuGOK0q+;Z!N8~^m~1h^i)SNSE6e+)_va&+R)ge6 zpT4v^A$CfH7jDro4m$3Rb+YiBFqgU|Zp14R5V^#{{X4yq7qpEi)urF*&UHKTlxF(gtT;@|!T);REBFkiZGTX@Kfm<<@b)HvkyLg5c)eFueN@g#(ns!2-*=Mkbfk zo&V?is=CviWCq;d{(m~8yQ^Nkdhh$*``*V`8LUd01$ajJDwo~u9phzeM=lCtdd{~PS0%?hhc#oETk+FB>3n$4BSr}ATk)niow zPaQr4Pp`42cNf8v@Rok=Z$~v!f+uW}atn}E8o7seOEcL?SjV75B9|8M*9zFABV|?) zRh=Ci-)Pq0$s#QgcLbBiH&0Cr_M?-O-yime%HhoH1r956E+Mp5WR3(r z2A~b3SL~7kiKkQq2as!UNMHqmd=Ak2!H17lE7msHehv(F@2r>QhJ`M}Cb{99iLRZE zxUwTTdF}@CNO@W@X%p#x(ru5L$*?`%Gi-$>^uIx2p$tle+!m!ywRZNzL$VxfpB-{$ zqVaC~;A}hGg@f%I2W**4nbK1mPrZHPoHLqEN9$*&o9UB9)6r@K&!j7(X@C>BVqtlZ zy$E=cFA8kka6>`C401!syPJ^D0CCo!Y=&>vC~>_|ndMe-d^~tf_=NLU?Kzzwk&7ZkHBMkkkw2irTwEbMS^yuHglH0O08X~HYe zjX@v#2bqt~^nKsonebPI)5!o?-T9ZHVF;z51H>GMvCiK%*7-oT%-zBj)VM@?siK9J zu+WA&lnX0p(L#&s#S2~1f)@IJ*{NY90C%GD%9_QA;IQu0V7L=$1s5ZzL@7hlzk{YV zw@zn6+k~4DIW>fH_jh-6r0d9^$X4(%5_}&1>}Qm_XYS#81|0zAA15A`Fhqfg#nMAh zp66ldR-TE~@8~=%a)BhfHaLXp3T|oe#f7aHSDfTjnCS=u_5E)p32feANH>JmxuFCvV9QH_w06e-gGKnAX2h)Q~zp&7*b!g*V zUD>u+duFQh@Ye1fajjh&?oJN&5A{xUowHr__WQ~;&C=G{?yYy#R93rsqS-m`5O@Sl zcE>|rx3^|POHX_l0zBp|<{{=CH|BlgI@dAp9r<}ri+OL6&et*5>jaPr7_4|qy|Dn& zaXo+(pjrta1z|1FXORhk=&Vr8dd?I;x-KNy$*tpNH7OS-ZY;Akwg4+5smd7vJU?ea zu7r*XZ6)cd!$}dO=9%Oh0sDF|zlBka5nccB65`lWQg^ni49*I`jSBXnu0a(TUuX^4 zlGy}$FLI`%anhUYN)C9*!i1zvf_4f#NqCPmgn8YmfL8GjVqWMBZDAK2*mqG3GF>cr z+0j8w8ylS)@9%>SwKqF9*f&GjbJ!pEpLh1o)NC!-s@i=+`_F}9XJ%{!_k7x5cmMdr zV9u;z4&LQumgH}TjSSK7l+o~7vNNf0*%umpXgCFx!>On6&9>UqN(3imhS7~*#1cSc zD~w#%{pO8lEU8_hMB??xl2<=9qYU66D~S44F45Q*mD~?H0;F?FPcvK%Xv*c9b~(Nf zeDh-)laM=E(yZFGNFZy1U5xRglsm$@RE7i)Lf+KT5HhNc4EFb=D31e%>KS#Fi)0Q$ z>uiiw*FYB!yx4G1`dx1&{)$QHF{mq3>DIJvWIHXH5Yqp_Sn%%rtYGiMPh2dX8qP7z z?E-O*yTm#ED|V^aQ&Y>Yu)l{6&n=BT4Cgv*DP7D))<%QWu%&`e9ds$;qHtO=oEXWK z?on^bza|${-VjGCMN={oM{i(%snb?e65rb~-;N*I?w(OHt2G#UgTPD|+X@xWQ$3?& z88#sBjTomGf43O_P3*%(*Gc}wbs>M=hm{mDOa=KHdIrNhm*{vI}7)Smcgz5R_0^rFxY$%y*(JNV{2{87^3YldA(ID{gr78Wr38M?;~?BXwPrI1^%m=5u?TGwOqK?7 zM&2*Fnf!Gh!m^b-ME>Qk`%vkdvYi;22?0^Y$i$ey2~i$dkl6J`N7m7D-J0I%^NI|} z#5)10QeL5CQXpH(f}MB2`17sn3#!~FTVn`E98=BSH1^V&Y@&RPt(||?tR6$m;xY3V z{zpc4?2j$WBaCbYLN5>te3Mvgu%2%lyx{1U0+8W z%4x|NF?s@d3fgBz(H=Pf&ZM=@ZX|*)3z|`$OG$JUQ-(YVtY)e|QdZsyLz3pC6!0F! z;tO(f&p;{tgS&`988KbJC$l^t_&7HM-v_*k>O0G?>NbJpR}DWn@A9;uq>t+8tU77ua5%4m8UxhCBqMKAt+-T$la*n}F@meg99$7d zrHx?=kRqSak|0Br>04UD7%4JIPf_AB+LTbGl6Ki<)Lg>9v)5}0`USTVfh8M|V59j= z;Yz2$mslRMdKj@W?D>`4$bIl2kym3-m~_ez5=wFIg!MOESBngV5qPb_ zD^16F?C)j79~n68Hg#C0l#SOhV7_R1SqM-toVypr`Y{LbT>t0*;`YjwgsL-DH0loe8 zsB^kG| zp=R9H%b~QY%12;vM%cGSxdu@9OT~f$9Lh%+`v_N*Zj17lxcE-R(qmCxlI54UY&Jc? z*b^upC4NGSWqN}1Con14_Mmrp1Y>kd$oW}Iv1ycQz_91)X-PoMFdet#>duJluXe$5 z4{{86ZLWh#?(x7YEf9gSn?JyiQ$VKC9G9(KW%B2o;h`S$vszGNww_)TCix9*p$o83 ze}(J^zZlKJ(g-+tDqj_4YTQ4l7;PedB?X48LRH>x%2bE_fy%8tBR>?uB$^9_Z|cvi%-_ zzZC(Iq+&)m3lhB@CqD|6oQw6WZ*U}nDs4A3gdBP^mCuJ`h_dT2nV=igMGzbz>|B3d zNl1P&LYutSN3b}`&Is{QSlvX&$Wk@(%Rx^#b|8d+BxnXLLr@1=@l~;mcXSL`4N;~S z#MT>{8?tw`$9wDhW@hm_lY7M1*%_z~r_W-KbWZpATT@$FqcB2K+MMaw5Ha|Ju-`g1v`kO$| zOzXzqo&gHFux3U&Dc#HZbnzqX-wHvv;POx;Bo7{>c{T$)i$S49h26p1Xe%p2nn=Yu z*wJo43L%{X*45Mx-N-(G%#n@?kRh|L+#~#w?41s$Q)Zp(LeJQLsPTyXhnkYu9jIh} zxUer@rG2bl2YJx1AAs#q_c0n4?dOEAghKmXJ}i82x}~$Ei==;f*I+{$LV{{;fQG`X|84#1CVNhc7yO?7Slf5A0pov31kj^!UgS^c0Eq zXu#)gX{xu?R+mfUEmj9hvQV3oMg=}&Y8{;u-77M$KGn|*uH)pS9mZ|!4sY>~*Ku5y z3Q7QvM;?O<8abYwx>0w2Bp2o(O&d}s_cUu-bIQ-GQ^q$#Jp&kB*B7Zk7)_f8K~jA zx&SDZ7Vxg%tqtr8Yr#T=ELMXLeu4@c5s=dOrR##B1RMpBwJ3_`Z-g$Ne-xNxV7Y^T z#W)MosEc_rTUmwd?LMZKA;W4xD29VAwlaJ)=s>{GL)u3nf0mUM%fwW9X?P?2iRC5n zwICnA-t&fdyzcXjI99Lsydf#C`#g!-WPy7F_M?_9pD|hq_^wn*RP>M8l7oi zQ##T}5;L^140>m5Fq6rG9jvcw){6$BEqvUtFzYwlo%MRXPAB23JQ((x3H`9|hlzaRc$p`Ujl2h5szAy<-uwGm?mhxa~1&eUOYsPOD zurlA<*@sH|2dC%)^YApDD_hH0?`J=D2Xo zKcFek$-E2N1QQff9mwZ&op$Q`%E#cw`*C22&r!}SwqF3qFSACvlhwyHEQM{ zC;69wcx6%1<+jegzRuge(m#;6Ls8z%!gB3I=j>LE$F$9}yFCA> zJgjtuBB|U!cRZd^o>GWVNWGA0zRRcJ!wee}+zC!!pEFErp<9O|!aD4ie5f+n<)eWk zW6O$*|4PA0!LbWOFN$+|9=!PC{rfJaT9O;HJ>xU|{nNlB7wxwk+xz6+^N;R=7-3~Y z6El6!4opoAAZfZ~_jx#vVvMqey?2#y9{(26$wIE)ls`v$8}i-L+nj(uBRqdd_MQ`M z#9SxDTt`TH8-`CVIctLhFRH{@T38cP#==ubPej=i3kGXNRZZG=#Z@&|O>+G#8D#k- zkDxr5Z0x(Mz;NC!)4CNkM>i78Q0!ziY!;5nYs+c2qnu{-IkP%A3$Uvzz~u%8cc)_5 zVSf@7XwR;ylL<5o{z0#k30%CoPNt=(PNq->k#dOEnozWD!<_c@o#!4|`1*iyA~iIW zI)Q{8F;o$Ib#~Waf8xbtpOPCRITP>ZHoW`wYGeWv7&S6+YSz}s1aW}aU|5e=tFG6n zktxIjBrE>}4N+5q@M%`GufK`LsT|O>1B!BM*AO2T_^4-uPgnC z@&J4V?2vK6&HhsC%@gcn(zK4_r}KL=KS$245oeB`d7fv%3#?NgQ%8A}sh=>O$jEQ9 zKwm(~j*5jE!H<(|abg);W11;9uLBJf zxlB|P6}faeLQ&MX6d+m;Mie)-K8*YY7+nuvWYLD7Tm?r@q0J3!{xtoptjCQkxqcg- zEA;a&*ndmL1Ni6HBP;c0y93ZNQ(%O#Dy3B$SFOrUB(;F+fXn(it3tK~Fx+RZ*SKak zJ|sfh%QY(1XhEsQcD+>Nwd<@(Nd)^!okp=Lm>+iQcY!n3t-&a!6w23NB$~SR8y@FhwQ=sW*sJ|#kq+Zb@BI+;3q$t&2 zL}dpY;T0NL;w)7lA2cdmBqBWa$dy+fUb+IZ^rn%qEnCJ$H!5$}w8yn8mdwYNKD~78 zf&++tWuwz`6Q3HNnHh&p0g}k}gBQ}C6=Rj59;e(1;9rS1-K?M4&G~bkUG5X}$+x+S zoxS{uVNZL78Ws8>+M)Mz0~=XIJM^{qSFD9cLSA5G1}W5B42qhIpc_WbMZ#e#x&!!` z2z+L&ggE*_zrg-hNEXnKe0-Aq|O8lT^@lCsZm7oBA>o53jH=h2;@L6^cnh$rMdyY_c|< z)i%+CBH-KxJ`S+qWx4_SOb(?=dn^Uq4`$F&Mdg+wjh8w&V-bLOFACYScZElc0wz?ni8<96LysII)ds@hNauv1Fk9{yOJB=2jTqz6`;4PJ|BvtL6T{!Q9#4 z82>LQvhYQ!aA@OfE0;en{AA|fcR*uvLxzJ~1A9CC5sWeaJ+9~L9t!yIgP{0aAFW>Z z(6V0LLw#7_wQ_d}#F{Hxse6dM2^%uW!52g@Hc#DR~eri^?z+AaS zx4RO2Xe?s90zPDC#dz@NRa{R}OektCmMPdvXGch``OtqNvoN(@dL z2u>puP>BtnKXGuWLq$fvi6(B_V1q3&AQ%a9n_IsgV@lV(vOh6C0>{R%hqK(Tiy%=W zz7s6IZRS&hq}=rQflwYPhRPO#N?KvcF|7cXl{w$eK357CoZnvH*q?!iszf|_QEXwj zD7G-dHdP_8r>d!{(O!p!6+ROPTY+=ZMLg(#Ny>zyIbq&UTz1*Pp~ckYi$fbX4rS-& zvgS(-S-?HlPJXx&(}~s15mElFYoe zjRWha_d|Y|q76TNKjb^Oem?{^y&v)mT(=+oyF#0HLH}3M5A;qQ%m2oH!xunHQqrh| zntm?ESzmW7Bx?GVmjsjvHdR^zKro){V4|b7Iivv0kg!SKBJLADcK9L6_vCB(tt#nf zM3dQUUT8J)ab&3!`;F>nto8E6*_6UsP{7Y;R(+hiE;~4by+RlKxxa-nAA4FnyogPT4eWQu2Ek7e5~+&LqJmDz<0_r7DYw{LQ?uXmD9U9|u4El10kGNox# z3M)Hz{_*`6Jv)Rz?Jo|^&JO8oNVM+-tl=5!_dy4aBTRgdBo){11K11`PchW=C^~Qv zB%zU^ePg(g7vABDt`?jK} z$sgf&22=UdN+uTXDbVv51mF3%K@SYuN}lgDXxj_m-rP)Ya{@f^YC8_mbDFnkBk1|L z00={_^;g()SgWox#9iTZ=i{z)&3YGNWV#}#>6h267fBh=BfnlrzrVc*;U#n9gCisJ zW2g-x3X6ckrw`ST0&of%Z@xxL#(GSCj!N(yRQ6NOc6-+x9B?$~ZFN&rf3 z%nk=7oi=YBeFK0cIu(chh4w`rW~eJts(%5@+<^FVz(K2O*yYg<_Lot^j?j&MVub8Z z*oJT*p>p<|cE32wAA-8*J>arY!!B2j?|)pWVV8f;>1x;snnNnJQSu%ibyroxPw)c=zpb37Y3C`57!&E+ZWmEPIjDG8Onk+Kh|s(dti<@l z`TL64gD0SOp!0`4sM}EqR?tBctU4rbwvCcYbMP2Pa6^KVBN^H8MVj{{r-M<|1i6LA zdzu=LP%alkPNhc=S>LcxGr|1|OH~ zHy_)}t^mEhiSRVL65np#dkkX`?-Fv%*91&&g56@Z9J9L3E$rdbv>~0f-Vf=%ML+yx zK^|J&59zgE?_D>uU##B`|Bu4E-UYjSNk0OHn*(_M;~$Jue&T zHQ-1EvW{Q0$>aH<{D>$4cPE(eJB2^=XJu=~!sFxw9fN}CyKsX34*90zedL?|BfM{| zA3gL{P>=yd=r!N~(6#R?t!M_+Q1GLFO8y|zQ2FgjP=!lSKEui{$G11@HQ?Tl4=aBY zE?mZ~sIL+yKl&+*?6cPVCu+cb$6{pT^Az#BE-^m2Vg zF89dOVWbGlJKXyf854dO;4-VXWA$#Q3UIi_0EgmhaH-yaye>7W+57@yFHprbc--fH zhu=Tt{HIj=4RQ?o4#u~p_FG|iSbn|s8+H;2-&i_fsVI&LkagYT_t;5M`wh_(Im z#F#z>6${f|gaToJO256v`D-+cr1L18t{2LDgX%hY|X<* zZ$o-1z0C=BLn&^=p4Zzr3vF&-?$UmsM{r0lGY@|nl0_0RQoFM|Wq7%>xkd!@%}N|q z5V(9CAcEdiI%>r&)ugCLG-i?z(1FC6X7~gz7y)Ny%jQ4;L7=@*LnQ-=co?1f{9Pem zSy@A*mb`aKhlA`0`5M6n(~s+vPg(e;*=e@{R|tcnslaWdQomM0!IqFJTb(GmGuqKR zs?|dxZ5`_zoI%wcWg^-YY`ao>S;Ifxr8qs|dYcs-fz=ZoNT4LGjl;FCJ)Y>jH|Xh5 z+-)r_hhcruTmZNXy!tY7%RLPro&cbb%_8C#a=ygjdxz2xaIz;Kcch40fRSEZv>?fh zx;Yr6oLIqRurnSh%8X?#qwJT3q&yI?PoEi!%t%7^hE4w+!@Wj*f6sGSw9BjJTU>+vBy(ZEel=NW{_H zc8})P@DDOAX2%b}_k05^rybc?J>wD;UDZntHUNd=$09ruStHwItC6IdW?M5U(fz8K zd_AzWYstrhicyl^L7K`98cugEo|93zShh!V})SGxx}8qzMqfRS!ojN3D%Z3BS}#!#Vn@>pLi1Ws|grhQ(s zwxrwk&CTv>OE+7!$8h?f;n>~toAIN)y+_A?)3X~HjBrtlT4ZxZ; z=#W;O>S9C4s{~Cpdq|jwkT>caMFTYao_dz_t5(eB~q=!Ykc4eg`RW?>O*lN+R z9F?Jj9(IGC$dwpPs9_6f>g>tSU3%%krOPj0%5K^?JTx~qq+Pg=_3t}&;ojWS`z{=u z8DygaGcyCZCkAH(Y~ZF0AW(hohODEu4BRdjpT>a8NEDIm;7HR+MZ5}vg`T?+o3Q&a zGfWs{={OIr1giNmqlgV(!k&vTiyxVtaAX-GrzQ3i?5_yf?2$}>UV&A>Q9h0}5`JAY zXS7<>-zrNm!!_9JtR^WUN2vHwI)5NZn(9u&2BYsMRF0x0Nr~(g;!K;(?^YRt&vTb( zs{2hd2c~*^CJ-HnV&Oab_azQ=-eMo5-4iye!N1z~rjb;3IEB1s!Hoyv^T{1=9(n+Q zc{Jt({PCUyT>8j&gL2eUttYUrkZ6E+j!Q5jGk&!|JP0cSxQxYvS66b{?@O(&;3YT- zqdJKZ-0LRnN=Uam4XZVsBvCaK`d)j|?qE+=)h$j;97fz7V2sl1L+yJS%d1`URdxjF z$qlOMq^#zUjfP#SsUHL(JU_r1#=67(!_$LJ9SE1Gk0!UYb@uzG5E|vNn7*mfv^!Pv zm!Nw&Am&K1;lIWl>F7DxdX9csCKs5~1%TZx}UQ-8OTf{u=w1b;CJR zlZR_iZ4MzoiiVIcR7OzEBc0I+4e_Q}9=NgPeh#*r*N^!p4^=W#ywj7No$9ySxkWQo zMw01vhtJ&_?+CV8HFgcQrlych*ik<|M04hdm3sy8Zcjr{>ZcRr0-?hR0$h;dh zaW3}bNLPA7VbR?~JM4+d^8RSFzq}l!tm2Wua)yEfeo6onOtZ|^r2`u)kyR*}9qqmo z3)P=V-W}^|@`WS*)tAVHN7X$VA) zlZH7OsXavnD^Uz*)veu+AgkwSp`0^S=r!hxAO`)M$&kD5Q2DR00ds#Kq>Q@AH);Hr z5WGMtj{&}MO*==^;)>;jD#18~SuE2edc&g~2V2l*R)r^HwRIU^+L_Q-K zmHum_Ie^3=O}Ei*Jbwx_#2)>tnvytinz2;Ui{wM0y!!Mu=-2zsZr`?W^+ zXvPrTWjp@=}FhAp7D-Qygil}O0_5IQJm2g>CVIhkw~DuyF1os$G%Q6wK?2c z-_Tg!7;kHAYI8T|CVSf5BZIDV#?##;_HYki_bl>j(jFen_SuPpo5RAQ&#e~mc$AJ`DA&a))*;27y7@<>NXJZcwVTDv$R$KhE6<_C`#19h{UBBe*5?kZ zJWli(B#zFMAN~M zsM<(JY@njDrm8Pg=`^VNX9ykr40PiyntC6|dS z*ZEo;s(-ENdwU*kvOf9b-h< z$CB|$PP}3 zxG&IjlI!0HNe=}7ERqhI?l7&!f`9`1=Q7*D>FFc2Wf$$*c^(ebSSkZ+qH`>IOSIo& z9Z7VKQfbA}L~N{#*@t>ugOig3-VE!RUm@w4cY{xHH^1Y$NV_eVOopA|KvOW)9>@Mm zVE?^@wfz5|o)`FLqUR4N{1rMt-&2rCLSrA*IEsDul#+9^O5_~$d=NO{+o0!usTX## zeUG^R7wP%z^hh?7jz`}BJ=b*+XC~)5Bbq1Z-)?s9?(5%E-)OVpn0aiitqnU<7p0q9 z>~2*}ICI~ySEbwB-PLtf)tP`dQ}t4LWq&l>TUF_B%}%;s%jgunV>lD-Xy9^PYb4Vf z2}HL=dV7$X0|dQ`sqR3Vqp_*JIpk@A3Zo@A-XCr91pRI9Xxg79l8!yB^FvPwe(2An z>A_&IFNl}EA)5YrB>lN#3pml)*YOlJg4TCVXMhx%_d@_WmG1#lQ;F` zp4ob^z>{YF3LALv9gW%kX4>AbB*S&_h!b159l9G^D5=lWg?-{heq)Nufj1$|owQJt zG>Accz}RV}bR!mvJb56cuc$zh=S)oW^-WFn`63aYCmQuw#(EyjjE-g=?HP-OJWqJS z5%&}BFwT(!Z@Zb@E5XY*+X`8SWM}+=@#Hw}5PZ z1h-m}>|QMgcLsKjY_--{k6cJfWZPk>A)ByZxS?W%vIH+BrdC-*O=F5~ z$9qFkU;^e~%B(8%QKu2eiHS8Aw1r+ZI<=uE)aD8@42O+(WyaD&y|Q{z(_YdVkymrU zHWq01dRxG5+1h&s+Y^)X!ze!sr4EyPz?V(1Y4uCzWh+yl-x<*FYRG<+g3Sv4TNoP^ z`O>^(j*{uf5`3gcE^o}bSBvj!8zEC}a!+1rN|;cent-Q8M)rktf|XCW!NYF>u$4mS@4 z(cQZY*`3aj9X=bq(nxmb^z)!yTVv5)(6A!Pak%`tU04s)t;PHr5jRZoVLF>^EtS*r;$L1~FOkwc zhLm13E1(OK$BnfqXiv`|q&J$%vXO9qg?S{C7{)UBnp^>yH^&40Wl>f2Hr9JhP?7r@ z8a$>Cd)w^ZXw+NheKgtM8#h5;Xt{Je%xw8=TEe_Nsbkm7}o{MRu4}jz1dq zT9Y(eDxWvw?Adg5ajAhVj^w3tyMDcZMvNP4WOK1LB`1hz`4*L5i`|8I47;ZNTI1Kr z7B{SDN3f~dG;I>D{E8*_9$^!OtpKoh0!Ig+#hxd9)&Mj?fm#UY!e94vlK19~&nuuDO|{+G z)MSV5-^Faq3&F$8PGQG3Ba%wupJmO$JV&+x2Xjg{^T%;Nhx<;t&pykXh5H_yV83{N z8TT8F`;CSBK30#kSx>@anNYCHxbG_5Z^AB&Q~%JQuGhZ{D`4lJ$972fY*k1@Y|7VZ;#*53EAPqQX@p8=n>_nYv1ocb5=S$p5bKE>?vUIRXB z@B47SQ9fwEN8AT|R>oJ3{x#7*!DsFB)W1_+!t(?laUbwmdArLMJiLKos-Os4CLbQ-{>y9c!)s5!??dCg{7F0y7KxrmTp%vtlt2eS&m))B zI{hOv+CPc=pjYztb)Hu_lqPr{I91Mw_XGQj{)zXcY-28Qza0I)BJRUPCC2}vexJP{ z?r#Ooc~ZI*u)ab1>Zy7?{GfTfel7((HTJa~eqmDs!vPP3k{d=|39lCFtb^_Dv~(cl~17BHsCnQ;$kDbiS7@cqiP{K6~m> z{pDObxcsp6WA<%|=iyQ8FtWC&AP~h_TX@OXuJQPt z&Va80HOZTpm1@9-z~-{OZs0Vxv)+^2V^+S2;eOMahYf#5x)f{Y7O-<8&Wd2`rhN&x zodbOQJ;0V~K*EEHqzuD2D8@#z2hwF4H6Hc6GS;LZVJTUtMP(SqOu}}r=asoeg@k0% zf)=EWp(I=Xsy_k42#o2(_%pbB=ezr9Qa! zE`g0khU~4F1t56#%F_~g$78FYB&D8ZOh6R$R%mm5E#hz<{1tokwpf4SPgP;DAf7=jf;42;f~VbmwXk!H6en@SI3famSp zeok|+&F$8@m`H!*az3l|Mbd6ZTf8+fFqml7kRN;Vp@XP?5^QJ)Hg#)X&CdwK#9YG5 z?d(4G2f#il9W!zhVZ_i>s9>RBF_mH2qP2kY1Iij=TFN0P%SFXU&zgoXGjQdcmG*#s z)-ExB;4HQ7)qrn zv)Fk%cNBo|hy3im3NUoHIbEj%1D)T5^b_eGwh8Cfz5FxjNARkV*vTK!X(jvpU96H_ zjnN|BtO!p45du+QhBOVC*tep!Ie%;nNd?E+?;3CK7#;0sA4fa%cnas=UAg!Ide+RCkq7`v$W7Q0b z)k)6|z>#ABPeE7Avs`_vroC0=>)w=2ZzY;QwPdULEWZ~S?9P%tF?*7@^#BSsqlQ5h zNHFCigaPJAB|;Y@>taP2r#c1(axr3NjOMt=WjK%R_R=N3O)e~ z^vU=ly_NCJKn4wG9o)ZX$Na|G$+7HUZ)Vgp1{;rO)K#4?mmtbC!Qe{b8x|lyImo+K z|G?^yomt!vdlTQ&*tLLvow!l-1HI@C(P=WtXS6xhDUZVRH>)->Yf>?>dim~^uUXug zMhm1NoL;&5ft9a#^f4!%z<=x$%H1M2(Z^8WO8tnU7@uU&#SJ)ouf7raByQjz_GJq; z=cK^*dR+OsH9&R4y2yFlBL7&V)e?XC1Mm)A029HGt5AaPW}ZJ0C>yR{(x$FX;!k`8 z$bttdyTqEX%0EF$F8oDua{d6kO;0V*Iaz*n`MuIf{wiWtHW12Y5;B^zE2BZ`#g5HS zxKihIfEQ6`23XwVIi_|Z>5*dTfU{vFosMv8;#|}0&)$CZFXtfAZ+zixZ~5^YJP)b6 z9n0@!)y5j`T{B{{&gUF4E<2 zq5&8f4N%0th^x0J>YJ?AruqbmcxwLUCP#y+HaL3xNL~4s?!F&H!Ya1}VMB<7pYQF) zZt(h_jHeIsG({^z%ZLFU#qGTJJly@@KF_3PjMc12?JQ0M zb{M)RLBR}XEPp|srlHaT36nDZnmlj>@%K1sl+LDR8fGfd&}g+bHY8GS!FXn$!SGOQ zA{Bqq@5S%#-si(%m05!pu13N?=J8cVR5!i6^Ky_(f*0ke_@(xXV@-3QtzVLuJr5b*hc-M7U%e~@V(1992(L)Lr zh-q9T_-#f|LgtB0q=b@Gl{t3P|&(m}65x@EJr$GUZgRWx1@ZSLs5WZ@Z z9N9X`!^o~9*|1;Q-sckf|nRitbWd7QXjMA zKd~gBiL2g;w_%TwzhysLd1pz@3nM>)Q32y>l~3sJ?8ZB9E_o+^JpZozC%qH8KlVG) zJ3x;{awAO=moZ0A7h%-=42j9`m=!)FTl{5IBO|5Hq3kgWJ%c`OEc8Kx#wCo|=))MX zfX=nWeduGNKDe|~I-h+WD{e#Pc|_=hYJd?L@+k`xLokq*1U%-EecnyLhencUM!-*e z4~{Io1-uQRk+qjuqovcLUd8!Us-+Vetg9Hi>Vt|>a_#Mmz5NQsWcm=a+8+YezFU^> zhMG<(xghq=VT|?fF;+L90I+2I{eXbwFs_?%-A?>qEy0EC6$Xmbu|cqoz>2Z2J4#hi z;M=Va6SPXvhqPu0v~DzpNd8@7cY=-pN=1@tAVTj-)3yYdNIDQ~AeDabc+N%doWC8x zjvZFzYR<1#tR3gCnKY(_wP|KAO8?Fu!C7?B+8~`cy^z*J!YUiG9)u@>i%8b1De#_1 ztY7pU=I<`eqIs{ffF-wR9`+*qXbb-Y44c_+r6Z`1Bl6e)$r;imMS_a%iJdO)9$lu< zm7o1q`<#YpkU@`s^^yA3hKs0%KTD8Ws-mR@xw-cch} zcO#f0Vh2xCU`WVi(BoN@ui^X}W(`^8cYrF$*3kYkb}n=&=Tb1t`^@It`$%8HkY6ds ze!w3>oX6p8b+8SbY&(>`wHhQJvI_aZ>%uF`u&I-+j*d&Armm=z)L6J*P|qtu&ccYK$3i%;hJiO363O%BL5?@yx-1P z8FGFrmHV^EdJ)C9%*N`9imFZB#?Rq>RUo$s6dIDP6N$tqG{)L!qI1&vJ7n*(aBE#^ z+^j$WK8@(#$y9X9RHADFy-aJ`gkqjd)Rf~%v$YBgOw>O#;*F(}5O}%NAWgGB@*2eK z?I2mXyA$O}*|4_-HAUsRN)xyZc`nY_Oc|4=(H#HIhA=O{HY9J_x@Bf6-Br5*>iCG) zzyY+yX@=sXG*basCvh4GYmihVKJ540csM1aJ#Jgf<1%l{o%9X)e1m@fkQZNG!n1I5 zSCl3hopCSr2j!7(vY7g1IXRL|$mmSJjlR7>dNppF&116MIp7`i;UD!kGW%TE$|B-%|}njaqO%d|(mJ!unE z4c_7%L$z&2cuU{~xqj6#n)=SHVI!(-z+l7|mj^}uoMtc`GdZtR^LPJ7^r*%F&fZ`^B9 zHfh>sMLWC+HkX>-nci-1yQit8Yc>rSOfCNx?}ct?r?f4*CB{r<;9ZkhF`Ja*C^A>hb$L5c)!t9lfN$FY(?h zj9lq=?5D!v5<3Tw0r&*EHF7f+zT1=R!_#oiO=zs_!tH~LNo9f#iT?M}13NCZT9Y^| zrs>S!tn!C4>?P|j73Evv%hSs2V0sXKS{AO&?n&(HpN3&mQ?lak+}>k*HqtS(bPdf8 zY*NaQN+&D+&cO?hA+|KbNOzl*V%e~nQB@;^P=ISS5G{FC3s*;IZ;&4z`Tmk_;gF0< z-g#L=7hm;tx5<@UFHBD^OtnS8>1OW8Hmq7(cZaoBM&7b>)V{LlR^v*qJf~?p)jGa! zyn%rY?Cg7sf_AxjR|%YY0K4^aj5|eg6Xqe*10voAS&Nh-Xd`M^0gVbx z8f9+73L;gZkl6Lym+x~H0>(!h5ZpcH=Ruyb3gXwkc4{EhQFhV5GiQQFmeloJ_P-?`&iL{wPK(a_lN zt>W5cnePSWd0{aI8^#!{|P2T z9=u{pDxt~j5SPth&MX&$a2!%h_<^s~fZe43dM|F=WHfrOtd5Ap=SWI*0mB zaJis_n@1o%gQWt?dqmPS^CB>mP-&y8s3eV#4)x&?Xpu(6rY_f7BJB0{aPg)P`&no% zOdhVww}i|+9#)}H`iuV%+j=LCqoRnvh?wi$-I?6e`;77hO0@h1)~9R(&#fuV2bv_S)e)d*b6gKPc}WuBrBUk1{~BT#RSha5j{f4 z3SnfcRj@tq-I6?;=t?$oq9#TWc^ zAhL+*x{{yI4h?HNs56e~xr7KwSXiVp^Z}4jPQEk*Utab{Q1KW->Nf=+?opCD2-U!Z= zDZ7hr1M`6|RoJ{Rji3*gz^Qs&PF+vmI*e?3GN7L>R zzaP}J2gw14bQ}%r8*En*?ADX>0lQT?jyr&vFJukq75~srM0ziK8)Oxv-~M!44NF8M z!Vci^=tHoB`Ul|@@PPCoI6(2i-Uinp`7&8<0kOpg{D|;XzEYOoEX&RKfsZTk(afH- z=q<&4(Nf$OEpcBwfFCWGn~XJh8`i*uxlwHg5i1HSiLUMg5ukG*VnwMQl8QnjaDvGwQYEv+`2%VqnH#sq{uW&CEJZM7rD!e(!M z7bSxYX&-N~!$s3(YbE`Q^f1-{alK#;FM#B<8}`o)Wb3#9k`tLIm;c7ljnKYY#GI1S zFf;2uZXwA6HSNV9XI#Dn<$}m^VV2HSF;QsO@d4#J!qT8yhwfg3_|u+$0Chw!LD-{N z+J(nZSj23irz8quJ3`M(p+AK40;lCs01U<4U*)wr^VE4%25z)x|k@9&_S zFnzjG!rADiQFZ&$0Uz*95|AJC-nxB)SA@5m=$3s0=oEEP*`12Tl6%NxV)K?np(j?< zKaPypixT!%8a8uiGjhMgZae^4ns(!7bHCKLqmlHJV+?v*WFVK2J;7dKlGzN#Cb1$N ztP5&sZi0BY{`e59ES8A)!}Z1rECaLd9ok#+V}1fcZ~-P)i^H@s?rxl+UBGE(ef0V% z3K*wIj9+hi2m2=bCFXcGCjCy#@oZ$D6({bU`4jgsapDNh_XzyBK^mMrS%z&5|1}&e z92|&xgeoccOv2%Uw*pQXGih(02=g&tp;AbG`^MIVi z+WrdTI|Qh92>q)MZy*N*KvqU*Ki(kn&gfPOx76kfc~wY|q>1%H^8i`UtfvPQ5wMOH zE+QO&i*eb*`ob*^kFB#2Hp3<}ILu(ZL6HTK30CX36W)b{v(wP8bfWeE7O7D8#L zqC&1KtE;o9Hj}w6fKh~5lHCOw>6F^U`0N{iHprHe*X0ELFum#nf)=w7m@brtvR^OI z8CUonvITj@?_`#+MZOZ`4k#X7WA9&qt$H)~K@01Go6K_*XBUt@$Unz^BDEsRcOUWe zX*YNx3VO5v^C3?mh1qFlE7JW->TdBxm6k9rRho~-T`ozA_r-g=60Vpl8uX)^7Qf$L zW}?yrq_>310+1v4P-J(P4mjv1(n$$Q9D|!jLQ9w6-Y5Xn0YwF$nhJ%cJ5rndvh3TK zh)jk<)3L5ukF12}J97Wf>qaC*IuOhBgxEDbnP_mx$C$f6%zhG{jzy=!DbynE%!Fs6 z_?}Lvrc@&LY7!cXu6R#0+Se0}^>#ubk?bJAlI%z_SfjA5083-H9mRf-h1OB*2T541 z8l{G$KdEA7h7~%Uss%@$(6v)0Av1cIR^N?Ez^=`kV9RuNhs>;P)23%Z$vgXaS3w9o z^&EZG@dB7jkq?05+~BJOfEMx;cL06 zXS672{zI7CVT+1{gkbYn?rso|?SdW=Ok9A;yHF>hnfx1|ixJ9wj1W2!6jh8Q406PUHImElW9K+cT(s%@c{Y?LdY`XFbDj)hYl^TxGB_&sSWUQJI*)F{a*sw-n#^KT$?!`}hYCp$A^88(2upM}rtDa5UM;Gr^{9jwP% zQ~`bY!9dEz23lwVm7^xi6Br2}z(@Ed&3nDxgts#o4)~xlMS3e?HxVgSgci%50wy99 z?h#Tqt~oem3lWgk_Rjr-T&52Iv7x@Ne>KVIqaPual3*Xcc znFwtf;(hPkcIQ{FI6QVv+SMqV-Z?(l%1u#7(!On{zIw?8$Wz@FobH&QJ)mMQ{}=xw z{HCg~Q$n!+jZ1gTo}{XI5mY_{lYwFtR7lifHCfIB%WPO7Hda8El$Xk(nAV-VlIye< zN(XubFM`~Omf|rp3aOdRqh>6lzqdCWZUN)oJKhV&k8n>oljvv(wFD_mCh`qeNtOOe z!G-7XvyQjnaaZJCS!3X5XeE+T0h8-3g;rVDlO~@T2?Xe$-#-#)hWzz5)$D=;LGC)) z+BVeP9SmkNK{hWM`O#=N5bVwbLYYj6J%As9VY-CBxrG&}k9|Lb$GStoOwNT~{nW;f zH^eicAbJd;^dR^v_)jW(pqFxUh^`X(XF?4xdDtoTGCpN?N>1Ywyw&n|*wg&iNb%At z!TY1hX#?puXe>_cl>t9Vq&TE2^i`b9bV5fcL}VScKaf8z%b$=fK8yT!ih?hJ8iifY z`SsYY*E4o~+`_H`Z+I2x?KMCd*I1C+r5C8A7vXYW1?l~&7|YP|hxx0ZHVde6`q1pj zICjK_R#<4mwPmQ&Ix`OM4Jyq}*W{9G$i+*Iqh-t@!QVkW3Kf)OMT7+kltQ_O+U?+G zOyI+JLlb9Sk`Ng*-3W{N>$Vx9?UYnk_yy_G0BssQ7PN5I^b2_xt|IoJroa}U^CE9{-gaW6Qod)*ld5D& zZMQ2urZRZ5SI@+oqLnxy%<59f8`R$#?$eZ!E9Q2-Z?XT<&58Z>FgwWAvg*2|ckc~T z7k}ogYGiO=EZ}l=mQykZ#=~u{xWtk)JmfRjb$WXqQ-1f z(JgG70db%77!09s$bdXG)!RF@Yigl)vUegHtTU6%!?48y;ps~R&P#Axx-J!WiO-_{ zQ@R7ez?u>7=yy0I-N6WpNZK^97y-X9ItdKPw<}7Y$>gt-<&LG^-N!ahs!Fea-`w1x znNdZKkJnpeIe`4teyb_$SCpBW+iCtNVP_ilCI3h$&~fV1 z9*-=C+p3met(xoTNC7xZ@`9iH1^BsEqRBR*=2VD4f~Zai5)2C)hUcS%+PeV1)XG}O zr-$XKo5&$r;8i>#>1;a5{+W_VDaRGfqbWUmyE2Cd5v~8)?ci31!L@u5Y|LjAdEoHC z(2+jEF{igRIaDdylU-;+wuMpX3c-KS>LKV&)M0hgMx?>sxPRlm9ox{~Y*!*40e$O2I22r`0=he-O((u&%gS3w$!)TL zrt^t=^42T|nM{R;l3=$5n_dHzG#&vOH*#6rwUblmKTC!~X>TGN?Wu7z(o#k;;knMq zy_6^?6%41deQg<=yS^geRF!yFbYo|KW3{a%(b!&5UESRC54&a^npV-(-yiYD9Fx)ND?Krz5*3HfUN|tZy(9P1hoiPAJHesJ8BS-GvzyJOtyH0G`a$?u+6Pq`m z*xlLRpGfpWDeG%)K~QG14_^m5E&K01`|Nx7>wlA5ZrQm&k1XuGWy|qQ`}^9v(=llA zHP+bH)_4#7pQ4SF)???s$Ljq`mqR611yYV4Qhwx3>N|dDJAsIXQb)VXuZ6Zj|PLGeFPHr+3 zD1vgC0p%5$QRhW!iVW5;!Y0$$oG_0-`vjDPzXh#1shwkpEI=#0m zwI>~&4u_|s`ro0-as|3sYlTIwXL7Zom7ywzqj|gHD6gz6ckr)u?M|h|v#H%(xx4XP zWGWnKov#^Dryx7OllP-03|Sp~c{aqjJGKR*QA@$ASz%tNX3 zV7J9~HzD(i$~k|hMS=VRpBDOrY0N5g*N~iG8%u!^3g*s|bYr znJ~or*i0D0VS9Es-kv4g&yhd(Ccxi_7b^H{>ESIkC0=INs(coXUl5A=;rT_zk*9z{ zp0?0Bwz6Na0QxDH>d7~VgF%$8(>;XX8&pvtNfq@K6sb}!X&&Jlq_2SCELZ&FL-K@d zMdBZL%vqA}k|*^aJ@~;NFMC?N(fGhS+LupCSMrxhubxF>#k|%BFwHwe+VkQT&Op16 zt+r?~h{0>mQLe+H=PA1&C9EW28Hz3N7J8fw76j_8b={i`K@L6hHE$u24*5)P)fkLv zxd*kJJO7P_834_FC*b8F-9V|m1u}`CxR`@y9cxQoD}e2*@ASfchqdLMWP64vsT-l` z3;UYp)s$18f#f)+(AR&3@|f%`T-pZN@gC5Hge2lElhIatHSD@Zcs-N{N1-!8LwIn2 z9e}t5KM`;Qy?CHA;EO=3E1V((M{4j)0sUkVt|8}S5XgXEFt>t#g5JlTlg%#oZRpK@^pudKCs6>_PUgrt)ynHHsJMaVy(_$RwV$^FyH z($E?)R2j`LmF6YD6AkxZt=#a~n9EKlBOD$C&?th6z$*$3=qSUTAWyy_=)mHB^ zB{r9rAkdLguCqPpLoaPUPrzm|p%f7597)@x=bs{(gD8W(o;pcUh)A@NiVXY_aXY-_ zBL}ooClnsLb?3pmQ4^+IRpsc(^UwXrfdls+&Ap`XX50hSJrUzi@4xSeqI^!~1LONP z!Vs}=?*4lYAG!Cy2b7O1%7Zc=oERSf?Jed}CZ+AtrP+%z@Zbpn-GT>HG!+U~2w|8d z{3VW7K!_u@g($97Gg*&TG7UjUntHTcC%yQPX~)Xa{M3}ruS{*9+O~PtHR+n@?@cA! zV*zgwHLb#4emzQBQ{>_V>Y*o|6^ku^V#1!MXaFkQAjVqxLL{QRvudk3^87?7KK+S4PwLr5*#fYhJXW}rROV23TH^!TD}VA>Y%J?pG{ z7xllVj?ACfzT?E!ttWPDKQYg~+1&v{P!*JCt{)#5WX-^aD1Kx6n5hBKS=0m|m zpT~JWyjUIw$<4zC{alM%SEdols>251XFC5NVB~NxtJkcKaZAi9_wzAsG9M$yfMcS+ zA@uhpL1Xj%>PMLo&_eGk%#B#soW6MA1pMXfgIsaC|gDdFaph)iK`%0z;X z^@NcIvmVD&vqpO8{d_sfM;G3$srM zS4|{h)U_HW&qYmDHFf1R_2ni@jah9=RoB~O#kRrHR!0|1mF@L>Z@E@xDXX-aYs}_O z4X&o;rY6m@!EABr`Dt_ihhy*a53M?vx_)1r%i@?7u~mz3Lhk?QSmBt+wGFJma%Xej zvV*^X`MSiKQ%a9~&=I~!^PzD5XkzQZNih#o_>mRzhLaA5exnc=H`iDz%Ii05a8#Ns z)fTnZ@A9?R)Y{C7wT4Gvi*#Dc>#8d4)pZt=X0kNbhu!w(y4otDuz26{V&M$t&vYI~ z6rJf3?%6L6m~o~(#61_zH0qST1^xXu_BrP_QOe`xi`lo9f5&HmgM4DX4RD((Icpe2 zl~k1>KX`#Z06v;Fi9Vp+=G(0e;31l@okwHrTgXttxYwnXclOfo(f^5Mc*`z-YSsFj z0dJa$@n%bl!_m@e|15pbf9Mi(*tI;e{DWo6J@J9%%qdW2vech4>8Kj-yaIJr>3=QK zW}4HZj_Pt`O(k_6B}k%VEE2mIyM_xpB0mJKhC_0ur6%-SdVTl9!3KXG+n9hn(+*uh zN?eMLl!18!8xy!07{;uWYc=)AtB>*t7NuV=`~4}aLj{VcsZq@Sm<$tcd$+05)dc2= zV08KN#BvVbTBU7b4a(}OfoNL6gXA>s2zr8HDZ(sv5GMG z+*2GWt@#C5*ZesFgp2KJdd6&V;tE#2R4VtBCh7}(U*i`5^Jx^ueCm_X2uX+&E2XWk zcZLm1;VC%A_93|IE2w9jr|me$J0!2v$L>MSeAB1ltCfg&1!({bU^y|OlUeR=wbtteiuo#4MBB182GO zWUG&y<=!n@y#Xj0PJz6hl8L^OT?F|hJ|t+)P0|bW8g$vr6RZyS%$BD)HLpi=Y*O9- zSKGJ1M^)VW&&)oO&6~U-5Kh=60(RwYlYOSTMJwZ#AQp&Z~%ca(9yJ#4@5-*5~z&A*b7^3roc^QTF@=*%)$C z#gJoNhG)C;()fsD;=X{SvlVn<@VLvj42utg;ORCR<8aa9nLQ4Cb|Val&#uo*C~!lT zE(Tlvigq~$TfJ7hUJSzZ49-xiZ=kdRFFWz^SLjR8R}TV9C2M)xKOPgomta1JuF7}l zeo9y6_hPfUs;=y#T{U!ZF7K-5qNosbRn*ra*k^&LuY5Y*S8a}}9@Mt>jwh0W!k>c1v}{g)O; z)X$9z`$s?&CV%~MPmmJzJDv> zCO8Cx1nv}-8{zBjM#&?ljP!IYTO{Y|F$Ln?L-a>=rl3p|lt~bFgNH|Q`4ggbP%~J5jW&Be#VUIHo!y#l* z$)cr&{H=>jl!>V`&ZorYtn1I3G1F9cv!PL`^Nv|Q{#r+BY;5?Ptwd$S6f?T{6rQCVE5|0^nqyZ!$OAMG{hwCGvLqnoNLX(mY zedMMDwtgP>NqFfOc073PE!2meP3)ibZAH+WWh<`z33lW(e-L$c`?X8Nuh`nJ)EQ`| z5;ZN;GZ6%#q|IRQQwG^NutA?)sJ7YLptVSli^ms6oqu*HAC@yp-qw?&t~ zhr6XWdAB_ma`j#jhKBt3!^x>7+Ra*=@;1|HQk+i=TXug86caXG!f6aAaJJP-l2!vaKe;!Z*J|2`A40j>!F6fF7Yg`;Q z0QLtb&xXPLv%0eE*bx19cXxCY5X%$(@D+kpJ@n_%BT#Nzv?`4Qvg` zfP9}086=Md1FtJ?V{S{X50{zif)HoX<>NfRzYAz8NIqLc>RBkMxGpS${o;_uLki8)vjS^hCtg18jOmO?_+u%1kj8uBupL%)po;a;Bl6W}etZ*Xl@(?WsI zp>K1#sS9+z2!Bo91I?cmpzo1-4&)61tMIsnEPXOCz-_~I2j6hP zo0p4nf_c+lW1jm9vhbsT@5aahp^kXmw@zsDpr~&>N0CiBuvLUBF2uz4GP5l|?8`c3F zsXsf~Czw|Ht3p6mZ46pY%#H5^~MIglKu+q&_K!n%UCr0M>J^wECmz- zvH=bitO$8}8C^jn@)XLdB1UQ>88}pJKFuc*g^#9*Bm(EoaD4t}rTZ+r$XiplYvz+A zO(x(rk|FRL5jGG>6N)kuNdulj+2{sx1Ilj4Jxc>!NxB659Aog$Ne+35SZNX70l5?Q z`4Xw2cav1WYO0(1E4Jb`2_3i|y9Df~6QJer3~cya6~BP7yBX!+yh0kT0Pf5+06hG} zSU8__(jBnt?Fd7#TlQAa^Srxp@DQIL@o~XG=CLKDi0wih8PPXy$N1C+xQW!_xlJ3B ziJQv_Tc@Gk7Yle4<5mFwr0_kJmWR)f9QGQ*uYo^r3%pI-3Eq4x{4H?aHrA2~O+9JT z`l0VdvRG3FUwjDlUWs<~Q&OnG7>Z*P7a%SXyCt~Zj5^3d@+eut0pA|xvTfj@W(VdH zpyze~XeqWB;4PuwX6Vk^U2$2sDYX39ym;1TtH&e*?1eGAZvPO|bV-0QO&_4kRH1N~Z~+b0eNiIdPYV zzYno{bs7-!;q!pADx83x{BO7V{~~#vT*ikq(Z*>7ZJ?cWm>!@m*&5Zd5m+kJo4FOZ02??fL=zt@^|I z$MjF?pVObyUkuq5a#zUN(9F=1(Av<}&?AOqLyn=&&}Qg2+-$hV@Sx$C;aS5ghSv?3 z!^~l}utQ;|!d}Et@Nb4!g&z(-7k)APYD8^BYs5nlPewc!aW3MWND>(vnI2gjX^U)( z?1~(XoQOOe`B>zM$mb(pjl2{!8Z{BUG5SdKJ25L_?u$7Zb8=4V9P=F8oHyru5Ze)Z zIQEU$D{_0UYL7n-pQ1;DaTSy zrJSAbpTBqh!38l3PA_;qbu{(0)VEWwEj+sL_`+uvo?Ccf;iZLFrBEqe%9O0q3aM7Q zlBP}TO?xTr!lL3umyN_2YfLrfq?^(Q($A$|Ouw2@ld(NxIO9OZJsA&Xd?(|njAt`m z%=nLtH#4qeYBO6i4`kkx`FiH%#fjK3T)4Pmal_&Vvy!v=vc|LaXT6(sExRGRExSK^ zSN4JI`?4R&ma|W0pUHkX`?c)1bDDEHbNX|3N8&2O0BHD9yzS;j5e zEJrQJEzejVx1O**XML%lwxG43uQ0hVz0h3PQ+TTIY~d?~uNS^kR8cfh^gz+$MW>6N zFM74;QZXy8E#6q%QQTKNUVLyVTl&z_$CsX1`drEBWp$;Gm6^--mK`d4r0jUvnX>a` zZy%f&(oMuXt>QyyEgo{mSH(`&Zt#^61KwD_>ao zT19=uM8#_r?^bFn6Dv1Xo~?Yl@|rEiw#Zg!tFkrNI&I^&C+*B0WiPeY*$>%|*snV3 z9CtY$bR2V>a?W#_oPEx{&O^>eoX4GKoad|Bs`{(Tt8cD;u_m=sGg|erEN{brE&#bpv&`)*Y^UtnSL1 zk~Ot!TG#Zg*}LY+FIMXxpjN%cOF0qyFGVzWpzE*UDN$)PifCR-Z1Y2+hev* zY?rscyd!Hz-HyXMF7}e%^E+xN$-V}OM@=g6WoxSPO?s>ayyL)#J z?|yRkJ9`{^*6wNE)3K*_&trRD+?%tvaPNw}NA_OZ7qf5CzQTRa?K`*c;=ZdlN8QZ# z9%8KlXIb^*U6Zeh6^JbCI>87)Zi!03eiZ(gY#!zlpb~$p@T=f>Re-EgafY1hR9u7S z;u}?5OQP_8fRr2nUAqwq0wPpFs|Zy#NVUhp(GJ= z0)>Xp9k6CD%EFT%jPVK{K{9dXp@K(JNfY27MGCcbc3=P4fVaEHFIml&rBY*$N3yvF zdVM2O{eW+~$L*IYhx|Rhfk7#&$M5eSEM2ms+w1Qc>d1Hdb}rf8?_bg($g`DP4W90y zUe|ynztCJ#*4SWcDO2L})C85cdbQCrFzEI5NrHSfVdH?eqhm~J9P9VgdImf@fr^-b z5Poqbgt$&rV~=-Gs`B;ur47C=|A=eABO#*K>-O{wdOD?{zE018sR@F)C`aOLL zah*b7l4b<6ge@IBd~RH6 z(7j|`Roy425IfpmKN-Ub-d@s8da%kT;r`l8EV!eQ(9(N|2ceC)K+y}@5nR;+_u-?e z9^w}Cm1GEE58?*MAkwo0A3yjGl2XjbmVmQYPz;d{l8;`JEr3=Z=s6^A~B5EYrxF_V_>dL^qRVH0bOyqg;bMgZD0B_#?D-Pt(!C8(boTiWm z8{q6*oEK=uy#RVGwNNW9K#Q=F7s)SZAuXcCbSa)}cGG3#-)Jcct9*mu{y!XfNGK`>2oh_F z_~Q|7BWb0#a@sb=zhF2cmQXmPtZH)LA3T- z@)vq1y^H>XxWE1)Jw(5Rmh(&Er}vBIC9`VBG)k26Le#i=ddq>s^W(WAKM+(o}b#_4zIyrvHTdxu4Ky=}+l%^q=V&oF#ge{)|44Gag=`|B5ff|AM{*Pq>->8}9o4oxVc0 zkXG_G)?ZH0bM#mAJXY|w(*Gd;kN$?fO8=9-Mt@6AlYgSG)8Ekx*p2@N-ZXfV{()Yk zZ_&5uAL%c(#SS*WU@hky%ph+y5&1LiOb^7^i0ZU~InZ(lAB4%XiEQ4jT z#kfb!#vAFm%*66oK3l@f%)+d!0C%oMte7ojC3ug&l$GJcu;pw8TgfU|C9^R*Hc&co zZ(Gf3*eX_w^Wp2*8n%|LWA!*ss)235n}JPiBin?#-xkc?jy!mz~Ry_V22a?`}C*gZ3i$?Ra`%x?@*H`Z7>R)#Ap6N3n0X!~x3Dj>!&n)5libYi zCC{+?*jL#7>>t?!?5peu`x<+YeVskT9%hfQZ?H$%H`!zCTkI(NHv10yE_mru=K{jd_)vBX{9z2zIQDo+q!7-;iIiC)xMearOiD6nmPTU_WFh*^k&M?b@cg zI(=owfM?hfGSug_I4hk>Xe(Ajvl?2}u#ksli`}7ISBh)ov#Zx?zRD8yx>5~QK9$yx z%AGFvfUhs4(%0?l^Xv$>yS)SMp`Bg5p3yLSr_b+lW8&u5JKQc%AsFzv{CcOj;=IgO ztIFG^%4%23w5w&NhE3ZJH6wu&L9FJBLBRUD)R7+E$db3fq}21%lFSDJ)Xri`464CEaQfx|yw(O1&${5S3L* zLAIr8Xi>ugHB{Nz)hekJ*XT-tuBGOyT&B=h+SE|xQ&|w=QjO$NyOMiG=P>uQHu_Gb zmOLWhOwfl^rZ!bbyIPoCWo}o6v=@bWrWvVn2eR5iJZkx#S$#;zZ?+Z*I?PRnS)EIDLo>2DRgJ1t4V?j5RT-UCkwdd&8&b_K zyn|I}gpMQhN5@e+Op$tBtfX5lY74P|yV}i%L^mH&y7`Er&d7{9hLP!RKB9Ekn6Z6~{wYZL7`i z^>(|$y0&#~Ljw$;y#fvG-nLyqyegt~WVugz15W2@BbsK%-nUvg0zs70^v& z5IXP-Y9|+{VkMxVE^a76C~O5x=knlJ+rfX_JjFd-x?9vg;=(buc6xhzxpa{;9)f4- z#E;(N??GTt9EO7N;g_d#<_6C+OU0QWPACL_0yN4qTOkys_++F-&bSf5Xj(nhhj31+ z8v&~A;y*&a?%9^J79b^Z#%pjoE^`R?8vMeGAA>g_XOwrgNZufkA~-HRWC;za}&u(nEL7m=dVa_XJ@r;o=e-bG-uvlJF1 zQV(|{(gGE%_3=yJv}(TDs`-LcGx!49#LV&`U=XId5y2}Ul))D$MCTK&s2|Cpd?}C% zs=a~#aO)Zre(eDP`r@90yJ<*)9p@aFc#imw7g}7a2Lg?6)y!$v0E{( zX_eRpR6E3phNjgYnyvm&u=+#O>d$ghf}!H61Ug->p~CO*LWcRz2!0HT_W>3aRLew}^3ouQngKsZm1gehD(Y7l%CjB^%roVTD;xC>O_F9<~m0uyEQ4ecBdWe9|q z!4b6#jw)p+7%xN6@iGLRQied4G6bP0gJZ&8W}7m`m~F}|#B38|kJXG%v!Mqg6yqO4 zF-9R2;{`%7sYAHT04oUoJrP2C1s@FWf9G2P5u{~q`J)XX8N+5;_ zQS?$}kTsht&06QsfKQRfCML#KvrUY&R&|U-sK{xtDso!Q%9v`l73p_+`}l3epvUd& z>l9opmI8xk&<_{p_jKyvzcGXfv8-q=VxY5$0o`o1E9NOMD|6Ta^HPIo&{*&9Fo;fg!oW zgXa)4M2enfy#J;YuH5vQ3krlC5Gwi?sB?^hf)X);gI&10tif>oIs9!|&O*jIexmvdRhPU57dlMv^xQ_GYRNV2Atp5P!8 zlO&U-W@n2et$vC`tzRwcH*9W}3sdB*mi8`bqN!PC8Lp>8u~gx98#{0yi%eQ%f=@0S zgO2ugTb@i!vee#{Co_{V&6t)aYfMt-6Pox0VzbL}cB#GHHp$}cw#f{QU1s*iQAv(4 z0F>%DQ%^Th`$y zFgesNO-K_cYtpRCfQ8mKx7Vk*8d{o-Eom*1T(O}UX(`+;swjDKh)FisbB|#GURXU8 zmqwcr&BbVQ$*iMGrfvu#hvekR29w04je=TQ(g704ThZRaN!lGk+Az~GLlm()Z8>Sv z4JX_*yCFp=Txc#tutW8B$vI(k@k$lOCMmo^WGMwg2BbvQ8eI;hh{#XKE~g_GGEb`( zoGFU8f1~Y*$OxiwqKZT3=d#R#KFuz?$b%X94Q(nPx?&w<(Uh;a5Hz<)Q zX^4*#@$sff5^Ha2o{WvP%hY9)=j8G(ho)tljOITv_>pNM>OzxI-#p3tA?hr zmSc@J$tg#n`9&Jhc!KY&ILWL_7pR+GKoau6##s$|AJ$L@1k( zn(niGS4T`6q=+WA$bwFDSVtC_ZM(O*OivXlf);*@ab4#ESW5%30&7= z*aHe&H%~iyjjJS2UTVruD$kQk{x?#za5u=8p^8XihLkT=bKd~du9}#rHdezIHDd&X z`^C^yLTN%gEL;jFmMABIObfr7A;=~ph)oW+=XxgcjgnM80iI>E$)tRRpR7l3P^l%k zojaF`_03OcC7qP=gf>$*uf@h)ZWz2b%7+BTs&-kA+MeBS(Y0usR`Wu6Ev^Wp31t*Z%cQY6 zUn$OTAs|m)87NIyU#+foKGXTA%7H4b zfd9znR;-ef?9KHl7+j_Dmi$RGjYq$&oR!*;Qa>xzHY+udH<;f?bJ$ICX>KqSl)%1noUuiH)kVyT0VN7qEMA-G7N(b zZ~da>|7}gW`g#rQ|I&)Ny}2JNHx|n))n?iR zt6+izrQ2hgf*u~1FBhYi*M36$YOtg6aWam7lbW4HeRL^WbM36j<|T49O>X?a>UJPYJhZd z8jg544M(~-4M)0#Tn=D8LN1PZgaaUd>?YIQ25=fpq$_q1?2>{f_CLJ zzuUx>;J05vIr$e9l#?Go&Xo$k+ZB`(OeiQPxWjZTTugCgeG1MK&^U4Tgt4r}mMe#P zWKDYgXkb9k<6|st2G2BLYDw?HaHrh<^-q!z+i~J7B5693!!If#YPF@I`T9(4a)>TW zjatiW`a*3ETc{IJ5w=sYr=w1XpEjJt9(N80 zn)!97V={|hKNU)p2;yi-nOw}HPK55oZpVrP?nXh01o5$#h&ooTH*2#PK1>~z^Aw%B XP1fFtvE1>5t`jFbIJjcyDERvy)saR} literal 0 HcmV?d00001 diff --git a/samples/Archeoids.Browser/wwwroot/fonts/Barlow-SemiBold.ttf b/samples/Archeoids.Browser/wwwroot/fonts/Barlow-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7c974a4aa67c689a4b2a844b48f624cb4eeaa6bd GIT binary patch literal 108348 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�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 + + + + + Archeoids | Archevolt + WebGPU + + + + + +
+ + Archeoids requires a browser with WebGPU support. + + +
Loading Archeoids…
+
+

Click the game or press Tab to focus. A/D or Left/Right: turn. + W or Up: thrust. Space: fire. P: pause or resume. R: restart.

+ + diff --git a/samples/Archeoids.Browser/wwwroot/main.js b/samples/Archeoids.Browser/wwwroot/main.js new file mode 100644 index 0000000..6982e00 --- /dev/null +++ b/samples/Archeoids.Browser/wwwroot/main.js @@ -0,0 +1,68 @@ +import { createRenderer } from "./renderer.js"; + +const canvas = document.querySelector("#game"); +const status = document.querySelector("#status"); +let failed = false; +let animation; + +function fail(error) { + if (failed) return; + failed = true; + cancelAnimationFrame(animation); + console.error(error); + status.textContent = `Archeoids could not continue. ${error.message || error}`; + status.hidden = false; +} + +try { + const render = await createRenderer(canvas, document.querySelector("#hud"), fail); + const { dotnet } = await import("./_framework/dotnet.js"); + const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet.create(); + setModuleImports("archeoids", { render }); + const config = getConfig(); + const exports = await getAssemblyExports(config.mainAssemblyName); + await runMain(); + const game = exports.Archeoids.Program; + const keys = new Set(); + const gameKeys = new Set(["KeyA", "KeyD", "ArrowLeft", "ArrowRight", "KeyW", "ArrowUp", "Space", "KeyP", "KeyR"]); + let lastTime; + + function resetInput() { + keys.clear(); + lastTime = undefined; + game.ResetClock(); + } + canvas.addEventListener("pointerdown", () => canvas.focus({ preventScroll: true })); + canvas.addEventListener("keydown", event => { + if (failed || !gameKeys.has(event.code) || event.ctrlKey || event.metaKey || event.altKey) return; + event.preventDefault(); + keys.add(event.code); + if (event.repeat) return; + if (event.code === "KeyP") { game.TogglePause(); lastTime = undefined; } + if (event.code === "KeyR") { game.Restart(); lastTime = undefined; } + }); + window.addEventListener("keyup", event => { keys.delete(event.code); }); + canvas.addEventListener("blur", resetInput); + canvas.addEventListener("focus", resetInput); + window.addEventListener("blur", resetInput); + window.addEventListener("focus", resetInput); + document.addEventListener("visibilitychange", resetInput); + + function frame(time) { + if (failed) return; + try { + const active = document.activeElement === canvas && document.hasFocus() && !document.hidden; + const delta = active && lastTime !== undefined ? (time - lastTime) / 1000 : 0; + lastTime = active ? time : undefined; + const left = keys.has("KeyA") || keys.has("ArrowLeft"); + const right = keys.has("KeyD") || keys.has("ArrowRight"); + game.Frame(delta, Number(right) - Number(left), keys.has("KeyW") || keys.has("ArrowUp"), keys.has("Space")); + animation = requestAnimationFrame(frame); + } catch (error) { fail(error); } + } + if (!failed) { + status.hidden = true; + canvas.focus({ preventScroll: true }); + animation = requestAnimationFrame(frame); + } +} catch (error) { fail(error); } diff --git a/samples/Archeoids.Browser/wwwroot/renderer.js b/samples/Archeoids.Browser/wwwroot/renderer.js new file mode 100644 index 0000000..aa8697b --- /dev/null +++ b/samples/Archeoids.Browser/wwwroot/renderer.js @@ -0,0 +1,140 @@ +const width = 1280; +const height = 800; +const dim = "#4f6e7d"; +const white = "#dbeeed"; +const amber = "#ffa642"; +const cyan = "#66f2e6"; + +export async function createRenderer(canvas, overlay, fail) { + if (!navigator.gpu) + throw new Error("WebGPU is unavailable. Open this game in a WebGPU-capable browser over HTTPS or localhost."); + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) + throw new Error("No WebGPU adapter is available. Check your browser's hardware acceleration and graphics driver."); + const device = await adapter.requestDevice(); + device.lost.then(info => fail(new Error(`The WebGPU device was lost (${info.reason}). Reload to try again.`))); + device.addEventListener("uncapturederror", event => fail(event.error)); + + const context = canvas.getContext("webgpu"); + const text = overlay.getContext("2d"); + if (!context || !text) throw new Error("The browser could not create the game canvases."); + const format = navigator.gpu.getPreferredCanvasFormat(); + context.configure({ device, format, alphaMode: "opaque" }); + + const shader = device.createShaderModule({ code: ` + struct VertexOutput { + @builtin(position) position: vec4f, + @location(0) color: vec4f, + } + @vertex fn vertex(@location(0) position: vec2f, @location(1) color: vec4f) -> VertexOutput { + var result: VertexOutput; + result.position = vec4f(position.x / 640.0 - 1.0, 1.0 - position.y / 400.0, 0.0, 1.0); + result.color = color; + return result; + } + @fragment fn fragment(input: VertexOutput) -> @location(0) vec4f { + return input.color; + } + ` }); + const pipeline = await device.createRenderPipelineAsync({ + layout: "auto", + vertex: { + module: shader, entryPoint: "vertex", + buffers: [{ arrayStride: 24, attributes: [ + { shaderLocation: 0, offset: 0, format: "float32x2" }, + { shaderLocation: 1, offset: 8, format: "float32x4" }, + ] }], + }, + fragment: { + module: shader, entryPoint: "fragment", + targets: [{ format, blend: { + color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" }, + alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }, + } }], + }, + primitive: { topology: "triangle-list" }, + }); + + try { + const fonts = await Promise.all([ + document.fonts.load('400 16px "Barlow"'), + document.fonts.load('600 32px "Barlow"'), + ]); + if (fonts.some(faces => faces.length === 0)) throw new Error("Font faces are missing."); + } catch (cause) { + throw new Error("The bundled HUD font could not be loaded. Reload to try again.", { cause }); + } + + let staging = new Uint8Array(0); + let vertexBuffer; + function label(value, x, y, size, color, weight = 400, align = "left") { + text.font = `${weight} ${size}px Barlow`; + text.fillStyle = color; + const measured = text.measureText(value).width; + text.fillText(value, x - (align === "center" ? measured / 2 : align === "right" ? measured : 0), y); + } + + return function render(vertices, score, wave, lives, entities, milliseconds, paused) { + // The MemoryView expires when this synchronous import returns. Copy only the active + // bytes into reusable storage; never retain a view into a movable WASM heap. + const byteLength = vertices.length; + if (byteLength > staging.length) { + const capacity = 2 ** Math.ceil(Math.log2(Math.max(byteLength, 65536))); + staging = new Uint8Array(capacity); + vertexBuffer?.destroy(); + vertexBuffer = device.createBuffer({ size: capacity, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }); + } + vertices.copyTo(staging); + device.queue.writeBuffer(vertexBuffer, 0, staging, 0, byteLength); + + // Read DPR each frame so moving between monitors and browser zoom need no special listener. + const bounds = canvas.getBoundingClientRect(); + const dpr = window.devicePixelRatio || 1; + const limit = device.limits.maxTextureDimension2D; + const pixelScale = Math.min(dpr, limit / Math.max(bounds.width, 1), limit / Math.max(bounds.height, 1)); + const w = Math.max(1, Math.floor(bounds.width * pixelScale)); + const h = Math.max(1, Math.floor(bounds.height * pixelScale)); + if (canvas.width !== w || canvas.height !== h) { + canvas.width = overlay.width = w; + canvas.height = overlay.height = h; + } + const scale = Math.min(w / width, h / height); + const vw = Math.max(1, Math.floor(width * scale)); + const vh = Math.max(1, Math.floor(height * scale)); + const x = Math.floor((w - vw) / 2); + const y = Math.floor((h - vh) / 2); + const encoder = device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ colorAttachments: [{ + view: context.getCurrentTexture().createView(), + clearValue: { r: 0.018, g: 0.032, b: 0.049, a: 1 }, + loadOp: "clear", storeOp: "store", + }] }); + pass.setPipeline(pipeline); + pass.setViewport(x, y, vw, vh, 0, 1); + pass.setVertexBuffer(0, vertexBuffer); + pass.draw(byteLength / 24); + pass.end(); + device.queue.submit([encoder.finish()]); + + text.resetTransform(); + text.clearRect(0, 0, w, h); + text.setTransform(vw / width, 0, 0, vh / height, x, y); + text.textBaseline = "top"; + label("ARCHEOIDS", 34, 18, 42, amber, 600); + label("ARCHEVOLT / WEBGPU", 36, 70, 15, dim); + label("SCORE", 590, 25, 14, dim); + label(String(score).padStart(6, "0"), 590, 46, 32, white, 600); + label("SECTOR", 830, 25, 14, dim); + label(String(Math.max(wave, 1)).padStart(2, "0"), 830, 46, 32, white, 600); + label("HULL", 1070, 25, 14, dim); + label("A/D TURN W THRUST SPACE FIRE P PAUSE R RESTART", 36, 764, 15, dim); + label(`${entities} ENTITIES / ${milliseconds.toFixed(2)} MS`, 1246, 764, 15, cyan, 400, "right"); + if (paused || lives === 0) { + label(paused ? "PAUSED" : "SIGNAL LOST", 640, 343, 64, paused ? white : amber, 600, "center"); + label(paused ? "PRESS P TO RESUME" : "PRESS R TO LAUNCH AGAIN", 640, 430, 21, dim, 400, "center"); + } else if (wave === 0) { + label("CLEAR THE SECTOR", 640, 245, 30, white, 600, "center"); + label("THRUST. DRIFT. SURVIVE.", 640, 292, 16, dim, 400, "center"); + } + }; +} diff --git a/samples/Archeoids.Browser/wwwroot/style.css b/samples/Archeoids.Browser/wwwroot/style.css new file mode 100644 index 0000000..95fb951 --- /dev/null +++ b/samples/Archeoids.Browser/wwwroot/style.css @@ -0,0 +1,20 @@ +@font-face { + font-family: Barlow; + src: url("./fonts/Barlow-Regular.ttf") format("truetype"); + font-weight: 400; +} +@font-face { + font-family: Barlow; + src: url("./fonts/Barlow-SemiBold.ttf") format("truetype"); + font-weight: 600; +} +:root { color-scheme: dark; background: #05080c; color: #c1d3d6; font-family: Barlow, sans-serif; } +* { box-sizing: border-box; } +body { margin: 0; } +main { position: relative; width: 100%; height: calc(100dvh - 52px); min-height: 240px; } +canvas { position: absolute; width: 100%; height: 100%; display: block; } +#game:focus-visible { outline: 2px solid #66f2e6; outline-offset: -2px; } +#hud { pointer-events: none; } +#status { position: absolute; inset: 0; display: grid; place-content: center; padding: 32px; background: #05080cf5; text-align: center; } +#status[hidden] { display: none; } +#controls { margin: 0; min-height: 52px; padding: 12px 20px; text-align: center; font-size: 15px; } diff --git a/samples/Archeoids/FrameGeometry.cs b/samples/Archeoids/FrameGeometry.cs new file mode 100644 index 0000000..a915743 --- /dev/null +++ b/samples/Archeoids/FrameGeometry.cs @@ -0,0 +1,131 @@ +using System.Numerics; +using System.Runtime.InteropServices; + +namespace Archeoids; + +// Shared by both hosts. Vertices are x, y, r, g, b, a in logical canvas coordinates. +internal sealed class FrameGeometry +{ + public const float CanvasHeight = 800; + private static readonly Vector2 PlayfieldOffset = new(0, 104); + private static readonly Vector4 Dim = new(0.31f, 0.43f, 0.49f, 1); + private readonly List _vertices = new(160_000); + private readonly (Vector2 Position, float Brightness)[] _stars; + public Span Vertices => CollectionsMarshal.AsSpan(_vertices); + + public FrameGeometry() + { + var random = new Random(1982); + _stars = Enumerable.Range(0, 180).Select(_ => + (new Vector2(random.NextSingle() * Arena.Width, random.NextSingle() * CanvasHeight), + random.NextSingle() * 0.5f + 0.15f)).ToArray(); + } + + public void Build(RenderFrame frame, Session state, double seconds, bool paused) + { + _vertices.Clear(); + + for (int x = 0; x <= Arena.Width; x += 80) + Line(new(x, 100), new(x, 744), 0.6f, new(0.16f, 0.27f, 0.32f, 0.13f)); + for (int y = 104; y < 744; y += 80) + Line(new(0, y), new(Arena.Width, y), 0.6f, new(0.16f, 0.27f, 0.32f, 0.13f)); + foreach (var star in _stars) + { + float flicker = 0.8f + 0.2f * MathF.Sin((float)seconds * 0.7f + star.Position.X); + Rect(star.Position.X, star.Position.Y, 1.4f, 1.4f, new(0.6f, 0.8f, 0.9f, star.Brightness * flicker)); + } + + foreach (var sprite in frame.Sprites) + { + DrawSprite(sprite, PlayfieldOffset); + float r = sprite.Appearance.Radius + 4; + // Draw across seams as well as colliding across them. + float dx = sprite.Position.X < r ? Arena.Width : sprite.Position.X > Arena.Width - r ? -Arena.Width : 0; + float dy = sprite.Position.Y < r ? Arena.Height : sprite.Position.Y > Arena.Height - r ? -Arena.Height : 0; + if (dx != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(dx, 0)); + if (dy != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(0, dy)); + if (dx != 0 && dy != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(dx, dy)); + } + + Rect(0, 0, Arena.Width, 101, new(0.025f, 0.045f, 0.062f, 0.97f)); + Rect(0, 744, Arena.Width, 56, new(0.025f, 0.045f, 0.062f, 0.97f)); + Line(new(32, 100), new(1248, 100), 1, new(0.3f, 0.46f, 0.5f, 0.55f)); + Line(new(32, 744), new(1248, 744), 1, new(0.3f, 0.46f, 0.5f, 0.55f)); + + for (int i = 0; i < 3; i++) + DrawSprite(new(new(1082 + i * 45, 65), -MathF.PI / 2, + new(Shape.Ship, 11, 0, i < state.Lives ? Factory.Cyan : Dim), i < state.Lives ? 1 : 0.2f), Vector2.Zero); + + if (paused || state.GameOver) + Rect(0, 101, Arena.Width, 643, new(0.018f, 0.032f, 0.049f, 0.82f)); + } + + private void DrawSprite(Sprite sprite, Vector2 offset) + { + Vector2 p = sprite.Position + offset; + Appearance a = sprite.Appearance; + Vector4 color = a.Color with { W = a.Color.W * sprite.Opacity }; + Vector2 forward = Arena.Direction(sprite.Angle); + Vector2 side = new(-forward.Y, forward.X); + if (a.Shape == Shape.Ship) + { + Vector2 tip = p + forward * a.Radius; + Vector2 left = p - forward * a.Radius * 0.8f + side * a.Radius * 0.72f; + Vector2 right = p - forward * a.Radius * 0.8f - side * a.Radius * 0.72f; + Vector2 tail = p - forward * a.Radius * 0.4f; + Stroke(tip, left, color); Stroke(left, tail, color); + Stroke(tail, right, color); Stroke(right, tip, color); + } + else if (a.Shape == Shape.Rock) + { + uint seed = a.Seed; + Span points = stackalloc Vector2[11]; + for (int i = 0; i < points.Length; i++) + { + seed = seed * 1664525 + 1013904223; + float radius = a.Radius * (0.76f + (seed >> 24) / 255f * 0.24f); + points[i] = p + Arena.Direction(sprite.Angle + i * MathF.Tau / points.Length) * radius; + } + for (int i = 0; i < points.Length; i++) Stroke(points[i], points[(i + 1) % points.Length], color); + } + else if (a.Shape == Shape.Bullet) Stroke(p - forward * a.Radius, p + forward * a.Radius, color, 2); + else + { + Rect(p.X - a.Radius * 2, p.Y - a.Radius * 2, a.Radius * 4, a.Radius * 4, + color with { W = color.W * 0.09f }); + Rect(p.X - a.Radius / 2, p.Y - a.Radius / 2, a.Radius, a.Radius, color); + } + } + + private void Stroke(Vector2 a, Vector2 b, Vector4 color, float width = 1.25f) + { + Line(a, b, width * 4, color with { W = color.W * 0.075f }); + Line(a, b, width, color); + } + + private void Line(Vector2 a, Vector2 b, float width, Vector4 color) + { + Vector2 delta = b - a; + if (delta.LengthSquared() < 0.0001f) return; + Vector2 n = Vector2.Normalize(new Vector2(-delta.Y, delta.X)) * (width / 2); + Triangle(a + n, b + n, b - n, color); + Triangle(a + n, b - n, a - n, color); + } + + public void Rect(float x, float y, float width, float height, Vector4 color) + { + Triangle(new(x, y), new(x + width, y), new(x + width, y + height), color); + Triangle(new(x, y), new(x + width, y + height), new(x, y + height), color); + } + + private void Triangle(Vector2 a, Vector2 b, Vector2 c, Vector4 color) + { + Vertex(a, color); Vertex(b, color); Vertex(c, color); + } + + private void Vertex(Vector2 point, Vector4 color) + { + _vertices.Add(point.X); _vertices.Add(point.Y); + _vertices.Add(color.X); _vertices.Add(color.Y); _vertices.Add(color.Z); _vertices.Add(color.W); + } +} diff --git a/samples/Archeoids/README.md b/samples/Archeoids/README.md index 4424b06..60b7330 100644 --- a/samples/Archeoids/README.md +++ b/samples/Archeoids/README.md @@ -1,10 +1,10 @@ # Archeoids -A small Asteroids game built with Archevolt and [Silk.NET](https://dotnet.github.io/Silk.NET/). Fly through wrapping sectors, split rocks, and survive with three lives. Ships, rocks, bullets, and particles are ECS entities. All shapes and text are generated in code. +A small Asteroids game built with Archevolt. Fly through wrapping sectors, split rocks, and survive with three lives. Ships, rocks, bullets, and particles are ECS entities. The desktop host uses [Silk.NET](https://dotnet.github.io/Silk.NET/) and OpenGL. The browser host uses plain .NET WebAssembly and WebGPU, with browser-rendered text. ![Archeoids gameplay with a cyan ship, drifting asteroids, and a score and lives HUD.](archeoids.png) -## Run +## Run on desktop From the repository root: @@ -25,18 +25,45 @@ Use the .NET SDK pinned in `global.json`. The desktop game needs a graphical ses The HUD shows score, sector, remaining lives, visible entity count, and smoothed simulation time per tick. A new ship flashes during its temporary invulnerability. Clear every rock to start the next sector. +## Run in a browser + +From the repository root, using the SDK selected by `global.json`: + +```powershell +dotnet run --project samples/Archeoids.Browser -c Release +``` + +Open the HTTP localhost URL printed by the development host. Use a browser with WebGPU enabled and a compatible graphics adapter. WebGPU requires HTTPS or localhost. If WebGPU or the adapter is unavailable, the page displays an error. + +The browser project uses `Microsoft.NET.Sdk.WebAssembly` with `browser-wasm`. It explicitly disables the samples' inherited `PublishAot` setting, browser `RunAOTCompilation`, and threads. The SDK restores the managed runtime packs through NuGet. This interpreter configuration does not require a separate workload, JavaScript packages, or a bundler. If you opt into WebAssembly AOT or native runtime relinking, install the workload matching the selected SDK first: + +```powershell +dotnet workload install wasm-tools +``` + +Browser AOT uses `RunAOTCompilation`; desktop `PublishAot` is a different setting. Neither host changes Archevolt's public API. + +## Publish the browser game + +```powershell +dotnet publish samples/Archeoids.Browser -c Release -o artifacts/archeoids-browser +``` + ## Read the sample - [GameModel.cs](GameModel.cs) defines unmanaged components, spawn bundles, resources, messages, and the wrapping arena. - [GameSystems.cs](GameSystems.cs) contains generated queries, systems, and explicit schedule dependencies. Movement uses partitionable `[Each]`; this small sample runs serially. - [Game.cs](Game.cs) owns the world and schedules. `Step` advances one fixed 1/120-second tick. `Capture` extracts a reusable list of sprites after simulation commands flush. - [Program.cs](Program.cs) connects Silk.NET's window and keyboard to the fixed-step loop. -- [VectorRenderer.cs](VectorRenderer.cs) batches procedural shapes and a tiny bitmap font into OpenGL triangles. It reads the extracted frame and never accesses the world. +- [FrameGeometry.cs](FrameGeometry.cs) builds the reusable coloured triangle batch: stars, sprites, translucent effects, HUD panels, hull icons, and pause/game-over shading. It reads the extracted frame and never accesses the world. +- [VectorRenderer.cs](VectorRenderer.cs) uploads that batch to OpenGL and appends the desktop bitmap text. +- [Archeoids.Browser.csproj](../Archeoids.Browser/Archeoids.Browser.csproj) links the same `Game.cs`, `GameModel.cs`, `GameSystems.cs`, and `FrameGeometry.cs` source files. There is one simulation implementation. Silk.NET and desktop verification stay outside the browser dependency graph. +- The browser [Program.cs](../Archeoids.Browser/Program.cs) receives animation frames through `[JSExport]`, runs the fixed-step accumulator, and sends a `Span` through `[JSImport]`. The [page host](../Archeoids.Browser/wwwroot/main.js) owns keyboard and focus events. The [renderer](../Archeoids.Browser/wwwroot/renderer.js) copies the active binary batch into reusable staging storage and uploads it to a reusable vertex buffer. One WGSL pipeline draws the triangles with alpha blending, followed by the Canvas 2D HUD. There is one call into C# and one render call back to JavaScript per frame. - [Verification.cs](Verification.cs) exercises the real simulation and captures the OpenGL framebuffer during a smoke run. Structural changes use `Commands`. A hit marks its rock immediately before queuing despawns, preventing overlapping bullets from destroying it twice. Three independent readers consume `RockDestroyed` to split rocks, award points, and create particles. Adding and removing `Invulnerable` changes whether a ship matches the damage query. Expiration runs before collision detection, and both collisions and drawing handle screen seams. -The simulation uses a seeded random resource and a fixed timestep. Restart replaces the world and its schedules, clearing entities and message cursors. The playfield has its own area below the HUD, and resizing preserves its aspect ratio. Collision detection uses simple bullet-versus-rock loops; this sample is intended for a small arena. +The simulation uses a seeded random resource and a fixed timestep. Both hosts cap incoming elapsed time at 100 ms and advance at 120 ticks per second. Restart replaces the world and its schedules, clearing entities and message cursors. The playfield has its own area below the HUD, and resizing preserves its aspect ratio. Collision detection uses simple bullet-versus-rock loops; this sample is intended for a small arena. ## Verify diff --git a/samples/Archeoids/VectorRenderer.cs b/samples/Archeoids/VectorRenderer.cs index c4dee68..28dc2ab 100644 --- a/samples/Archeoids/VectorRenderer.cs +++ b/samples/Archeoids/VectorRenderer.cs @@ -1,19 +1,15 @@ using System.Numerics; -using System.Runtime.InteropServices; using Silk.NET.OpenGL; namespace Archeoids; internal sealed class VectorRenderer : IDisposable { - private const float CanvasHeight = 800; - private static readonly Vector2 PlayfieldOffset = new(0, 104); private readonly GL _gl; private readonly uint _program; private readonly uint _vao; private readonly uint _vbo; - private readonly List _vertices = new(160_000); - private readonly (Vector2 Position, float Brightness)[] _stars; + private readonly FrameGeometry _geometry = new(); private static readonly Vector4 Dim = new(0.31f, 0.43f, 0.49f, 1); private static readonly Vector4 White = new(0.86f, 0.93f, 0.93f, 1); @@ -54,11 +50,6 @@ void main() { _gl.EnableVertexAttribArray(1); _gl.Enable(EnableCap.Blend); _gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - - var random = new Random(1982); - _stars = Enumerable.Range(0, 180).Select(_ => - (new Vector2(random.NextSingle() * Arena.Width, random.NextSingle() * CanvasHeight), - random.NextSingle() * 0.5f + 0.15f)).ToArray(); } public void Draw(RenderFrame frame, Session state, double milliseconds, double seconds, bool paused, int width, int height) @@ -67,38 +58,11 @@ public void Draw(RenderFrame frame, Session state, double milliseconds, double s _gl.ClearColor(0.018f, 0.032f, 0.049f, 1); _gl.Clear(ClearBufferMask.ColorBufferBit); if (width <= 0 || height <= 0) return; - float scale = Math.Min(width / Arena.Width, height / CanvasHeight); + float scale = Math.Min(width / Arena.Width, height / FrameGeometry.CanvasHeight); int viewportWidth = (int)(Arena.Width * scale); - int viewportHeight = (int)(CanvasHeight * scale); + int viewportHeight = (int)(FrameGeometry.CanvasHeight * scale); _gl.Viewport((width - viewportWidth) / 2, (height - viewportHeight) / 2, (uint)viewportWidth, (uint)viewportHeight); - _vertices.Clear(); - - for (int x = 0; x <= Arena.Width; x += 80) - Line(new(x, 100), new(x, 744), 0.6f, new(0.16f, 0.27f, 0.32f, 0.13f)); - for (int y = 104; y < 744; y += 80) - Line(new(0, y), new(Arena.Width, y), 0.6f, new(0.16f, 0.27f, 0.32f, 0.13f)); - foreach (var star in _stars) - { - float flicker = 0.8f + 0.2f * MathF.Sin((float)seconds * 0.7f + star.Position.X); - Rect(star.Position.X, star.Position.Y, 1.4f, 1.4f, new(0.6f, 0.8f, 0.9f, star.Brightness * flicker)); - } - - foreach (var sprite in frame.Sprites) - { - DrawSprite(sprite, PlayfieldOffset); - float r = sprite.Appearance.Radius + 4; - // Draw across seams as well as colliding across them. - float dx = sprite.Position.X < r ? Arena.Width : sprite.Position.X > Arena.Width - r ? -Arena.Width : 0; - float dy = sprite.Position.Y < r ? Arena.Height : sprite.Position.Y > Arena.Height - r ? -Arena.Height : 0; - if (dx != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(dx, 0)); - if (dy != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(0, dy)); - if (dx != 0 && dy != 0) DrawSprite(sprite, PlayfieldOffset + new Vector2(dx, dy)); - } - - Rect(0, 0, Arena.Width, 101, new(0.025f, 0.045f, 0.062f, 0.97f)); - Rect(0, 744, Arena.Width, 56, new(0.025f, 0.045f, 0.062f, 0.97f)); - Line(new(32, 100), new(1248, 100), 1, new(0.3f, 0.46f, 0.5f, 0.55f)); - Line(new(32, 744), new(1248, 744), 1, new(0.3f, 0.46f, 0.5f, 0.55f)); + _geometry.Build(frame, state, seconds, paused); Text("ARCHEOIDS", 34, 24, 4.8f, Factory.Amber); Text("ARCHEVOLT / SILK.NET", 36, 70, 1.5f, Dim); @@ -107,17 +71,12 @@ public void Draw(RenderFrame frame, Session state, double milliseconds, double s Text("SECTOR", 830, 27, 1.4f, Dim); Text(Math.Max(state.Wave, 1).ToString("D2"), 830, 49, 3.4f, White); Text("HULL", 1070, 27, 1.4f, Dim); - for (int i = 0; i < 3; i++) - DrawSprite(new(new(1082 + i * 45, 65), -MathF.PI / 2, - new(Shape.Ship, 11, 0, i < state.Lives ? Factory.Cyan : Dim), i < state.Lives ? 1 : 0.2f), Vector2.Zero); - Text("A/D TURN W THRUST SPACE FIRE P PAUSE R RESTART", 36, 766, 1.3f, Dim); string stats = $"{frame.Sprites.Count} ENTITIES / {milliseconds:F2} MS"; Text(stats, 1246 - TextWidth(stats, 1.3f), 766, 1.3f, Factory.Cyan * new Vector4(1, 1, 1, 0.8f)); if (paused || state.GameOver) { - Rect(0, 101, Arena.Width, 643, new(0.018f, 0.032f, 0.049f, 0.82f)); string title = paused ? "PAUSED" : "SIGNAL LOST"; CenterText(title, 350, 7, paused ? White : Factory.Amber); CenterText(paused ? "PRESS P TO RESUME" : "PRESS R TO LAUNCH AGAIN", 430, 2, Dim); @@ -130,83 +89,14 @@ public void Draw(RenderFrame frame, Session state, double milliseconds, double s Flush(); } - private void DrawSprite(Sprite sprite, Vector2 offset) - { - Vector2 p = sprite.Position + offset; - Appearance a = sprite.Appearance; - Vector4 color = a.Color with { W = a.Color.W * sprite.Opacity }; - Vector2 forward = Arena.Direction(sprite.Angle); - Vector2 side = new(-forward.Y, forward.X); - if (a.Shape == Shape.Ship) - { - Vector2 tip = p + forward * a.Radius; - Vector2 left = p - forward * a.Radius * 0.8f + side * a.Radius * 0.72f; - Vector2 right = p - forward * a.Radius * 0.8f - side * a.Radius * 0.72f; - Vector2 tail = p - forward * a.Radius * 0.4f; - Stroke(tip, left, color); Stroke(left, tail, color); - Stroke(tail, right, color); Stroke(right, tip, color); - } - else if (a.Shape == Shape.Rock) - { - uint seed = a.Seed; - Span points = stackalloc Vector2[11]; - for (int i = 0; i < points.Length; i++) - { - seed = seed * 1664525 + 1013904223; - float radius = a.Radius * (0.76f + (seed >> 24) / 255f * 0.24f); - points[i] = p + Arena.Direction(sprite.Angle + i * MathF.Tau / points.Length) * radius; - } - for (int i = 0; i < points.Length; i++) Stroke(points[i], points[(i + 1) % points.Length], color); - } - else if (a.Shape == Shape.Bullet) Stroke(p - forward * a.Radius, p + forward * a.Radius, color, 2); - else - { - Rect(p.X - a.Radius * 2, p.Y - a.Radius * 2, a.Radius * 4, a.Radius * 4, - color with { W = color.W * 0.09f }); - Rect(p.X - a.Radius / 2, p.Y - a.Radius / 2, a.Radius, a.Radius, color); - } - } - - private void Stroke(Vector2 a, Vector2 b, Vector4 color, float width = 1.25f) - { - Line(a, b, width * 4, color with { W = color.W * 0.075f }); - Line(a, b, width, color); - } - - private void Line(Vector2 a, Vector2 b, float width, Vector4 color) - { - Vector2 delta = b - a; - if (delta.LengthSquared() < 0.0001f) return; - Vector2 n = Vector2.Normalize(new Vector2(-delta.Y, delta.X)) * (width / 2); - Triangle(a + n, b + n, b - n, color); - Triangle(a + n, b - n, a - n, color); - } - - private void Rect(float x, float y, float width, float height, Vector4 color) - { - Triangle(new(x, y), new(x + width, y), new(x + width, y + height), color); - Triangle(new(x, y), new(x + width, y + height), new(x, y + height), color); - } - - private void Triangle(Vector2 a, Vector2 b, Vector2 c, Vector4 color) - { - Vertex(a, color); Vertex(b, color); Vertex(c, color); - } - - private void Vertex(Vector2 point, Vector4 color) - { - _vertices.Add(point.X); _vertices.Add(point.Y); - _vertices.Add(color.X); _vertices.Add(color.Y); _vertices.Add(color.Z); _vertices.Add(color.W); - } - private unsafe void Flush() { _gl.UseProgram(_program); _gl.BindVertexArray(_vao); _gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vbo); - ReadOnlySpan vertices = CollectionsMarshal.AsSpan(_vertices); + ReadOnlySpan vertices = _geometry.Vertices; _gl.BufferData(BufferTargetARB.ArrayBuffer, vertices, BufferUsageARB.StreamDraw); - _gl.DrawArrays(PrimitiveType.Triangles, 0, (uint)(_vertices.Count / 6)); + _gl.DrawArrays(PrimitiveType.Triangles, 0, (uint)(vertices.Length / 6)); } private uint Compile(ShaderType type, string source) @@ -231,7 +121,7 @@ private void Text(string text, float x, float y, float size, Vector4 color) for (int row = 0; row < rows.Length; row++) for (int col = 0; col < 5; col++) if ((rows[row] & (1 << (4 - col))) != 0) - Rect(x + col * size, y + row * size, size * 0.85f, size * 0.85f, color); + _geometry.Rect(x + col * size, y + row * size, size * 0.85f, size * 0.85f, color); x += size * 6; } }