From cff5a9a84a1a037d320d00b70212e0c8405d4471 Mon Sep 17 00:00:00 2001 From: Dmitry Rendov Date: Mon, 5 Jan 2026 14:29:47 +0100 Subject: [PATCH] 5 - Add XRayMonitor logo --- README.md | 24 +++++++++++++ REFACTORING_SUMMARY.md | 76 ----------------------------------------- XRayMonitor.png | Bin 0 -> 14693 bytes 3 files changed, 24 insertions(+), 76 deletions(-) delete mode 100644 REFACTORING_SUMMARY.md create mode 100644 XRayMonitor.png diff --git a/README.md b/README.md index f0611c1..671b502 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Let's fight X-Ray cheat with simple Math! +![XRayMonitor Logo](XRayMonitor.png?raw=true "XRayMonitor Logo") This simple plugin monitors players' mining activity and detects potential X-Ray cheating through statistical analysis. When a player mines significantly more valuable ores (like diamonds, gold, emeralds) compared to common blocks (like stone, coal), the plugin flags them for potential cheating. The detection is based on configurable thresholds, allowing server admins to customize sensitivity according to their needs, and uses [LogBlock](https://www.spigotmc.org/resources/logblock.67333/) data to analyze mining patterns over time. This plugin requires Java 21 or higher and is compatible with Minecraft server versions 1.20.x and above. Also, it supports both Paper and Spigot server implementations. @@ -29,6 +30,29 @@ The configuration file `config.yml` is created in the plugin's folder after the - `/xrm Player world:survival` - Check a specific player's mining activity in a specific world. - `/xrm all ore:diamond_ore rate:3` - Check all players' mining activity for diamond ore with a rate of 3. +## Adding New Materials in the code + +### Easy Extension Process: +1. **Add Message Entry** (in Messages.java): + ```java + Quartz("quartz", "§6Quartz: §a%s"), + ``` + +2. **Add Configuration Entry** (in Checkers.java): + ```java + put("quartz", new OreConfig("quartz", Messages.Quartz, 2.0f, + Arrays.asList("nether_quartz_ore"), true)); + ``` + +### Example Future Materials: +```java +// Future Minecraft materials +put("ruby", new OreConfig("ruby", Messages.Ruby, 12.0f, + Arrays.asList("ruby_ore", "deepslate_ruby_ore"))); +put("amethyst", new OreConfig("amethyst", Messages.Amethyst, 5.0f, + Arrays.asList("amethyst_cluster", "budding_amethyst"))); +``` + ## Support If you encounter a bug, please open an issue with detailed information. I maintain this in my spare time, so fixes may take a while, but I'll address them when possible. diff --git a/REFACTORING_SUMMARY.md b/REFACTORING_SUMMARY.md deleted file mode 100644 index 454d692..0000000 --- a/REFACTORING_SUMMARY.md +++ /dev/null @@ -1,76 +0,0 @@ -# Checkers.java Summary - -## Overview -The `Checkers.java` file provides a maintainable, extensible architecture for handling different ore types in the X-Ray monitoring system. - -## Key Principles - -### 1. **Data-Driven Configuration** -```java -private static final Map ORE_CONFIGS = new HashMap() {{ - put("diamond", new OreConfig("diamond", Messages.Diamond, 10.0f, - Arrays.asList("diamond_ore", "deepslate_diamond_ore"))); - put("emerald", new OreConfig("emerald", Messages.Emerald, 10.0f, - Arrays.asList("emerald_ore", "deepslate_emerald_ore"))); - // ... more ore configurations -}}; -``` - -### 2. **Modular Architecture** -- **OreConfig Class**: Encapsulates ore-specific configuration - - `configKey`: Configuration key for the ore type - - `message`: Display message enum - - `levelMultiplier`: Impact on X-ray suspicion level - - `oreVariants`: List of block types (supports regular + deepslate variants) - - `useNetherStones`: Whether to use nether stones for percentage calculation - -- **OreLookupResult Class**: Data container for lookup results - - `count`: Number of ores found - - `stoneCount`: Base stone count for percentage calculation - -### 3. **Helper Methods for Better Code Organization** -- `getOreCounts()`: Batch retrieval of ore counts -- `processOreType()`: Single ore type processing -- `calculateAndDisplayOre()`: Ore percentage calculation and display -- `determineOreColor()`: Color determination based on rates -- `formatPercentage()`: Consistent percentage formatting - -## Adding New Materials - -### Easy Extension Process: -1. **Add Message Entry** (in Messages.java): - ```java - Quartz("quartz", "§6Quartz: §a%s"), - ``` - -2. **Add Configuration Entry** (in Checkers.java): - ```java - put("quartz", new OreConfig("quartz", Messages.Quartz, 2.0f, - Arrays.asList("nether_quartz_ore"), true)); - ``` - -### Example Future Materials: -```java -// Future Minecraft materials -put("ruby", new OreConfig("ruby", Messages.Ruby, 12.0f, - Arrays.asList("ruby_ore", "deepslate_ruby_ore"))); -put("amethyst", new OreConfig("amethyst", Messages.Amethyst, 5.0f, - Arrays.asList("amethyst_cluster", "budding_amethyst"))); -``` - -## Testing Results - -### Test Coverage: -- **21 Total Tests**: All passing ✅ -- **ConfigTest**: 6 tests passing -- **CustomizableMessageTest**: 5 tests passing -- **MessagesTest**: 5 tests passing -- **CheckersTest**: 5 tests passing - -## Future Development - -### Recommended Next Steps: -1. **Configuration File Integration**: Move ore configurations to external files -2. **Dynamic Loading**: Support runtime addition of new ore types -3. **Plugin Integration**: Add hooks for other plugins to register custom ores -4. **Performance Monitoring**: Add metrics for ore processing performance diff --git a/XRayMonitor.png b/XRayMonitor.png new file mode 100644 index 0000000000000000000000000000000000000000..e5c7a4b3e97d1ff3bad15a0311147c87913f34fe GIT binary patch literal 14693 zcmZ8|byQnV&}eWeF2!9_++9j3F2x;+YjL;GmZHJk-Q68pB$NW75Fo`V7M$V^kKgyb z_s^Si=FaTy?A$$9&W>&L2MtABY)WhZ0D!BkB(MEKKmLc9$S>DVck6C11j$QVQ4UZK zrQUmKpxVDxe+vLKCA@mDM0;stxholY0RVVI{~^+-TcyoQCx!QWLvI~7J8wTrPg}qT zOGj64ZjJZ4^g`Tx+h1fZ$W%W$N<6@YW#wZk*NRE@AAU`2OnSXzxn@<{{MFc08jvcL<|7xiwrNn054ME z|LXm34qD;=>Pmm%{{!R~P00TvsVye@!u{V_e7wB>jiL+9dNn6_N&o<&gv#=7b^Xof z`uxI3=WeB+dJz-L?R_oZXDp2ZiOZsjk$u6%kYsXF_1Q{3$nedagJ87sA(|>d(7U%k zkX6VGtGx{k7mu6!GJ>w#v&0bBqgh?ou6zX#_d$8v(A=|pul)1=lK{=Er23vaapcm} zu<*MUkX3@s^FqQt9abU@<@js-#Kc6BSpB4G5(ye4Z8Y&FGgVDYb^n+VX4GUebIs-& zDjtT_WbWBl*2qZm!xTxaJm0%?F{8d?f|+AwRM2@v|GIlFP%~Ez1CmnI$_yCzA`(lH zXElRz*sn0Lu}>_*LJL}B7D|zQVd+LhoG++&@4{2ex|?( zu^MYQQI%)j%DlE)V=g^jwZQXvm0>1dqF7!~Sq`pCH@Ug!p+KK`CPL>Z&~9pHF$_BtQZ;eWnLmfhb&D)YV?5Io{nSW?;kGa z*92dufKx!(!H8%qM=v$ziuxw|9^s~)>z~scBj1lSP#KX4`Rpum$q^F_#hC!s)YUW- zxpy1#Q68+#LS!Ul8~$#*bCcw1UX6zTf<(#6%jfc`!+gwO-t~Lg_0HY( zj@b}$YhmA0Nwb_S`9xxtGSuD0ntBEWzQpcvjgwL$ADt6(FNi8jB18gxJ;yA zUolYEw{mhqLPUv>ZjcZX;t~^kZ=G#x)DF4$ox}a_0}fjZ63M#?IOLgxh4mOKv09vb zGaC{u&r9Oqk!F0OjnX#B~a{`{t!m+!`xsZV`y~0P$)s{qDUUeK#(1x4+wD?dX^#P?49GmG4MiPQVzU zh0M~PCtHYi-e5POaKJWPq4?1c9QYcAal;hmv%l*gW*pdiVIvlHnlie4RdZku%@y|k znK(OZ^CdcwE^ji*`@0|m5@h{sFa=$ca#{La<|VHB{T0o_LklTg?=?$U>%|0+7_zl} zmGp&k+)BPXRxekqEnq1DAboc;7jVwaXk|-kJEte~*FAi%es*G_bpkAFU+E8njy_+A zhMiAIb$~);V1nNW%xYHa{-R#seUR*iL;P%KRgoEYd>zwCxutxpruvxx^$!cV-#XSL zk8)dDT0B2SOnYO;1^sTPqRDyR_$z9Vh=2(E-DlU8_nQ5NmB|a+bCfB_L1}%xDEWHz z>E9(>8t}nTw70U6eIcjVBbQUA-)HG~0ig*xinG7F7<;^0Y9rNavsNI*qtO1nI4|w| zW3zHa#CN|nmZv~!vzMX{SKUqW`VLAX0nHJs0j>3yTVewPVU(Bh%^0$MBApzUZ!BVz z#^RSoB*e2jj{hty?-vB?PZMiO2CoJn%9(AyTQG67YY%yHG?sVK*j};&N1Hr#;SA&v zmOqZ4Wh#X+NU;aU|$7F96ry zA8AJe()n3Q^&6-EHwE)~YNC_A^Rch^lCQ@>H~%8GY}QOvrF#zQCGK_*fcbuuNW|LJ z^{*Xz?Ul+y!M-5>4Vf5W z^qW8_Z&XQr{psI-2{!GJ|8DRmp=h#ougbbwzD-GQQJjurk4KB#B>~@54d>oJl zb)Lr$77ej!W`4w~$*Dt6y&;IY*)7&GzbLFG2`wluRm_FU7Ps1*6YMm55gG)4a(OQ}e2WeVdQzp)xof$`^}t^nC;rgC4|^>}kp zUxK<1Ib>0a0n#Q{1+fUIhO%Kop+6C`T$pW6H$x-YH~=Xnq|jU`#o?krQhy zim>F@ul@H81J4Z=7EkBFcQ9llqXJ>U`%|!ItJGzgAbVAKh zhYK1m-Klw-!n{p;paNMX~55|cC4wybCF&- zi-mDD(ADMs(H08cl~vc_O4W|K0JpyEH+VGsH$|WZJk;NR!jJ?)EwMHqM{1Jtb-l{1 zVCf+&KT6Y^_c2(@*8(5QSgK3Od zm1Dr!zz>qkge~#{HqIre%1T3+z%)naSN8UHHnz4qHnux<_S<&$J6kVrXv^N#_Vz1b z+W9!oTHocBg)67D=kvQ*^8l|dOGEHMuCtTfJNY);rv?rxs!jo#fjhF^l%g zGz!C@hgdUq>Xv_#dPtzCsL#xVd{%NwvfQ0JGuNvjSYc~)>!ynFOQ`QYQN=*Y^FRyd zAkfVhBN#fK;cuDe?5D@O{@WR*&H6z1^Yp&3lX0`Qfe?GDwa(S;OUekOF!pwW<+8CD z=0YDc(fDuI^jH9EHjVzf^qeVLfkF${>T#}bys5(;P>o#C%jr>zZ%j$q)z| zxxK-hpl}CTSt_Nqef5E9w;fheK~C0|7YaQ@!*eZY$pj-Om`|pqyRJ!-gr=8Kdnr@n z^7GfCMxOWBMb$3KMB1<{8v=BKJsIlnS!auHzuqNKrS6YwJi^n-u4rq5KhEJ7AbvsP zeR0N+Plc#DGW2FiCb~S&i+(|_retb<{;UKl#|j6A^fyPK1G?*LJV5v{%EAsQd>R$o6fHn;J^wwJmZnyS*AZ5}%(TVM*A4HLU#TVBSqkKQP-1?+=Gc$I8>Wn3vt*s?OQ3QtI63XV=6Q0zi7FaW z#Bp}Ty6FuJjPbo#|IyvOc-OsHqNtIcCrNtIAuKd|yR>wFHHD8lboBJmRbSjXHF@jT z*S6wP^XraCc!NpjzZnV8`S|QC3FDRZ*IVnpP9FO}*748=#6DOeO!GJ;acyIveLG?Js{tODvbMiIOwFAFGgh^+b!0D0cD>y_B>BJ zERBi$xTI-9i^Rmkn*<03CVb;?XI*YDzBUWAb*zTmBML%bj?-uc=G&?o7X4OcCR7NZ zva321gRLMX?t2pn@v;HiRZ@g{uCxw$k?lzzE`5as5=^jdf4(jvhQuzKXjXlo)Vc#J ztllx?{)$S}{d=KSN#xbI+Nl#UYy9KF6gRDit8Qqha9DQs-AJs=#IMP*gC!C2m{R-F zY=w(^w|VsfzT0b1=fPPltC_URQtnvoh2nyn+H|Ieb##*wvvJ@B>Lw?f1k+d@{?r+_ zk>A#ejD;VxwFNpI&!*g8KU&*;qDdy zury*tbgR(fgjZMR%m~axkl_*8b(R<#BGmw7%q*+&oLdTV87iA)o4*P2}!{W91%G~-AtlNdGI7zT|XWqEF9~wC0KN=!^hJ@F4uNHKQC&jC(F>dYD&tgYA=*dA(LTF zJkHLJREcZ$hHq)vfVOZhfT-NxkI4>SiS(vFk1wp9V+@V-T&tg#FQ};IR{eN2sFK;! zZD#DLooq=M9{wg9K=>IIO}VqoQa0mihia3PN$NfJ^z7j^h8%asj_+v{P=C(o{Jf8% zJNVA#rXlpnj=QIuXZ*@xR3)MQ$@O4x$<_Gb$sR=^{>+xd#r$c0+aUkB#=_K;*I}1y zXcUKv-+!-pt|0h|OZbVPCb{@FLnBAH$^CqW$1e|0D2pbm%De-r20JX0ilH7VjR-JN zo0TqY(U?W!iHuZ*$%4rba8P4n{XQ);KWS1!aZDr8t%z{G zd=?P8w@p&=MqKrAP1d<~IL}4U^jxPCz;G<{3QFvEA5LNO9z%V8Q9*w{rXN`GXy zZs(Cfvjn`Zzyf;P_zxjtJ9R8@(~u_=KMN7N!`a@4&shs%WYC^}GpalQci0q9fY&rr zL*L!**Xy83rBQN~7>?P+H8EXa&jt;_^;%@7>W{|`UxURyC`4$ z=xV1BFpJ~GHOwk1woe+FSU_Fj(0yzgm&#ZAau$V$E6{p8o+(d@PDO-M6drV9CPOFX z>f~C0Joja57Th{P4M4%b$qayQ8Nt}%D1~(OCbrLvz62zv1WVHZ7M8}F$_B_6W{B<; z^QfBM53hC{_Z#7|Sj5c!qdn){T=KV(K`+s#C*cE!+lo78R6yQaV(BHq53+oI2+H=} zpTbv5b(@PjxPp0|zSr%&Iv;7kh!Qjd9RB{xL}vQ0rUjZM?sCBn`gu1#KnCi#`#n|P z^{-x{o`X_~g{^^yo|!q-F_lQxNdfv>Ycn!|G9?YBsP`iyJ}=bO=kah7r~?7maia0fki!M@1nM2Dxlv7>rD?O$`5X_>;w z_awUz*<#8AkC&I$5Dh5w;1w{ps(hbiZtdl%b(!{0TVu=IyPP6kqQ^91GdZcs*#x{r zTevHlRFw$-M0x7MXN7ie23AEmLr2Fd1B;L`AGo=g<%80AGm&;mxrZ5?<$Dyc3LIU) zlnoZBu5mWK-HzC^*X*@f{WiV^LYyZ^XOsuPr9^P(=C6Mil@vuO4?jG`E7At|&dgRl zqT?QlRPJ^uTCAR}6y><~Kjd3j$OK-LQd8yCm*PYaB+fL~77d|W1RasSs_$at5gFwT zCsA1mB8xyhidkC#`0%juan^rnoWc(yQIo^8T(AWaEG{CC#^;HKG;@lGNJ+3wj!orS zVWC=~TGB{)+Fbrp_lc|PZv~621s(jAS(C6kTewAuXuFR)6Y#;8IlF!dc9fOcEr*PL z8F)BPD_c8haKc1!6fuKe$1m+9&`5|ixPh#OGec}3S=uZFpQFMP2l>D8&MD(!1)a85 z;A)XzoPZJwx%Uq9k+68JsDD$yC}7c!^g^pBvd*ys{`W~=BQ0=f=Bnq= z%Mv%46)%|j*W+I6w_4Mv7AmfV0vq`94|z$l^!xbXOoTALhpz)TqrVv0V0<DeptsDS0}rEQhQ3uFR~ zBKbro=bx5FeLG8+7}x2>a$%Tq?fSGx`vCWP6iJ?elWhaDHw^8E(*EO<8F92y)7#2@ zCr^rRe$|9G3aX#`OQp@VB|P1()-?3vxF^yF{X?3S4nrkZTC}e|bkAC+9o>iNwU!>T zzK!;MgIAi$$Rc#v9B`g}a9|L6^W#TeP$X#_g|TS&$DcpbEZiOrbf#!Hq;@t>HHFQ8kOW49Z@ef286;kCiAFxLhwCAjSYf z#60)HR#&HiS?Rgi^K5Rzm4tL5{~WD#QncB}iSqIYGc>-HU`NFN^wTAV1}2#$0(nEv zw#FNJi=WpSJ4Ou*uB?ytqEi%D@6rEeesYO9)V7wpYLcPw}?B)&S?L)zc2 z{M~yaiZx7BxQCa_*k(d>ctPgIC2eFL1YhaE+sg=YzrSi*du$9ihi31K12_yquTR;= z0i_jen$$A2nxPs2Mm~BzUw`3MSYy(o54FxZ@-bAoh3l8;Y~TQO5q?CgXcdy-w8*c+## z4kkG$*lC9rEPqveqoFsu=05jcK3iT_NQelp!Tfali7Bq_C2tZij_c*wGNb$WsX#YN z4+xbGn#m7wCT~JQxgYu`P_E(dOd>`l?cq#IH4^Hy{FS-5($PP;kB2+($q&>yN*7aa z)Zum7!$D^1cWLqb#Jql9YGboyTQghKsAaPBdv?}y!4|>U=@c=90u@CEl1R(T6A{Sq zGMa6^e~%K0J8qBD4Kbti+cTy4<i1I*o%)V-&a_hcrUvkoPc^s+h zkUX7D(R?~O^(t2<7zBi`1b)$Ol@9S_QzsX(d8IlE)I^%iPtvK0`X5TM0Dmo~an4{{!lPDy)pY%c6K zv)VgUAy-FJZuyxSc0(+m+S#(0r>mjO`WrJs__^^%*`D>NCbgthV||a)8xD;;(N79X z2`5}3htoaxTXrj6YdZ4o2b`4Ahl>Hcl(<7z6-PoSKo&9Kx3}rw7WbcqJ+3PIZ@$VngfLYhs5sO9e&64f7+xD)Er_Tfv%6I`Zxw z3(TJ#_I9>N@O3I0dpZ{D-vDHtWU4G>4RpoA&d#bko?Dn*FwNkLR7>T8;|OP}c|_T8NG>53Y7o#sohTV`tF1=P~yjP>CxG(f$Ch`}F`PdDBn zuU2mlA3v}^JYlTK7o(>X3lK>MH%kKNT7pjMwZ4^v^xGsx8Bt#(GSAO317ldCRCTB;mySWxgz)XJ~}$8iYm!GEMxWvz4}P2nGu1q z6jF6tp*jHP_`~VHDqM?CRe}D>hzcq}UMn1V`sDDt@^)WPqJWdD3kOGogqiuu?Ccw~ zG1|TZe-kwo-$REk1|we$eOt5pSWPaAv(udfeV3=RgQMxN0zwIoJFunkRTyQ7Ycu2X zlIes-eq&}>vB!J(ir2|n{u4|`bGc5gchyFL`_Fg{JtH)$esBNVtM5r<>>}CWNcUT> zH*+0bJ6>{r)g%xlYx%*CiQE8fe#V#daxNc~0;RP4)M55!)7s5-u{R?#GBX>URdAep zHaStcpy9&%(YYbyR}|ONZqYY*K?UDV`vZlM*i~vjm3Z`E@e|ATb&Xs%N$M_Fl|6Fd z{fh$=a*iHH&ReSVK4Q=^O^$C?FfNLj8BUJC0a()`ZsG!`$BAb6)fsRsv%sC3s5M>) z=4d53vcXnP%PeMfLst7-ulo2=)t?iBC(|=9i&|4Nlcir>qfPDr_MMyLL@xEXQNJUz z$J?h=UClrZ1!Mg{ogn+)Yj#G{A4F~7Vt87Ef*hw%$-*ts@3-i!H3L4Ddw=d{*(=wjkbTUt<*94 z2<@3_FuNb>yOzGZJ!{Z`@$c`Oe7Ls;7#D6&40~+eYvksnrf%i3BmkZLlA5XJzjar9 z4nG=qX0|jQBr?_>nE==i%WVzt%os5`JuGv^a4yA0!%pqtl=LpFJj^!8V=riXj}6G7+LU$ z5?@LN35MNDkZ^wO@BIm@wk9^ENp0?X(zk(qYp zyOu`0*)%*J4`gO-GRun;u)AB8TMPdC?$VtddwsLa4QCeyaz@0^EtpIyUc}*3ats)Q z9&}gU;V5 zhiI5tYnJ!vvLVAFAi%@y6VrEqPa=63B^d=1G|TS34M2bz{zgUR2f(Mfqeq1P2i6z9 zSEzIMU;zjhLpXtZJTNXtoExOSHf#Af**iY%#u*kSv;1Lge*PH$eQ|uhKv;H8wngyM zC0Ra*i5v%sxhQF#I5wZbqgjyvamv={DWAbyRr1fn=wM&j9ZG??idKb&7hVXS+?=97 zvw0n~Ehr00R>={$UU6Q~%i;IdSe3*TD#}rrkWNTfxnnM$0$2b_KK`yCTj};BPWf5P z-DM=14;SMcsng6Adi#n8bg^gej3mlrylmw0`bcO=_xJPszPT`p%cp&ALo9yzbbNLBi*=b4aTPhC;17XkJTPy4&j{lyp4<3 z9g{M$@|1`$@n!m`%n&*F9*VM4X$rVWw+@uNghmJV#`}&Op8DehGc_N;)`+=O?9<)s z5Q|AX^@^m!M~iX6Z{U|uk40&@Lp%Q>$ZUfcjR&HwaD~O%jgufgccS(kV&HFQU2HG?H@Xc+gn5qySuejj`dZaTpb+J;^&p-Ool0b zGH1#b4p|tiX~TcNyb4Y(BQtoXHN1$J&3V~fV1|?NEwvgG6zOHFH!u(Z<^!V0nZpyi z#Ij0aBN8aZ7+J)Wl^Eu>ND{9kvZ`%WDv6A90TF?ue~x9@%Bc)Jl1VHUljMHgsK#9- z5X>~I4GF#@WFip;5M&g$4U68|!SLn-0qJ375A;L)IIv@vKbT8wsN^V{gRN>XK^zWB zAb$n3`>EYez?+`5~+Ln=bJqC0y#a zP`yWe79~=pn?rSFZMCS5nZX+B=mtTO2PM{frXrV^n&U&$8f8E84+FK7J1mkhNS%qaQ*v z+TI;3eaTLuMdJ)m^AFk)GUdepLM$tK^76~E(QzbGpE+9qQu`3Md}9deL?dn5ec$1$PK5gP@})xu0iYtG>az6s;-QQV8IX>&3jheh3tW9wP(Nm0^+-L* zB0AQBG1lEQAG3Zc0uIxR<_@sB=bg`kay^gUHldLLEeCASl{Rvx^875{>F78)#W)3M zCtr(PbE>JFsr1~J{;Ho{Ae3MF(Z*$4i+NeXPgvT@#tn^O?5?9x6=G(_{FP`5j^C0qcRVFSKNZ%k0?7MUNLaOuRwZaqDzO z8Aqu##7sonpeZQQ9vTWGwwUehYTEqbH8pvX;znMstiCa*FO8Gr({d z6`om7cwPDe<>mfTv_Y16e9-R{9@`I3TV)>QRcMX0WSX7i_F!VfFog$1lntt^!*Ggf z=Gtw#Pb^E@AtChQv$Ckelf@8fUl(1-oQ!knzx4UOA-vg5D%mJrRHY1y5_pY+rkRoU zV>{hkb9Xl>8&-jVPchMDXVi#_g~ULQhNUbgJIp$uy`l=l(q3%(lKTqFV2XfU|7zf> zEQX%pXZ(J?`8OTTrqnHbZ|?ix?W?+_D;J(se^Ko@I~>XniP^~;IL~~AM5y5|6^Lhj zKE@fr)#aIo$2*^<@1aAHG6TD$8{Ad73|QJG9$*g$W~scgA@fUJ%`Y$}gX{!}_R&No zH+Zu0(`IRRx{H@QDnoQ>$Y4RL-NIg(H;G=B)ab6tp8u2lu+VF)NY_k1n%_vfP84qQ zt$S#XcUkFuS+AW9a$Tyl=tQ&tml5%1==MK8BKBgil{{{C9f3pdUPW4XUg~KlJBr!w zm!dM;g9))Pzu(fQheOFfR@e-eYP(kG$M-lkJXW_S9d#|v8)3it=#*nHq70N}o-3lj z+IA2J5GFmo=C&_g6}GrNZLY4ymZj1W9p3ca-rlY#D>sqDTo{rYjh2lD_+-$V+@n3L-*|mn*um5*SN|*z229<unQ++4G=$ z?1~RtyLwBIkFbIqf0WMij-v?JWKtE{efa@g#$aRlT-#eKn6UKzD!E1%B}ygp4?vFt zOE%fqSXG{#fkL)4LLWjwj`DWVUZgBhyK;&`DTrl)8!J&e?}}u9q9U6U8_0>NS}j)3 zFZdy1Uibnp<%XrF8Ld=YF-Cr;T{*ovP6K^JAFX!hnuBu7Sw?xpfb&P$^{Zt zcv&n_xY9I;uad~AQVp{aMojY2QJJJr$HAF>y3Jr= z?Rb}zUL77!Bh&8o{1nbE^p>wDVmLZU^{0asCc<^Rd5x6KbF98eqj39AXb`h+<59nrwe5HIqCVx1c=(^ z;y^gGPXH<5K#~Zl;?nE#s+V&J4%KmZgo9rQOELXIqe`mcglXb5G6n6{3z3ltm4PGmM;J~{2LLdTQYdu7aJ-rG{#%Ue zMwN5|F$TNVAPv@x|6cS=-~IJk$W%jqz}0Dd{P!*xw?x3*L^2D{<9<7pu*)A)1G9nk zMb%Pf2nGEb=%nSvHro7*B7;N6mnfSJfxG?jJnemvGvy0`l)hw%ACnaGrM+#=*MB^o zbRnk2$R>NQ7H?x;_g&s&&<@-rzgjat3+9~_bJ@L+dEDzrkiIJ%-K?*!mPQ-~;7ech z+@F}-Jl(72WG~U(tQ<{A-!JBNwP0i4^ZIHDo$V(_KHrD{tYcyz2^7xRR~4t-tu(^2P3OZ+ zoi`=?$@^mDU|j{w@1)1aa*IE=!3(y*U6(c)OSs<=zH9*@-B6#&?HQ?8WUCKbDWK53k%4Ul z;w9Af$AUKSq6q`#^ZFhvO-w9ct?n_G@7S}eq30<^l_&4WH%QRzI#6;?1Ivmh$xw$hq z*i!T6pf_K)K}0$4eaP9Ey?*d5js0pVbA#fLrs!>dcJZ;0ZS zLzhC{Mdn^!teOA(`5T##(z8eS<~7%Dg)R>#5NWZ~LsjeVYzmu3(8`!=$DOy)J`$kKzK#Urqq$ph zbw${VtxTK5&GJM0fP+u8w58zigUd@w`&&KZVBn8BRaqPCCsfX*%PPx!)E0ACUlX`bl$Xnr-I5=dm%ClluCFyhD& ztxp$uR89%1G9Y6)LdeA0((||)(LOaEN@ffqj#$l`h$D+rJ{eA zPnx*i&c$iUJZ3U|Y%T;nw^Zb(q@~?H`cY-@Jjalu@CIH~{`iW4EC;`_pnHbL@^I5i zx_?hqw)eSN;_lmm9GUoeXaMrWbc9?FYti7#v~dbiN`1D@luix?Ui!+VpSV{0_9BnM z?(|7*9z>NN*NOqMP7ci7^-L4qlhtN{jSnY*LD zN0N4GH6*g*wVRmV&IJa@59E|>KbfuGt%}k)UKiBMExY-0f*_;5hg#^RHX^&8qY16i zH(`GDt)GP>XYYgq_Rofn!8)(+uxZ+x-N!Pd0hxsi3HN`pvOw91)`eMIG-;JO_Qlia ze#t80K=n!Ww#&<`ti4s{lcb?hc*ENA;*7Zahk;7MH{4H6wY7spe?N`%bhxe%g5_-{PgwpKG)(>#SH!Z=%cqH zvR3cx zWm}!&O7|oNKK0o6*ilLb*?qDV4p7ksQ|6TBJzI96V{hxlpVhAzx$b~1&)Z@x#6-+H zb2k-sn^*+o=r?Spm6zv+WZHhqweLvP zw&%??AOhShOOiK<-2_+tC|qPm4r_W}LaoU67k3LajQK51TikmehS7xm*W5wHDC+}- zC56f^6}I1q>C^=(e`{$q{gYPevp z%IPn+@WjWN%=3zHj1NJiNlL%@)lG0o-+ga#)Xo!kXZ5_ANm3~>9LA2X>-(dsc4eH- z@4?@GY(thT3vJeti%NAmQJYgydD|`)?a`>JQ`d%D#e_{X97WEg4)b1t+1gICRxFnG z4?BXAOto?w;3x61$Gs5c1-#kd*KOTS~qKTjD=8 zi4Vs{&2gvqo7{Jg$yw<^y<7SP1l5`wrY4W637QplUp&mt9*%AjEVBAd1tl{Yja(Bdzdal z2+P0m9a`+qz(ybY8H(`%mmA9_HWN0T*beroGQ55b+2Z}-wzr_9Xx+UPza3LVjE~_W zQme?_qk(0q!N&SQ#2o8$_3vSQhNcD7yJrCX73r0F#5bJ(4hky2*O0H5`}pPm0EPyt An*aa+ literal 0 HcmV?d00001