From 04f997e044611c56cafeaa0df553d3383bf3e5d0 Mon Sep 17 00:00:00 2001 From: davpapp Date: Thu, 22 Feb 2018 11:58:54 -0500 Subject: [PATCH] Putting constants in separate class --- src/Constants.java | 5 ++- src/ImageCollector.java | 7 ++-- src/Inventory.java | 9 ++--- src/InventoryItemsTest.java | 7 ++-- src/InventorySlot.java | 1 - src/InventoryTest.java | 45 +++++++++++------------- target/classes/Constants.class | Bin 810 -> 1144 bytes target/classes/ImageCollector.class | Bin 3811 -> 3800 bytes target/classes/Inventory.class | Bin 3204 -> 3436 bytes target/classes/InventoryItemsTest.class | Bin 2393 -> 2369 bytes target/classes/InventorySlot.class | Bin 2732 -> 2576 bytes target/classes/InventoryTest.class | Bin 4680 -> 4580 bytes 12 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/Constants.java b/src/Constants.java index 63030d3..d58656a 100644 --- a/src/Constants.java +++ b/src/Constants.java @@ -12,7 +12,10 @@ public class Constants { public static final int INVENTORY_WINDOW_HEIGHT = 350; public static final int INVENTORY_SLOT_WIDTH = 171 / 4; public static final int INVENTORY_SLOT_HEIGHT = 254 / 7; - public static final int INVENTORY_NUM_ROWS = 4; public static final int INVENTORY_NUM_COLUMNS = 7; + + public static final String INVENTORY_TEST_DIRECTORY_PATH = "/home/dpapp/Desktop/RunescapeAI/Tests/Inventory/"; + public static final String INVENTORY_ITEMS_TEST_DIRECTORY_PATH = "/home/dpapp/Desktop/RunescapeAI/Tests/ItemNameRecognition/"; + public static final String INVENTORY_ITEMS_DIRECTORY_PATH = "/home/dpapp/Desktop/RunescapeAI/Items/"; } diff --git a/src/ImageCollector.java b/src/ImageCollector.java index b69f31b..037b648 100644 --- a/src/ImageCollector.java +++ b/src/ImageCollector.java @@ -77,15 +77,16 @@ public class ImageCollector { return screenshotOutputDirectory + itemName + "_" + counter + ".jpg"; } - private void generateInventorySlotImages() throws AWTException, IOException { + + private void generateInventoryImages() throws AWTException, IOException { Inventory inventory = new Inventory(); - inventory.updateAndWriteAllInventorySlotsToImages(); + inventory.updateAndWriteAllInventoryImages(); } public static void main(String[] args) throws Exception { ImageCollector imageCollector = new ImageCollector("/home/dpapp/Desktop/RunescapeAI/TensorFlow/IronOre/"); //imageCollector.collectImages("ironOre"); - imageCollector.generateInventorySlotImages(); + imageCollector.generateInventoryImages(); } } diff --git a/src/Inventory.java b/src/Inventory.java index b86476e..75a8483 100644 --- a/src/Inventory.java +++ b/src/Inventory.java @@ -36,7 +36,7 @@ public class Inventory { } private void initializeItems() throws IOException { - items = new InventoryItems("/home/dpapp/Desktop/RunescapeAI/Items/"); + items = new InventoryItems(Constants.INVENTORY_ITEMS_DIRECTORY_PATH); } public void update() throws IOException { @@ -52,12 +52,13 @@ public class Inventory { } } - public void updateAndWriteAllInventorySlotsToImages() throws IOException { + public void updateAndWriteAllInventoryImages() throws IOException { BufferedImage image = robot.createScreenCapture(this.inventoryRectangleToCapture); - writeAllInventorySlotsToImages(image); + ImageIO.write(image, "png", new File("/home/dpapp/Desktop/RunescapeAI/Tests/Inventory/inventory_TO_RENAME.png")); + writeAllInventorySlotImages(image); } - private void writeAllInventorySlotsToImages(BufferedImage image) throws IOException { + private void writeAllInventorySlotImages(BufferedImage image) throws IOException { for (int row = 0; row < Constants.INVENTORY_NUM_ROWS; row++) { for (int column = 0; column < Constants.INVENTORY_NUM_COLUMNS; column++) { inventorySlots[row][column].writeInventorySlotImage(image, row, column); diff --git a/src/InventoryItemsTest.java b/src/InventoryItemsTest.java index 2696f0f..9b5f90c 100644 --- a/src/InventoryItemsTest.java +++ b/src/InventoryItemsTest.java @@ -17,14 +17,13 @@ class InventoryItemsTest { String testingItemDirectoryPath; public void initialize() throws IOException { - items = new InventoryItems("/home/dpapp/Desktop/RunescapeAI/Items/"); - this.testingItemDirectoryPath = "/home/dpapp/Desktop/RunescapeAI/Tests/ItemNameRecognition/"; + items = new InventoryItems(Constants.INVENTORY_ITEMS_DIRECTORY_PATH); } @Test public void testGetNameOfItemFromImage() throws IOException { initialize(); - for (File itemFile : items.getListOfFilesFromItemDirectory(this.testingItemDirectoryPath)) { + for (File itemFile : items.getListOfFilesFromItemDirectory(Constants.INVENTORY_ITEMS_TEST_DIRECTORY_PATH)) { if (itemFile.isFile()) { BufferedImage itemImage = ImageIO.read(itemFile); String expectedItemName = getItemNameForTest(itemFile.getName()); @@ -36,7 +35,7 @@ class InventoryItemsTest { @Test public void testIsImageThisItem() throws IOException { initialize(); - for (File itemFile : items.getListOfFilesFromItemDirectory(this.testingItemDirectoryPath)) { + for (File itemFile : items.getListOfFilesFromItemDirectory(Constants.INVENTORY_ITEMS_TEST_DIRECTORY_PATH)) { if (itemFile.isFile()) { BufferedImage itemImage = ImageIO.read(itemFile); String expectedItemName = getItemNameForTest(itemFile.getName()); diff --git a/src/InventorySlot.java b/src/InventorySlot.java index dad2d8c..b31c2e4 100644 --- a/src/InventorySlot.java +++ b/src/InventorySlot.java @@ -40,7 +40,6 @@ public class InventorySlot { // For test image generation only public void writeInventorySlotImage(BufferedImage image, int row, int column) throws IOException { - System.out.println("Written inventory slot image..."); updateInventorySlot(image); ImageIO.write(this.inventorySlotImage, "png", new File(getImageName(row, column))); } diff --git a/src/InventoryTest.java b/src/InventoryTest.java index 3b9b508..54cbb3a 100644 --- a/src/InventoryTest.java +++ b/src/InventoryTest.java @@ -12,17 +12,15 @@ import org.junit.jupiter.api.Test; class InventoryTest { Inventory inventory; - String testingInventoryDirectoryPath; public void initialize() throws AWTException, IOException { inventory = new Inventory(); - this.testingInventoryDirectoryPath = "/home/dpapp/Desktop/RunescapeAI/Tests/Inventory/"; } @Test public void testGetNameInItemInventorySlot() throws IOException, AWTException { initialize(); - + // TODO: Coal is recognized as ironOre String[][] expectedItemNames0 = {{"willowLogs", "oakLogs", "oakLogs", "willowLogs", "willowLogs", "willowLogs", "willowLogs"}, {"empty", "empty", "empty", "willowLogs", "willowLogs", "willowLogs", "willowLogs"}, {"empty", "willowLogs", "logs", "logs", "empty", "willowLogs", "willowLogs"}, @@ -35,24 +33,24 @@ class InventoryTest { {"empty", "oakLogs", "empty", "logs", "willowLogs", "empty", "willowLogs"}, {"logs", "empty", "oakLogs", "oakLogs", "empty", "oakLogs", "empty"}, {"willowLogs", "empty", "logs", "willowLogs", "empty", "logs", "logs"}}; - String[][] expectedItemNames3 = {{"oakLogs", "willowLogs", "willowLogs", "willowLogs", "oakLogs", "willowLogs", "logs"}, - {"empty", "oakLogs", "empty", "logs", "willowLogs", "empty", "willowLogs"}, - {"logs", "empty", "oakLogs", "oakLogs", "empty", "oakLogs", "empty"}, - {"willowLogs", "empty", "logs", "willowLogs", "empty", "logs", "logs"}}; - String[][] expectedItemNames4 = {{"oakLogs", "willowLogs", "willowLogs", "willowLogs", "oakLogs", "willowLogs", "logs"}, - {"empty", "oakLogs", "empty", "logs", "willowLogs", "empty", "willowLogs"}, - {"logs", "empty", "oakLogs", "oakLogs", "empty", "oakLogs", "empty"}, - {"willowLogs", "empty", "logs", "willowLogs", "empty", "logs", "logs"}}; - String[][] expectedItemNames5 = {{"oakLogs", "willowLogs", "willowLogs", "willowLogs", "oakLogs", "willowLogs", "logs"}, - {"empty", "oakLogs", "empty", "logs", "willowLogs", "empty", "willowLogs"}, - {"logs", "empty", "oakLogs", "oakLogs", "empty", "oakLogs", "empty"}, - {"willowLogs", "empty", "logs", "willowLogs", "empty", "logs", "logs"}}; + String[][] expectedItemNames3 = {{"ironOre", "empty", "ironOre", "empty", "ironOre", "empty", "ironOre"}, + {"empty", "ironOre", "empty", "ironOre", "ironOre", "ironOre", "ironOre"}, + {"ironOre", "empty", "ironOre", "empty", "empty", "ironOre", "empty"}, + {"empty", "ironOre", "empty", "ironOre", "ironOre", "empty", "empty"}}; + String[][] expectedItemNames4 = {{"ironOre", "empty", "empty", "ironOre", "ironOre", "empty", "empty"}, + {"empty", "ironOre", "empty", "empty", "ironOre", "ironOre", "empty"}, + {"empty", "ironOre", "ironOre", "ironOre", "empty", "ironOre", "ironOre"}, + {"empty", "ironOre", "empty", "ironOre", "ironOre", "empty", "ironOre"}}; + String[][] expectedItemNames5 = {{"ironOre", "empty", "ironOre", "ironOre", "empty", "empty", "ironOre"}, + {"empty", "ironOre", "empty", "empty", "ironOre", "ironOre", "empty"}, + {"empty", "empty", "ironOre", "ironOre", "empty", "ironOre", "ironOre"}, + {"ironOre", "ironOre", "ironOre", "empty", "ironOre", "empty", "empty"}}; testGetNameInItemInventorySlotHelper("inventory_0.png", expectedItemNames0); testGetNameInItemInventorySlotHelper("inventory_1.png", expectedItemNames1); testGetNameInItemInventorySlotHelper("inventory_2.png", expectedItemNames2); - testGetNameInItemInventorySlotHelper("inventory_3.png", expectedItemNames2); - testGetNameInItemInventorySlotHelper("inventory_4.png", expectedItemNames2); - testGetNameInItemInventorySlotHelper("inventory_5.png", expectedItemNames2); + testGetNameInItemInventorySlotHelper("inventory_3.png", expectedItemNames3); + testGetNameInItemInventorySlotHelper("inventory_4.png", expectedItemNames4); + testGetNameInItemInventorySlotHelper("inventory_5.png", expectedItemNames5); } @Test @@ -77,15 +75,15 @@ class InventoryTest { public void testGetNameInItemInventorySlotHelper(String inventoryFileName, String[][] expectedItemNames) throws IOException { loadTestingImageToInventory(inventoryFileName); - for (int row = 0; row < 4; row++) { - for (int column = 0; column < 7; column++) { + for (int row = 0; row < Constants.INVENTORY_NUM_ROWS; row++) { + for (int column = 0; column < Constants.INVENTORY_NUM_COLUMNS; column++) { assertEquals(inventory.getItemNameInInventorySlot(row, column), expectedItemNames[row][column]); } } } public BufferedImage loadBufferedImage(String fileName) throws IOException { - File itemFile = new File(this.testingInventoryDirectoryPath + fileName); + File itemFile = new File(Constants.INVENTORY_TEST_DIRECTORY_PATH + fileName); BufferedImage itemImage = ImageIO.read(itemFile); return itemImage; } @@ -93,8 +91,5 @@ class InventoryTest { public void loadTestingImageToInventory(String inventoryFileName) throws IOException { BufferedImage testImage = loadBufferedImage(inventoryFileName); inventory.updateWithFakeImageForTests(testImage); - } - - - + } } diff --git a/target/classes/Constants.class b/target/classes/Constants.class index 1629fde9b7c2ff2b7bcb46ecc80500246fd5fecc..31314005315ea3c706e1a1a109841500dc368631 100644 GIT binary patch delta 448 zcmZ3*_Jf1#)W2Q(7#J8#8B8{EO=YZ?_4EsK^$YP2ii{6&4GxKS@eFcx26F=(Lp&H6 zgnY6R%M$f-67$magG-7s^U|$37?cVdb5r$G3K9zn^j%VmvrF;|^n*(CQj3!l z3sN0D^+QsNON#Y9^U6~5O7e>;^%)tI5mtGIxcUZzEUZVjk%K{%k->^c!%I?g{StFi zgHn_8)AKS*GV}9**2tk-gX$#?1`S3AHJAl*xSa0^G`m=T@?1tKHeDVDO$M#Wdl{1% z`6nwf9juUKkY`X}U}Rtih9eV$B7-D@G7?_}$X7$+s{>Usf=mFC+CUxpU_Ju_tJZb~ iosD24^nfHAP#9#KK9J-AvsoDo7z}|tMg}9Wj4=QO#BI0$ delta 113 zcmeytv5JlB)W2Q(7#J8#8MHQXO=X v5vWujNHYRyR;}#}N*jR;CI%HC$p#i=Vo(LLc_0cH)ELx(JVpi$uqsUe82%5N diff --git a/target/classes/ImageCollector.class b/target/classes/ImageCollector.class index 4bc1724a8d44a507a38eec65d70f461f36e09274..d8851a8a058c6094082aca73d63ba4a9ea8cd520 100644 GIT binary patch delta 69 zcmaDXdqZ}E9*2;4dTL&3QDRA|XI@!qUP*pYHV_r&lQ6`Yi s$w5(59Fo7ekz*?>XCMOyLl6TGL-1sKz9`Oc1}=t320n(U$&2{R0CPzpSpWb4 diff --git a/target/classes/Inventory.class b/target/classes/Inventory.class index c7a17dbf9faad062fd6884a45dccd6fda89e7e83..74270db82184ba85c4c4d0665d735840b2f3e17d 100644 GIT binary patch delta 775 zcmYjOO-~b16g{sqQ{eHU&{!3U1n`4WA|o*pk%(3TNPt2BDMh6n>{tfN6x#txRqz8p zR=RjQet}DfM2sZvb#3Ctg+IU_pbL$+(}*tSzI*Q6ckVg&ZPa|P<)41P{{Y||UTpJ^ z%9Vzt#iZewVLKVkT6Ct<1NO3MJDKe2z=Dx7bLF_kpe)*{GDI1~ys>QPRz~l$(q=hg z4E^$@r(u1<%sDxI|Eg~NC5car#K(Fg;o;sk;^3G>nBxX!%5amxUu4VcR&fwEruyU5C)s_k7CSV3McXr1i^ z+%LmDh6DQoM>Ce~2s}V11It&SfOUa~E?VU%y!oPSD(kb*;Gs8Y3hm%HeQj^iH`MBz z*u!MZH?@oDceox6weG^$rY;XoQuINkcpd_ssKW&`q6?>}a=65VW&{Zd!V!#+T~E<1 z#e-B;3Hxw}vQ5fW`L!azlJZAIqraP!Tmr{s9Hp}n-Dp9NY~%gP94wjV^}hKnx>l0l zB^sblzUD2;0&Mx22U$k`;>|UKL^DJ*!z3+&ddizI2pwbcVr93IgCo}}Yp*Uvsy(j) zRiU}W=^d;lI@D^`R9AJvg=>ipZ4ZT*U-fIdc=T^*$@e5Viz0w2gbiFrcIHM7K16YQbojSYlSv#t*!TJVjp^wYSO3E z&K1tgfqy^;7K?(4V-@@jI&tQ25I3>Va$rB$d#$tf`g3YG<$nMB@e6Q)XM659)61=| zRfAS-v|gRjzpSogbEi$d{%Ivn92pHVtC-`Cw(K2eQ8CXwy=z}_ z9w@5R^bfo4tSDA_q(_}{F{E*fx0QF&R|nV bj~DwFq+UE?kaJ)VqHC*dkioWaN7(rX+R0#m diff --git a/target/classes/InventoryItemsTest.class b/target/classes/InventoryItemsTest.class index 177f4c0b1829779096cf7336ab8dc42cf5f8c250..4500f75f5793727420f1dc2361441bbeefc3525a 100644 GIT binary patch delta 1003 zcmaJEtlkeHZg+_7+B-1rmx1=jms8?45dmp60o%)K+`oH<{8?|u5`pKrGTbRxT< zKWAcx&FpF9@Im(?ELK=T*WpJqM++h%;Tak+(W>Dn1D{VlO~tH-u|aDg%@IY6LA9PZ z8H3aknbvU(9U9shs+`j0n6;S7q^Tk4%*j!XTU;?HJF$s)Tn(sBM?kUBvxWYb9u^F}%I`SfBo|x*yc7rM>RJR*hejGB z2%!T9(MM}Zg5iKRsDdCAK?f1W1=?d&o2#Mai%_Vg48wGsic3^l2`P_iC>j+preOq# zcqktGKU*dj*-rkOZK8y1)FqqygRSqfjqz2eYp5s?52!Y#ws5mZ{ljnS1|b0vkJ1e3cGv==1EQA>DNg1Qn3x*-28L7wi=ND>XED~g7c zMs7l$+)*l(hde{(C%qg8^b$tLL)?_i@>v^qZDiIdcl{N0%>sh$ypz9BSOn>q?EyUr KJpmTnhQ(jPf|XtX delta 984 zcmaJ=OH30{6g_X=%)B}d2<0Q?Yk@*L<^NGE78C>pQBV;n;-^Z{BEJ9{U6{Hsapmf* zShA6wkpv3Sgv7+e1XpZKT)H=L?S^`%MQk*2F*Enxciy|_oOkDg^Q+U?*?YGQpcV6L z#xuqpI3~Zdpm7Kc3T?TmqYePafi(JIg)-zbIrI8MmVO2AQzlO_Uaml@on2TgRKQ?~Ig{fvn& zbj#;_NbkWpfnNEAd-!?u$vwWxF3Z=dl|9U$MP}xgo*EdzsK9mkP0iyWjLDy>M;|wF z6Srig)?e0xJ0`-o%V2~T7b6Qx!wZjyl_rvXa=fDe@%6ayTe1q~=8^ zMKQH4fuEvQl%bny7f_z0Z4rVkXyrO_v)axv}4R>;Bd2yc)-~W$3HOPDyv^aopI#?S1hd|A@DU z3s6PUs!6h!H2Fx6MN0hWL=DYe9r3QlC>qmD2q7z)yu4C09hl%bFrg^Tgm$QZn~^82(N#GtC$pjizWDE22|O2rEJ&A!#BkB&4Bg(2l8gT2)n)x~)YrORr#| zNGqDyN^CuVHxd7tZvOM#&UY?P{)Zmv`|sluz!dK4(xXe2z_2M}5JMhpF*pmRE@GQO z&S+&#HS+4BkxlW?j*MOGSyi{PkVIOB7dnG~c*)LXHB(ntOGU%frz2|;3>=8akk8$U zYUDIMMO`tz##Urxk+Xi>%dR{_!1@&eP7e;PIbpujL|TH0l8j@Nt$RW7Rv1{4YiC?L zx4wi4-vxtfjBd*1nv5%4zjlZ(j#>^PT=clG5^Z2ZdBcn^(Lyq=gu+c|O{Ctjzh0++ z1HCl6;G`La8zTr|6n(^$b^-bkBt})3r5v+S2m k&_prVz>)8yfzuENRRRrMK2xN9x?s1CTU99{-q`BxKO(DA;s5{u delta 574 zcmZWl+fLL_6kUhuv_n%wssxoG%!3#y&`C&)4;W)KF(DyhLIM&*s9H*)m!WeQ8Al!O zig&4P)k4_|dBOE9$2Lt<#bYceuo=$$=W)-XF%A|Pl#=lE0vdI>Ijb3k6YY%j zPpV*8($I%XIe3(+6gUb>l4yQJFN{QhG0(pTy<)_nph-g%F@feO(=ujCxh118r!QpZHDBV?__@txBk!2DRgB^>fmWBPe#=QsT$u~T zqG%O(%pEfARC=~*pq*O@R*0hwO*?h}?}JGx6pVE>d|SWB&!NSDvN=@^BSo;OqOKH^;EpoZOuMezj5U7f0E zoN)@KwKg6_ca8L(Iff^>?OSFxYu}o(*NQP56^PpUhWFAd5H@mo=XMOoD1O%U=%+`a zWEm5iMhq#wm<8LKE%4pwB5?S__kY32=8b|tZ%;k@s||M4 zJ0HVSH7g#ME5`8g8sm^>WUQ;Wo$!pOYK+64@#z}lh&1w48Jl??RbxelO$M+yD6ppy ztwz2SrXFCZk?}+$<8UJ*1#OXn24`rpl+DJFCap>gR%xpQ;*%PtFfGttH?ORHTLbME zrO>nWu)f-#svq$s&(x3jx?ipz@x{L)u(v{==l^~K5h8J*M zU|-hOSLD6ny-4TuHDk^WMC7G!AVKfEyv(|WB`nL+Q4IX0=x%aajKjcM6srtND)^n-Mfvumv>TwVZpg zq-UAnj#iWRvg>%&I=)3_(w0EwNi%E66U{?b{m5Z8I5aVqqMV$?qvD;PGK#G0vdDRHI^Yd% z7ZZ6wf1=@Y_`Ez_KhyAYyveIt%CG2-am93QOzInk3pHsMkQeoNf$R>hNNwfhOdvuY6!mk&>A4@i$G5+|WLCX&IQf%F^Q;9WDnv-!XMN)^w38mze}J zwjAmTIz4JwGmaJ39Q2uRf{#mEnYG+uAa%u;y?PGx9Sd*AdJ8%MeEn*#;{U^%7-1>I zN3fZ9dlTHe(&C+n($QyY1LO04OBhzyF`^d8MyAyZUW)Y7>buH&cm@*?!cxLG!(J%V9lD6K>?xu5#XUUBp30T} zhI8zNi9diz_GJ1$Uz3t$n%|O=@v5KlPsx;=OkALLpGYQVyyl|UT=JSZubEd|m*>1@ zQ8pEElZbN*V-)u!>%=M6fYX%tX_l~OaFnD5xP=jtKS|n^8geSAA^aoY*Cmzoy{dGL z7Fqt9kAD@1RmHqrZ#Cm1%U9Q`C*2oKtZ`xg;%bV&iKoI2dqFdzJQ9zN< zLjDb`Tl5{y3vzD!g~?jZ2S2>f{e>?*jp*!I2v#q#U@1y5n}+i@e(n2Qp(S; zr{c53-39dn#Ki{)i`IX$#0vSPQnweI_$s{*KElfjk8o!p@udg&GR6GLeZ2YrZ%p?+ z#5ZU9e?u4V%fSUr wGLFqs(jQMtA$f6sx;1{!^W-o?5 z&UgO*oE3li&+q;KU>Ls&z$dUPp1rMSEi->-Rxelqr~-RdwA)%Nt!0;Dmu{`-DNA67 zQIZnaIprN073i>d%*ZZzYZr|?k5J!b%~}?SOqI1ItUM)osNt-UHLUXjN_WqkfO^4P z&_htLD~ufo2{cX_S$(FMxuxf4wOeUjsxebqdQQt5a_%mw*0NEM(w=eY1NDcbdP7Sa z&+}+#Vm+njEW^we0%#U!wgG8tR&4D0thX0HtH54+%P?c{OBEaK^xv}(LK}ANfWW~p z{AdW`kibA}+05v%g`Ael#V+cFRm;r9t`@U;A*JQ?v3N|vD#Sb;F?s$-7y$$Y4oLzZ z)2$gTqsOyxOV4<6iL^=X+o{PiGWwiRFzEYOHfvg%?G8aqnfayIN|Ele%^8-Sk7+r> zHaHrhm50KJAQZp}I(MTs6an;9#oLKc5GP67nvqVMYg6V@A&5SKfT^uIlbC>C&*ZE- zL7Zan(ze8DO62MC*t#CXFoR;0Zp_Vr{#W^8!8HwSaHb zaiV7~2nM~v;wfn{h;vnogU;e3Rg0&c#j&czA!qSI)#9*RTo|ViB8n2b=kgFyW>)Ry>`dtJz2Zsl7B;>tqh-6{$|;QAfB$j>ms>Xf7eDM@1YjP zEu;hvq)lyMmek4omC=^;S<@qtd7=&lJ#+H?>tQT{ccIZJc=D2TJD<&mU|=K&t!vpZ(#Y_o+}6@X{nDa9OZR+F#VvQm_;gJ?7eJ0_qW%LPD-`s+odm+jgGn%~ z*((#z6}2>{Cn~`^S$wp@j=Lh0Z>lK0HmDWnkRgmcd2w?-S$^w>>qpyYWI^LjPtOyo6Un_zvC*;Ja>pTX#s1rA(3$=ZpUyzRzr(*ENFacfoL9 zQZf2}$RmbD?{WlLWis*i2KTfB-&pYg#=0FG~%wj&JJ76Q;MU~q6W#Dmy zAQXNL`S{0b&K9yNvz34R7UBL*j$-Tudw+Bb;ooxL!)~?>_F@=~9ETkN>_HP}Ow>H= z!(Lm;hkat<(MZSpI9%4c+lCaO{9fwXSD`)PX+KKsil@DW zQk}LXfn)3m*}p+Vjh%R&ReIF;xwkP+idX9pDB*57dCR zm6t&iO;Dn7Wj)ZgUR%~CgH0eZ_(`Ct$aT<`<d?3!0lQ z(>8myatE}GiU*pTZd7=nL59&~nj;5DvYKh?a6wb0E9-zJhM5Nu^uy`{iQ4}_qHc&r zhE8r`BpP|R*Y3{t+1+`kd(`R1WmnE)Z{s*~Q5#h3#|RGao9iInKnJ!t{{V;Z4;&V) zI3h0KsL1elR2H4$9UK#XMwj>(9`bdf({~KVeb;cp_aeG|zebPmFPwjfsIn6$l{4s7 zQs`4&=lo6dD}O{x`6mX{cAQc#pkJN9pgM)qY63&*Jcd;bBkD5Fs3w1f$c+8ClONrj z`hl{AidMMyhZs5sI>Gq#5wX)|4BT-k*oqwR^?-v?eELS zc+JiH=VU&PMyAwF%tRwsoo?3Y=A7;+r<+%7kK6}+U`2FveCzbG>;`B6EWHoG!GS<&V-@}1TENo->Apf?J zEgN?#RGcOA2_AjYHgLo_>KdRDSS+Hl*0rLD+f*&&ufH0j@9~_UQX{re<@{arC?o1! zv`hOP&7@+jw_~tb9VCJcRW!3Qz5Cz4Zz!UJ{a+;}#jeGNWHd2DU6)DC72>$cT6hJ0 zoDbugjd94a2?*9Poh$`s-