From a36eafe3d0ebba6ca1e4002ef5c424e9b80c83bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= <91607630+disketflu@users.noreply.github.com> Date: Mon, 29 Nov 2021 15:56:33 +0100 Subject: [PATCH] Added multi-device functional toggle button for compliance mode Added a slider toggle button for compliance supported by both PC and Touchscreen devices. --- app/OrbitalCam.py | 6 ++-- app/poppy_api_rest.py | 70 +++++++++++++++++++++++++++++++++------ resources/switch-off.png | Bin 0 -> 7007 bytes resources/switch-on.png | Bin 0 -> 7974 bytes 4 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 resources/switch-off.png create mode 100644 resources/switch-on.png diff --git a/app/OrbitalCam.py b/app/OrbitalCam.py index a0355b4..5758ef2 100644 --- a/app/OrbitalCam.py +++ b/app/OrbitalCam.py @@ -37,10 +37,10 @@ def OrbitalController(keyboard, mouse, cam_pos, cam_rot, cam_tgt, dt, width, hei smoothed_dx += (delta_x - smoothed_dx) * 0.1 smoothed_dy += (delta_y - smoothed_dy) * 0.1 - state_modified = False speed = dt_sec * cam_rot_speed - cam_rot.x += smoothed_dy * speed - cam_rot.y += smoothed_dx * speed + if not (mouse.X() < 350 and mouse.X() > 30 and mouse.Y() < height and mouse.Y() > height - 150): + cam_rot.x += smoothed_dy * speed + cam_rot.y += smoothed_dx * speed # clamp X diff --git a/app/poppy_api_rest.py b/app/poppy_api_rest.py index 80babd5..74e8c5f 100644 --- a/app/poppy_api_rest.py +++ b/app/poppy_api_rest.py @@ -2,6 +2,7 @@ import requests import socket from math import pi +from statistics import median import math from OrbitalCam import OrbitalController @@ -39,6 +40,10 @@ def lerp(k, a, b): res_x, res_y = 1920, 1080 +#initialize lists for toggle button (swipe style) +mousexlist = [] +mouseylist = [] + win = hg.NewWindow("Harfang - Poppy", res_x, res_y, 32)#, hg.WV_Fullscreen) hg.RenderInit(win) hg.RenderReset(res_x, res_y, hg.RF_MSAA8X | hg.RF_FlipAfterRender | hg.RF_FlushAfterRender | hg.RF_MaxAnisotropy) @@ -71,6 +76,12 @@ def lerp(k, a, b): target_tex = hg.LoadTextureFromAssets("Asset_2.png", 0)[0] texture_asset2 = hg.MakeUniformSetTexture("s_texTexture", target_tex, 0) +target_tex = hg.LoadTextureFromAssets("switch-on.png", 0)[0] +texture_on = hg.MakeUniformSetTexture("s_texTexture", target_tex, 0) + +target_tex = hg.LoadTextureFromAssets("switch-off.png", 0)[0] +texture_off = hg.MakeUniformSetTexture("s_texTexture", target_tex, 0) + # load shaders render_state_quad = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Less, hg.FC_Disabled) @@ -185,6 +196,7 @@ def get_v_from_dancing(id_robot): # main loop current_frame = 0 +has_switched = False while not hg.ReadKeyboard().Key(hg.K_Escape): keyboard.Update() mouse.Update() @@ -418,19 +430,55 @@ def get_v_from_dancing(id_robot): mat, hg.Vec3(0, 0, 0), hg.DTHA_Left, hg.DTVA_Top, [font_color], [], text_render_state) + #toggle compliance mode + mat = hg.TransformationMat4(hg.Vec3(180, res_y - 70, 1), hg.Vec3(0, 0, 0), hg.Vec3(1, 1, 1)) + + pos = hg.GetT(mat) + axis_x = hg.GetX(mat) * 100 / 2 + axis_y = hg.GetY(mat) * 40 / 2 + + toggle_vtx = hg.Vertices(vtx_layout, 4) + toggle_vtx.Begin(0).SetPos(pos - axis_x - axis_y).SetTexCoord0(hg.Vec2(0, 1)).End() + toggle_vtx.Begin(1).SetPos(pos - axis_x + axis_y).SetTexCoord0(hg.Vec2(0, 0)).End() + toggle_vtx.Begin(2).SetPos(pos + axis_x + axis_y).SetTexCoord0(hg.Vec2(1, 0)).End() + toggle_vtx.Begin(3).SetPos(pos + axis_x - axis_y).SetTexCoord0(hg.Vec2(1, 1)).End() + toggle_idx = [0, 3, 2, 0, 2, 1] + + + hg.DrawTriangles(view_id, toggle_idx, toggle_vtx, shader_for_plane, [], [texture_on if robot_status == 'get_value_from_real_robot' else texture_off], render_state_quad) + + if mouse.Down(hg.MB_0): + mousexlist.append(mouse.X()) + mouseylist.append(mouse.Y()) + else: + mousexlist.clear() + mouseylist.clear() + has_switched = False + + if len(mousexlist) > 20: + mousexlist.pop(0) + if len(mouseylist) > 20: + mouseylist.pop(0) + + if len(mouseylist) > 0: + mouse_x = median(mousexlist) + mouse_y = median(mouseylist) + if mouse_x < 235 and mouse_x > 125 and mouse_y < res_y - 30 and mouse_y > res_y - 100 and not has_switched: + robot_status = 'send_value_to_robot' if robot_status == 'get_value_from_real_robot' else 'get_value_from_real_robot' + has_switched = True + mousexlist.clear() + mouseylist.clear() + + mat = hg.TranslationMat4(hg.Vec3(250, res_y - 80, 1)) + hg.SetS(mat, hg.Vec3(1, -1, 1)) + hg.DrawText(view_id, + font, + "Compliance Mode", shader_font, "u_tex", 0, + mat, hg.Vec3(0, 0, 0), hg.DTHA_Left, hg.DTVA_Top, + [font_color_white], [], text_render_state) + view_id += 1 - # ui choice get value from the robot or inverse - hg.ImGuiBeginFrame(res_x, res_y, dt, hg.ReadMouse(), hg.ReadKeyboard()) - if hg.ImGuiBegin("Poppy"): - if hg.ImGuiButton('Choix: Bouger le vrai robot' if robot_status == 'get_value_from_real_robot' else 'Choix: Robot qui danse'): - if robot_status == 'get_value_from_real_robot': - robot_status = 'send_value_to_robot' - else: - robot_status = 'get_value_from_real_robot' - - hg.ImGuiEnd() - hg.ImGuiEndFrame(view_id) current_frame = hg.Frame() hg.UpdateWindow(win) diff --git a/resources/switch-off.png b/resources/switch-off.png new file mode 100644 index 0000000000000000000000000000000000000000..dcb0eb3177709f4bd68a03fcf434fee2664f83cd GIT binary patch literal 7007 zcmXweby!qi)b-3Tz@=xXL8+m;Lz)>%1O!AnhL#WnQA$9Dkq!Z+1VK=cPL+#c0 zL)b<3(40T>?qBuDbzM6@8$UGAo*Z-^ebU91W+Nrgs zB$RV$eyA<!^$jDD7188}&%8#rloh%&o9`vnN!07}yF@2O zZ5v&zSnG)c5r{cXKLAoG^Omw^l^0lw#7;$TE3^dAzYC?b`s!HJJm#sqDF}&AOiXMK zo_VboT>r?QdHj7Pat=P!^pWe*Z?gjy2#xH$UQf&MBL=q~4C!vnQ*|9uR=j@%Hann) zGJz{!%^W^M9I>_gch1B6?Dn%S=;bm&mu$A2pb%R1-#C2|qo;IGC8ZxSBMnMs(Xop< zse-A}!6!Sy>S}rwOWKgG3(ON3hSMXo*Xdld8Hofk;z92v`|Q`;nHcrHW=$LSF0g81 zk*(y&)|jgIR=sK3#Ap=ETLBVP^XU`&8@a~|*NU3=dSJ-q)5dn^8~{=_NAImcgGMqz zJ3L>CG3o7PurFl`#p$F8Pu%ESpk%O6Sew+xz96A$ywOJf$?gY{0wwJY92Pl84$ZhY zOJrBgLFjl0)xweEZ7562$FaeQ)KP#U}O~D8LT& z|Aim>TT70)1g7i0z+peZ=0+XjA=|q8`d97lKZW^F9yU!BB>gY)>MT6VKJx*qDAe-B z)7*fB__z#a7NH;Xx?*(GZkr4l!Bmj#w{5L>F$hxGI)Rf*E$p|{}42&=bex@Y| zA!yThU{$s3_0fu(3V>w7s}xvGp07C)r+!Zt+insxE}9Dxv8okj5VbzpGs)M63!26c zThbO37Sd@))YR07+VUCX1$zK}=c5a)f^4mm{0VC=mnMdR^IP>izbt(5q9O3P0V zsLC-dnI|n15qDt0xQxHMWQ|ip`dFqTzsOhYYo^9aWDr8|m0inPk2^oJZXJtQ*H`Z( z$)UoV2ORvsH2P6|<7O_3mSnJ{o(U_)h1ike{9amUGY%x?F8=q6=hUw+UH-ndRfu|z z2}#SkM>Z9O!++NlkD&Lo?DW0EMc+&Uuqe1p*W1~f{JdnkzK1V+cj+Pb?%ktjX4Yj8 zGCfGK0XtR|BrNy8GYC4)OusR!%6CGk)PDRFTNDA3SV1I6oVoKGW1@^W)nPld5a;hH zdDN^5C#HU#c{^&~7P{jEWK#F@GL1xW06UaS^nPlE9#+o3&fUq0d*yhcv%3I*;84_1 zxs-?&l{#VX)itFYx{H&=M7Jr~;f|9NyJOxG7e*mCQnFDaNB+q&b3kaqQ!t+o6fA}W z6=K-}m*DP0`7wwe5+0p(v(I(kgYo(Y_@xIXxS)TG4tTes=z{mbLo&_e&&kg>Yo`u?L_z((Kgo{6ny4@K`RqWXFvWqP@C6o()o)oBkF>Ijf7DXIFMjgD*!-b=QBRgya z^9HkbuD;)NGhPEA7>&94DE6c7qdN^MkW$m~_XWD??h(E0{J(Fi&sVB3c!Yzv#1CwU z_nO2;zAimS<4Xahv(*nHWfoGEnT4Yjm2Fp(bvk7Y`CM<*3;qrlMx_k#IzhsZZ?VME z43{-W(?PA{P=)&0t6NRme&ttw{C((Q3dCLxS-CS`Gk!8pn=%G8e=39B*Mix)HMf^VS;ff_9GhIkA{{kxXnZP-XB=g(ta|Pt)hzZJi6gJr5>@QSB-3*Jn0y< z`1IgZ((s{RkGG$W^M>hvQiY+dP<{&b%trODdbTj;NA+Ri3>unoIvre63a^LVIYt?F z!|p1OEB$wmiM;JqdRZ_TjDo${^fH<{LL(A6X9|@|v~7ESS!5~m?bQAOJDXBKk~cSR z_3ffOr*;ZqBC(xDx6*xX{K?5l=IV*9_*k;oJ$FM>4FK{|6HCYJ&3Rv7nG0|6Q9ca! zQIfGbEN1L=Dqpqz$+>9#w%gs;%@vmdUeg8 zE&q7akhAdA2I90$vn#Et4xSh-&qHX0e*so?{P6oBF)=a5?={FCQUUwF`f`+Y9lyp8 z`mP#rHsh-s(9dijUDLC(_vRbKw@D>bf54MG9~~)!-s zCInv4n-!Fsb)<=G>rSykfN@w|cs+rB2#AXI6-+kSdLAthin$&sHH)DvNlgwBSs!IA zX#R2+(}@0F9t%R_3xJ(Q_A46h;^Lo|{wF*3YN$_pZcmVSA|yTw$Aed{ua5j#tGkcG zdIH`U)xK@M?&nZO5lfASV-+T*P*r!Co&;up&HO_db-RnTFKW8i#*gko0f;Oz*Kzj+ zjrdJTr)a3s)Iey1OpH>fw9k_EpC_6-9?e8zRW5z9K3ph^3vcb7xSL1Fff5s;XRCQp z8*bK?KN-RZ%mimzx%}Ec^}AaciEVQC6**+-{>;$O5Op4zSI%@h0z{!%HT?N$ zv+4%YyRpH(V3x4G+(wG-g?C%B^{JL#C*=g&jn~?JA~yW&C=&vJgx;bHbBuc?AxuiFJl-k>agSmYp5JI$p@1HysMH>8=k1l zR|fn%f@aCsW#y>F^#Lb@fOiK!r1~?)anZjb@K#Ha zE_v~#f&GPN&VA=yaq|K@Ht`$#*j+Hh$xZUQ5LYzfD*_>uW{xg=qv^G`@!L*&Ibp3l zk8W`}UKG}6D+=<;X!JMGd!ub@T@^#N%wYe4n9c5{65a?5S(+YhHGvD@Q1u)G1-gjF z^@^sBpB`pYr3y6BZm)IC$wXmc)lb1tlnV!_F}D;B|3eIZ0Z_6jWt{Zt3T&b0x?b&vZM#!ZQ^8MLlPlC#pb7ib5G69&m|0Q1JdYP(*9D{;Rw=q?Al3lTy&olbkGeAf+-JiYj#WFuUdC;>6~njBai_)LDIcM z+Y^n?2I83{aIpxnE&V^8)(=O^#DVbEE;hT!w?wqd21ZO-s(u^h3myZ6B>?%H!Gm_R z;=B%!P*-}D;uR>=I0{dwgB&Up=CS9n-oCz%U0oVH-Okj8WGclQe$W$^B!}+UhTrj3 zBdW^E*_e<+lg?VwNPL?;5FBSOU~~`WEdf!Fq|B3ab|RlnunAZj5qP$kaEr2(%^aF6 z&eRFh(QJYnvO@T{xedEx88&6rCvRc#?4cLv#jgochWq`30e&^yuu1V?qd_vl${}5F z^YP;U(&g&%+-+~^TO>ozr`Nnz^OT)@41|sIP9>yBE8!+aoM*#hyd~(?&kTvqs^3UF z-3Iu3ATp98CDxBCcMa?#D6AjD(;WhMOn#10IhiBsj9r|N=l@&vzi$2yn*X^muXZ37 zv2C6H=cfD>Z1mr!Pyo`d16T$BtqtP)9epH6SK}1M{I=RU!NdpoCFk(^KWSF05eSTT z8;89sSPZ+P7OfVjPOWK#GANl$#ICW}#nAEqd|Z=W(XKE_NM-XLxwEr#gtgf1h^Rm2 zdJHG|6@0KHJJ)015AM87wME5Ky|jSPRKDS zOQNu} zgwI7SgBc7{OSZJIX1G92^VlbFLRDZDvF=3+eWj2@^BH7_a}Z!FB@nfU)w%11^q%sp z8{F?#-KKI>a_|1^HoQt8z4vRVXPy&r8(q#508W)#CXKejXo3jvmZOa7)_%+ext+*X zke|gTKSl z?j!si7ul~K$m!NU_wm_FY@p4Zr3gkqPd*z7{VSpp5E0AIxde?+KMvV0Zgm~xv~2P# zFR^dk^pcOTo(JzCGDtll5EfLX5teIHI4rf8xTNH(NNQF=4vE@>xi1MmtN-;TbCJzt zz0%rYbFn|H^Ur~<9z#MS5CNq|5C4CN1!9H5ed)l^l!26Sc2aqq7S>FNTCjnxkq2igO9`_%S*!gmHg{zW@bgq)&qXRGQ98>#U{zZNiBGX z2TVMY#9%4-02*6nYivw^xH&bZXQJt+0_bHcq#kYkE+s0=K@R!jI8oQ)ayOvk2Dkqs zNFr|`h=KAU{b;FKfB9OIr5APJ`~ZR~0-^d{y-((R#pe)2ghBGYIGzv5Cn44dN7@NM z8k_M(1v>W}95@N`dfe!;v!$A#6mKd&lir0yySGoU?`RO~fjN`74e6WNXOzcg`12{d%F%p6EKqJ#W6qjzHRinlw%nOdJfh z!5~Y2m0R5^v8t;evyAO6g%2ceiy`Uy@#5SnA)C+mS9CpURL$88(byuxJhhQZTh$Wl zh8ny*C*<}^77j`?c_+;Vh9p~FzuHu_EBt;W8KL2n$Cxrf!dI1BqeTc(#RSgA*q!eE zal>Q5lI*TV?0Yxb0F%7Mp2UZ4;16T%Nw*Zl>`$LzuNqJm@LxkboL!rM_ws6va?sfk zrS4!9C@9#g?Nat~?>{li@P(*t@yOQEJvv5u@DYKfIaND!8_f}$_8Q~{ivajz`-{(>Wwsm;#GeI$HO=oC2ojQ-Yb3%bJstu-soJot_4&-jC>{2w~HHd6drIDTn(a3jLe zjKp)i3VqD=SXM^n3$4SI+N7dOI7lA(SrVcyU;dQgw`sHz8ea}f2d-qdvU2t2FPYNm zjb^Fa1jJ1ddKq78J4;)mPaonyYuoA!9?_snb^Dx4n=oC-do@j)tvXh))H2aTQP!iz zn4ITlZu0k+O4ydAlxKprl_%Rm+m2fMy_&2rR5y81s$?(Q*O8lyF(@>?8$dqzbsHDl zS4IDxfD5M!7em9tUpm2iQ_+EKky^w;aJ%i9777lV0m~nxva%&u0$*s329e%T-N6%$ ze7u`gm5p!`%Tl*CEw?OqJ1Af05-!z(oNItUa-h_+vd`9Hw zxWJ1nKJof)&nRzDo9pQ6?gxeh9c@UIdOg+}iqMiztd|~2k_7vF*xlW&b67~{L&~q0 z&=b01y&Y%+F?+ohlQDEkrD8!Uj zX8WdXLY<~b>Z>yx76C89v?z3c{c7~Z{d8;4zu=UhopJ;Bmj~xNqwWsBGYhWfsUyW@ z&yEd7%R-!-Vcb8@w^h1%+zxyXUiR*ALnI_5y4r^^-$Z)Dd!B??)jg8=(w1>yNSn0a z-dqv+nNUyZg2{8{tZm3+S^l*Oyr+?3DaPfNqp7@-yCOD?#zEG$kL<+v=l8#v?`~Go z32#DI`Pwna_G`F-p^I6Ja3v>q zUd`{Q2V63lk^R<*BjidPurqD3X`>Yl06kO~g)d{}IxWUjJ7}`s_*G#u<&SD&<>BFp@Y|Zcqk47n zp;r1ZZ@hhpbSpr%j_9X)^6RmdkN-y5Oy_q&6gi!*>z2#~gwsKqKP|mf+}cUzC|p|k z6#J834%K_B%z0>WH;un9Rz2CVK=Mu(&pWIB2A0;@gVB!?u zCZ+c2jrn>tHqLY*v%cf+Q8K9_R=@ns@6QPucZ~-wC|EoUuQgBf0E;F3f>?l+w>2fN4H~HeZTGVTIiZ9W3lVY@D?J)8CQe`yy{# zKgWZJb zQEF!o9+Ygr96rnh)WO}H@P!EEb{}S_iN8a^T~cdq!k*!LR`=y@ZOPr9K&(7N$Mjst z4zzF~ww4a&MwpXWEX@9@_f+BxGGToc=^YtZ5!K0l)@ZC+xK^X-nj9P~M#tfyNSx@!t<>r!NXlR_ z;Z?zjXTfXOZ~Z`##wWZ z8t0#ZIiSiYZXfzzYSL$$z>l&R>Xj$tr+SM%!Fh`zl~=lvBWcPnhYX8=rMI^!Va_O$ z9LHI!;J!Dh^6mURbJZ(p5p97&lWxt|3}cMVww)NZn(7U}g!I_TD2ltyM`t@ghE=a#2jQkbS0Q2hwQhtaUi(RB$ z#LDDJ*3Ts--WbqnmY$)L)NqRw)p?JJ!H5t)$K*l4wJ@FxRxHwTxYP7rxhmIe=E0#G z*yQMHY^2F#j%|Oru6?Ba>HNjI^L)_3e2kFO%k1p=674jhth=v8rk9rcU+DTww0ke9 z{$Bg^=I-*C)*G=0Li@7}-Cde6njI5f?N_IlHv|QT&w@S}78k%)Uco)I&f^c@Q*8bM*ozz3){x}8(YXSe2gj=P6Z%-x5W{8pxk-51wST{w&JK zd{HpOkROADlR!~%ZF?c-w2{s9IiG~gD%-^=pAD8dY>;^$|C(0ZPtI0)`r9$dcYQPp zd%xMF@_t=W>4Ub$WV?2+((g?4(168@A8>9)w!3={*$njkeupq#u)UilKQHgvQ+GE` zoOV^*XkP^WxlFG`gX;%N&lYr=sHKd6Yb*yAr2|Dp%GU^GMzP(fZaWimiU7^Sg&>60 zRDF$1S)XO%@?$(Crm#kPqRh;UicQAY8_#^gdkqHR;HjpHd;A$A zkX%c}(IW3u(OVse=g9f~U~%_Vvzx8EtY)!L<1VOxi>Gbx6e_FWbfIEcO6MNa(|7%9x%yDrd*C8upw--&ahwP1i>IHc<95Q4 zIG>e)G&Js^MnJ&v97s@L3TjB>8O3(tb#=midCyZr=^N-)Eo zTQ!7BRFnWk{&E;M`rhbaxt>`Ic*F+{JfxOSXR2XkPtdn%4DEy?hpMPdLu~9P_y(S-1UPs#7vnzY=TL1gW2LRi;donylP+)bIC&j0_D0it_WX^Ez7X2fOR190f|u z5Y5)RtYiuRuB*nN_^>6U%jNq{;{GS`k$k%8#;n~bWs7SbYirOKv*z(E?sKgTvUlQU zBg7#G4?k8euwSQZPfz5B$~p|h8@oTbwRm0gVHKb0lP_046C5WQXYi-P zTjyJ0x_m@)42CXpOj0AVImLQehSfGgk-ub_uHwgqRNiK%hL*W~s~lxlhlazsC5QvM z`E8jLb{lsp=@vCPL%y;@Ye;02ZQ9!@+3fU`NDv3*qRRPwPHa}RYvDwsnOlq95kkVk zFEk_EY3R(tMr74!SBrr&Q-zw^-wkGJ?Bk#NI%fhQ5Dvyjf6X>|QJd;$dFm~1cDDTf zU{;k~YS~n&78v^UPK(8L7AGgC(rfYovcj6;Q7mOzSlQH{Yt>S(k+#HO5e^xLn#WBU z&T$WTaAQgrzut8OopeSWv{xpiFg<)}1)M+ovct0vxx{3>Kl1~2=PMe$7Aga_XV%;c zJK#mT#nEqz?*I{2bK!6<8w#-9U7=fkPogrbf3v+1KfB}f*hlSWd&pz?**rAGI{Ayw z6wa9wCktV_R)jhxd}l}yKUvwo)Wq=+UQ!a1jn-7O`C}nx3G*$!>*I|K9j(fa`TlyU zH{B*hZuUJnVsGY6q~+R<_M{*xYPrn_Bxnri*I5!STlsU*jwzY0J3R)oAir%P`}bB21)x!?=$GDTs=&4q@qC?G28i;&K%6D(A@p)gY# zVpVP1?d=}K-|BL(!qlXh#DShHNdoyaxKB&@Z+zjh96L!5eZ;ms-_d4|H$kW%-C+_- zLceC7Ah!;0v$a}s;dt-9ro_DQwXRRBr0V~Dj8NP}S9$utZ)=-YSQI8xPNw~Qyrx6z zNcfA5GEfv&^S!Snn}2))8GLqra__h@oa$4W0n&dHn!bQ8X1dkY(hWS>L)a5 zsh<4z^lO=!xM1Haxa(tI41B0BpqZkvmsHnJiW}wVDHir?s-{@AKo98q?*`1Fwe*uHosey#MrAsuv^{@8DAi&EpvjI~To6{tT z;cb`aN4|-Eu>$B>Wc${rkNj-UD%ti-L)~1(AwMiI3O9@FcJ?P7=feS*7T+%zt-M8T zWgyQ8Uj9jZKg}u@uIALt`{M)cUo#gMbS=Kbqokk<#0?s>7MDf8-Y6+TW2VmM!M`n? z?v6XO^I}K-=;)ixV5elb{Kwa#W#`A+TeB@cp~h*J#Nlpm z5Lj%$v{^szT_GJGPSB{xk(=Sw#HC@A=bZ7%K*CxL9|kv&z&2rK6Ox8{G1VkxNqtS9 z8;fE_fXF)IOcqPj{q$o%&ZC)U3qVSQNTz`8=k5mC_?#RL^pxaY6-NgGq}=-Xz+)j zkzDlI;+Y^|M+Gj2ys>4N61MJG;X~0&S%mi$Jy_nBoeZ%$@;TzSPsGJB2xt2CHAZsS zo!Qk!6&c0*TV1614!4$f2S!*M3D)oLrcizCV5cnW`bQ}faF%CL zYwgu%btxR}nix4~x2Qh~TkMd)ks7X%z-j{NZ>n25YM@OUq5MolN=<3igEvPJUtYcQ zJ{s3oHn}+2ZORkcDm?r-t{GZTo-3Gjia}X{@secT=Z8PNmYOpH3jF6|4>l%}xzzeP zSMjsBdJ6&hO?vlQu8}4n+z_@0TAWzSH(1{qT<{fWA#f$Z(a~NmaU!Z_C8E3WukWgT zjo(o8W&5>tbqwV91S?^>QDg!nl+4KD$2#G!jysWE$S0 za>~@dK{>Mt416Q4)47rLn#%6?Gzk^!)Q0vs9NMn2DCHhbg!{VFa0NiLm$+cg3Q-Kp%ZWK{d&MUvu zdnxG%5W~%FjTuW6M)2sC`;_f>x-nQCD(xTD1mIX6>l$oHLt}1q8QK0}bCOaSNK!nW za-iLFhvfA)wzRa6J5jB)a_ijZdlw|4#QgK45wu!(o7#D(wmrgH4YM+sq#Sj)rJ;N< zvN`f=l)GC6;}afFb29~yuY)YyK)xfu?h%9C;*zx}NT!6HDpO#n*;}2&eS53RG(m?B zgUncq{!US$6TwIsmRSg|mTFB{nkoedwkOfpEnQ994$tai5XOBlDh>_*=yBrJP5m$xmtXu4^IWO{pYJW-;K;g8B=7nCOoGJ6$l+XP zCt3s<2LupKW_LX83YaNM4;*6(q;6pEv0g-@NKC`ks<=?@VL`SRZm$k#T@{=5~^{%876U^Bvvdwlgm(1 zta;4r=8FW>eD0%Y&^`^~>xE)co~Bk!#(Eg3aI98Lq}a3h#v7mMjcOgWqyzVCz0zL) z2L%VgLdjA_e6kt?U)(!g>@d!0z^Oe1Fr|)V+b#~_Js=Pa2$@zMEbada9N>5)xv8S~MV)kU-h5kmBe0@C~G#(K%Nf9dnV!c?R@Qd6y7CKgb zuu5=qb|rO0-t<+}M%9On8ED9;+6o6&**OBl=Ys6gNv(WN#a7hJ4JV_4h-Ag)Cuxu` z_o3PT%i9nNKuHWA2>7F((TpPOwkc7J11R`p^z4 zAQ+}?Q$1Pga=SO0=BiALn*dSR!x6Q9F3d`Tjbtm%3OoqSknx~jQ3hU|%>6|iE8hK* zM>Fx!`fcZcWTlYvNWVY*mfKMjOr;|_AzP$LiZUKE^??xrbu^-oYMU!d#~&l_-j%SW z6vwQiYA$jdT zZZ2pjVPCTWXul$7Ry$a%Z%#D0nQb5A4d8n$;qkDS$V?P1bQ>D_WFe%fb?vofaCS6h zRRk_uF^GPQcq`60ZXB&QLkta%N}*9YU8KYpx~*5OzYlaGMUZhq_WqOswEjrgy2c(| zbLE=PPj#sQS_*UHmZdwVa0R)oSF=hv#w=^2t^;kfv$MQ(gntyT)O{f%bvR5AV#zZE z4MDuiy}O}@GF;r^UJsL>3Vlj#Wr<+y%p+3={=)+?2k$s>;69ZQ*FzY(jL zvt~Vy#<-ZiH7wNr5VX@W*hMxpgvEd%<+My%`ubh&U!tFFekj&SziY{fKtZgcI8h!{ zFJHd=+Ho>p1{jk=Lb*W@1*WI#Sx>}lTK%*vlTvszg^GHafRKWBb~`UB8<&H3bYhVI zP$wD$RD0M@paY(HXKPLxSxAfSi3ZhTZZM=bF4q!IKG$O<0fC(<;>B^qQ`ma9aE0@Y z{J42k${rWyRA2hxM|zL`cVy35>;UmA!M!M}0w)cm_QA~bf8l(#!S#U(F;GmCm2^$M z$bj0!@`9W}sH8LG!nNtmb1Y^I=Dv2Xc^nq~Wt8Nzj>Jpa;q}21Ifa+D0**v@_X_&E zT!+7=joLbH(nAUAII_rW84n9;S2bh2iMk$k131vO%Zrn;rw2b=gt?u=8{Vfr??&0$ zK`nFD9Lt3~n|B5aOZFD-6OOc(C4lgbYAF*bDX? zoZvJIZ^f72zo8XXM3G&8a1G4QwaK3o{98HbWam=+fk&xH8DBBjulu0o+BGClz1o1t zGX{D@zl^)`DmX9bIocM=+3dBT3}}Yr*^=v77gK)Awt#&`{BMy#{aARaw0VAg@u2z8m5HuL{zAEuBeQ88wC_iuBWfdIuQhh zG2_?E{K9cx)wUkE2w>y{Jr#m^zf!|+h7tC+N@(_T_?~Im8`B-Od$^^;(q^>p`FZ8M zi+5rIN8*t)LXOf>uoV^!hW=ZV(wl0m6p&D^|2HY2`A&Tl zZk8d?{|iZ($N(6KM2=!N_b|AZikt{kylvOZs&VEQzZkuy>_dC zuf)e>e&kB{l>8ho9&E3wW-DN<{vWmMhuxE|6nGvfKFD66b<3hh+I`C4Xyd=$b(fEO zXI!@Fmr)_V&!i~g|LGfpVQ=p=A(J0J?qURz{p90U&&ig*2xoBtxS6V|1rCz;#t#Z& z9G3};uN*Jfs!4@6`w~F&mm+~-M&0+Ae)FRK@Z8yh-laz4c&J{x5rCFWvJKMp_n59N+?=Y(2L#_d1R`u! zY0M_$F0m6Ujk!-@4!|WF#Qbu*Z&Q5RwWI1j_&14T^fX0A%DqyX83<5RLL7EE3-ptJ z(6tl}vz(NJr9c5HjcGh*f*!($*a%h|jHkCC1Pa(**wORz{Ir5kx6ohO6=@%o07{YN zN#C-W!j8bdwj+7r{`H-TM0(F}1Y1d~`T93Wr57Qp2;p7Ym!?tVTsM}2qRE1iWn$g9;WW&2;i-6 zRXM7l4?Z^daO5HpBvmCeOz6>f)sve>#d;yztHY_{vj!H8Ju(LIRWxj8fAV;=mLpCj z-n2ntL1tkID2#kP4DOPu?I7&WZn9E&E6aNLCGW)L$wHO+UDZBC=*AJ+iPQflo_9sX z{PYnH1Fk*4p<#G?k1U)rdEraXK%&dUfY9E3=H%w8{`*KxP75b5fTI`;(Wa*CX`VQNyC)>bbd*q)~zy65vF(Ta_ZzjLz>dFZan( z+T)~Mzup0GN0*&P(pvPk!fUYyrH$^>_D8%0z4>NU)^Ypk|C%s!@-`d&sVmyjlXM9% z?OTAt0#qK>tid|IxZ1#*0r7==iUz2l~XCETvw4CxQfHicLYu3 zpQx?ybD!Ma@n7LqH zwx69wgqSi2oBBcU{i}-uv%(?IFqqeKW31p>o~Z(h-RU}K>1Cn^HQByy8W+Ys!qrgz zREJ%8??sI8E@Ho6JR)lJpCV3R!b~>0yE;~*=ugxj=SH0PT^UJd@~87AUWq> z%wng}FKke%3iY!MDwd$3IHX6vkBHzB(@gq(*2<%!szS*t`cD2-yQ-4Mn|#+>-y4&* zqHj7(ZrRxN(8=k~XH$G6HW$df%Dj+jKo3^tZ})?)E0D#@Y%jazkbF8>e&0c{vI>dj z{oa4h^NPAd4YMScge4SBv*T}r4dvXU`LWRGwhr2O$i21zkN(;OJ1*5oYPmjAn%2+G z_aE61-j|q^y>?z1Mqx2%s90VVKY~YL*gi+ktP;NHCER`Q6x+32q`T)T@rZ5pxEW|X zDyOa2NSQ6lRb2p_qrg--g-FNUtJ#W zF=lg4aSMX%5+PttdK*vJnw*w_vvA3@Wu~OfOpsMspdHzFBs1DirF>fRHJ=Sz3m$EJ zT`)M#R{nYGjrZu`v3AJ|8-3J(w7M-Pthy}0;7!k=cNR$Q6j)EmW8kmDk=iU+`$D-D z@)opH3Sa2&JW_H0@=^kE zTbWH?k%rCpARd(eaWq@;A_PjHZhGH-xK9f43jij1F*I0_^;T;nik zicN5pYwZ8rp6z#!HEBtd()+cj*S%+@{Z3-Vh~?kxrXh5M^cpWHbJpG~L8I)bgGGN? zrgD>v0}37SL3ET-u^(^5|J-IP>+ITe^l6kcTOdnLeY#cAWaup$##+m9(j?cCH^Y1A=m4$#v@6OV|6RI-s<{h-|LdH4tCCt~~Mq4jwcY@*sYv@ZdFrHgRkjc38wUj zC3)zk?BXH-3w(jfjTI+H+mcC?F80OJeTo3(3?8u$Nlec=Z;UMy zmnNVDV#IGk-#ViM6%zv$6MjjFbB9WxFZQ9$c8?#|rXJ^HKOm6-hR$57NaH@H+mLu6 z1=p`7v@s!D&$svMfI(6SD(3w>hi}HG9{rJtK|kw}84&=Dq2UhI<6{Hz@}dIPbLu`6 zM@=5zn|;376@KMBu5m^f%(2WmnhA~blDn2)v{dNo>iSEKOC;Yn4XS~sUeS<4knL9R z`Qkw5Vy@3KOs92Wf=MD6T35)3d{|)8U9MRjrsSoFp-DVLSY^b-doRJ}-O*HgfYi_6Uv-1kM3G;RjSq`qGy4O&{Q2B9wx?Qv0onm-1GyWN~)ESuVY8ChVRE9UT)8?#GR_IMlA?J)@KQNNe%Ib24#bg6jS6p&Se z4BaE6Gf1MspjQ<{dCn z%0K&T6IFoKg8+=s`0#VLGxhw1u+l#DjfHt?tJ!_E4rzhgK_3RMh&+GtPt@_W4FijB NkQQ1`y;9W{`+sfovkd?M literal 0 HcmV?d00001