From 057b50a0baf404be66dae6ca77f8fdcdde0136ff Mon Sep 17 00:00:00 2001 From: Daniel Espendiller Date: Wed, 23 Aug 2023 20:47:13 +0200 Subject: [PATCH] support template rendering list in Symfony statusbar to allow navigation to template entrypoints --- .../collector/LocalDefaultDataCollector.java | 21 +++++++++++++++ .../action/SymfonyProfilerWidgetActions.java | 15 +++++------ .../LocalDefaultDataCollectorTest.java | 24 ++++++++++++++++++ .../collector/fixtures/template-d6bc80 | Bin 0 -> 127277 bytes 4 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/LocalDefaultDataCollectorTest.java create mode 100644 src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/fixtures/template-d6bc80 diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/collector/LocalDefaultDataCollector.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/collector/LocalDefaultDataCollector.java index 0d0667d6b..f57c4c460 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/collector/LocalDefaultDataCollector.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/collector/LocalDefaultDataCollector.java @@ -1,5 +1,6 @@ package fr.adrienbrault.idea.symfony2plugin.profiler.collector; +import com.intellij.codeInsight.lookup.LookupElementBuilder; import org.intellij.lang.annotations.RegExp; import org.jetbrains.annotations.Nullable; @@ -29,6 +30,26 @@ public String getRoute() { @Nullable public String getTemplate() { + if (this.contents == null) { + return null; + } + + // try to find template ordered loading list from "Rendered Templates", to find main template entrypoint + Matcher matcher = Pattern.compile("\"template_paths\"[\\w;:{]+\"([^\"]+)\"").matcher(this.contents); + while(matcher.find()){ + int groupStart = matcher.start(); + int i = this.contents.lastIndexOf(Character.toString('\0'), groupStart); + if (i > 0) { + String substring = this.contents.substring(i, groupStart); + if (substring.contains("Twig\\Profiler\\Profile")) { + String group = matcher.group(1); + if (!group.isBlank() && !group.startsWith("@WebProfiler")) { + return group; + } + } + } + } + return this.pregMatch(this.contents, "\"template.twig \\(([^\"]*\\.html\\.\\w{2,4})\\)\""); } diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/widget/action/SymfonyProfilerWidgetActions.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/widget/action/SymfonyProfilerWidgetActions.java index 05ad7fbdf..eb7204476 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/widget/action/SymfonyProfilerWidgetActions.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/profiler/widget/action/SymfonyProfilerWidgetActions.java @@ -28,22 +28,21 @@ public class SymfonyProfilerWidgetActions { public static class TemplateAction extends AnAction { + private final String templateName; + private final Project project; - private String templateName; - private Project project; - - public TemplateAction(Project project, @Nullable String text) { - super(TwigUtil.getFoldingTemplateNameOrCurrent(text), "Open Template", TwigIcons.TwigFileIcon); - this.templateName = text; + public TemplateAction(Project project, @NotNull String templateName) { + super(templateName, "Open Template", TwigIcons.TwigFileIcon); + this.templateName = templateName; this.project = project; } @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { Collection psiFiles = TwigUtil.getTemplatePsiElements(project, templateName); // @TODO: multiple targets? - if(psiFiles.size() > 0) { + if(!psiFiles.isEmpty()) { IdeHelper.navigateToPsiElement(psiFiles.iterator().next()); } } diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/LocalDefaultDataCollectorTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/LocalDefaultDataCollectorTest.java new file mode 100644 index 000000000..c085fbdea --- /dev/null +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/LocalDefaultDataCollectorTest.java @@ -0,0 +1,24 @@ +package fr.adrienbrault.idea.symfony2plugin.tests.profiler.collector; + +import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalDefaultDataCollector; +import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalMailCollector; +import fr.adrienbrault.idea.symfony2plugin.profiler.dict.MailMessage; +import fr.adrienbrault.idea.symfony2plugin.profiler.utils.ProfilerUtil; +import junit.framework.TestCase; + +import java.io.File; + +public class LocalDefaultDataCollectorTest extends TestCase { + protected String getTestDataPath() { + return "src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/fixtures"; + } + + public void testFoo() { + String data = ProfilerUtil.getContentForFile(new File(this.getTestDataPath() + "/template-d6bc80")); + + LocalDefaultDataCollector localDefaultDataCollector = new LocalDefaultDataCollector(data); + String template = localDefaultDataCollector.getTemplate(); + + assertEquals("test.html.twig", template); + } +} diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/fixtures/template-d6bc80 b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/profiler/collector/fixtures/template-d6bc80 new file mode 100644 index 0000000000000000000000000000000000000000..15f83b54bbe59bf4a7ab3cb60c029e85c4aa7a9c GIT binary patch literal 127277 zcmeHw33J;>lCFP>SG)Vd+iUT@9UVJriL$k=Yb4p-{X!88h=eG#NrD4_vfPe-zx{og zRfV%i0w8qQQcRBp;;72X%B!+6vy5K1_s#7!dt09U*_>^?b9=4c)~Izg>{R5Bx#5^I zZ|mJLo^^U#!y9Wd!kw*mMz7NQ_P5(>-~+=m=tiwZt+jhwj`^>J>Ef%CUaQ{QI{!Mo zwr5{2ckSuio}szR51u#w)pTa&^yF~sTL1}gH89LqNl>(($ZiY_`J2_NU~B*(bWwe0^{Vgw{+s^A zxLeddFgG>58+$~U!>Hf)FC-4HZD(o#8;qo}-J@d{h z(@XDO4{r>|HNBrdUhHpo_?v2P%k>Oz;ST6E{-n2c@@wqb&>o>Vt5>U3s3X84CuD$W zalQs~R|QJcBY)1+#D>4SwkD>l|L(>#MyA6L8ApVg+B*dF$O3=#IJRdSbXY;nzX>bHlsA=&o%ZTyLw)e=CBd9Ac*^wp%njz(28v#zfFs zZ%c4|6+|_%L5H`4ThLo%lG^kc7+Ml4b%H)rU)Bi3Yh7E^7v@`wday{1roBllLL?!Z z+MbxRv3C=05pYcH(Y9lLaV#;LV38A+N+D+1R?H#+sR4J3`Pcy!Zd;h$;leS|1`8kz z2A%e{s{9u(8pEME_qHd-Y`nk}(CsF$iBI?XZ%5|4fBjr3wcieJ9D8c^%H{C{R5U3I zq?N6iHz~~>8{)+Sq4LXhZkeZcxP5JU!<+2|h@I{N`2UG_Y|g-&)@;mQ0k7k~tohs5 zBNJ2XnQvcT2}Fu%oIxUj)c950`D~i=ZDV5H3OdIf>S!CIAn}Y@0{tD?e_4}>QErwh zuiyM$t-gEx@oF*i7VlmkTC>I7>$^^C&}zJU?cDaNm2Ro>U$5VT)a-JtQmx>>>g#>W zF|X~ra<$qjDGeZSMqPA(L0>$*1)EK*p+PW~??_<%_uX_7y$c~m8125brhv0-+*;T2 z@{4&jfBRGUCw?wuTLg(CRv)Z#M)q(qm4hS#!W2tPgIX9F82JoskAXwRR^%mD(h_dY zpc3c>T;ABEo&-f!Ywc16|Eu;ol?soVy1Cn)-^{n|D-i0fDI_)%5(v6Z1PyZkCM5Rz zIUXFH?DeUA@Wg_rfPP@Y4|fL_2S@yf`OX~d^-I2d#|wK0 z=ck7|f6(h7pdJ$tD0KJa@Z{{Ge|AI<@Y{11=FpzlOfb~$$@}9S(Js0i88b`3j8_lO z2mJLpeOhfdNgcR9S9&As=SuZmz0sS@_@dRD-uzst^yb#jjmo=vz319|zu6n9i>r}% z^sZ9v4MW$q!}qIne~M-+J$LbQz5T9H?YZNh>y>wndT(gZeeVnZto3YMG~P98J=fzm z8$I)myQ}qnDtU&(*HyY6|K(pB&MVw^A6x}3deQ6P z9WQuiWM287I`gT2{bvZpUqaVr=-LfkJE3bMG!$cK`fdJY2N)a9t>8xpdm)4jjR3SS zRsfp&CAc1iu1$C3cSWLve>5@8f6m9DYcu#U4L`w;(4%qa`>Uy#QEF>`B|7Kpap+p& zj_!M7K|OSR7kd9L{7$HS=*R%r`7D6Xy^UOpS)*2`p_k@E!5DnszV$~s4UHNmZ_v`T z7JBJ(a1EIojE4lU-;^C1=yWc4hP!J7U*mr83F*5Pv|ItOa();P()kW#b`0QWX6NZ;wDA|t1{qqm3 z{V=!U(~@IC-pXtD3us4Pd&E5QdNlt$-X2*b#=>{P9V~{|(KqPE%>3eiLBGQvKxl;@ z<7Wg${C167$RO@eYRA)^)Bf4{!T)7F3pHvq=mE@x!=2;zA9voX`+))c{^D2C*&h%4 zLQTTb85`E5XLz5tuN-S6Y{e=x?eBZf;a2SZ@eB)q@_A`I9}9aJixl7T z-s}JJ@jZRKH~4sV$eq`L(;IjoT$uRKkBc!aq(&t%Bc-7|ea+p|bSQIf=NM3&(d{+{ z%L{_Cu(G!2!`?s2;DT}qsNbeRm20hL{ViVw?`U4(UL@vsKc1b@FhiK9MUSKso@aht z*pLT%c=urcV0Y&N)+Rql&H>F8=v_TEXM>ODfvpKM@btGmdRRw4R{GxxfH|YP~-yNJDa36rB)@rxuePTo0Cl=*a zlYrxmk052OK}%ieiyfc2sx2alh3k}ExJ=Bl;;rD$c*ZNb@F+`S7R48|0Gk`1 z%jVtOc4*|(POppwad~20m6trG_QS38LNEj$yE9`x0-?E|J$p_=u3^Y=&fPuh_jw}8 zVOF-CahX9bUw~Du85W`L&@s(fxjk%OcSnuUz-&~ELE~yP99&fm{9|?-l}hKjdv$%S z&`O+oa@@bzIpg(&X2DSfC;Yzi@#4eD*};Wabbub?>@}K}e>WCzZDCyw?~z)_sQFpa zE_y%yc+@{T*j4bvWCV5oe(y-~7`+rFC6MJm!S_c}Fw+YlBY1&?bim7Dk#+IMDGNTJ z@2)DiA9Qqn{z1x*!<~=EyB{PE_qMQ#pSdpkAJFIrtl${R7%M2qKV9?(pGc($X2Tb4 zIM>t{80kg-uz&gi$W~uy#){WM5^xFDeuowUW1}x>2_yIiEaUK)fs&owU6M<`9309? z13mGGN$Lv1it*_{a3T4qyc^5i#(yJo?wDAQGAOWZ1Lc=i$U3aezOL+%2AMyZVN0t%W^=#`Iy)3g5m z!S8e%oiHzK(+_;;E5a5Chyj&62zUhtir@ZE*T3Qm@zcLIHl`*tLBPxM2C*%npjQsA zmdcO+HN9UP1OBJ-g>6r+;6eevT62#{6)=-LlVb@M=QJJXe;nS5?>@i6{1UOfG9I`{>)fs_D1us^eKZ*)pbHfV_6^YN;G zi~M{1T7TzkAlqdim%I+5Bzpvd@&yHkqj$EzSh^tXci2CEFRUCjNObz);^LHKz~HR^ z8^jc|82D6r2GP6h=Jf33;smY^0t!Q-&&n`?7{&mYQ}|Kn7GP2C9EHR$mkEid?cJ}%h?Rg)jP#<&s&yW4{3+}}iZ|ZFlfTy6A zkTqX`8<(V+o(xtaB;Dv&w?Wzf2K5POj&uag6BMyeHT0WobjB4hG}!N7?0$efC!`7} zNw}Kf&GUz#pW8S!kcg4EhTMfAAWTBgpV+>t#c~STI5EMRo-M((i-)le6D;&i49y0}a%)mV!Vz`vY@#Cdn6b%rlEQg!YB03I%j_ zaw4IoSX>3YE)=ORKFkV&hyYQLw(+ z5)tx;MJ|@f2aFfR9yE5>W$WD)NQugRio2rR<4@OZo5$# zb=%c;qj6p1F9{J?a{sb(-X}i_-D_i_=h#OZW6S(s6Bs$z5$yfj?hQ6q%_H;Q{^4t{ zUb9iJ(bNACaR8qXFMwUcpR3LPqe2`O-Zc|X4Zt2@aRWOL3gO~x=NNcAgMD?*i(~BS z5a%NnU`G41*f=#76YqbpIJF0elvuzOsm6J<0|Gcx9}<1f788P!{_snfCPk-vP`t;V z2A_7svWwga5`k|6e7y}L;O!D9-$wgIAJhOlp}13CsbLSXfjvatK_s(!;KDQT#lY_I zARLI(tX*A?*nXvV*2g$tj04(USNs1kRY6xf^Eo1K)ZNQ{j*JLy^m=Uzx*5Rr zYfQ0t@qaTYe-R@2-gWT=YlCk9(H)k}@E2}}XGw)i0s5AL9x`c& zs0|q{$0T;3C=n(4L z0G^{XUZe+P&}!-NH^O2_sicl4gPgQPGzUeI;bWjb^~dn3&@}OPSvs8>cY6qTfs>13 z!O&|HQ=7V1e0|`VQ}@(#{8qNB)JhiE;nhDguRj>G5l4_&J#L}_LQV~c6eLO*G4A2V zvZf$j1Q?QOls>@l0-vpmE;JCn_YG3SBQy<$X>!NOFkpWdaNzA|Us)WepYPfctJ zGLKXnEqHYh;{<_LeT321E2Snzu!O$XB0zp#2m&ZFGW9Gn)xDyfRZ`YrN^f@Rr7leh z2sj-@h_=YJJmy(pdsLcgq{Ws+@JvpW&m7K-ZE`>K`Jq`}hA4kuEZ-Kym3lT;aQxFEcq#pV0D{*L zH&ETe?WA4_1@<%B93mLRD8}!SOW1h(!FYs(rb))mU?Pd+`{$Kn zn1Z+qR%Hh6`h>u6S^%F3?eoH4(R3q?X(9E9G(2DUYso_7)zdP*ied{g6|hFhz+vYi z@#ir)>$_ai6~LHmTv+aFPNZz>OHdf;BmAW{xF7w<))WYyIr z+5;=ZMe;Z@rM;1hNPJz$@LwbfZMnsrsD*ioHWUZh1R7<-Nv(#@Tl=Kc#B+X~ZSTD*-ut9h`<3}`qi(m`lE;uQb z3H-}~HhnM8sU!oUL*&mras*#qI7l2et|lf`9H5wz$7HTYTUc+(T;KU-X`6R@^DAxM zmVEJwYi!u3rL+qW3J@(68YpAIP~E09HoXCA*-S`?Jga@A4pzT;d8W%t&mV2^2)D}* z6JD^A%E1Mcf-XZ10%mwt^e<@mg#*GCDTw07i8s(wI2o6rkOOH=?juau{9-$wm30}d zCddwvXt>`a#Ns`gSLB6Np2^~^5XK-5(*}!%oFfrl(pT$z1O|Jw1>BQiu*ccSsI@qH zFRw0^pZ{p)=nv^0Dnc;OA`X%&uv>W%XEZQUCPFO60G)!%e~E5?K|JE zds*%&GcoLY{SjqNL85^)0uotvQSAXmAWY|<=exImb^fXRMyJNtiEWIKys|*%ifd1B zM#y`r%wKPID~%>9Up%V?AxVc98~8_Ot<4xha#RMj-FF=OQDZ_MQCmL|j(Q~LYxJ-j>2gmi)R+iAPT@rOaCQ0xn#3uf&r9SBJ0&;ezihE3^F*H*;p-?Il&@bK zM7Pyc4i1-zMakA@xs4`G`P?k>W3B{#MCbNqEI~YlBCHwK+i-33xzjIfmDp@dv%r4I z^7>A^P@8fEI4hhfwreXl%x~ru&aeI)3;);|jp*(NK7anX@)j}21}f`?x4sYFDu6Gt z>#bAAro!{jbMpx1;6}Vv;O@!eY#+T;vVJbX9vRKqq*#DxX~WB|Ok$ae2d%AMm3N}? zWO&ZCAo##U<58u|qh$feP1f8Ry!*08t64&bQ2wXopDB_-z;9Gr{vRO@D=StjdvyM& z;SBzCpR1R@v)T66kI7R%)b>_Z>IcKru{vGJFwd7;HYq5A0=M-aFaY9*;+9OLPr3zr zXe(J|U}2~Hx$;YwqaQY~*j|Ds5+zrkmZ_GV{#WW3+Kzt4)>yaH*u+QqV^*wsCi+D~ z`ot<2{Yw2(8oKT?49gP>j}0`-j~K80V{u9b$_Jyg*A?A}I@Ip5wNrYFBO)miFte~^)-IPV2*-$1hYj4a?4mjRMVeYGmZ#;M)Bbz)wl#tu% zVef?xh<)|bs}YJf(gCf=7>sm;4N!HgFCavp0s@>HIJG=Jz`Wk5Rom?v&M^mw7{aYM z56^Ze$~Rm#G6*V>N9NhiWdxv0|9<55aySupNo9z+dKGzE)Gk=KCueUlotw_(?!@M^ zFln5<)(Z0>^mssqH*5y)ENU2j*y$J5LH9nNH> z!<1vBPY>61b;6$X2Ox5pHXI^yruHgON|K2FmFKjBg=o-x>^b29a{g@nz&~lP`0Lk*ybDlx2ztb2T4?d(4P= zH#FzOH%z#g&m=@k`J=DCT}Qc6O0s5|*yFJ<VTZcE}&D>*~Rnq}5d#z*hwtF6oe_ zp>xZb?8Bl7w_(?e%sGx%XTcSF2tLBeH#00FV-J8ecj%bLG_5$+=ayX& zRJ`4)mv0THJftc`<&k+?-kHw_zw)8%d*&@in)r1{NbC{_C4fM!W5YuM!|>K180su! zYQh|Ww5gDu^+(fq2MJV*-fQv~brMVbUgU!oeLy11Z=%gjgzvz7p?*W}bm>kbe5VS5 zW%ZhoTabrVuNAokY+Jo{=qY@U$AO;0_jnxWDSS`NLS!6d zMq+X!e;fOU$gZf!Po9EHSgr28Q43p0xH;=caWwF#F{0fo59Or;eF*HZXf8pCxA2*}&|d zeU_M6X9KgB`dMOToej*s`e%umbv7{XSUgM2th0f!Lv$}%`^oF3);b%Qcdwo!&9v6p zz}PK(rZlt82F9N0GsVn08yGvs&lEH3Y+&r4KU2)Cvw;ys@JunY&IYdElOOo$YwdM5 zFybQ&1V(-1_!5r6pa=;{jxZ2db#2>JWW=H*BXyr&8q5s`F&N04h=zZ)*s`P`G#Ozr zKxhGdNpW8{o;UB6%T<)aso;OrUZ+y2l<6sln|n7lBG8dI*xP#Fzu-;xI{9KbmW5+I zEyw(VAnZXXie-uurx-GXltiK^IC7Cgcj{!asel-{p^qWr1HV@EzZQskp=J;cp@IzP zXB(d3l|hPqidRs%SC<@qCITlNSKaOP5SMaojTa7LUnro5qI~j!)5(@8CS%+Y&B@~n z0J3KyVop8~V3CoM53Gz>I!7Q7fa8OuAip~a2964HO!U1O)p+W3e2HXf}b`Yx?nlCL#B=7T0 zS2q;5FAJKfGTQPdbNS_kV+>8>YGSIg+5rXm{EjeU%;raD^4>&32*q{@Vj`KF54tu4 zltNfe=(PCqc)uaZgB8uv= zor$c2cE=enrqEMRi4-2H74+G`?uKSPfI1YwAJvWeb7fP2t5pQq!R>&uiL~;ZP?-Ws zt$xT3WjmWdjGX#MPzKBsn{>U#08V@xNS&9FpwG5;qNC)ggkbz^fdF%=Ji4Gky~;=j z4p=|QElcT6^&5!iKme*C6IbXpMmmVJla`^J^)f8!^+YO|I$D_$!cs)Wtr2_*hhpyZ zx*{D^>%?(3nGuCcuP9Q%)y_s!stV&8nu5zzqad`0)FhcM8>V7{z(ES`t-0&YMcH(o zH@GQtL(@r`9igg}QpZQ0e=^$%kU7G>2 z6$_(~q-tqJc@6w7MftTgv)r43pW=|9txm|qO`*A$tpWDApYR&8r4{S<2->p6k_I%b ze9r`0NDXdidTYSbiuz38W#fXCODPR}zR(9r57-67UYBKlB2Xhz2E%IxDhGvJJvI=; zO5$>#y-R_~((6e_(@U;yQflZEZSN;n7qiOicq|xDS0S4v!CD|y`tQzcB5;;)y4H!}1Mwt3J8 zDYrUj=b{fPBVmqE)xt%3e%OCX>8QN4t70X)%2@E(I7%ZcRyL~~+g{%d3iGXIs- zq~D&*enJX&~AR+T(FVb7E!wYh)ZU z|1~lWng1FYhs=K^<>vPx^Is$55c#hhTM@j6abQBI59CXNs-mgHl-P-T(eA|5LeMD#TtL*y+AD~Yiy#Z#bz2w`GLS$-aGb<)=T4EL=LuiX#rU)Eui~-+ra~hE-=qe0Rn+Fqts4W;i@>X&v zZ5~R5RNBd*w3Cz3PEJNAIT;->5TXFJOUQbLtv^`AzWXS=g{IQ9Me;VNnRob5eZupQ z(0vcvYMc!3dW$PESW=c}I;YotH#|y7EjTy5TFJKZUbpA>#=fEo7O($<(f0c1*R#cB z@?X8zx3ym;sJ>fTV72dtc`&=YKdcT)Y*3!LX3# z4$i;>v`+Ok=$$USRO@SNn6r`XsA?N!+OgdhQ(W$cw>rz(VVCANC>$UPZCEq(3hn`2 z6DN=y$VosDI5GOUw|&qe>8P4*m7R98_KjR{^K?k6%0N!Ui-nLA?^+Z`PfLccp(wIP zh@waa=cA}9v}lZ?3g5yml9EtGqaZgD3+W9hhzn2@A&?5Dpq(q%!=9`c^P*`eh-?m` zAT}p*k`UM7z-lhHQj2@ll3@phlF+(Ed_=lmt^@APuUv5{pA2f!iF<{}pe`7rI1v;b zw1#fTRA;&&Q!gLgz~qigo{(EHg)?@U$J2MiJ|fkufo(In^HixOI%o~mbd|KB1x-Gx z!76t%s)>?zcn`)m+d+m!8PJ=_nqYgj0B!YDsU|uh8mgg1JIfkcx8|gpW`b(88`Ysr zVVxFO7j9Lkz=1|hy1q98a5Jd`e?n2Z3R}!Y>#E4qXo!gXTuemdSI9?12}}9D_q7u#2h844rEmh~!*M@2U1 zh)PK&@;MbmRQD0qSRf&h>tsVZN~6_M&`xpkh@!f3(+>HC%8FJrG@`sd?4D23$co_2 zu zsYXTmrFkDKA)(R*?uKO*HV$LL>LJ6rixgjVtwSOj?i*bv9Juct0|nnlJJ`suu8_Z? z%!gp58SsZ6m>i-(|6W$X)+x-FRINbOY^D$+SSc^ZijE$YQKj{2XD3IvHe=-Y5aIeo zk|B+GrQnNT`!Yv*K_T=RYQ;r6Xd?-K=CJ65y6E6y- zH;6qFQibP-tR=J5Iv18@Vbn$^KxLJ7VQLHHd07c>giYI%ThmcG_|*71v5gUS_7+G% z70)yT*g=>BS$7I} z!fd2&js@Wt^J;ry%|6H6>N}&+A?}K7JjFdaB9ajXT+K3J3oTDNTdBG3DHXI(GSbrd z2Y8u9ph@fmL!FZ+DJnN5Bsv?q7(JF_nwv&E@ zjIo#cb!c+39#yZU1yWB@DNJdEsux5{kL4!lDr(aE;8UqLP*c*Z)+&$?=SLLrWtz8CUke*4oL*k%gE}n z*Gpu|7fL;$_=CWFTT0xkLEDgW3XFt$*wsAci?Ly?b&aR9iMBN%-}hV7phz;J%v9wc zl3^^cuocV6J5egfbI#DXu@=_(Z7P<}T37MpYnc{^i!u0toT^YN;`MU{8wXSH$ zYF|ONq_t=mb3jS40wRwnr&2-qCIT;O(#&q}0s~?mHmgNtLvhmdqf%2emEs|&DQp9# zkesOie3L#K6ZHTJl10U4LPf`^QDq(Ep|h=|b#`wifkNscXUw*WwT*Cfu}ZCg$Z{=| zDSx%KDn5wjqBt`U zNfeHjDaBfH>$nB0W~#(|=^CHoh@Fx#LM2Scv7N!lL@@Wn9k`w`o$KaV^jN5_p5X{1$`i&K+uOa2)A(h(1jKd&-?U&;&aZ| z5^RFefJg=PQt25f-D}VaKYcJ7!K@Sn*jhS?c@5(BR<2z)ANCl9oCCRnr;Y?__ig8l z(7u99sOlt(5pC3M;bfAqttqVAA5TdsgOcmn^8uY-0}Wx%AVTodyc?Qx4<}bW6rE7; zS#hwfB^9k3AVDy+;hx#LQ(PD)7@$=Mx|7-N0!W^o<4#}Uc?H?1y)=aSYl7SEpKQqA zIe)R;l|IAnHcWPPDZ ziEIM}#C-t!=D*fS87eWIm1q>i+gFY?8k=R3DZHX9?@7e(5)BrbvC zD(k`~Tms=~{03Arnw6Kg!bw}LnuBema`=!#mXV5j(dgn zyAnh=lU5Lq){WTI<^<}A=WH>XS+nu7rBi}x(%C!?jzl%!UUaST%$P)M9wBCBw}p~O zm0Z<6vo5vA(!wTXO&CEL7f^ZpBEF*H8BtbDnQR+n?I59ukbBO!Rc~lKlT?A8C5+ZH z`S?V#!Z3bxB1sF|#zgWoOkz5ifJsH`3(Z0*SlTyH`%+u7baVxE6sH4y`sfVcVd0ef`38{BQ)8>#sg#F z-H-4hog@1Z1n`TrT4H zIP!!=M+?oNJwquivoy4)*h1hVq@bI_A&Rw1BT==x0c?)UtHrp){|<0sB#J*fZpf{J zhDD|8LZ^|!AJTT5;i#I{^-r&>|q@PmQm#s!B;B)m%3(a1Tgy zmN-C%K#z&8q%y(_>LYi7kR;cG#o@Y;rGvRK{7ms1!B(r7CI*v3RSK14MB@2DQFF*} zMP@MNwmWDpt7^J-jHwB06O? zC@fD>Uhz}f#zHDf=NnF9p4#aQo|-?`84CA-Vn#;E$|+N)<>4I3oKvQ&oj`}VD_$@; z*zQ5*ix#Hox?Mg~>jWm2npycwf)w-Y@Z7A>V#>TnLb7gV0EZgts(h4$#3WBmN}Bd_ zI0}`M9NmzPqkRC>bon>3OUTDyE)~g)syrJ^p^m{CFbvf6FJ&+vTZPVFJ5$%IXYR=` z8!UA8pCVyklbO<4jif`Cn{f9tN0i5rrqj)4=OJxJI;5K%-1w`RpgP65@bcAn36LYw zcC5d6hpBW6rz#QKI(xDKu^MZLK6SW(&|=u0eWKg+PqEAe4@1WO-w+TvVP%3t{m_{Is!kKmR@clR)i9Fjm3|y;nh7HlExB2_w0cNH>Gpb9%Ka)%DpfJ1 zh0bR9T&N(+AwO_${Lt6Pd`pgyztDgVK@EHXp2pcSGknXOle9 zni=;`LfTEArJ`pobQ=>;VHHjvxRgm%ZLPQTUaOS!qbV?$@l5%MsJw6b>1LCV>tI_# zJ!uqIaV2mbRB@?#xF~?Q+S-8?`BF>*TTMyj>MxC6ib+^Kln>L<5olUk&9|2MMPo4Q zoCmaH59fjB*b^!);F;6;1l3FiWI*!qY>|bIuyj7j=CNuhW^1D@+~t{pcten^GJoS+ z9MuXIhgn^AR0Kh7a70%*7ZO{Ev+Ok1t6K83wJyAZrl zjI7I%?WjBDB4=9bGc0(fUt%sN>}dnV7t7X}V=miT4`jj9T|KTB3ZDAJ zj@?VREwG-n>NfFTlS4AL9UEsEwI0!sg9^88Yn_r!t>@*usBl|~>r@mShyfQ7yNIxt z62MkLyw{5fLJF-}vHY(!D%U`;aiDDuBVM6N$M~|0_&LhtdFFUk1roInkMl`%%zwYL z{SsV#V^7WU$e3B?WK+8?PjGcx>-BpHu3i@7{UZcdcl16xaJuxhAiaE!Xvb7L$}i`_ z-r5$2p+jM>+M+D(;DtQF#!+3N4#TB5y0quQcC;S4dRSS8lA}mjyCTy@i z=wsB{b9+q?Q0iXs^#T0C?y2ect!&dtJIySxgC@?*YY`Fd5+K|JMIfdIg#6Svn0X7f zSEct28@aqHc96egI$Q5fdbBuF^B|7{*jHiA@^|DU%uBJ;8M(LBt5TU^!p~2yMwl_` ztxmT9DH8B32hOCecUL@lutOKlWb55AAp?&I68c4u;rGxO-r)C1ProYUlO$uOmGZsy z05J!E0<0NIgUpbkM^N%!J$E~q;KoUhDhDfk1R*C{y4=EuF~$ZyPdyz9JFVU~qGf|H z7rLloj;ZDm{flP`WJXHKn9tQTA{K@AAP83__p1v^3q4U-EZrIt3mw{+XxUK>?W5ue zK8G_zer`HQFSY(6atOVJNOZh~DV2TCkWbH{V2m~*B|HYM#A7%N!L+ElX3ehc02B^m zW+46Q3nf)rhT`TaK}wXr34N0UAC&>&li>y0U}DV13uGmPJ^)1tC?d6wM&`A#n0VA5 z{)Arl5vP6qUklTLz!2Qx_Ud2{g(s2kxf&Q+yvE+Q+yOE;!G)vH2GNQUVe)CaLlQ=6 ziae);89~p0+50*NicmdPaM^Hzyhu`FR6`<3-n%qMmpdb44yka7%3MR!xSE*q2Jhd{ z$DkRJx5F~AQ=u$&aClfeQ-A1Q*(q_YL*+uU?kO-j%MzAy95{`8p{8nH(hkB?M`NSG zht$N-NY(qF3>wKj4|&B9&5-fJbObV|>VWbZ64e2ZjUZRLwNAC(t#(SyPNj_k8sMSc z7WNJjPpkC`#k7E^6pLO#>TxeOmIrDT${x=tA&JB_-Jq%~dEr5iM4wCH>2z|y13CC& z%wUh`a*eipbq~f2iyuRXE!ImqjVb15ozUAy$zq{NrKBOsPAXY62A#OBvD2G5w-;{8 zR}3MooWC`#`p(~+UeD)mZ<%3`yTvS)1Uk_gaZxR&op3sPK&Wqjmh}2Q|3K1ND`+3` ze;u9eIF9i(L}Zj`EWlr7+vIE;@QAk6+O=TJY-Bp+oDT?Z;v~+@4~#x=gUyAgS*A!^ z7ts*Vavstqt>IExW56EzCf6~%pb$C?sPimRoZ=^l%rT9T)MyOC7nBlFDvnoDBXeSg z?x2MgN)eJuyns6E#%MtGLSThsO{EiIPY}i=*U@AoP${hgfyz;@QmRxc%~rkB>~`zj zX1iJKHp!xRQ1ogA@p{-hrFyqkuh+YsM!ntaZk5>57aC= z>Ip)hWJ0}we}bT=)2UAo@KpNx3BsMy7I=D)Z)9XVwc$vYsRz#-9I6Rtrt)FIw-8<< z3412D*^|)98LFUOH-M6TdOM>SROuel2+s^&7LZ1`|B7hlYsygPburh=u&V*T!UW zg=!=N@mv_Q)UNanQwQSz)GS@o1F{2vKyu{5{pwrBQE#P-I3wotlPZno2M|_L$ zM?fR<$Jf9>fH|31bJqg+*vTUwI8mUwxh*zlgquKZ%tT+n5h?tsXq}R$d7|bqF z_7I~gM@GdJ2OPc^9hGiVg$jJow&bR`Z-LtK;QkD(kQ(L8!$qLH3$n?&VYMFP{#bN~ z7W==o%@GY5mIu*&f3r0;x(mxO%~k1rJ-%Z@(qUcJui-62h%Dx6wb=y*r_2CmLC}L^ zVw0HaqZ>?FqjTv(%{DtyIuH;LO5}}rs?W$w)SFjpY4Y*VxaX1XXn9a7Q0JMs|0rIcT7R;kQRd=8}BU)fl3 z($AHjtOS=xZBV=!HiZ)4YG$M+>vd9Q!z0c}nv5AW#LFF4088hfRjcUuKstGr%|V_r zxXY#>0-pxyb$KYDpIAT^r6vIHJd!cwk3S}UUrh}})nznl*XaW~4SgMph;? zNcG)igl9w_)H|px%3R@?*Sq$Dv^nWVtd}TwGyll3YQq7kg%7?Kk`KS|(V~|}qJAHp zkH9^y9x(RBWMo-#z`#uY0aMo6DVE2CzYg{efmJ%=e6t2!)nbDV2*bpXlS23*u*%HP zc2xeqVjlvIv~xJvF(ZL;W&0HdOB-vW6$I)pfTifh8vl~(>|aWN#4jJZ)$>`ec6oJA z{@48Ykoj@HQaHEp6bzIEfh8`i^Njou!?@xHr&num`fxj&V2L$H_VTGT@nQBCJcCrB zGC6~YHAkqOIU9aGm{A5lP27$%UQ98OmuKb|Yc`^l$$JyA^&&8M&D6D;Fw4Ov8%^EF za^W5mYo(&m03uJKfg@J;{9Z5jsI+Ae*BX1gP5?J5odS^Hm}7E$Ask+L<2EBN&%uG- zXC_L<-{uhFYXyWBuf9sv35bxX2eP|}g14H?8g-~RkQtpfwy}i3whb*&`@9A(UcFVx z37aIjm8glz&X2T#!cd~hK0lIzwAT}kgUAcvGZ7)RmzoKU8crizxmc;@IVD`l*uZ@l z=!7x@Pv@?Zk}5~Q4v$M?#HqTJRnBuDe@i!$uniGg!cc!@XcisC3*go6HD2?Fpkzs` zg=;lyAeve@1aW4ZTx8G!EIpS*?fv^TD>_=GR0M0RlhLgf3dNBG$)u=axG{L?u_t#m zWim%&sNq!-8%97g@cgp3`*?f1WY?p- z8WASdCsVpeuC*@kC?3dwTkCdmWrYw3H8`HthEu&wX66aIdbwTLv-Hfllowl+7$RZ= z0F^MqX>H1SNd1()gR_&93tD-R`<9(0@F{=6S}dA0f=Eu3e&jfU>4IKwRvV2PF9@Oi z=Hgzr-L7?!l!@gQ`I48m)~ePUT?(y4SK`Z7rQT`dcok-uWNYL{hJT4hly21I=SG;W zSGw`0laiPgfdKszxv*6w1J~lCRq3`Wkr6cUyVj*0mpu5WROUVb4MMHBA`c$*$^&hyLLnV051MCZVh+n zSo6HNAoqEACL8rl=prhITh&IJ4=!GZi~7d6AR%Ip;ONQ28?;jv#zC{j$2Dr9UP}*g z)@Zht6PHg8*c{8i9&{AVKYlZ>lx{8i7oKe+P|q3s=_bW#_OG&wT2#>>P708TP|oUd z<+%o#P{onfNEO#ts~#x!^s<&R_gCUEiNuVbZbGsJ^qGNE@6^HAB;swqB%IVhS=aJakXpJ{K$b(6l<;9SiK0B;Whb+Gr4}1~cLN&{S<+F--|e;=%PsJnVsAO`k*%PWc^N;+fk!GG5D|Fo z#tJH0$FOxc&qJ+2;8hycrIx#oM^bv}tcm3;E2*+Hblu3RB-Nx5o^Zg~bP93pLPxSwj#Eyq`WVqYq5>t=2? z*+5op4?rlObnQ@LMV-HxSKD*B#8+oj(H6tPLAjhVRmgYOStl@+v*=+06n?3P05mL| z;h)GX&(*g?P@f&m7@iG}S9 z@}%kaQ^||J%kRWoYQcl`jx}~q5j(2D(V+_Bpp_-TV)7BMk=qbN0yq{~9FdxUTKeqZ zqC+&lENCUO)pd=MRAhBDx>6(FvxhjcVrE{dQeX17`WZcOK{z^?Ze#j* z=J`{m6^N$!BB+3apDS|zfd+I%yUVDkNjV77CR7rj--x<_ZdF|!IWQ&l)Y$_!;lW04ZZ^RHMZVx#JH4pZ}8$1DF`JD;; zg*%BN5i_ho!P?IgxNLzjay7IBrDXFVJjyRTxJ>_^`|rf?8a!B!Rn|tpgx{f>U7>tO zrse@&pOM6&!ie$LH4i{)2)eRIp?7f$`Ej9JlK-H>uEpkEYpn!~sNY@waNTfI$5&B9 z_nwK2WI^I(@)La)3CM(&*4406;q@7wxZ;SJ0iu{FmymAbZmU!;)#;kEOyny#=MAZt zp%+1wc#&Iz;8QJ4h<`#2!o4%Xxb>F38KKf{I4-v7|z$%wMwm# zd<}X*{~Ee8XSeheS0j_J$O0i%roz6+jGN!g!{Y!%ol><_t#P~fMb9a76YGGXw{Uou zh+TcO0-=Y<>6yse4@-L<{k%>%D^mhzb+#aFf z8}s2JexIU;{z7!&z@Bp*sPJ?0^@*lD^3fOgvLNqzE6eJ4K@m?;~3-JdjkX|bc>G1n+g7vA7 zy7&adN2QqxL=!NjL(*`Va8cMNS4d2bgxVJ&$*QmQ@`IeJh0r%epQWX5sX5E6CVbSA zE?Y|2oDl_3p(`j>T=&%I zCAZ478friOI}M6yH>DU^0OCq33y5&bY?p<}H#8C*S|tsGPgHnoVOXU$#j-%DwrCfA z2^-bpdKp`oI?Ge#+?Cmi3cJzKXpqYh^nws%dYu~SroxseHip|s4=SBc^|v0gw5eJM z#daXK(o(Dvxl@sRs1O?&iUzMr@WLKAGLT22M!6|gHTFQL{mamG8W~WSJ&+5dgcpTR z*BO>W!0Rwd78c3Zm!R>-3L2-i21-Y9t}#}})mpoR>ba#Vks3^^sp;L=$V+3l#rr