From ff583810566f52432422b8f3a5bfc09f16c829cc Mon Sep 17 00:00:00 2001 From: Banks T Date: Sat, 8 Aug 2020 14:21:38 -0400 Subject: [PATCH] WPI Image Test Mode (#81) * Add camera config for calibration to test mode * Add 3D capabilities to test mode * Add resources to main for jar testmode * Refactor path utilities for test mode * Apply spotless --- .../src/main/java/org/photonvision/Main.java | 44 +++++++++- .../photonvision/common/util/TestUtils.java | 80 +++++++++++++----- .../vision/camera/FileVisionSource.java | 7 ++ .../resources/calibration/lifecam240p.json | 34 ++++++++ .../resources/calibration/lifecam480p.json | 34 ++++++++ .../2019/WPI/RocketPanelAngleDark60in.jpg | Bin 0 -> 3222 bytes .../2020/WPI/BlueGoal-108in-Center.jpg | Bin 0 -> 24557 bytes .../photonvision/common/BenchmarkTest.java | 8 +- .../common/ShapeBenchmarkTest.java | 8 +- .../frame/provider/FileFrameProviderTest.java | 8 +- .../vision/pipeline/CirclePNPTest.java | 28 ++---- .../pipeline/ColoredShapePipelineTest.java | 7 +- .../pipeline/ReflectivePipelineTest.java | 6 +- .../vision/pipeline/SolvePNPTest.java | 47 ++-------- .../processes/VisionModuleManagerTest.java | 3 +- 15 files changed, 212 insertions(+), 102 deletions(-) create mode 100644 photon-server/src/main/resources/calibration/lifecam240p.json create mode 100644 photon-server/src/main/resources/calibration/lifecam480p.json create mode 100644 photon-server/src/main/resources/testimages/2019/WPI/RocketPanelAngleDark60in.jpg create mode 100644 photon-server/src/main/resources/testimages/2020/WPI/BlueGoal-108in-Center.jpg diff --git a/photon-server/src/main/java/org/photonvision/Main.java b/photon-server/src/main/java/org/photonvision/Main.java index 85f7aa829..b71fe8320 100644 --- a/photon-server/src/main/java/org/photonvision/Main.java +++ b/photon-server/src/main/java/org/photonvision/Main.java @@ -18,9 +18,11 @@ package org.photonvision; import edu.wpi.cscore.CameraServerCvJNI; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.commons.cli.*; +import org.photonvision.common.configuration.CameraConfiguration; import org.photonvision.common.configuration.ConfigManager; import org.photonvision.common.dataflow.networktables.NetworkTablesManager; import org.photonvision.common.hardware.Platform; @@ -28,12 +30,16 @@ import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.LogLevel; import org.photonvision.common.logging.Logger; import org.photonvision.common.networking.NetworkManager; +import org.photonvision.common.util.TestUtils; import org.photonvision.server.Server; +import org.photonvision.vision.camera.FileVisionSource; import org.photonvision.vision.camera.USBCameraSource; import org.photonvision.vision.pipeline.CVPipelineSettings; +import org.photonvision.vision.pipeline.ReflectivePipelineSettings; import org.photonvision.vision.processes.VisionModuleManager; import org.photonvision.vision.processes.VisionSource; import org.photonvision.vision.processes.VisionSourceManager; +import org.photonvision.vision.target.TargetModel; public class Main { public static final int DEFAULT_WEBPORT = 5800; @@ -79,12 +85,12 @@ public class Main { } private static HashMap> gatherSources() { + var collectedSources = new HashMap>(); if (!isTestMode) { var camConfigs = ConfigManager.getInstance().getConfig().getCameraConfigurations(); logger.info("Loaded " + camConfigs.size() + " configs from disk."); var sources = VisionSourceManager.loadAllSources(camConfigs.values()); - var collectedSources = new HashMap>(); for (var src : sources) { var usbSrc = (USBCameraSource) src; collectedSources.put(usbSrc, usbSrc.configuration.pipelineSettings); @@ -96,11 +102,41 @@ public class Main { + usbSrc.configuration.pipelineSettings.size() + " pipelines"); } - return collectedSources; } else { - // todo: test mode - return new HashMap<>(); + var camConf2019 = + new CameraConfiguration("WPI2019", TestUtils.getTestMode2019ImagePath().toString()); + camConf2019.FOV = TestUtils.WPI2019Image.FOV; + camConf2019.calibration = TestUtils.get2019LifeCamCoeffs(true); + + var pipeline2019 = new ReflectivePipelineSettings(); + pipeline2019.pipelineNickname = "CargoShip"; + pipeline2019.targetModel = TargetModel.get2019Target(); + pipeline2019.cameraCalibration = camConf2019.calibration; + + var psList2019 = new ArrayList(); + psList2019.add(pipeline2019); + + var fvs2019 = new FileVisionSource(camConf2019); + + var camConf2020 = + new CameraConfiguration("WPI2020", TestUtils.getTestMode2020ImagePath().toString()); + camConf2020.FOV = TestUtils.WPI2020Image.FOV; + camConf2020.calibration = TestUtils.get2020LifeCamCoeffs(true); + + var pipeline2020 = new ReflectivePipelineSettings(); + pipeline2020.pipelineNickname = "OuterPort"; + pipeline2020.targetModel = TargetModel.get2020Target(); + pipeline2020.cameraCalibration = camConf2020.calibration; + + var psList2020 = new ArrayList(); + psList2020.add(pipeline2020); + + var fvs2020 = new FileVisionSource(camConf2020); + + collectedSources.put(fvs2019, psList2019); + collectedSources.put(fvs2020, psList2020); } + return collectedSources; } public static void main(String[] args) { diff --git a/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java b/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java index 5882a4eca..9ee7747dc 100644 --- a/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java +++ b/photon-server/src/main/java/org/photonvision/common/util/TestUtils.java @@ -17,6 +17,7 @@ package org.photonvision.common.util; +import com.fasterxml.jackson.databind.ObjectMapper; import edu.wpi.cscore.CameraServerCvJNI; import java.awt.*; import java.io.File; @@ -24,6 +25,7 @@ import java.io.IOException; import java.nio.file.Path; import org.opencv.core.Mat; import org.opencv.highgui.HighGui; +import org.photonvision.vision.calibration.CameraCalibrationCoefficients; public class TestUtils { @@ -39,7 +41,9 @@ public class TestUtils { kCargoStraightDark48in(1.2192), kCargoStraightDark72in(1.8288), kCargoStraightDark72in_HighRes(1.8288), - kCargoStraightDark90in(2.286); + kCargoStraightDark90in(2.286), + kRocketPanelAngleDark48in(1.2192), + kRocketPanelAngleDark60in(1.524); public static double FOV = 68.5; @@ -130,44 +134,82 @@ public class TestUtils { } } - private static Path getResourcesFolderPath() { - return Path.of("src", "test", "resources").toAbsolutePath(); + private static Path getResourcesFolderPath(boolean testMode) { + return Path.of("src", (testMode ? "main" : "test"), "resources").toAbsolutePath(); } - public static Path getTestImagesPath() { - return getResourcesFolderPath().resolve("testimages"); + public static Path getTestMode2019ImagePath() { + return getResourcesFolderPath(true) + .resolve("testimages") + .resolve(WPI2019Image.kRocketPanelAngleDark60in.path); } - public static Path getCalibrationPath() { - return getResourcesFolderPath().resolve("calibration"); + public static Path getTestMode2020ImagePath() { + return getResourcesFolderPath(true) + .resolve("testimages") + .resolve(WPI2020Image.kBlueGoal_108in_Center.path); } - public static Path getPowercellPath() { - return getTestImagesPath().resolve("polygons").resolve("powercells"); + public static Path getTestImagesPath(boolean testMode) { + return getResourcesFolderPath(testMode).resolve("testimages"); } - public static Path getWPIImagePath(WPI2020Image image) { - return getTestImagesPath().resolve(image.path); + public static Path getCalibrationPath(boolean testMode) { + return getResourcesFolderPath(testMode).resolve("calibration"); } - public static Path getWPIImagePath(WPI2019Image image) { - return getTestImagesPath().resolve(image.path); + public static Path getPowercellPath(boolean testMode) { + return getTestImagesPath(testMode).resolve("polygons").resolve("powercells"); } - public static Path getPolygonImagePath(PolygonTestImages image) { - return getTestImagesPath().resolve(image.path); + public static Path getWPIImagePath(WPI2020Image image, boolean testMode) { + return getTestImagesPath(testMode).resolve(image.path); } - public static Path getPowercellImagePath(PowercellTestImages image) { - return getPowercellPath().resolve(image.path); + public static Path getWPIImagePath(WPI2019Image image, boolean testMode) { + return getTestImagesPath(testMode).resolve(image.path); + } + + public static Path getPolygonImagePath(PolygonTestImages image, boolean testMode) { + return getTestImagesPath(testMode).resolve(image.path); + } + + public static Path getPowercellImagePath(PowercellTestImages image, boolean testMode) { + return getPowercellPath(testMode).resolve(image.path); } public static Path getDotBoardImagesPath() { - return getResourcesFolderPath().resolve("calibrationBoardImages"); + return getResourcesFolderPath(false).resolve("calibrationBoardImages"); } public static File getHardwareConfigJson() { - return getResourcesFolderPath().resolve("hardware").resolve("HardwareConfig.json").toFile(); + return getResourcesFolderPath(false) + .resolve("hardware") + .resolve("HardwareConfig.json") + .toFile(); + } + + private static final String LIFECAM_240P_CAL_FILE = "lifecam240p.json"; + private static final String LIFECAM_480P_CAL_FILE = "lifecam480p.json"; + + public static CameraCalibrationCoefficients getCoeffs(String filename, boolean testMode) { + try { + return new ObjectMapper() + .readValue( + (Path.of(getCalibrationPath(testMode).toString(), filename).toFile()), + CameraCalibrationCoefficients.class); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static CameraCalibrationCoefficients get2019LifeCamCoeffs(boolean testMode) { + return getCoeffs(LIFECAM_240P_CAL_FILE, testMode); + } + + public static CameraCalibrationCoefficients get2020LifeCamCoeffs(boolean testMode) { + return getCoeffs(LIFECAM_480P_CAL_FILE, testMode); } public static void loadLibraries() { diff --git a/photon-server/src/main/java/org/photonvision/vision/camera/FileVisionSource.java b/photon-server/src/main/java/org/photonvision/vision/camera/FileVisionSource.java index 6bf9fbc98..f2da07b00 100644 --- a/photon-server/src/main/java/org/photonvision/vision/camera/FileVisionSource.java +++ b/photon-server/src/main/java/org/photonvision/vision/camera/FileVisionSource.java @@ -33,6 +33,13 @@ public class FileVisionSource implements VisionSource { private final FileFrameProvider frameProvider; private final FileSourceSettables settables; + public FileVisionSource(CameraConfiguration cameraConfiguration) { + this.cameraConfiguration = cameraConfiguration; + frameProvider = new FileFrameProvider(cameraConfiguration.path, cameraConfiguration.FOV); + settables = + new FileSourceSettables(cameraConfiguration, frameProvider.get().frameStaticProperties); + } + public FileVisionSource(String name, String imagePath, double fov) { cameraConfiguration = new CameraConfiguration(name, imagePath); frameProvider = new FileFrameProvider(imagePath, fov); diff --git a/photon-server/src/main/resources/calibration/lifecam240p.json b/photon-server/src/main/resources/calibration/lifecam240p.json new file mode 100644 index 000000000..349c450c8 --- /dev/null +++ b/photon-server/src/main/resources/calibration/lifecam240p.json @@ -0,0 +1,34 @@ +{ + "resolution": { + "width": 320.0, + "height": 240.0 + }, + "cameraIntrinsics": { + "rows": 3, + "cols": 3, + "type": 6, + "data": [ + 353.74653217742724, + 0.0, + 163.55407989211918, + 0.0, + 340.77624878700817, + 119.8945718300403, + 0.0, + 0.0, + 1.0 + ] + }, + "cameraExtrinsics": { + "rows": 1, + "cols": 5, + "type": 6, + "data": [ + 0.10322037759535845, + -0.2890556437050186, + 0.00406400648501475, + 2.5573586808275763E-4, + -1.462385758978924 + ] + } +} \ No newline at end of file diff --git a/photon-server/src/main/resources/calibration/lifecam480p.json b/photon-server/src/main/resources/calibration/lifecam480p.json new file mode 100644 index 000000000..fff629bf6 --- /dev/null +++ b/photon-server/src/main/resources/calibration/lifecam480p.json @@ -0,0 +1,34 @@ +{ + "resolution": { + "width": 640.0, + "height": 480.0 + }, + "cameraIntrinsics": { + "rows": 3, + "cols": 3, + "type": 6, + "data": [ + 699.3778103158814, + 0.0, + 345.6059345433618, + 0.0, + 677.7161226393544, + 207.12741326228522, + 0.0, + 0.0, + 1.0 + ] + }, + "cameraExtrinsics": { + "rows": 1, + "cols": 5, + "type": 6, + "data": [ + 0.14382207979312617, + -0.9851192814987014, + -0.018168751047242335, + 0.011034504043795105, + 1.9833437176538498 + ] + } +} \ No newline at end of file diff --git a/photon-server/src/main/resources/testimages/2019/WPI/RocketPanelAngleDark60in.jpg b/photon-server/src/main/resources/testimages/2019/WPI/RocketPanelAngleDark60in.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7715e503b8bc54abf1321b3a506e2ca7961e2563 GIT binary patch literal 3222 zcmbVOdpMM7AAaX-m=az>%5gH2W^yXRu0!9jV^U_6+0J?=|oHJn!>7_wTvy`}at@q|c!h z&W=n+2!(xB6Phxi{3)Y)xHH>R7I z)6F-12T6OOEsz`@Pr&2k2m}I=C?`*Xmyr|{NE*s2ituVp?KP`4wX}2$=!QCa>-Dv? zC>GT9#wOlaL?TInq`qvKx~Z;~uIc}LN$XJs00RysyP(Aj zg~niUc!C^JUSS1o5rQ(%jr8@t5xN+ zj2f7E1;-QR)mEx&Xp+|&QmE_9H*T`9+-$YwUkpd5Z{3c-cQN`0Dl0@W|MQ@rlW)>6t%gQ4nSU4!AD>`T~y?ABK;Y(sE1xb)qi=E}Ly}@LWv8bTp)o4o1^0Ui-{g@fFHp|?1XLUm4 zwUU!3t1@-vYMf#=|J6YSPZ#i|@gId&a zN%J~bEeAy@EJr3JW8^&+#zV&Zr&xZnc3!`Hw4-$DMxSycw~|->{6_L7LP@$D;dlJ6 zpGS2^42pxT7wNu_B{FgE!V{h9AUYQ`0EJ+#6CF&(J zTQ~U_)vUgY?QecQRbpN(gS~_{K3$L=ca}khAqgMgrhz{rR2d%D7$^yHrutKm?8-tU772L_*cG)DyFJ2gkTcH5uDrDwvcO;S z5AabX`)*uYVL_jB=yXr7|+*_@sC?0+bSBFhL)#N zgg6n{5oA|D;K7FSAvTNo_uT|tA@Ud7tH1y+K7(Kw%UicFbQY*47CNvQNOxo)M|a~aYI_k^wmlqiHgil}v;KphFjGx6s^7wal zA2W(AY_Azt7NjRB=BwQde-W4_`flj)aoPorr-7Jt*W&xITQ
    BV6G}}&io2DA@1}34Pyma_mv`rKZMNwpKl8M}Kel06*Znu5U_@2BnT20q{ksSsRO)R@Bx`0h?k^-5Q4J;5RfDjU`Nb~;hgVl+Algia#w#` zWV%}l`IH)#9-leZkrv^2zh~8XgN$%VoR%^%I8u8nyVLD;M6RUx`JR1K*`72hv?Y7y zW(jY-dHvy=)&7Kml~TyJlybH5YwWYe3 zPLBZ65H6|q&e4AR%OY9-^nA>|h{w;xHB;<84F8!EuA1&OK2ePdr2L#U7p0K%)`7;B zsTmKx;H~Z5S*zJ6hc5@xJl{QBr90bX70rEFks6S5P+u^$eGk07 zDS1AlzvonUO*@_5bU-8P!5@3i=GL9<8;Y7%cwzEwMEg{8(Ao0R@gZ(Oy5Qs+G>{A0 z3%Cjf4srB*2*HcoGZwZmKGPmixP-%L{-nw!b#fRsWtI^>5l@eLd&ylI61o@`YJIS| z>YbL=m%=i+XWp}5S6+x|A_JgXn5=K?8Qb>t$fp2VhzJHmT?&94N>Apj+iD~>Jin%@ zl&4vqy-@#T!|@-Ak5va|hD7w~CYMcrb^7(*@X?sYgU2$)4WD&uTC@f6q>!-Vb%R3N zfft0t?GJ<28ScIHZvN!B_*E4C$o!3*M#Yw0F{R@+CW(e?e`MR0d_70K@A%F!x|kv& zG^hE^diRhLdHb3c>Wjq2yz z{HL^4JbU9}e;H8pLTTq0r(|pE-_9VDT#l)P`%iv2bRsQ{$zr-kA3>N-rMi$8ZR$S_ zgfBsi*g;LEmPPYLQN#~nk~30f1W6R73Bv8a)c=Um_AS{V$r1UwT}W@#F2V(!SXr)Z zI)A5DQAyuAHB4Vy`0>Ew%Ntp5=_jo2yxSf5)jlt?$;m6)GtAd{ZqZJz74cJpV?V7+ zJ_7w!m=e2#DUoo$4k4y(6L^n>uFVdQ3HMbchuMzi^p52%_ph3=Pko?zuK11d2$tU_ zthAkILVaAv+g$nH@prS~LAWB^WSBvZE;e#A>yA;|8~IEtyS-wo@_?dU_q?!EV~pNh z`|_Tz6v|8B&ha-)l;o<6Mdhlc%sBZ~E(=x(eBHC+>ifW$>2l7PV&dT_R;bo=vAlX` zz-4DU%$PyDDC*rRda2XK;xnwLnQ!)27N27>XzU4K=YUE;6UJhZScnyWt`=Uv@d1yn zPs99J#KUz&@3)CQ)e}4@0SLPoXn0ZtYf>O{KCq|7;*Ap*wKmJBmjFBrDSODl0RP1~ zVk;UH#-&P$Rs-K*3zn=+wqdddkw+bZibHUeckL5}HU;5Ks`L zqXt3|Q4j%<7NrP?0?L>7_uc!g`{%uP*2>H}nU$=4=A3!<-p_vKWaeZRNCB9@jEsz6 zCVI!j#Kg?P$;v`+JnS57oTqsB_)hVh;^h~F3h_fk1$a*hOACua#U&*r`GsU;Wh7*w z5|R=i`p;OHS-4qQxg{W{AQJzd+etsD0sufvp#N#W|J6VYU`Dz*tZeKYAOQTo=ji?a zp8bDJ@&XJXFqnaU2lQK@|4lr74q!aR#3!w0!p!gN%OVpFQBTY%XFYA&{93?ed|Ot- zFCvMJT~J6^MD&cDyaG%SuBoN1qpN3j-rT~{%G$>D!bLZCk4s4ZfUAK)D0DF9X5_7? z=$P2#l+?7l_wM6z@p<_Lg+;}L3KF@ps=B83@zZB5tzh*nF;j%5@7ctH*C<|Xav-6+T|6}z3JDZdKe;NIMZ2mtcpY#By zSV0R6STIN$U^oQ=p8}nH2I%X3@(JJsgXmv@PXWfj@88hzFN8*!^IMjXE4_ZJI5R77 z7bCTI5pT(y%_2hHq8KJEsG{Jib6(*Dbr=ARod`oG^A+N(Q=c&4eB@*G_bbD|`xS}I zhHJ-Y_52>^OocT$;fkVELztSCwh$vu6@>!8CeZQlyKpEKs{l}``|LK?S&<5i;x&c} z!p;`M5>Iq1(o&f5e_y5LnnT%WM8_E zw?#0cC~Ef+L{p!Y5+*QDy*7k>0YwDU?BuYJ*olMkbS`-~dvD?>+94iR&n!)rE2t36 zv=>!nM_yw*s7S@KF8f)CQgZ7iIxtL+Bj?!`3Hfesko9k zWxy9husI8$j?sr$3<2iFNP%Rt!oFmv@&>_O{7pV(?rkb1?vr+icDiJ;8fpd0z2}t1 zqDzJzls_1Tq1vgWX?%$buw{9rB~(Zd-;ERoQIu78c?NOHHD0ck!3;|-f6**8aa43U zm(i4S6T6?87uF#&8jNtPpm^oe;T7kHj`07n0noTj%rg4u<()1@z(drY5hH2V z6d`_g-7Wee9*+C8i}G{<42c#*7Mdl}9azc4Aef+3PKAmEVYn+Jj7%=-YZWGg^CHOu z;^$TL$L;50S*CHq92PJwQ0CvY>M(X2KzF}#<-tAO0r^;)17V*7l1TMS4mP}nz5YFQ zdpQ&^22YuoVmu4$q$X~v#IIurdP$ef;DJRmfrapbBp)uwCWwFpG^`0e0~82zBA%cN z=W1e^#?u@YZ0B>UzKij{LR+uO6(ti`kam8eOq>Wkf(FfsA-BjwfBX}cTY=~U;}YWK z&g+UH_vlj{AppCA@F!;iV{#V+2uwx{5S@V7iJ&fNc59Nsc$jJOz!{*ZgEXJ=Iu$ZQ z?Zi*x0B#hS;eb?IuI6F5CeMuJmxsp@{2>#OD_A?OGone{pV6=%?QB+`6}XshRoXD> z5qh(G=$nK4PjxtmIWrzT=SvYWTx&{YA$Vo(0YPwf$?zG4Ln?i{?vo%MV(j{^ZX1jx zs{~l6ATKr6#Sx2 zbTWcfVGF^6gaIx22#8BN2ZF3>7z0nHKhkmQCOd^KGvSJY)TX3Nltdy<0fYi3d0kw@ z?@Hw5NwdUqqnbjc*DY-T$68XQlQKj01dA`*fLf+KoFS@`1;PM@)sK)68!9@L5Lr%z z!wF#*=tVEE2-z6v&g++np1Y>uz=8u{7)uj?q*KndW=(&SH)YR2U7re{b7+aG;gvw^ zjfcI$#*oqj#wQlAqGr?BeIbJh$$D;D7+)eqY)uVgg}x>w4l}7(V4R4X6a`Hb&ZkIo ziPr*AL@LPE{B;!X#7g!|5J7*}&SbA56U&h9(!>qMIVtS=x3^P-%kKk__Hr-Ar995@ z@EI?ti(iT$r^^zyDK9NWbS8w|aQ&W*nibI?i0u3Eu=>kR^eV&CS^8UN*fFl zeknk#lSaBIB1Iep|IRSsLlt7@Mgt{O)Etki;o3ZfA3 zx(!IaQjYa<^#mR*Un#Vq&n^|(@-W;Kr41rnChwZXvX3tLCDGxrYAI2g3%*~a#Ol~3 znPJ!yYA!vpZpwTb=EZM4s(`$Q;L?deHzzx(M*Any5M0M}Or&q7*Pu}}0uJ!TjgOE4 zW^}k6xc=O9CXpHE8;&|4bLO!th*Hf;sF>;e6i7S@7&vo=c$rCj9UDbqApj10Es0F@ zO-!Ph0+kgDawrO*0M7$jA}e~?kyl7-5GRIz5NDqcVaG6YPNvEqR(e>GYAjE%!`Jq0 z&|dZ9EEDS+H9YM4i4Lqh!SUCGpr^$L7}QFW$oziae-Y1jEVD-me8={8e}Ew^OV6VJF-tx<8Z#|C%zb23D6D1OJV+m>qZiYkzh-N$TAEKW^^d=9uFgUcN zOvu78w!|%BF`N&L#n6$|>KbDSl?~nx3B+=)q#sQvg^{az6vn!wRY?Z>M4)t!e;&&@ zjyE3)p}Vcz7@`Rs7D2>-r9wF@*I>Rik#Q~_H5ZQtehf|Lsa5nS+^SY8ncyblz6YBJ z!qW^i;#~Wh$gLdQ-2bLtewo1AED|d$_aHZJ*xWLC*&dTI=OQ9Tb$QC~E_(S{iR-0V zs_P5U^Eae773H$WiJm5|9+eSJz?-fZgFK1?f7G6xmAi7DCH2k$o+MhxL|9p$GpW;qJCdRkjDnT+Adm=hp1 zD303d&h(fcUMyFX-7c4#m|2d-ZYm5DL76bnQsSEaX*#N!qS@v%@!e5QHX%*LiV6k^=N8N$;I~it9MM*juoL#H1DL) zuEHe4yA`u9*(7{>c;_NJ>N>X|f8@{EpVb^}_fG(~6ChuR+fDz-DEtICJNuJ#WP}+j z_>!+J4d0afIC%n$X&u*cmnm%AoqsTQR_%%0zs2Ln^38bx`S8gpbL)l3(F^abv#Z#) zCR$z*hs852+uyV1^D@mjF4}%5nP^WVoYD6Kca$ey$+w89Qv3YaQy;z6==F$`! zkZ9(22PVz-(xLDj2itg+A*=1kx}=+HDTUEr)t@GTe&lp?>n;9}#p%AU937vzK=ZvH z7xsa_(@;|eACi1ldw`xjX@+b5e-p8&dw-oKp_*t*y3 zpPv9d#V5e;7rKSMAG0LE{~$?@$I{Qs(tnoyEiEl$G7@NXWLjTMkC>2Ld9Q7LIk)=t zSn7JlEB1-s`)zOH2MBDdV8h2K0qMrhZv2bY zeU)B3plGkGUoACaf9l;03SF+fl+ZpxM7uA#CDq0l-!;(n$x$*`nLF!X1!nt}&Y3gZ zc)v5Q7Ohu(|Axw*vSG_#&6)Vp&o3ThSqw@7mj7vv36D@lx){sM9)-ra=E}qvxV>Xj z8#o=N7%C%wJ3d&;ZwP+@E+tOUD`J^$Ifm7#+--PWr&;k?^VL`AwE>GIGI*$5w{oKA z{hJq~<(RtQHog4Wt=#l&;^^neQ@)V)CA=_qUSyTDXl@!9yJd@D zGlvUtI_WvbBVZ^H8~KN+h|feM=^Z0+f>{Kf*AH=NVuEOa2xilGf1Y}gYN|b8wC5t6 zmKl#SnbNSv6PTuu4&mm5RGxa+I-=E1-^E4D*9JXj@(IV=TVk|M=0wqKj9U7|*DaCR z60Pufv=%)6^pOC%yc6{z@7?K)%Q9}EsrQE^fB%U8Vq<9S*;Mg__+P{d(7Ug%&fY%1 zz13I7{i?R%a%!p7@{z#fTC@t;$>^e_n^!JEm(02j}U{1ZTw4ZbPGTxj6h&Nj6|5A!OLPB7`@n8yok91d_d#T%j#}Yc6%YBq)`%YG`TP_Sq7%pp)igkcj!&7)Clde# z791!hRibkuN+RhW+!X=o?!_QdDk)aIk0@%~$WmyifT2Zv;So1F{1u^49V$Miz#;gf z-w2S0ayuHm->*~*iCR(KXIC7AIDyOodgl%L_vwm;Bx8IX~bEuX<|wK!Kcg z{c*X7u_Kv!v|#@}TGDXNy1j%z7=Q)24s5rpKzf~3nq7P3BeCMn_$dlU2T^v<1!B(I^s>?^@-n~V0P4~0un zgBl%!2=fC!rP7w)mDOhQR7-S zjZW>frQUWAo?JtI%by**H3sCd5pM^ObIOW^gR(6Jx>klx07L$NhXUNn`WjZRuBUek zM&EVZ{*V?ae&=7b+owV1;x?Na;l$qMo!l^%j>b3L5Sj)}Z(y@7;wSu|jnC`N71QsR zW}4qhRF}4V={eWp+bnxftGtPn0S7czTAFlOQ}(X)|IiUvB=1^>{f+*vuzyCS;)xW` z!+OP8k!Xi56#h9$N%fPJVU6p25eMN4tF8|5)>(6TeDG|v@_b#jtP@B3(^po`R9Aae z#toD_!AA}?77OT2)&T34UGN?|sscjC#fejRGHw+PERL)c!a>pl^b~9toH>=(z^Y)d zPr8g{lAlfy<0v8606N4aEPuTUnt?AXRs}#&ghbhGP^Nfu`OnF7cDoiaD`^b-kXvMi z$ciFR^LHS1Gr}FkZ3QY8B_q@@O?vD?Ku%CA( zzX$_E$7fVm|Gh4lI|07tKdfio&!AkmD$cKCbw@7x>DZv;cHyOsq}j{bE?2~ce^fBO zmHCmKKiiTf!elihkE50SBK#hWkQ}@{``Q)+~jr0dGb)Mg+uW3XTH$z z7TV8}th}2~8f)3F?BsA>Kbt62tNHl4e_KZQ+fySI_Va@ov!-NHm*Xkk^+JCB-R|MC z>HDlB{&<@%#Rezm_sw=JRv&f77*ceYvKAfs*5qOd8U#jZcm&;7k>H6qJ!gt4c*}$+ zj6v)ZO%KTOgj>QXD~S|PcrVV!HVdg{#n+Sv{fp*al0@oOEU~Lmq&P**a$_pPn*1{3 zVNFe^1^|hcP(d(7yr#WhSB9R^LB}Z!oT94eO$HylZSuO!S5ByNG9sBdogcwGX~6}k zOj=ALI9eutz#ECk#n#$eqVAwuWj0Rr>*lX{K+O(L@6T|Hb-^r702|@dKO1ouZ)nJd z>5^ZAg@R}*0N`-PrNt$-Fgj17AHrQXQ+3Mh6%xGklj#{#D2w0VdZFp%&nS5 zSLjl%)$z7djY2Hmp_M>!g4}u$co1zKQX9PGlJi#8nPUB<-COZv z^r=Q;SNEwY3XKAKoXGJKUPmPWEb@4p{+mQ_8&c1uDP;vuv*$D^Z6O9w!A({qbUEOc zQHABIN*7fD?BSDLcf*ZZ7R^92Tb4)_nP8rJBW%hN&Q9fw#GVIurvgi7WEgm<@#_ri z#-a?1<|>I)GeotIP?sFaN>d1Dw=#8>R6YE zIE7*Ea^G~u{GJ+p>>#S{SNgOs^iAif?h`fJ%ZKW9tPD}#rkHkF>J{>0#{(Jev($UG zy_s#fTYgkk<;m$A=n@6x?nY)&vTlG`Xr>>0wWs`EZ56c%hz&p7Z6EhhwEE~5Vs;+< zF6dg^#V+2eJ*}^K!yCoDhk-3Bw}vEz!Q!AA$J)`oz{~wTCbGq=#3z@$b@!{qUOu$+ zyDojI;dsQtKf|`W`p<|!F$P8m%FjC6{}(oRa5bm#3VKeI$O*QJU3%2Yi}f!VA6ZG9 zGs&4E=1y5pzE7sG zd7bZANs14)klv>-9!+v3!%GgTq$rFNzz8JoMHaCdUQE9fM*);Gf-Ec0aXi5!T*Dj` zjxiS!Pk~2PEKwDR3^+i6EJQVGd6h>`DIr*-!Y-r8N@2YcS4mICM8ocT9(b%^jxJx3LdOSA%wHMA>BFRbL8wnGW zi5I|A?`{1=sa=rt(4^#^+J*)Z^2hcma^Qi|M!G*v=S6t?Kg|M9dHBL!M}_%F^Noto zu`LxzsN^Da_m7*g>-pH{`f7bRWTRT*LLfnR<)NQIR5M8^L@#tncAf&y7!tjm!jq@%it%>u2u zAyP?E;^YFTJx+9nn1gU}8D|o)ruKtn)XDe-h|I^iU~_AK*)905%^kCcH}5Kz|4T}f z7KV%>s#2a$y}XW6Vef4IaaQN&;Me^Dr)mGzl*eXg$K+PNbTNFL?6MPEX){^(*NLo6 zY4A|QuY0Q7+Xkxjb-ene=7Ow^IiIWQF?4pN{H5Hx=}M(P$F#d)(ek*Y&!U$KG?$wh z2yW)Nw5Oyi!X&97z7*lLc>AEndY$jd@s?l$m(yT#rFXrYG-wm84V@I`vzK#>^#Qle-TCx!Up4D3 z>k?`Yh-5Iq%ZHN3vG{6OIK&Xa@^OpL6s1c9Rv{!EG6SX*wK`qIVJVlb zN?z?K2XkX6(A9b_Kw=7G$_zcIBr=MS@ODhPq%x!(5Y%-JX$J7rLs#Mb&`G@1sz}8< z4pt9h55lmgay8T42~2;2(wx40-tty4&Nbf5%;%Ud z%wa8m>sFA*sAM<^6?Rn`(|_srI1UoP=aK7Ry-%(aCgBvCxW?d|vEx1r7%PnuD#NbH zJ}HdXwV47844hGAr_-lSAX__dEzJf6swzV=6kO0m2#Gy9b$ApOs(NHln%5mvNOg^4b$s^5(d5s>-%@YKX)Mn(+cgEj ziMTsAnNkIx(ueM=g@)aFNKT^>xmaA(%ojs*v;4b0NBjrAw!h^5?L+&%fdUh{Y=52m zRg3X*0|n~0p8F_tG+5^*2DCW3+WvxX+6(%v2z?Jfkjq1we}PZ`ZBhx_O&yxL^XiTT34Hyk)Y32l9a%&f!QvlTo20oj3T2 zT?7~A=bkb@+|RY+{#d=mboH|f#AY$iVMCs;PI@oOiZ05B^P8|<;|sas3-#qV0ob<< zX}Y$T*`gFad$rtc6u5L>UiSUadBL-nX5oz`spj8`_89O^9T_CSZO*~!Gu@r>=o?ZB z5nN)A5Ay~_;GC1~E&SpX6(&}OLOLzZrED@nGw*Ryvo-Ib^A&La=`6Lw2j=Rg1&MPS ziB=9MMukc`Q|Y{k^2BzmR!WbeHyDm4M1`3IWVrXjX^u6$xp;q*q__*UU+Up#;GsW zzb`cZcC{b8vUK|d=rr!ls-G$}B_*e|MM=Hf-YgW>A=n+Y)1S#$ytch5M&|^0l^XBh zY${N;#dA(L|6D4sHM;toHU8frCJUh+UA)VA^t2+x46ZJSRdmUV?{!Km};!%-`j~6Ep0+awsy|1y^mH1kq-n6 zKz}Y=c(?70gw$M&!<#JW3m^8qT=z5*d#@Z>x7vc68+Xs5sE_wek#4>{X@@q`l1wf)>yio?yl6XV9=lKQ$2OwpxvFw zvK2?DfmQk@pGuD+0|!-!4=ks%RM$j^hm-AG$^<|TE5ritq)JsJrm>MAJ!%$QN?7OL zRPH4zEH$|isQ?_K%~b^p5);W3@$*o;xfC5DN)E>nY6$s6mm!cr^MG7W(>+|AC`J@6 zK76$XZ-iRyf^%-%*5E0IrX1n|+iEEOw|&zY%1tQob86nMZ)&GAPk`;!!r{k$&`VAs zg*tv!e}#pmQr9&x$w(!THOXXCsOJdJ%oJEbKGsm z^31OjIoB$_oH;XHD{xgt`+X~4#Eoj>Z4G<9M}MI6bCO4>ghBd_FBoHV*^zX-^nA7zO8807s_XqHOGSTra_C_1^C){f^FiDd-{Gi3>HI+YF z;`f(!R+^m8k;!!v6~V>_F?f!ii0Irk-;}9?mId3~NjhuBUJ-KuJ?H!Ru~=QJt)(?x39{1fT?^BGt=_#nJs3ZNJwW**CpIwbhF z^KT&z;3<+B42jKs^EgJvNi>!{j0m_)0wlNxZ(yR8Hh-(QIRG8sCo@iWoVBhVmL1tE zM;;~$%Qi9Mo_#9xOoWzX2J8GT66F_d{uFJat#xgIQ}BtgAWXF7UTlr`w=&w5`O`vU ziK!A_w(SIzE@ITUFDzfUFL$SP>0#D9`mKDuTu=1v$u>Sc>P&r2>Igj4s8u<07!2L7 zls%lvV71;S;pZmB`;|(gM9s2dLrlCJ*p>;LYNb~2hUp65Wy`;xyj9L^PQH|7C;k&n zLSohfc8?|)QGeSznoBC*O@b%6IM=`ruDi;z)63M@&LNHUuks;kCkMNJu8;s~= zD)+2zAkA5StP{rSt77nZ*K36L7mMoqhI)tjR}H|{V65XHfCwLMEo=X*s_UV4+bo|kEJ^K<4Y0t%^KtnW$9J+++Rve}# z!vp9M^8mg6v^t$m&|-WbSdDiR4i$!TrSlSXw;XFXxYF9Kt(GdTl*zUlkyc`;Wp-Ft> zyx%c+fYbj=^%cdAvXC&CLat=6?l2^6y^9H+CK;SyV*RUd57Ob}Wi;`xr3{sTyv19J zIUHZ5JGN{uM?J?aQAaJuEy>Z+BuVJ#6E@lRQ@%16tb>_C?md6hTQ~jS0tj#J(w_Pi zO2}oxSznYbd}|@4k?k-}OLPq{efaC!RHp%0$5&S0dVfg#U;e5_(wUX}zK;a%tX>Sp zg|0+x&6 z^Lu&U)xzQx)~!tWP;_!Fh`^1pAYN*P20n2C$TAP^`R`Sk9jpssCOQ?q-BfbYIPg3H zOf?67lgR{1e}&m;tB-e#)}j7;4QKU2pA?T@UQ55_Y{3-e@eOgB%d!x$DdDcEr!qj^ z3K!U{9D1YJhK!=us{JAV8R!PUMb8Sc>r((G4xM&mi z6xfP;tdDJGZzAxD-i8MCo|Cs!u<5=m9MV?8DvX{V))!R zC!i_iYh@2MlX%FZVlVI8=Q`D?DcW%NYDq$^>!0)!0J;0bIy8pb*=4p@4KKY>ijq9NEvriRt zIEX3-QKON5f>yg*PBfhPTgfXS>pMpOTv=wmrsaRM(HO8|8$UT@w@r5??z7 ziK)gX68xJU&>TmIrpt#DT0Bl%z1+q47*!OG-awj8g;tLhguj@8L@{oSr zXh=sT)wc|Zh6ii=n2p-obYaY5?}gEoP?DWYvW+!r^^ohckij_8**rEjCqgOYL^I+E^qLGj+7JbG>=wd1)|Bg2-hS%6QB?)zyMy<12ki~-AH%No zWZjykI6Psc@U%z(erq5xGG24%b;&QyV($B z>fBUJk}GzjSIw<)!`hNabrgrx$UeO^Uu6iEpUy-9B65$CEuBO$^QGw+>n0UX`{T30 zXkOLY4WZ}X-0eg|zaYuI1NF+sb^QskpFcplh&OBwOIka=<(JPMcP~IS_ZkH;51%)$ zB%ize;VnFBGws>43)izFP&PfkAi9;D7{Yb_@WsFA*{3Msz@ouy>Rv5m*Vd_N0gV}u z#hTd865=@C+2vSZrUIPQDo=+#R@7>9J#c_^0U7mW&CDd!=UBRsh)cKfpo(6GfsWe& z7+Z=I#1%^sn$qLBAe(h3|6{cFVqtox%f_c$8DRzAwd1Q+v~YYHnZlU~>~%=(g8nzw zs5qgtgrE$4$M)UZ7aN9Ze4w+Jn9m!8-R?EJlfNcNFi!4-g?ieI@BPq3h!g_){u#3~ z1!G376ur%=2j?*zT6;$F6h^{Y^ZPKysr&qGSD3_jYSm>LPvdQdrVEnhvhsDSBO$CA z16sPQOGV?pVyEkM%3`g~-`KDCQVdCGMNV8fWU0`j_9HQW$JV_bMA*k$@_#8PB>m-v z^8ZdDF_tPVXYM&*6~A_wVN{r@Xb%zdSvjl@#R&wNoX%}$f=IC|fO>EiQsd!l<`Vw& ziwjGIG3EC{BVsC<3zDH3$?o;vIJKHr(!k#keKO^P++50Spz&`3Eb}iO4)Co%iFei9 zpVRBu-e3H7s4+IE@4&enZ}`B$d~G0sb~MUn$&I*eLE4c9g2 zuJ~<{x$q?u&F*sU`_(KXwNo$axVi9j{;{IBow$-bkt^&HKzA}K@xi5u;U@4dbSQ&> z#nD?kt)0>ooV$<3bp5fcXhwNXj7)8?x<<}4Hg1x)qJ-IADY1UBjGK1l%&Q~8yH#`E zbD-R2?&K*vR%xbF?8qQ^*Xmhxqifsb!iG<4f|j3A`;4*1`ER10n?bNTiLOP-yQK`< zDGxAJXp4}kK8}|ioDHo1q>R>%ACKMZjIX*hCTkxNn9nVt zdH&4rnVKzuls9DFgh;^y$?elW4-Oh(A8toB1V0-&i&x~c=E)e<*k8EA@WR(#StLB| zu6Rb33#jXb{l~O0yK5;I&L2--k{0oX%>ey$w8{L%N-Txl>%=cPZi7(I329p;bro)4ukqd(kp~5^Z(uY$`jXR>h zhsxKQ2#Ck_L2tg@mrG&1v)2OT1;GJl1QXc!+J)n>PIKM)(cryn#dpg!f$XJMu`Myd z)-jL5qwc+&nb5LYo<8$b%@%oD3*su!H=Ub3aE#(K=K?Cs9QY2W=%UO5@7RQ5Gg1GP zVj?e{U)49-JMQtKa!Con>8ge}cAk123B5_7npEdkKXK^i_g@6W!( z=&1LFYT4l3$HyaOy`u#?55K!e{&M`;aOuT|@g2L8YDenVp31<1j3{Vnz7iBe_@lK| zJ~wW$WJ>wr1SQ-8>C@Gz*kZT~Gei{d5>-R6;VxHC=l5JDy>wZON4*s8vqAC3(>0z^ z0NmL}s2&VwUs+APZCw95^G`k8&?w~NxORJ%u=9rXf;&2ByKv|O<7w1(Z-3(bhOgcm z!B=IAm;E(51=;V6wweolY)xoi)MPFAwCRbF(I5QAVKJMR^ZNCsQb=Ee#Q3BkSG+uz z?cc|rC-ru25VF+OHHUv)u`=Af;H*K3xs)Cgt||0Tujb`zKBlVnrS?cTz0TU5fl8lo z3dZy1bt6@@pc7CkE0-48Z`T%2XQhR|*6RjT`gF*2cj?D7$%lWWD9BG_7i~S%UAKIN z=2S<&Zm$xAa_Pexq&MEn42MtG>Z`#^ztyygwTQW_Tm{0w*-S14!ruaKeQw{ET_)%j zc{KcrfB*V$%8?NlLr-AvFwVXpf|Jfl>I&2IDph(#K?J;wvEdQ|lyUxs@cY-&o8|D# zwKC`7HDOa^mpOb))wAXr@iak0nwgbYqqO7?_s}c&{?|sdU75NAk?{@N=dZ_(XJ{E<3Qdj9g)q9g=bi^C$=JHfC)^#``_`5rL0D>rHC1 z+b~01n^<&6tx^D8rOd8C*L=_c8mPb{AYC<0NqMoQd3$sAWiH2T+fV)pZi{qvn2V-0 zKV8S_&T@}`qmxO^#z^Y#*Gtd0+Y;qVjn1`-Pv5E*nYqNhdIDh6@5s7qye$4584`GG zfBl2zD`)Tetb7RPPLH@!P+#sTrK&soaUY=_YS~9wpLS0DoivTkVJ-GJ5Xcd5h!pde zbCdjy%G;ya-O2xUI>Dv0ES8`+&UvNfqO=sLUR5&LUM4$@U}jaHlul(BpU&tp7QJ{I zO3>pHsaomDW)j7M!8rw7Nz01iRAyO zDE;3ZFH0B1i-}e;ZUwks-wx@``Q0{1y)>_M0tC&%Iy$e4{9yqlEZ89q1M#;k9})bf z`Pp2a9l^SL4yS4goR|d?q)3M#ZJNx0o)oTj9R zo?rcTMZ)*;wRk(b=eT2fu80kb?%mg|=i%Xdk%uVj48Kz4smXa!H-_{}@x^PB|A5x& z_YpZgZOykepFW4YG`6LM+CDzbS?};JH>ZPkMTF}9uwK2EcL-Fv=X3DbE~i(^5G0et zsxt)V%zm6Hyf7&Y4XPo7g`uH8?1_wIIHxmR{zQPK7o3%7y($naK17Y~A;B9!*6Bad z*lCk>=cb`pO+<3|;bd~@9+jIfZn8gxs-+)Jf_s?;8KN;XMA5_y%^9BW#%%Gnd%i^{jiJaWiyG+2L3DRfO_eYE6E&m#}^PptwxH zfV)(8d(sm*fFgWu{^B1F`((8-F1Y98pmFT6j`x-ugJi$kricwGs<~T=UGjkPnyi^T zuG(v!?a|GejySMz_*wPi=lWq|j^uRmM2pcjovEjpgV_~$oh@s6>7_`biMf>NxEVjx zFk~Yuu~gs&*KZk-&>scLj?Vt!x=MF17)Pkbeg)q$L_T}GXC#!hlbLqu`-fTd?Y6%h zWg-Snr6SvgGdMp&CNU!f-P+`?!+ioIwXKAFyZTm57Qf+`5DQxu%US%zGxM#XZvJ|A z?&Kc$t)xwBRa;>kXUcX%^?n1+b(xTJF#YQ8jU^68eT)3wRkqGMml_SjpWAES*7Q1fg)7ob_&r^C#pxLZVh^kkwgwvSqBat0LBc|jzT2x*GZ ze+Zd4i}Pn4GZ=5j+p%5L86nm}ldV`7;?dSi51Ulw(#Hd2I{eUzRP2PP*p#XNG!A|L z9txhwrFqs%C0N$wJwJEeg}mW1#$DtqN$?NPXH@sb+*w-7m*O<}-*)3W;J|l0zv@cm zI~wK{%CyvCPeZx$(w?(ue!6{nhq#?^k6>H>qtZJS_xD0T4a>JY?r#wZ3?VC5AFGY3 zIu9;vI2C@foZJ`?V@kfMpSNuy!sveQ-*_n_sBG|)GU17xZ3z3*n>j^HMKI%jPp&pB zLPtcdi9C0?`1dN4e1e>{=`J*{E=Z!E`l zbyVb>-MqsdZQXh4Ye;k@_`8-^=$3kThd>%{T(iz$;H&1GQp>Xumot2wY5qIir@~7= zh}d$!dei;o1mL{gw$nHu-#@ROcmCtE$+k&)b>{xCc`mla%`@Fmb1@>X;!q+}T`*nt zMLBWD`OTdBrPZgR5fQyL?~14Ho5S49N&;LFY7fKbFodwPU&W%FwEfKOi*?`SpZdf5 zEPi()cZ!u~I!{TWWD@YXuxn3bD1=L=icmlsM$)6fZvxou^Q;lIe(VTTE7qToI;K-y z!_LhQm$T)mSM3N8wS==G;?eeMX=scct3sV)hl~W8ONzgA&&6*}%?ho?r73%T048|f zWGRnecHZHRucrjmbW(S3AoiooD=o7x$1-havdh7-KR!Zt$Lw; za*BXoIstI9+ha+aD)r=y8x2LC$XbJ>FELnJZ}M2J!03L??+aTG!&L|k3BAVKLvIz- z=SmW7?gaj-KhFAG@#Kjpf~+>8>BM<*#S8rgLx!J?arwHFL`!NY@=TyBMqGzepmf5BR-;-Z4Vsru;0t zU!awplf%11Iofi7T6Hqmt75VwdTi9EI|=vNFUm{ygUT$)pjHR6wwe3$EITkygJ)4r9?j`oWG?`aBRvv+Jr}*RER9yEu-s(5#p7kN!_k8`2 zd${Xs0tb3tV|)3N;h|I^)Avvj++V_N-Uh3U&f~sv=sv?MllLvOze-MJ4pTqmo^>WZ zf6F+0G5aX_yNLvGvhv)`EFKNX>nWvzjvj`FlE-5CFr%tgV+;CeE@#9!Rl5E|x1tBS zL}!5LMY>dhFSoh2>wZ5R5}dH-jn}uo+VOHuy;?-!?%x%!cnw$ifSBUJa~nm9t=$F6 z|5)BL7G}#}*>r#~qx@aTAxHk|d$&W*YPmjJ{}lTm8n{;1{%u*(#p;lKkkHw1=i=g~ z!1T~mzwP(Nf$rZd90%^=6vgz25YMt!d0!NyNaMxtAn5{**(ih4r_UL6jQxD#eV>=L zm9ESi^SF2d$XM<*>OFj}ZhN>Ei+6u*-c56hNUqeVkG=P^$n~qmt={*1j=!Qp19A&k zdGR?VqVC^Ca}hX^-%v@LSbdR8TF0a=TZhBc;g$T;4`ng9@SoKOr2Ngaiv%_3+su{f zjuXHoxRT1w=wB}%>_b0*lWi%NN;;SlURQ5{jVVfG#E;dyV6q&xs;^()0Vuqc}` zcu^IfFznHsORM2eK&3DfxTY_6p9IE6Xo||LSmZh*wxt*Xg z-#g_G8DgU-RtaGuX*h}g+4hI|gJM}`&h1i*H8ZIDi7W(kZESjk8jFD3Qm~C!*+arc zrx;sw<+TLfe;3~;*L{Bs!|Pzo%jY$`&(5mENN4?QKur$3|JCaC5?69vj2Q;dyb8{G zx!Z4l87P!EwPXH@EMexiY+hqp@~26nUHoH&M;z|{weUb4kEQL&a%D2%Xng<7qbVV` z=Lgd+#n)9TE-gf;bqF)NW_gM3-uT4RLu*8hEp@4g1ib(5?6#qK?S6fsvDRF`i{+cf zHzl~0SoN)r^;4TMZ#9Z0%iI?Jg?=GeQdX@Wi!>3pRqXMKVH#W1EmkXY` zccqt~pj#bCWe1&xm%P_`3H)RgF;v<(0g@$z=`vx*9;&6P%z^W43}*D!rgN(?sH~sx z=0&)h5lhz2;{wm`1-t0@PybT71v;JS=MEZ^Rc`PHlSrxXirC+^inyGs zRX(a)^Up7OM81{r@ZQ_D5kL3mZyRNJ z+UHsf+V$T-xM@~>6(g8jep=RV$1!`6B~gt35AGXg3^{@CbPZ6Y=-1HfV{o6%t5(rt zHjHDwf6HzM7VMU>Y#gLsSKgCAqI)ua9U!A=v4_#-jr&x%m4=RXV1lz$}x866wk>R}T4H7_q zC7AZ_*Pk{#E0;_^gK>>}Yat;O-~Uf1@tohes*kXa4xNRssg48pjy1epUW%MK0it(s z%k^^K{CCPusa^RX=8$xxcmimh01J{@$1ywlv{H4ved_xsH*=@A^L2UTCHxbb z(mhchsmfy%UGxoC<)j~EoDeS0oV%q7H^YTabMWE9G^O?#!skgr;M(#enIOjfs`R#4 zQH}>=u@MV6;YmoHHbcqtKX%LbH71zNkeejWk1J2S&sIBGPUo}4@^|FNI^;bW!i5os zuS{{rPVNhSDnP(kI%?h*TRJK3&ACDCBEHIpL>aZDF&qCJx2lX3sMX6*{c$vbHLO*A zX&jj}U-iE#IMZ;b-Zzd9W6xHWkV476JGK~Wc0eSI&)O%vHkno)Y%QqFh z?(3dH^<(jKr{HdRreFAk94~vtbu?zzXAiBIU8w1GJ<9=m_?*}!wA+6yz{eXkm1lYM zJTUeRom=A{x;9dGbu+O)R704QN%4y&(^Ka!V z$m!@Vl@9!^Jv~vfFE@N7ugr13VunWg_4VO%4q*&iLx_WkP)Sbtkjt(C>q3#$$GOpy z67fGj8Xu0#7Z66m+}^8gxvaod-GblmOU$*VfuS&wUv}X;A@$J&dY0C#<@?S;&cC4U z0Mosx`1V5owG(tL!Cd9fWFOL*rdaY`1m8{=hQVMw-pxXGe0@lo&^tZ}P7iVly%(Rj zK5U`K?8_)kI~E{@2Emmk=!2Km|MxUZT$kv*6P6x!fo8gAS%De#9|P($$S6KnU~)9f zd~jqf6!zm?89B-FC(N4gxfSDy#(YKQvIo^hztYU)7#eGQyHyfG*ZJj@2{+RcDZ?*pTz(-9%E6Gxpx%P(? z=U?Orp@j?2fsN)a!(WxfCf@v%JDb0w7*F)w4&H|!1A2k_6&GJYC3HN@P|2l(V4~Z% zZ8AxHwx&xX6t3Na1Pat=V(+&TX7*g?grOyqT7LJuyfdOpaGrSswbk#+sv6Z_u($DA z3Vwt0zs)U8tIHtHoJ|lHpE94jF7P$d>8O|_3WpwKPF!nqSI{khg@SKU^Y6&aU9E*4WSYuhy1Zff~T#oPqG^+ zuGv~q=<0c+C{M_5UJfHiug9@3sD}bFWZUzU=Wc5d;=K>lkB)3o5 zf$dl#O$fPk?7ZLfZ>|=F9!3!*gfRze!54x{ppZ>EP-wH?WIhK z`IE-U+ggOvJ>6_fMOqFgt>W;B@qdf(D}N2pmJiqdLD-&j{rBwn#IEppP2uM{NB29S z{~#uguBX4L_AhUiGU1m>cV7O3SPH4UH1Oz%FB<(%=yyEBBmG-V zIAfa~`i3xiwg90y)x$e)tT|NQn!X!rd`RjN-1jQ@i?eYItKn6;{vHWqp-_!i_J zq$+&5d&s3SCNlEiaxxW~^WChZ4E;M)v`q8VhHGWKhE5(*FCt*S8KATqOxi1krGBls z`g8r%cYMYyB5R7vLF>=d;KoVI`rQ{Wm5Je2n%U)<`_IZt4i+G;B-}LiyGl^!@ z&WpcG;b{~9yH$1N8A^7+9HK19nv|i!9J*@d&GghU=UmXtsMNakFtPaiPWBdC(!Y}V2_JHS##Y6rPuc0nvggi}hN#{{n72|*5hwnuJ3r{ZsdG^8crs|42ycjiqZ zoZ$(VF21b!IIHVftlV01_N|%4wj|B2n1|;f3rmG=dzkM9_o;_&S$92FHSY)Z4#Q<} zU2pFFHouh>W0FvA}Jsv?F6~k%`#hv5d*6pb7 z%G~QdyC|z3c}4Z;9zBAOrtaduyV`I+-I(V54>E3jF?5ej$R=+kn%;4#_j&f+_=r8B z@4G+dmk`axgCj9DKf^;@w?DbY9nkMUUZNRtR*s+32C*^u4Mc$8A zIuIji(1?V{B*NT(`sE=xrN`N^5>7T9w9Y}g4XXyH-yJ<*ZVr=};ce&z4`wB^3+%{tFF4c z27jxgh?|EW3=7XZ!quDdQy3a$Nb;@7MEQLeEycWzy9MKW`OJ~mZDLy;3lx}e1GwUn zl8l=k*i*UG^X8v(Y;K)HselKLOj4r?GUAFdTl*gBQaIHFBmdQeFWWR-GS_72ua@-G zQ_c8>_A-YZyz(Ih-g5q4g|dI6sg>+Sx8IeLcOep~%vrjF{^$J8F|r0HGoSi{E{7s) zI5&-v(1c(l2#SRO30LUfAE2Vq5k=NrDQVA&muHdKZb$BPklLZsPCQ~5BKyM6rq9dk z&Zy3qg-VT@l$#4NN#|KtC_=f%cE{V?IV+{N1lNVd1$TfBuHq#A7l|{NtaiPMsD#qM zD&_>Zo`oLJk>z)Kle4@S(3xeFBMgV`dpIwOxv3~ROS1g2{))kg1%_MbRT?HGwoCRJ zjAd{LhLKVJXkP1KLWqB74ad-`IrX+Nn>eE+`evtWd+l_Y_6Vcg!M4bwFPU!=t?TMlVOrWLzgUKNY6HiDYSE?ft{(LS&q$EHuWk245|m_oh0-# zuBIT5&OeSZh4Ul}o|ESst~n#lIiP~%d4#bW=hyUi3WIBN+tHHC0^8~Z#i_!)flGo3 zdH_}oq6X?el6wEYx=rg{mh&1im9O15iK*ME zNLBX+OTRZ|+M{=?DGyddlYYWIFU4A)iS1aJd>Ix8A>aEf<#i8$#F@LVOWls303}p? zj!U!`xf+2?rTb%W$l+m86&hpyW*OR`JNFyTdyo=zOHJC3Iro&F;M?y(SNs?9E#&hS zr@K8g&G-ZIWfIJuN^jNKQvGQ+h~F?C?7p02-Z&KOy*Y=zLuYl>6`k0{pk zCJ2J7k)tRgxVbZd1I*%;GG(XonQQ`b39LLPC3$vfz~ua+n-{Ddv=$UOiWHYJ6c^ zu-$~O^^#VtJcI=knL{7v|AlqBD2cu)gXd^AVc|ukh9Hay@5EeHKLPbJupgl=cfnb@ zrX}Fc+K;Fem`r0ylA0OslUuWyqyB=)hgq?T|FMyO#e9ifq>3ZXBP;h*ZR!vEQNdX( zm|UJr5Ub7zscL2NJR1r(q@&ccwyU&&eSs;*^j}pN9g(!+$wZF0A3RbS@;oZoiz*FZj zC!;M2C4(iC+M@YH$oPW64pCT5A)ordv`~=t*}-c(h(|^pFZ-!z7}qm>#d;k%Z9ft6sFrHDGSPQIhv+6kj>oQjI<|_CM`7eRDu>|}8Ls<^@-sFQO#<66=vx#ZDayIeJ z^ypxxR8=dr3Pb>?_VZ6}Z{b;UP{x;X$mv*453wsfzJbeperAB`CjDJI_eh&X_ zWDt-P*v4%z4wvZ(G*Yj*l0TV1z1^>XDq3|BmI|{#r3?uAkA;}n@IbjVjgx_ZgeCzi zWMT#C04pS1rBVBFf6|jj*+y3uD^t>}zM^hI71)Q=4?=auoIty!mIs zc>Z(X87y7Q9tn8>+^eing00%x{ew6^Al(xtyx$@?{ce|e@g(V5K-4NGZDHN@i^T{d zj}*c5>uA5(@gk9$mP?oP)v>ujfwF$s$ADkN4rcLYK>d&9#*&u879qs1SLVqxZXjK@ zfeG8YQ|tZ#$!GFjLjgbb0z+umIZvn#5zg=ttpuVHaNxg%MPto=Z?c;{rN|4dU)m#NtWpUe<_>EVR z$A#aIb!q3vT0R$hdKR?5y2_DpS&tEg4kyn2GJ<~RU#T8vw5y5pL!?!JUfR%D4 zAs7gjNlDt_SzAHI4uXyK4W`FAn__VAF-btSQxxby#L(gbnUL}cB#93R!g)!rSz&># zp{&a1qtom|XVK9#V-c+Y+QP_foi6|^Q4G~vz<*c%u0d6e@ONRNis5ntzYs+TD`R-h zquRjrt{*o-qQUBIaDy6EF^LaT?Pz>Y@PHm{p1yMV!M1(!`AqJJXikFfWnDbs2HGgr z`O#Fv8K}&l;PB}SY$+-P`71S}sQ*Cu5GbD@u$68>Kz$vnDCMkaueHUzvU}@jD-87+ z{dVEg%RG9ef@RQKfdP#?t7b4_n}|>?;FATeHr@Uad-mH|zX6R7(Ep||xU*R1lVQa4 z1Qx@!&2!<~>2%VY3sDQoC|AYg?;o42HnUBX2swt&h^6K{!u224I(csKMD(2FJ!O;* zlq)?>)_bSvSMnq`e~*iy)s3D)Sb^9^sqyGxQ>N_ke*Chc&S{r}K6Fq`59(NRVp~?nCJR@^f+ zP`jvyOUwj&Iwe)Zf^^`jr0+a>9y4v4OwrGGqOw9Kvq{PC<*+BBW18ctAG`7GS5i3h zeVZ8-ZOaNz_PL)=HCzlleA_WBd9dx19Zgry0@5*=tZxCD8Zz0Zno%=Fu>E}oS`y~i zss31Jwx-em(N@;K4+`>Tl(Fg6K#A|Oe31vgY8F;)76S7dq^e|w{JpkoUr4c^&s@>x z-lrXFS((O+*(nL)smwP4(1|F@D8u=!eZGxlkp7e$WIU1*J#Ae79=4)N&XeO2?051s zo(d*C>R7dXbR!ObCu^icBGk2oPZ-sD^=R3`==b5=;gC&f$ z=fq6&5y~LnRoQx8&-Gjj^gfWwX$kaP3#23zm30ikc|hMH#{s#Fj61XXDE`%6j_fC1F7e>ynM%IGeJ;0ke!i>QIV2&_NOr$ z%MD1jh0SKLh9c#dC(>vAT&Is$^4Qy1O~R&Kl-JL5+0YiGlQ*1?w@X^tWV?{nlPS#V zRYypOsHr@YEzLlRuBXS6-o|n981LrUm*rhp!c=Eu^ZPI7c^iS~?;L4-5qdJl&3)cbTReHvM2mupo3?YPj41-)zqX>G>m^#9n1jYGpdGoqB5Q&9-*M@ia2pH7rS6X^C ztJ;rWAcI_=8-YIKFqiLH!v0w=-|9Uiom);EgfwZ{Q8<1Nm+K#8`TOYXYpp6tCrxsOGRGYE?m$t zI|{Fgpp-LZT@5>E(zKr&VJ_p@kfpiqjD2Xd)X1|a7nY8Y7w1!5tR8SoWbUXw`jImHaEYP42J?6tTP70!Omld938Pd`ksdJ6O3ipC;2DWos zV8r!?B}xe})Eoj15=*qsnpf}%UV+FXe=->pLU=n-$4N@|)f{v)t*(s{W{U@HOAE?irZR7MFzJW)H-* zTQ^mX?>gC|FQ-dBy%ulgb*H9&MJ!Vw>fUeWuvRQsG+G;Gm+bt4xaU6t1<&Is&;}_2 z!$^%$Kvgycor)SC^l6E+>G#{bn>h$;w(x$UFIvK;6nZ1nhTX%fl_`9TG)7l)eO70d?!wGAY{EhD~;tOT})N@Xw3Xoi%O}dOk%)4lpgaH5z| z@?2Dp#10+~HDBlcD`P)&spmV2QvC-xef1~+hSpmo{ik{=R{AA1R<#BNMpyH+#$G)f zYK|*V`FWBY5wq`B;LtOG6e}C^zTkenhKW%(6SvY<2ZO5&)l`wFZvMGPE5#T}gGKAf zTFnicxwORg&f304d95ImI^HVnFe|pQ0XU(N0dw7R(gXOH!_m zf8I%nrscvipZ~Gw|I|Dk3q~}GDqA?wax7zXXy@5wCXGRjL5>4{3R*V9^!w(RZHe$UzAFkh!@dAQkn1{~=!OH0u5Yq4v$UR`da#Or@M zopyRhj0>g1IWiofZE|5c|FBNgZI?IX!oyzcmTL{8FuuR(~rl z)mhv5eUVH>xKp7?eA4278_x%P;PHx^@S#7PKpr0 z)@}1JZ}3yTsM4+M7L`y7+>B|@4qjT!louv%h|6)D_P7#>RS_MPL1RqlX5b`Zf}05> zESZ-w^bu_hH{^NFq(8%ABIBz(?#idP5)fn|>DY~)Whm>gIs9f^<{{zXSBf4@C=YHwF@-yIq`pyq~Q z+6|kDaFJ}=r=Rqp8CuNw`r6jOdrVLhmxmRLUlN@8hk_rRpi*}!4IE1_|WPhY6HknvC0DY5!+VXp&K(0EU0Rvm4!xt^U zT*u4@6jqyXnlQkUwP>VkxaFNltX8Q0M7-X3agrp3AvNv$+9DW*?#aXRnT0{@OBaAi!PgJdoVhhnb<8|hSV3op z;~