From 27e03246bf331df967794a51bbafed72175aaf87 Mon Sep 17 00:00:00 2001 From: pavl-x86-machine Date: Mon, 10 Mar 2025 17:39:32 -0500 Subject: [PATCH 1/5] NativeBinaryLoader: limit the number of loading failure --- .../snaploader/NativeBinaryLoader.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 6bdf0d0..5bc1be4 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,7 @@ import electrostatic4j.snaploader.library.LibraryLocator; import electrostatic4j.snaploader.platform.NativeDynamicLibrary; import electrostatic4j.snaploader.platform.util.NativeVariant; +import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.throwable.UnSupportedSystemError; import electrostatic4j.snaploader.util.SnapLoaderLogger; @@ -84,6 +85,10 @@ public class NativeBinaryLoader { */ protected boolean retryWithCleanExtraction; + protected int maxNumberOfLoadingFailure = 2; + + protected int numberOfLoadingFailure = 0; + /** * Instantiates a native dynamic library loader to extract and load a system-specific native dynamic library. */ @@ -234,6 +239,10 @@ public FileLocalizingListener getLibraryLocalizingListener() { return libraryLocalizingListener; } + public void setMaxNumberOfLoadingFailure(int maxNumberOfLoadingFailure) { + this.maxNumberOfLoadingFailure = Math.abs(maxNumberOfLoadingFailure); + } + /** * Loads a native binary using the platform-dependent object, for Android; * the library is loaded by its basename (variant is managed internally by the android sdk). @@ -264,10 +273,17 @@ protected void loadBinary(NativeDynamicLibrary library) throws Exception { } /* Retry with clean extract */ if (isRetryWithCleanExtraction()) { - cleanExtractBinary(library); if (nativeBinaryLoadingListener != null) { nativeBinaryLoadingListener.onRetryCriterionExecution(this); } + // limit the number of retries to maxNumberOfLoadingFailure + if (numberOfLoadingFailure >= maxNumberOfLoadingFailure) { + numberOfLoadingFailure = 0; /* reset the number to zero trials */ + throw new LoadingRetryExhaustionException("Library loading retries exceeded the maximum!"); + } + ++numberOfLoadingFailure; + // Jump call -> Possible Recursive Call + cleanExtractBinary(library); } } } @@ -281,7 +297,7 @@ protected void loadBinary(NativeDynamicLibrary library) throws Exception { */ protected void cleanExtractBinary(NativeDynamicLibrary library) throws Exception { libraryExtractor = initializeLibraryExtractor(library); - SnapLoaderLogger.log(Level.INFO, getClass().getName(), "cleanExtractBinary", + SnapLoaderLogger.log(Level.INFO, getClass().getName(), "cleanExtractBinary", "File extractor handler initialized!"); /* CLEAR RESOURCES AND RESET OBJECTS ON-EXTRACTION */ libraryExtractor.setExtractionListener(new FileExtractionListener() { From c4501e2106d56b4cf307b2f69bf30f4c5a0ec866 Mon Sep 17 00:00:00 2001 From: pavl-x86-machine Date: Mon, 10 Mar 2025 17:42:29 -0500 Subject: [PATCH 2/5] Throwables: introduced LoadingRetryExhaustionException to limit the number of loading failures --- .../snaploader/NativeBinaryLoader.java | 2 + .../LoadingRetryExhaustionException.java | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/throwable/LoadingRetryExhaustionException.java diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 5bc1be4..d6e2894 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -249,6 +249,8 @@ public void setMaxNumberOfLoadingFailure(int maxNumberOfLoadingFailure) { * * @param library the platform-specific library to load * @throws IOException in case the binary to be extracted is not found on the specified jar + * @throws LoadingRetryExhaustionException if the number of loading failure exceeds the specified + * number. */ protected void loadBinary(NativeDynamicLibrary library) throws Exception { try { diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LoadingRetryExhaustionException.java b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LoadingRetryExhaustionException.java new file mode 100644 index 0000000..fa594fd --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LoadingRetryExhaustionException.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.throwable; + +/** + * Thrown to indicate that loading retries have reached their maximum. + * + * @author pavl_g. + */ +public class LoadingRetryExhaustionException extends RuntimeException { + public LoadingRetryExhaustionException() { + } + + public LoadingRetryExhaustionException(String message) { + super(message); + } + + public LoadingRetryExhaustionException(String message, Throwable cause) { + super(message, cause); + } + + public LoadingRetryExhaustionException(Throwable cause) { + super(cause); + } + + public LoadingRetryExhaustionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} From 85c3349c6ab80d2dcf61c7ac5af829eb736d6e7f Mon Sep 17 00:00:00 2001 From: pavl-x86-machine Date: Tue, 11 Mar 2025 07:04:35 -0500 Subject: [PATCH 3/5] Gradle: updated Gradle to 8.3 --- gradle/wrapper/gradle-wrapper.properties | 2 +- snaploader-examples/build.gradle | 4 ++++ snaploader/build.gradle | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f398c33..c30b486 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/snaploader-examples/build.gradle b/snaploader-examples/build.gradle index 057c1b7..989f057 100644 --- a/snaploader-examples/build.gradle +++ b/snaploader-examples/build.gradle @@ -52,6 +52,10 @@ tasks.register("TestMultiThreading") { application.mainClass = 'electrostatic4j.snaploader.examples.TestMultiThreading' } +tasks.register("TestRetryExhaustionException") { + application.mainClass = 'electrostatic4j.snaploader.examples.TestRetryExhaustionException' +} + task copyLibs(type: Copy) { from (libsDir) { include '**/*.jar' diff --git a/snaploader/build.gradle b/snaploader/build.gradle index c5e1323..5aaaa3f 100644 --- a/snaploader/build.gradle +++ b/snaploader/build.gradle @@ -4,12 +4,12 @@ plugins { } tasks.register("generateJavadocJar", Jar) { - classifier = 'javadoc' + archiveClassifier.set("javadoc") from javadoc } tasks.register("generateSourcesJar", Jar) { - classifier = 'sources' + archiveClassifier.set("sources") from sourceSets.main.allSource } From dfdc3473975cc238a03128f4e50a3ed900bf0679 Mon Sep 17 00:00:00 2001 From: pavl-x86-machine Date: Tue, 11 Mar 2025 07:07:08 -0500 Subject: [PATCH 4/5] TestRetryExhaustionException: test for retry stack --- .../TestRetryExhaustionException.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java new file mode 100644 index 0000000..70de1ee --- /dev/null +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.examples; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import electrostatic4j.snaploader.LibraryInfo; +import electrostatic4j.snaploader.LoadingCriterion; +import electrostatic4j.snaploader.NativeBinaryLoader; +import electrostatic4j.snaploader.filesystem.DirectoryPath; +import electrostatic4j.snaploader.platform.NativeDynamicLibrary; +import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries; +import electrostatic4j.snaploader.platform.util.NativeVariant; +import electrostatic4j.snaploader.platform.util.PlatformPredicate; +import electrostatic4j.snaploader.platform.util.PropertiesProvider; + +/** + * Tests retry exhaustion on a broken library. + * + * @author pavl_g. + */ +public class TestRetryExhaustionException { + public static void main(String[] args) throws Exception { + + final Path compressionPath = Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", "corrupted-lib.jar"); + final Path extractionPath = Files.createDirectories(Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", + NativeVariant.OS_NAME.getProperty(), NativeVariant.OS_ARCH.getProperty())); + + final LibraryInfo libraryInfo = new LibraryInfo(new DirectoryPath(compressionPath.toString()), new DirectoryPath("lib/placeholder"), + "jmealloc", new DirectoryPath(extractionPath.toString())); + + final NativeDynamicLibrary[] libraries = new NativeDynamicLibrary[] { + DefaultDynamicLibraries.LINUX_X86_64, + DefaultDynamicLibraries.LINUX_X86, + new NativeDynamicLibrary("lib/windows/x86", "libjmealloc.dll", PlatformPredicate.WIN_X86), + new NativeDynamicLibrary("lib/windows/x86-64", "libjmealloc.dll", PlatformPredicate.WIN_X86_64), + DefaultDynamicLibraries.MAC_X86, + DefaultDynamicLibraries.MAC_X86_64, + }; + + final NativeBinaryLoader loader = new NativeBinaryLoader(libraryInfo); + + loader.registerNativeLibraries(libraries).initPlatformLibrary(); + loader.setLoggingEnabled(true); + loader.setRetryWithCleanExtraction(true); + /* Native dynamic library properties */ + printDetails(loader); + loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING); + } + + public static void printDetails(NativeBinaryLoader loader) { + System.out.println("--------------------------------------------------------------"); + System.out.println("OS: " + NativeVariant.OS_NAME.getProperty()); + System.out.println("ARCH: " + NativeVariant.OS_ARCH.getProperty()); + System.out.println("VM: " + NativeVariant.JVM.getProperty()); + System.out.println("--------------------------------------------------------------"); + System.out.println("Jar Path: " + loader.getNativeDynamicLibrary().getJarPath()); + System.out.println("Library Directory: " + loader.getNativeDynamicLibrary().getPlatformDirectory()); + System.out.println("Compressed library path: " + loader.getNativeDynamicLibrary().getCompressedLibrary()); + System.out.println("Extracted library absolute path: " + loader.getNativeDynamicLibrary().getExtractedLibrary()); + System.out.println("Is Extracted: " + loader.getNativeDynamicLibrary().isExtracted()); + System.out.println("--------------------------------------------------------------"); + } +} From 7dacc8e9a31ac1c1cb72e8883c5165bd134330cb Mon Sep 17 00:00:00 2001 From: pavl-x86-machine Date: Tue, 11 Mar 2025 07:10:55 -0500 Subject: [PATCH 5/5] snaploader-examples/../corrupted-lib.jar: added corrupted library for TestRetryExhaustionException --- snaploader-examples/libs/corrupted-lib.jar | Bin 0 -> 27686 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 snaploader-examples/libs/corrupted-lib.jar diff --git a/snaploader-examples/libs/corrupted-lib.jar b/snaploader-examples/libs/corrupted-lib.jar new file mode 100644 index 0000000000000000000000000000000000000000..7a02ff8a958883c2e1287e732811afa6180e1722 GIT binary patch literal 27686 zcmbrmW0Yjuwl$iSwr$&XR;8Vlwr$(CZQHhO+nJTNo%Q8Dd*64@J@=gb-q&8VwSGjj zzUCSc(dQU*^fBi8DFFlw2><{N0D#YAt_JW=F9-l&04X7bA2edp!gQZw002L~pvVB= z;NbrYiu`ri{{xl!AuT2>B(Fd#C446}F)k@VLpuv2K|?t;FsZzxN6$FJG{Yn}b4@2MIVGlOGet)^LMKlBjdJPN!QKJj*G<8|wZGvv34Gmx|Lgq2 zh(GP+@E%h7Cv(571pv^uwxs*d2#CKBW|oFbe*=U2XPB;qg|+@az<+-Af4wX1{{{kT<}5cKYJ&&*T1KS z$oP?37+}^RFdZV|U5R4^R*@7gUZ48^4y%qUkzkH>{!PBWT-8I!u$%joWk1cc{gi1h zP2C9dN+BoLBTwtCqG=(op|Havxr@c^e(*>s6^o+JxHI=*3WTWN$b!C;MlK-aW zygD46==KA!oOzP|3mr&Yp`FNJ%Xd@lu4K0z^(L#9CTm__|{C|q%IJrO}zDJba40S&o82Ny_InaLv{8^YJRY^PG`a+?0K&8WIF?Cj=efL4`;?ny)7h{gB5Mj-kYb z_(iDOUF0OMLXOq-)0h*<|RC#^a=Y5hLkV<}Si-gU}O5mZTCbpKr zS_O4q77M3Q4UJF9m)nJf{{fSVltofA;^@cb!$R&d_KwyfA%k@Y--)h!x2V@4)4?;; zsqzvw;oL_H8?%nd$%g0cS~YN(VJGe(jlFun(sKIC30Rb zD>RtG({Q=V`+_%Pr1=hpJGYNMkj5M2jq%i%T2%P$P#-5d)^h0Z_5=b+0o9qn(3f}S z*K5!b&951whQT}5!Va8RdG=)a?+^znQDK7QWKzwDjt(bZYy<;0&7dmb2Lu540Q$Q* zf%w1KY5aF=rvJBi5nVeyU1LK5YYPiQeFsxL3&TH&{U@I*70hLjejxJ*XgAz{11DE1 zAUA2RtoZ4Xw1A%{CVwr9-#Y-ee$hZ}<$UHO@vHh7Pm)=dA@11OJK^Tifg+kvTrW-X zYAe%zy7lOCVp@B<3n)c^HUQTJ@H%MMKYRB!sjhOQO>e;?llR7H8!S)%r%mj3+<~7zjLYHkiIY!EEWEl5=`2tSY^1 zqmD&WOV+|NozFrMqFp$YRKPoOeZ0d;jSDI{mYybEd2OVynbLYC&Gdc`vHw?@o~(E1V|&07vm{q8F=bv|dM3Co za&jg@Boj0qYnOp~nk>?iFvIS7OCSBZ<@tdkeb#2d^47vgq2$dr&s40wQhG8r)^Xg(j{AN|ZuGT7BQ%i+$p!PH;bcZw#?{`0 ze65aHIY!uK9eB5c@R4*G`9y`9QRePqDwr)R-^am6b+ZB0>6u~S?(57mo@a&>6pk+- z&Z5z>>;oxO6v^t|iSqbpKSbh0QsM1z+Wg{5_Hi)|xz!xPajtsgtT-BgkXG2S;EY>h zmf7_TT!`4o1Z_&fXIPK1Ag|n*znEJ7-UIY|N+EkVg`0Q-K}*n?Pe`07LLicusQd}^ z;I8x`s9_PsrEdhjSeor94FPC~gtpBk4xu~xCVIq`-uWu&InwM%nieu}^yb{l{pdemZ8# zcdax`8$&o~8O}KO68lxQmJXsOR0u{7F-qRU%-tzqXDaq+PXoU{w*Q!FdnP=Nn_p8c z1oWR{;J*d}j{mEv^Di+WQ~AXiNfG%|3yX8qK}9VG5>>QTFTF|7&{nK8Nv>xN)G`M= zj8RN$o)oaE)yL(n z*5~I@^Y*t25iKDYGZYu*2?3n`JX=qGIMN3P!WJUVDScJ}&E{CvbKIb{rbh%2tsu}= z3S+F%9VZ?x)&gS%@{)&K+%&%zOjI3${LMx?q>F22vshPrqWMjEs(Q%WFlaiX7YEnHbfRRhLA}{Mywd9 zSB;U!wLsD_IH_J%6Qh1HV$9dMZp@y0GY&B|=@xaa^wsnsyhd8QDy>()?IX_NCC;Iu zbgodox?}av&505=8N!1|t8US$;Ff5S0p%5evOp6|CK>Rb24Q? zd<>g4FhL*wwwA_>WS2uthhfieG;)i)&Cgp9qoiXtvV-3bqsV#-kwsi1`djq34PSqq znT{TuPs}~cA2ngFLc1#KkH>-0esxvv0(p$= zT{19q?Fm7YK;-LU#L}QXFn3L;BoSa+XdCo*7J)iMx!$bUw$VeF&C0F$(<_8RX3(d3cnF47q*oL?iXpO>K(q9W^3wuBfFkWt17&IPat*| zi=VCLvw@(t!5GVuxYi619~Ww{=m;6~{f^5fDRwb^yehbsL$o5mwi&qc-HB~>upBHq zUctWR8l^Vg-ZLGJ2)f43jMoNYk~!A(Kjn7N5@N4Z;C%orDE9^C0O45o2~N72X{&6dG0{Wybq z&75|{oRn%CsSPgt2FQz8%B;<=lltOO)ZH~;O7GL~{?hckJ>ZjXWan|qhc6ne$UrMB zljV7XykkmEI!u&Q?&F_=XZtgi|P4P1^L9@Q4Hv{$<}AJkhzl0O#1dz9MO$$a>73t;3a!oTrypd>?s>2WL>%A+mFIik}+#oWl0gn2S zE76t0=SKs%_;>u)mBg(?s<)jFsk!ApO*77~4{U|uFOvhh<@b>lDfEX&ZuS=v$Vzl% z=C+IE2ewQp7nn#Q8c{2n+j=MRQ8~3mSy_%yOmJ^s_;Y2|4b5e-n3v?`iftbOhl&j1 zJr7N0>~VO!V`H`7(f){v2rAi@)n5@Y687(+BH6!p>ZBq0Ac()wPeBrp(K2=ovmhx($ss3c#^h{~9(%4dK9ybaCvM--apR(# zvgY_fAUT39wFAu4iFJsKPEjC;_Hhp zTz&PGaO{Pa{A`-fSGeY?$9{?c@?g5bm>eUC^42+9%-4UEsotMoSbnRd%vWqD1qrI- zD7T~)$vsns;&gyEp@+`s&FR6q06K#cFtvufpK9;Iq5;pC#C4ulbeI|MNf(8SFA$@wYaxtj9|P;VD~+i7KcM^CI)Hb_Y<*$q^?>&7^smBXS<`@)p*YP115>uKx;^~cVL+b_^Av$Klc)NFl>j-0VlRCG(! zT!hxFQU`3-`7ldt|7aVjen%j@e0=(i-JFeB+}^Q5annj-`Z);6Op5zmB;Se5HfT#B z!wJhftYurEY_k?q9RwliEwO+VD@x$7Riu7wZS1p=Jdo}63N>y?wx5hPP|dCM8yg?s zOqotszYu3z&y_s6%mOUd4&+5#x=bH7dn_6)eLq9>YQ&Zc4qojVW!GbN+w#a`>ewN* z24OWHx(g)*;WW2ckZ^+b3*W+KQuD#vA3Twtyj5nTR}Uyp%hrqs9s^;tRDh(p0($Pt zCt7`S##0<$GwxPW?F_iKt5zPAhCJ`0mfJKR>}J4mT*nn(bCb(h^J8p7!}IRWW+G)9 zX%gg4%_6rukWD`#?9h^4q>kmBakI1K>&KnhwuxR6Rs^1y?vIe%MGuR!2s5+2!gjOu zX6T+La)PHh?)ND{Ta8UM`Z+X$g)UT(fT>hK^u$2WY76?DcVP|pzt>Aj#m^)UU~%Qh zlkfy4yu<8yd7WZRRZCv&@~02zSZEnk35`hv`;n=?P?o0FO7}U79ot+RU~6Clqp9?> zXHz~$+gkdJzSE&^^|yQDo6AbdToC+z9^76+(s1=FFLnLYc6r~cMyH!hNmknso*gd^ z{5B+k#3t~r%b1eWF>MdvNv@yS)oM3`R-z3+HyuzOd)+w0>y;12KyI8B3qLz~L?o*E{!CqLu9 zg7>8aM_Co+(i6wrjFJWxG&ngFEqdVMwPUk^np!OH;J7itO+u+{-0E)iO|15R=p~(FqhW$h8`cuPl zbTGB}8zGD8KU^WL>tO2iSHiFOHH7_NDwf=))jT~qk5+x*BRaJ(I-MqLbb=7x`YXENKKBtOO#LNIXJ6^nO`}dRZF9GWXst1c3 zuEr+}t~yGH8i6^;fnVUq-S{;(Ze0Ps3g;dN-4=p^+J%=7r5UduXHw+5B4NEvN^O4( zBtg85h7AIwn0!$mliD=|*CB`E{D>T|ls)Q=is_}nH9>K$PH8lX--oLhtsXZz{evPB z5nwfyyl@TXO-5#9eM%`EX@Cw-90ZDIS<5Qd992~dYiGzO)kmdtYge8tLA`vE7>lR% z0I+(c7FV7BXe)GdaUhfFN7}qINdDMpa=og3%mnu0SUyzI(VFSxBzNmWRSt9Z7)1Lb zPx5)=8{1`7M;78U1s00*E{U36dIJu z;&x9M+|DiwW?NY@VTCRZKFfyC{9aJMRPYnF)o#}yn2X6xY`-OU)APVCs}uF5p3IT* z&3#cVPQv)xx9xi&qu0|Mzn@Ig7Ts^&-~OPNpQxzv!WXri{?e8Hz3NHww`38rv$L}P zlO}<3`<-2#I zI&*q2m_VQ4WJn!94L#_5wT@dP>$Lll;yYb~eBw287Cz}iRhW-2RREdB9V=jKAX$M? zG%XkxJYcQzSrJ`EvOGj$nf9u3-`H9+D8hT%#QwW_B_vp5)GEDP!6ju_A5F%CdS$$7 z%eif?gG$mX6bQrK9>IuWuA%X#6Z8RQu?WKz`K+N0tfMl$f&fOi(b^UG-J%luX>L@D znLW`3uMFp?Glz}}#BY7i;9NqmN@ml{s7*tlXW`ZO01>{Z7gt(#DzJE5Q-k){F_Fv6 z;|0OJ@P^1nhzFK8X_aDM6rE%VQ8@6R;)Zo%g8+HFs@^Jc@*ND%&I%46e;Jj65j?hC z4lVek8^mfm-$;!nPCqXG1H`I3B`)4Be?$J)|z)yb#5)jwx7Id#FFyK)gHU-~Pph{V)0BKRX+&|G)+d zYh43FyT9={)PH}Wq^X{ruAQrxmC;{pij+71lFre+U^mxh715E3@V5YR*L}top`h#_ zhEhQhizGs_+vJSImPs{5_PY1-_?ameZ zVFEwNVi{Hm!|qhdh(r6paa*1~>`lRY(nM`t*x%0B+D~4z=sM)*LSzjZqwH|YB>O{a zyjyUIqO@C{4x)U=v~I3cP~MtnacPlv!$489jP9G`dSjD%WZFSDlNoGf0_VV}vvtfO z&%8}pkhOiQDAR6GrWi1uW!+`visLf48ZQluqg^>;!I@Ictkub)Hh~{P2?ki9co7m# zN{(G*@-l4mf+b3M0gZA;lC@g3WfmXOdgei%xxE7_ki&dHqpp|rae44>@b5+e+Q4ZN z%w;Kr8d*mA%(o)Ef%hmU66C|o`s6d}&`(9+d?9)P+Qd9vl*X#NfT1kXGPjKga#1jRA3wJ8irAf``w<=szrTJ z>$2kJu@Cb-Fe5iORG%Ya&t|m-^GJv|f&zc~#VbQhRu1srh?8?@&>$UIQpc>o5(oLJ z2p>A*&tbxa1J8xx>A3e%1dL5i6_v~thS1C0zK?p6c|7{Yc)COl8^hDm+k&1HOnzV) zVSWr;g}T*581Fv6!~HQ;ezHn3rhH8k6Og}K|FHZ$Kx;idxu~X-k#kn2v6GWg_s6px=nlf=8hNfo?%ob!8T6!zOy{V=xvK^Rj(fc% zrHm;r;?P;>L`GA@L_lmtF6WUMsa(+86|lMM!}{}Y_v2ond|v_apb zX}ixxFtoeX@5+fi+u&~7(DOrsX8d-J)ej-3-y=;9*b676%GlI-y)}z>`CH|^vhX~3 zz`Er}&hPYV)^P91vew-wAe%9}TZ4Fs%C@7uEYwUYYZ2szgFmeOel9lpaMFjpylAXOz8YXDl}_0RNd0{{pMQDTe;;$1{%@)CCvh@Wpj@yOF?iTk4eHX@i=@(;#ByOs5|~L; z#U&_!eTg^cXwn;gtu}~fSdgAHq-U~ot+RIh#Dyg6LQ#|TK!it*+jA-er{sl)M*%@; zq$DqS21Ew-b-O$_Xg8g2sM$`=T>ZWEd*hDps?&9+vHkK}jT|*NKHLkY2OU78@DUec9X5@Vyz9<(_D4SZ1 zS*#1KtP41!?PHP(gEYlsBR}~le8j0|Z2Sg7Rmkaon>d&ffdD?Rh#bIk{JL@)F6toI z-=_?XSKtmyWFj)kmSV(|MkTjLk)%T3f?q>n3Bs8VqpHpztQBl6sNq>aF@r+M71nVY z3Mo^v(>5pB$2e>Zdt~%IT<)h7nX6rFa-tMzQ8@cqO+aqjCLWxoUnG!hmF||IT9_Id zf+2G$HYjk2{M*(!n*&lG!>B6uC{kxptZiJQ+ipo=F zltpISl~!7snqX>ztilV^Kjq?X=dx0Vli%%0yo)YCu-;_B*PBkVgipL&*qKKhyyv4?&hftV!V_|7UI5F)6dU`f@HFJgV z<`AMj{XSr}3=ZR)hMyLUwc=`}%qc5IG*p6&t^w(E9^!`EN%??#G!za z7MQ$VdNN$PQuQrS5CM!W1XMp@ul|trq^JfSV}6ztAS0sH#l}Lr`9s;3B2}vJ@RZLe zI80bMO)P-DcNa$V+E5IF^Sz2mvi_MYnS3cARk7nu!U*LK!+Fd~spOq;DCJ4Wzq2-OW2$yVV&8ktg^1j*LEw56%VRH|F*z`>=0OvUb4XjeK?UQq!CQ7=H%cQ1r0 zL~?Ob==QGd2E_rs9LOC^qYZ^x9=U>_Rf*5=yc14EaBx_*Mb?|PCvMy;YkZXS_B|08 z4-on)&5px_@#ws?HxP;O-wq3o_!`%WiL2!I2#3dZOjagSWE$2Q2V`&F8U|pVBYFVM z*d9qLROT4C6IhBSC+Fk{pgVoxr4ItmZ1X8SG&?=D_Mj-!p&~Vn`ozeKy~Os$%Yr;0 zRr*VM`ULPZZ-AG@pi_cQi`P4aouIn%c9lZcuNU`AeK%-o+&G%YP9HOikT%!y;FRTC z)hLwP#}>s~IrB9(jo2SW>n%A!)pNdYCD{Np@593ABkr$oebCyb)ETXQ7$DfoKd;Og_G7{soFc9GmzdIXD=7)c_3l2m8!-BhQoB6U&S@OW%b zrW`vBzRo=2HSWz8Sk@DPEb92ZdNjBC3q8kITn)pqaOVK5n43o_Gx!8w6T!eqyrc6W zkaHyDOfvAq>V($CZ7hcZ=?xZWG8mWqNW3CK@Ha61~YBax!HtFL5d!(R(1f#q>fUR{wR`!W1%i@zEJTM&cdATlcg&rf?HP=OY&-H*ea>&?eU;JHU52Qns zu#Cv9cQa5zr*^M}_+`|4@27|FSau(@5y zbPZR+YJ~wxTZ+5Rp0&)eeN);*^iFL!VY39wwMwGB4lJAj9hP6pK`h18ltSw4RmOFk(==(9NQS)>@%-0@AP_pn#*2Z`sIwXL32RP`zelj`aXTh~`Q%Hu_K4 z>Gin*@BvNt5l_U$jDq}VunNIPKW3pl7Lz?5W71j&Y5g%}Gy?o{x7? zklfRFxDW53?lH{BH;|Z{dCW1uW*TB> zchG`F(Kn^W9IOb}kaavMZKR;a+24@cLO#-GxZO-dod+l}{}#PiKRYrDKfG)^q^7XL zpW$bd^aF%#!($gn@EeKH2px>63iYls8xy0FhwzAq=alq*!{&8ytp{>1vr^lYapc}F z<|*6lZRRl7x33yBdzzdISJcD%R&bI#90!5Gg&u#i?TeG#8GfZSwIEuVtDbh`ByBAJ z)?#@0xL__8*bkoW8Nu0I+^UW6$YA%DY)Ij%;7whw z*kWDSdR_3C-E?GqD1z;ACdv#qRYnd~y@VQPZ3O@?zNsJ_xDX{=dCk8ttw&ptpf1u> zj&b5qDIEn|aUQCSmo9bHHg^2pVw4#%-rn=|yWIibI^}h?1v_Q+w)xN1qx~lD3XitH z9Z_EQK3ejO@wSv-Kbfnfcl`_TM!8dW@b-xUWwv59$&iY;?D;!Xo*B+T1BMCVUMx`k zF{xIg&)m)CSL)%irFQL`aX{^5U?s&+gUHaPpVJq;qn^1ne-zvd$}TiS>>nCZcvOBW zjUBbG#=N9!o^cBA?@uu(=OLUGi7CDS7)Hyz;@9606utMC?AGdH;QoM*Zq+Db??zuF z#1Gqi=iJmU+#-H~TrREOQLo-DQvTU{)tB7La=@8_Mj!3ne6+(s+-S`fW2cOHI?Ol`fDhX|eEnfpYt}*O-03y14M# zIl3nNDOxteMY=bE2nFPv(Um$$_}=CN7gbkgspDZnYDbmPJ<5n@T9vM*M!R5KTTj3% zmb1D>sB5h08IyJHn6~K`?wA`zxLi|Yo$eT-#oQPP)k#%h3Z0P++ckozZwiI@2D5F4 zPU6iRqr^m!H)^hYLKx$()+%-I?H^^RCLyNmIlHz}6S?l%eH~U(3Ch1*8bv3@S##|- z1b063-(M^+e{Y3jyxH1^@r4}*IAJ~G*n}ASVOIDT3G0P}~h_f|Mp|khGF3cI5EYsfUa5|2rQNbhXm8G}Zr04)`k{Qe2l?S3=eV+cqHblLe$9E=(xs zWd->G$P6N0(@S9$Y07}UQQ&B(?o&dIpnf>FF3(5K0ArA5N;drwgapcy z!DDQG;keX=eUknA^Bt=P*y}Dg@&|1SiEDGgRx*kv8U>h!xgpOY0R6!c~5Jv(wCHPVHH$EO&xLDicqM!VArv5{)AThu%mon1CeH-0q0b1 zikho>DbOr}bjRX_jPpC9>V}gmS*F~+NGtEoLeK;QJDH2nlWF?L5SkH^0ZbhL2nhYp z0b!a8V+GUHcnqRwv)G)J{D(iYy^@;Y_7!@JOe)Gw6iNYxY_iXC7;FOjFuJl4ZzynM zXbr7pSi+!*XdD9RTCj&OzRg2R9!k~|@`90&svKezwXVUY0z~_e3&aqQw;3tG8JfM1 zECl#~%n51n?YaEwM$+Tyy9Mpq|AAxI6W6jrW>&UK!Y5P)tZjj9$TZoPiA zTnwW?VJS>d_(n0usKx-K@T=N&vP(C`YOyZ73iV+e{2EF{|Ja4f^jn?}OffP^p^nmN zVGeOe{veSXL5_S65?KQ*B0j{(tcJ~%uMzU3|D8^t)o&BoWe^9boGd3+Ul%!b!lv4O z>r|dil%UX`&!H;*2 zBF(|#ZCc#&D3UdYm$KsERk-TU`v|!u_G*DkQh2tdC}GTZQ_JY&-Cyv&;h#BI9Ir?Zi$`4?COO^P)?Ur z0pc34p0kRf_6B6R&&auAvEt3g>Bp_qdfSBGwcaoF&;Fi%0V7I%i-^|+y8qnNd~K*U z$b?MU6vXO36mN-UMkWAb3L!6&IO-74CwQqvx>fxqmSs!8=A_JqCZupwUrKh z6xv}eZ-@tUo;arnyzFHvHc=LT9&7!T0b;LV=B!Y`hluhxYEhg?(CazOYaZ7 zKQj2(RMGaZuLfkKFNgP^i(mhySNI=AnZI<>KgAyqMzWh;;x_Ur_EajS9Db7ekPk}m^WM(omRWEa@m|C;_d;GhuHe(bn&)X{B*uH!H zPYH;ln)jIWr_SlSj;D{2kE3nAPtcg)*dBNR;rjJcEA?#IR@1e#wHs)87R#*#9LGd= zVP$KZ;hm&pU;zbTXj?U9Dynek)-|zFq243|VoxW-&Ngc7VuO)Bh6NRbLsJan7$eaL zHp<5KaL1s~H?rs$KR;(A(Q)>0duWEq2Aa%W3sUv<1I?ntT^J-#f-3 z8(+ZRa4HR)mYhG5({Vg62>LCGqBU7s&rsj69j6&8lxq3>;IALHlW)H98iXW6k6({L z6Q$-)sILZ%yc1z0+XhnJkJRFwL_G!k;DD4yxYfr{wv7~Dp6guax!xrPY6+lD%r#QU z9Hx-mi3cV%l>A{R3a3X=XQYnHMxDIdmz&_+BERf?d7M;)RFLOvmhS_h85AK97k_@37AEEwhz6~ci<%V&UWHPb51 z9=a7h4zqiZME~v^rP6$DBt&NYT>EV z@a#Q_fI$KFS~g-I)ciudY#U%a)X|_L=u8^4l4^wmm4R*GPsdkW{-E;{-Z#!wCeKHh zI^(x5z5<%_2qa(xb1cG*@*lH%WNzkE@n$=g4dQ7POta z0*Vfbz=KDITg>xPykflWU6C8v735me?4ispeq9U%K@dVV+ZzRvnp$s^=`Z@gz*oZC;&1nk=_(IgZ0f{*l729GgsmiYN3dfe2t;MdsZj0`Ccuv&)Pca2$VveOyap`=?vm^UJhZz%(-9&(s6sK zzvElPIr2PeqsOSIJHHP+ZG=&3+R&@4U*K2_f@{I#mQYPwxf*{LuOtF-fPP- zU!6u9=?AD6^w0Gh+2Us;C|y-E4Y_86boo8FUxf~qVLrP#9!qTug7S{E%hQ; z2GF%%w9Zc(_A+$KSA4wQKs8ZhjEK-_I1Um1QFjYFS!gT5bap)bP|sONm@s6Jds#O;$)@qShry!d zjpF?trb}vu<{@f1)+Ij~#_;JH$Cs$;M{C|6Pw$W;^!bNM!o&biYA2QXd>(2scy3S;c?(oF#&mu4-B5PAuDE;x1qwFBD@Pib_rHvTOLEMnGB|H&O`@PNyZ_I zTUw(8FSmL4Nh!zC##Af6mkDtBMYbN2q5099V=7I2Il1 zBa_$eZ7Sp~ICQFmYjsui#xz&KX-EXKe4$%N>?F$Exnw9{Z%K{-dO?1Q&c*&H!U#X8 znz;=dLD1C88SdF%LGuRugRn93cEO5Y%5~gV{QJ+bkL~Z(>woG1k$1IsFtq%tA^+Eg znM7I5e{3*l7ILZ-YPco1-Bl{U^Qs|;F_GK%7tF%c4wG^r?7#e8Y~`G`s*2>5L>D8v z2X`%ka5;mCxQ=GT=sdNt;XXB**}dHT8(>9XQ^2=o1C388CFGv^TqS?5o~~6~&r}?L zBH;$0K44XbQt^=~cg4iX^BK6>K1-DYTtl%mLWJBt5gpbL6KRWW?RR`r8d7Pk^!Tto zAkLc$zY3&6(voG&L4Pi*(ok<}!;i&Mg)x^P5I^gOlI)t96a&k|ngBz%>C6X|z9G%t zCuSri!(#Cv%f!!Tvk2CJK~tl4TqOvuSloaQ-wha{xMT8(O7T8HD5pt-OmAF~eDwLn z;u$HVo!!eb6~x2U@b@G*=>iU9G6-WzOPtUGstCI)Tf3o01>qIT?REL^pI@C%nKiu) zeS$oneNj_V#Bd4mYME2@7i+SEP`EYf@21>)EKz6gr@13oC7rE+IGTAXH?-H+G}&X= z!OpM~_ANd064al2V}PveNzb6XI#75wakBJ!yX|h}a{W{mbwL8v7%1r0n@-DCU;j85 zcr;nwRpwXyV)TDhiP`?m{wxbqy?>O0|J=d#uZXWt0scT(m|8iy{0;7_B{4+9MzQ`~kME#}yTUC*RHKFH9aG4TXyB;NXCr z;fjF~2@gU%dUmz(rnNO52fVMHIkh#hy3O_UKE?5r>HOqrak+k~*}7m<&yatxKRt8E zf2fGQPGW&fr60daY*Z&iWeZ*#zo*xC$$0QflmJA@J(MCAkl<@~0`&+#LE$mEf5gm% zD{xIaD&$K91VOuIGG{tPp=5~eoo6mE&WO2au2hJwHV_w9PUMVpY0x{(e)~v3OtsW7 zzm~*MQe~Afp4M-**M9jfOT3EpW}~M}$M`7&rOqF$#ZyA2E3e#23#Tjc+I7`|9IzZ# zgzLZ~4>4@R-6}R#>%}z9Tg`jD-aHf3mT}D?6@A~TX!&h~Jfz|IuIG93Jqgj{Q2aF^3|h2f)q<( z>hffAb?6Dm;#1n}2ob_1uD@~MwyV+8852RX?u9PeB3Qa;E!L8H$oe_I5S5n0Zk=L; z*Ne6g>_`u7HrEU&!Jp}cwPQl#?Fx+t`qmooDtdam=_8$KM~^BP-%k@@rT3B#M2B2Q4|dcmq8$) zwHOR=z#$s|7l#v-d{II3>lwX=M!5b%T;YkItMshBLFGfR7%As~_A%JLe% zDR-jMb`Q-`Y5af{*p`tgBUn3shPGPsYBPt3ZQW;IJ~5>f%)|+9(GukJbin@Q#&AMX zaJA2A88jwpz0b+h8hm_MmLGVg`D|jrG!#!kYiVu4^m~D+0nb`y*z4Ra0hiv{vUvJM zB(XI0B2%w>Xt~)dmRG$c$Z6WK!ZX7JJguD#;lTI&iLX$M16f* zuDH{YW7_F;K&X)ZPLM6oLmML!@pZ}Mib%&u^NE2-O&@D98L+ew-^zUZ;?P!YYiGKv zG}~xSQ%`caXqvMz*`#?^{Y`Mjx_OUW5?8>5y;kfGYA&)cwMCzCx+1dG~O z?sBXXlA&UMXG8IH>N^k6je4i%&&C8KoKvgX@sbD`3C9a@CP|WPOq5OxYqV`|qEB+% zZZ}dz#4YKE?{G&qAx^lpbOR!tZs3?BQ)H(2T1RIJZeX@a z&N=N!*}_w%8>I!6+CwsJ6#ENa7-yg(DjYULAOc1nUB*5U=`KUvQf!P?4W)N&U_89z z?m_Mz=cnXZxtJI_tbmHw-(h*>g4Y~UgFlLsvx{CqQ+U-2KyOVxWtve7#u&X#Y)+B( zOqx^OS>ijSH^uw&`wTk*b;4z@R!2po2JdAXUU55(G!{SOc{+KA<<)xg`N$W1w|)rB zR-NaHCMpY_+IuT6bVlP5c7@-Cvv;dpdpbyV(q7vCcs5YUUbeV>EqNEO*4*OH-eqka zmSea*72br(>I_@fT-6d8p;F>K#^u@6-y{ltMZQ5xxbrs!ra7O4bfb$Ug+X38k^epC z4W0r$@L4y(?y6XI@fLSIpCpzcInX@*deC*x6aDz6e}Um{x*bqBF5QbuufD#xC&BK> zv`=1EJaVs|qE$Fv!Vc6eNr)oO!Mm-c6;ZycC7P_Id?j!7A6AFUvf%$rV@z194cE6%nb z&2DH|Yll93J!+NS^^fy?hjXJ5cAwL1+~^Bf&hJuOh6L5Rf>d!Rn&6_4&$35(vqB#{ zJJV3De{_QuFzm&Wb|Jn#eIKto)n!}ew|A!ibwMjYm;-i2zeWBvOW}cNwI>j+lV~ z%UBioJ_>ISmaac~Sn{2OfLh9qQ0(kSWf-tJe-ylog+&zk1Wr`oO{mmU5IZZfD-n_b03W49u1?=VK>05j;`hnE{uN;<{^hp=ymT$K>Q6x7exUn-5;4i4SVyU?CF3jDckE^fU?%(ew^4}1n z4~a%?#|0UdPUo@b?>m^YMGw_(4^Q?C^0-w*7Z$H5?h6OcW)^=5k zCU;`F;aY`{W?d&az^_<5wL^!uyHiQFI&0Nk6uKv0pF>2<A zaAZxoFZbo!%cdTU-NEDU1sH34#H-X%d|1UzAxV1N2*ZRggC zlqQPwRq@2-r}0sztF@7_o!Zr6I-3>CH&H8qYaP|-K|x#Cjvg2EaaV}%van#$*g=WF zWoN>&n1YRY1`D;4t*P_d4#kdLyA)@jHM0O5?FtDFq+AJAC)Rq=j$3B)ag(3CyVLS@ z(M3#d+>RAN-O+)3(E@0;isB8^Mbbm^3?x~YOJ&dL2#^Xr~1>L;#E zzhe$)@G%$I+l6#n-CI8xCRt%vJ{2mlP#^-lcehA8K&SHuYH<*}H#)U?gT?nkY5H4kfz%`N)$8iSSh zG<6uNTVSKqU-e{l=KaRtzJPZFeaJD0Oaq;3eNn-l}5B&e(7|4WAy6YZ~5BK8m zb`zU2hO*~xqTDB|gM;p}9#}}!!$5r zNw*_d7JbF4%p5NK|5SF>aZ#;ZS3*!yQlz^Cq`O;?Zjfd`T43mq20=O%>5}g5?k)iV zVQA?X8b0{E_kz4$zxP}GbNKyc@BQrOoH@_ToVC{D>{T=BxCTMpcl7S*m3=tLrKJ4k zv90~sv38Tme$o%tU6pqUQ&(As+<9gL34~#D=F?C2PtgK;=1YyYXr7JlSbjo|bX8Gn z(3+j?)Wg-Z)Js`b>rxk6ei;pp`i`m!o?Qpmum5-l)16Z^1xBfa1<7snXse$P<<9ud z><%?Gvk@|wHMqylpR2^K`^Ba^dZ_5uV9Xx|T$&Xr1vLbpRoZ`zd&RZ=G|@GoIQ44y zvQqtB+et1~Vm}6`#mJ@_wdN{t12Ao}uUUH~8+2BF*~gN;k`akK-POb|sXBYks6}U) z@Vx_RHuC6b?K7QPYo2QARdz8iq}FRrz_*W(d7f$H4b5RXH1o3juo^o9$qbC?ry zI_{OgQfe2*xN8_k8Pv<`=l&xN-~3T1Y_DQAs%cGqfWB`VLQr|e5}#j>u_PeqE6 z@4E0Jbv2a)UaG_4QNt3aqL5{iVSoV+J`>L;UvVcN><_fG{Gem&4Tf+?dCZbxZ&TC9 zz!E=HW+mb=k*04#o<`2%TFZqwG6uxv4G(|avNGJcD^8tCHqZ7_Ma|$0bxM}hN)}Jq zmIXs;9+xu_2lg$VJCpp}V@wI^d@ARXmal@7NCe^*lpp2`m$aINh!6*LM0T=9Q-eOV zC{cN9&BLyRe)1qFvf3gokLz2Qzd)!N99FQBUi*crq8YavQeoY#tG#{R$U2@(s(0d5&M1X~h zbpQ(k#qs#+T%7Pb!7h=O_Ja_;{>g1&W>70^Liqt*@`^V;ij(kapx{b1%|*}14IY}4T}ApF$`r-Hksz$MYe~=W1{*!rg&?f(yAeTT|GBnGno{l6I6-Hh+2!Q{ zTVtvXyEl``iS}>Ck|U7f?N$$IU<=2eoe`xYs(zIjH+#L5fUK;649;vVCthcGPMZK_ zZ=?)}9|ak;IpuY*8*A_$PVcg4G(6J=9mW;$B;!9XQak)MlMDA_P!mb^@WP4(8LSC+ zl;QNr)TwP&Dbd(Cu_op!F!ZNrNFWtit>Ib=%P!obr0PwOn&y;uI% zEA8K@{|fkJtu-^-e2wT3p%h(jyf5Gp4Ndb&z>PPQ`q8MndlE6#llSq_n-Am$hn{>Y zV2&l9S(MD;Yb%8yil8zy1RA`Kq559ARkGgL*^}GV>1=hwq9L>5+JJ-S`iaQ^&$VBZ<*@P`9W<`;u(_~nCnhCBiAA)MU=64zv`2# z2NDp8WS?(#1G3a$Mx~Y^rHHbcsA}gkzZpj5LE8?HzenQA5u!wjsR@(Cg?UJb_6%w5 z)D7rsoi!^DTavzvNAG51y<;lu_Uh@i9?6m8n1v)hKNSAunnk}rML$SaQ$F6?`bVqS zSyU)NTpUvWb~*0(hIq#^(sC$*M=5&;dvva<$bQaR0X;zh6>R*5&K|?G|J&+rT%bkQ zeD)ISP|I5O=@8)M-o$>al!wf#%aN2UP1zHEG>`t(`N!^;`U`ah#ogm0c;3p2rcj2O zN{y7K8o*W!Omt2HA_GZ>kuOPapIBdhp(d<-^zrN4a=!yF+4P8L>H*f>~V-jZ6g=Z9R&s!b#NgBe0ksc!7o(@G9zgR!au?t z)3eMo0Kkn@%HyuP>Un4er|g%!5lZ!jch+cl0|zNeE~0@%=7Q*fnTur=IzGE_jNU1pC6o`WFeQWVEtn3{&L zc1Ku75^;7-s^eX7y|!A?^oF7ftpcBe+%IT#c*Qi{cCtz9;MG<5BR%7QgT*ZBFBhQT z7jeA{y|0wn7gJ@ioU*k4pL7ui{V!RY7WP1q^lO^uzvt$BW z2Wm4_t-|2toGwr_wrU3@U(dW0iv1A3byD8Z=gm?fZm%76uX}5!D&2a=YEuzMC5{b7 zzc=05&g3dwov+)BabbG2Rb?VDwfv<&Laxb z3^eIC$eMtc^GeyDuV8#E%9Px~&?e{O8^V(2H8NWw8=oq@F$o>EvC*wqV&$@d+}ek% zU->QddIu877lRuas)ff3JuhTsF+QI_yJxxfz7{>&&Tucpb}A4*e;zrL7Fj1T2i4rU z#$UZeVp)|{XTX3xJnBqcuVJ-aSGTVt{^@^ zmom%pu!vbHT`fQyQz^i->2T89CcTdQL|ye@*??qHE?eM04i1-j=01`BQx1-bA^wJ&(dBM z+gl$MM?R<5T-JSMIHiB6s7l(o#=dC+(}|kvi^^pFq~K9)SY(DhuS5w#`VatU)R|Cl zu$91B0EDd}eBq4VbNc1cpoaD*1m}V@u%-8c$rN-BR8EHfn1{5eV0x9GBpOGIxHms~ zOWXUDE~0LgmAwGQeLdm#-@H?>&fbT!jENzSXmVo{L>SdqSc`5a)E%5i&t+g*@mezS z(l<-#$Lbph=uj4nQA7#XL8-`p-aB~-2`lO>xv4vd8tzE_MQvd8<;5uyZT>T!J=9d8 zf!!rJTJl-_vta zWp_LSY_LDtE9^XwQcah$E42b+_L;YtVgQj@u$yyc{Y7UfQ}wo|>wb{cix6n}ng#y8 zVd%%MS^l`)F2m=2i3v%(s0UD*(1Tp95Tw>*q&?#RtblmNFBjVKSD%LKQJ~%P=N>aPCnI_ zU|HVGB;0X@TyzuBfpnDDpOwjoFMTV!=TIqTuiODOpEkSW<*rt;mfG8p;9fYZe$HG& z)pEz378|DsAHk5&?$2`A@34uatbm>^?|Uh-T@C5T2;b3u5Ewq|L&6Ggs9)hFTQuWR zvWEi_De9^u8>|Z_$A7AmaH^2x!CElL3je`sn+pp)(^oLFV=jekHhIGz4Gn7%A;#E@ zBBqetk}`m)Jn_o}RSLL-s=Tc?Q{w}#YoJFNtWRM`i$9WrlrSH@RBAzgfRIYdG)jAp zrYbKE+u(F5Fn@a~%@50%Ey`0FY?5S#Bum+?Et#&eu)|s|EU{dr;L60YXmAlki;c8U+QlONfAkBmR2Fl@09l3qOdTYsbdYxi^>h3 zx5AQf!@`SSo@xja%NWAz)7hNS;Ety|E*iH5h{^}+m`7`me$4Q)M8I;64KbJoNDj#M zf!W|!XGe#b^c0@Wa7^a)j?oy&3MmIp5_iG@_i3b2gTzt0OpgIrwRu+wxDIqdsoo$SYT z@6z2QmKUMB^jR}FP{mV8Tg9kyo{`nOO=5%0&_x;7!5^WS1-Iq>bw8`E`uzp8wG0qrf*I?9Z_y$&|tYGTz6YXbNZocvtAA;15 znZ>9FAp~PUI!6Jtl2K20tXXIqh?MeU+l&j3zA9zy5o=xYwimS5>y?jq)xDYWb=O#} zpoM<;-DyAinRKNrj>A4mO&t5}802)l8n!n?jj&6@yfheA_w8aL{27rjB+j3_e&w(a|RH zue%QxdbDBehqrb-W0>7H#GMvsBus^xKSn$l!HRUzRl%O~;_--^KME&dOOg!vIMh!F zv(qnhBBl#8bk~JXg!GHWghwAT*@@RuZcKh|$5LNZLSUI83^(A8Fq?)Tw2w$g$vpj0 z&dfrn>Up?182UJU)74IqK{(c|MZe5amlmGR#~fm-447-zGT1%_HM#>dK?5@&k#mcx*o`(0K2N3U(72`kRcr{^{T-S??FI zvu)J&J=__i@#h!VY7IqUL!iP!eGxfiy0Owht_znoi^r8Ao?5yExf-gj6}=Np)@Oie@{L3)@3w zU-`bKM>fi`@8er1!SKZxExvURUVnuKt1I;4J+0(b-g+houZMQt&P2T~pJ^Q|)JR4{ zpI}8G_e#09nm#4}Qk^9);3>;)R0UMbgiL{cM03Wl$!C zEBDCPhd5i+%rLO+T<{+?m#_q7rk+$s5*cVSH%*?XFPS_>l;{iv;*J~vm!OTLr)FkW zCXLk+tp+bTXtewW()UsK)!|~8I}UYZ>9ymsUQ&4(?E_4#IlCEsINze2AHCt$Pr)u= zIKe5+cByuujiK{uh6jAqzgn6Ea*SncaA^WuW^?T{7^i4^Gq2{p``}ywLljJ9aTIt% zfT9$`Sd^Nb*c&pGAR~@?zmTTO%9Be4M(%m)O;BKv6?kZ%3-YaOLo=M+y|{uC zX^t&N#d?8AFJPxlmfnpDXGkloSj*TbqAZ+F_qIu{FPZ=lLZ#Z8y4dfaYb{k&x$~tN zGZ&aneZi`a-VLlFRxpDKAJ%Y2aF~+RR!FgnSby{BvvKW+NhRe$sWEl4d3Eul7Cu@6 zzWF)Ubpj(o0g9Jvm@(PW?_>!3Klf99bqU*JX!i-$$Ibszg+)qQFu8F4DUT=^bxv<% z|Fh!w4;h^oQfQ<{7u4by@gY{cIImjM;PhqlGctcHvZ$wQm=jbO1xp84*wC!7dw|4) zR|w|qdUq>u=a!G32fwiX)@8-jA%z={5H&#JtbK{c)0sI=^3KU{cUx{(jEcf*;3~(+ zy&$bfjLTVvi>fmvB$A|V3#Qebx1=r>VDB}+cE-N(V|-#>^7iU zjswZG;yMA;AGvmZ6SOnjpT|_bnpt##Pj&s$qxbLd-E?ZPp0!qdQv(rlOm-H zxM74c5>AW9BPtEQADOdEI`z9u80~6bc=aBA%C!$?2@z4-p31dn_`!4iK~=llpsQ~| zG4>E(-&YH7Sm$`j-BZiKgrkY?%=F6S0>LVNVk=a4y|v9Et6U3HMLk~UV}kKQuG&&b z&mrmlvqiQ}%g{N(1_3v(b2`7d?@Y(%iEgD&oJO1(2#7DZa`Xrm;zEJEtx@UTuXc%8 zg@%P@VZXwyDN7(9lZeA~+CQMffii;VoOod2R~j&UttTuU_j7n4Ux&O)D;~t#su23g z)&J^Y*NPCXHCbx`Z>t8OkBk2RztfZ-`#H5>!afo21LFo{xjZk`5x--sG&J7U7euya zPmEmQPY;O3h1U0p>L0A-BJYNT2B@QS1d*kcV(eOo>pfqH2sJDvu17X@d%oZ(E~$Z% zsfk!^y!2?TCeL4kXsm*G%ZpTq7vY$QRQvgYvG|;&$SZ!QS`4cV_Ccsc5q|iz6?K#= z#NkWjR_HYP#V!XyJ0Z@YfMd9{EoEU{NFtul3CMDO&Y1v*6;i>4JbwjpFS_X`KZuN{ zpWt-!6PWv_=93vvFN!oui`z^+na+peG8X#G92J_)+PXXPy;fiiBGK2tROqua&sR|# zJ>20IbN`Gr9b|KVE<&DJ-%23NR~;NZrnHsmC(cB8CPL?juLOeycp;C8(jIMAd=7OC zt)5;bh-_jfI+Xon?UX1WUW&-@Ksu!W(dvMv5OE5#5KcafVCsPzWY*}FEzS3a4LJ-9 zIFXVupKR>T5LtK<#dPm_K;+1IKxwVKw8Jn0)d)J0Hn;E#Z+H?l^Rb7JAp0VA*@lz7 zE$)-ojF~YZvN1uFxW$$H$QKzaC2I}&=RQEIB*kD&u8HIUQ+B7`8)rKzxDfNM;TNc%%15xElFdGZ>Kz^6HbMAsco)Iz@_F$~oDHrC}pm#X4mGaC)KI zi>@(wubzts4ePa$<%nN*hwl`plrtXMj1apQ60*iYFlK*vJCGFC3Wpg>$?EAH-H=niCd@Y{15$$SBx?>1#7 zS&N|t#_y-;rcLvLqt2OPMW|C1qQ6bHEds_iEna397uaYtiO0c3zqF1T^D2i=@Tga* zG1KxhDCRUr%JK}IFjfniR?6A%S)6a?`rL@A-05|3x=EKCo-1_`(ACvU9W&N`_AuYP zS;CK$B|PzQ4le%cgP5r^!DR}5dN-nr5>oaN)WEhab)&3(PE!F?y&_hJag8)XuEF}3 zG^iRs7N@BL@r0otGB^6u7V2$N*uc?hQS?YDYD`ppWBizw56Jl#$~9`6gs~I6UL8cp zv52q4wo|=n@|Dh1SA#rc2zTbaxc@SD;k$4i6E-K2y-(P$Lxenw@H07#%!Noe@~$6F z0jJ}w@#1ppViM}jUl)B-wFQ|i1Lvt`&iEp*xuwc1)aE&l&y~2RxD!YA2aL75_8m8` zZ+i&5SAqCEtvC;?*dvDCDJsGd+KmEpw^XNxz6yN33QkFUpS$_R?`S#L9M9R_$6mzl zaASR1#Lm<{u;#D^vBuP{U}mOr8g_;KlrL)4wm4sCj-dgBgFW)yW@z9Y)D1`X$hU#@ z81wpfb?KX*=pi8C9{l9s{%+TY>sQ^uKN~yz+yepv68*vLE)aLOX1MX3yTy&4+&`gr z_Jp`w{JuNj%@z)~D7-%WxuL`DaPLRlJlns;@b%$8u6KVbbVCQY#mV*IKVd)3@@|6v z?(?SRUAz4o?Zqv~uZhq1g8z>VApSJ48^iuvv|j5#?&bbp`~F|YcGsVr{x?){&W@LLPn`$_M5CEhqs z-a_emqW?4L9TmcFeJKBQ=6=2U>#iSR-OK-%|KhLb?ylY5%{%56+y9c`U;G&Fw|>{T z?Z&O|7P!}Uf!_`7XW~2FeShlq#`5hJ)L6ey`HunIuT9^z%DSe_ECnQjq^_x~*MQ)lMA_P;3ci$wK)?z?iJUvtMZ{4w`$G;8;B-xZqN2#RhY&HTsQci!0l zAuqZq^7m?ZpTYI(f+WlOQ+M*Gh#M-|Ev)~F_*>EP@0G4^a(D3Qm$>Vv+1I4B+xO7T zDDSfCZZs~pX#bDcyN|(bEbor~cWk`dOooE@bT&WfZnp!uVdvdt*xj)6ZV~mn@P8l6 z{ki{jCV%{u>~D(Rzt7|iN$(bDLO*->g@bp0GVk&ih;L)Bj|6`gez%AJrSRRI()(@P zupVw9C-HMQe-jn{6nVpfxP|k*$bUEyx2NN#^xe;SzqXS5`vku