From a9dd7910a054a345e1348742505045affb4caa3d Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sat, 1 Nov 2025 09:18:36 +0300 Subject: [PATCH] Refactor ColorDescriptionService to improve skin and hair color handling by introducing new methods for determining colors based on gene definitions. Add constants for color keywords to enhance readability and maintainability. Update AIImages.dll to reflect these changes. --- Assemblies/AIImages.dll | Bin 114176 -> 121344 bytes .../Services/ColorDescriptionService.cs | 341 +++++++++++------- 2 files changed, 217 insertions(+), 124 deletions(-) diff --git a/Assemblies/AIImages.dll b/Assemblies/AIImages.dll index bbbab5d76224c065c5a1c8be771839006a8fc5dd..a0812a792416a2e9f337a4adc036ba58b9983d6f 100644 GIT binary patch delta 50340 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

Z(TN2QrIro0L`tBi9-m|O zvcaZFF=I}jrvoqTb_-&YP+Gv|OKI6CEr{*d(1MiEPr|_gA#rV#Hu#2c!C1)Rw-!7N z-Ju#`U?Ia^&`h`=!WElvu#&~EEmR{W3**0B$<$hSrU=FsGHz6V)NO+5mY6$2queqU zrlbUl^tfk|PT{eUuo%M8IEfeXiK3+2nF$;E7dvod;##Ihk4&zXg^)LRSb`T{9=Sar9cnM=!oENDi$TVojTxt8W-$oinxakYl9S@_zj~ z)zLxfF86d8AWA78Mx^QwN%P0+e3XlwMEEYp`e15)|CfbZCYkKhgxYg_C=A%2Z?DvH z%9cA3e&SfG_QaBt)Lq~JV7>g)UpJ!3()sGP3l}ILtHY!0eZFILEy+Tja^)~?nA-U0 zLz%%_O}%{6$my}eW+-#0wdutCqGI7cE_^u=Ic2P-;G)ZV|HOQ=MfjL>$p69ooWW46 z_AkSj5tygr996|s^~6Bkn@!WpzZ~DfRQ0&vIFTK#m*;F6$yD`hK;4)%aXWCjb7u2( zo;x&KWQ+Ckk_*om++{km`6kaDnlI$&Z5nSs*jzZvlHFP8YBWxI>Qa$CjTLhjOE;|* z+RRNPuX?hJE7S2%}I~r(*8J% zoX(~8A^jyByz!VGs{-F_aAeZut0#y>Bu;5#%0LdjNhJRht8=(r6!Fzck}TIjESmA0EFu>K z!S55urc^cDk&qP=+Y|gXLFQl)-V6kPKTssd7bn3#n2eW^xS_IlJ>Z6i$8GD!=vOhB zX$wWKD6p0vc+Zoaggu|^eR1Pbk>!%jZ?+qkjz2($*DX6;)!@@mFI+&n)DHJ`>~LLO zc?mn*gj(4Jo@!kDCne(Y)KDcRqr_xYBJOkKiICTGaEZzB5|g`?Xpal)s*?&$o+}kl zLMYL$iS*kmsC9TJn{*HisO$o>U=JF*9s3Mv-gIGNwf2G&=q40oZt!yi*=a4jbInTg zf59l7I;I zOlv66?eyLHuNxeaF2b_ZODDpGAs#N<$1?6CHJ5Wk?_-L_-&{;<`5Aqoo@HWJH4Lv9 z$&}6WkF++O=1Vt1V}zzAt+i%GNg2=4=H0rJ;zH67NNQ;JLdVdQ5|FHap=17C8LK(uB!&GEXd z`%cTV?mlIRK4-YK|CB!U7$=@=4+gtO9x!C%(QD{7mP`qb0xRJOK0&01HS*N*ep)75 z@-3|)Sy_@FXS@sRVtB-@$D=rEy?cjSH=Ww9zdzjCeX38-8)5x;>QHU1)q2|SzQ;?R z&>w~T+QDJnOXSy{cu3%Gu!0<+u_I`X;U5hP7nwX>VF&nGKR64)ampADzK>%4hqIn5 zIn|Cpy_W#*%cIX33`INRcq|6b4VyeO+vy11FB&<6dNWXRNzyBC3646w zq*R`0@SMLZeQ^9;ig`VzUlhM4+>)3del)_tcJn6ZmNK9`jr5<;elU+GZ#q4PxjQ9ssJ@B5tMNKz z+N-Asu(!I6apk47tQNmZjsq`bT8;(dz&n|YWM^H9x|6~9w09h>cq#zy3uO8$zQ|$*NC6JN57iZbZSq`q)5nMEUOpbpnr}(kz->@{=6~n6wo@_i$RTYE3 z=3@9^X%Ttt$1tj5{G8N@%cm3Y{;~;qsTLlIvV5*L7w^bUIA9YR-v_!$1Mnouq-vdVQoo*jCq zx>ye%hD{5{qwV-`j>~mNL=s?(VFHmgWM=W`QJAlt{S$!I^OtnoISOeaNL8eF9)sB7$0+xdVgOU{IHU?n_hC~ToP=a>GJ?nv zT;x`i<&d?)ZYV63aYnLvA}ZRs3=21IknoO(C-N4g@l5btjvSGpY2d zVz3z=)9}w=rJr#|J%TlYm442VGx7yTxsiPwEno>Ktq`RQ{HJzTdNM1$T2)kZVl&S= zae>J?u_I=kxcy?C-*L3yd-xny+DnwO{DDemu+kL?N;S5c9&vKyh+xOXN*x^KMzDK@ zQkHReX9^M7h?FS2l17mAtU4IF$w7j3F)Z`>C+R^^Agg_64Ey& zr2n3f-lo#WW6o8E_9QUAOGu}VidV>=kRFqeo}G}sA|ZXhMgrh<}XAs`Y z&X-s?9E&Pk5?Das6|67jrdWT>9pR1&TEjx;TKhs1Tld;a5uEOsXpbKg3m=qp204xC z$LUjfgNgYaOaIJitG)A(zR-S7v^YtCaBh?!2@uYU5;$Sq(OJ>w0^N^i3r1dp3%+dO zV7z_r&jvn2kz`U6tv@=?HKAf@RD~o!xF|}H1PB*L36cQek|;qEAY2+HNP^w) z1u!)K7c)Ugv0vWm=F6F{hwwW^XtP<$3%tKvKq+Aj;#YLQ2(gdxSE)45L4J(`^jv;{ zgZV%70j*A@`C`XksM5zUy@#ap{CF+Fz%#DcB6B)>#v4Gy!u2#PAK|x5*)`^K!sC>2#)FaGEAL3^ng#t%Q$Pm>O3FW{CL*m2`;oo%)7>%jZ9Iw zObWI0q#VHJ#Cx#~x*tXjctUGIwLj&lb%nkK3M7S$F%U)f$th@I6>2azXg+Fkrqtwd;rgViQnD1xFRqkPC}%8Z9TjbNAavH)?)C2W1(UQ^ zK52@*8RC?A5R{VkiL!%A!eKX7(m1I`URt1^`d}(0)O=+30$uXWmR;;^F(XH>M)<}9 zn>d;yB|dW`SAT%rHe53ro>1<%?h2!yUrFWVb^%TAMWLDFIIk&rb5i9VO5Wn;T_tW~ zD=GBEpKG#>)v^U94h6>lb!pfM<5mQZltULm%ImyhrgUFog?!fb^Rg#@c7PJBE7+K; zuhWpeHJY}+RO6O-lT!Co1t*Y4mA4d&xq6Ppn%7Y8`n2 z7hYP&Wk*yp8*VHM3OiY$e>m4m=NlBmelLelzijQZtg`Ub5=A!E3^aF^Irg`z_+~T*TZ#G)@E1b zbQ!qAFgh25QMr(*ek`kS2X8<;aSm3&(nNcD;>tHvakT6b#Q2uEpti?6t^*o!3k&6Y z_LQek=t2nTp%;#}o?B3FUWPTLCQ}b{9K>YB$kTE1t{$sMd=H%$Nb)nMIuxhjy4+ub z>cqOGdaCYcJ8+k!C^#rVTZuu_hJ@4ABQ7PewXHvgb(k) zh5m)?dYJc%_6>jVQf(wDfn^w8nl7VP6%hA4`T}ldXxc=6-?k2B_17aHS51*^0PaES z`SXkPg%hn$&+jAM8oCkU$?9Y&ro(LU9CL8_c*8JWsOm-We+e@k!$BsW>L35*+&bw9 z)P>!=SFh<)`pgYI7J2X*Opfl-gI8F~&H8q%I+#pjF?fPF)Oq|3Ty<=U@eK$pjlS~o z=YPw1?DgX<8Sj8a97O9kv*_5%c|7=+BX8tNB&+2TY7h$LX{v{r?J-JzuXE$&x%@gk zkV<=8x_=@D;=2JXtdVOte@SqlTEl*9KDhRPC_jNz-1 zA;Q(e9MZ#AArZ_&W0by<-y@tY&<++C5X@#4m%+juN3KAi=ZjdrXZPo*w{GX+%1L!3 zE3WyGxAs9*b>>Npr54IOIKFyn0(t_)VoE_Gu;og>BJgjAw5&hUKu!@u;Tx?56F>(Q_pU zf49dCXJ@5e;8#YK_SK}?CW04Gmqu)v>cUR!iahhNwH3&|dN^!^1ueF}Opl|9L z@WQJR=;7-vZE1-C#K8$wc8(_V#xMu+mWjGwHw$3p6!Rg1OrBEU*|#I*j2D5s}V8GPnrp zx}4aqV7QgoLI?8mCq+0Lh5kS_`~$7!m*!ZZ3v*2D+Kq*GgA+R~RWEe}Wu)gjf-=4{ z9Kr6Ry1LjQ4_7!wA9y&%SwrF*?YJ8~dJwDTU0W_(3~G$g^#HFu9wWb543RI1X&S)Gch6$vq0xg zBr&B~I`|m(D*$tXkJ~^BlUzN~J;AN8lL*D>B}{+nAn`ILZ##%w!Q|}+kt><}+(G2t zOn$yQ88>mkK1_d6=<*S{-1!DyP9O~BM!dp=$RpBH>77S8sjQ-h83fm&)BJ6ai=g>Y zi(*nBDf!eW;9eEc;I+63G=l4pD;2luHzTecuIE*HS?+A8^_L16QXyt$JM{$|cjaOmrNwFlZMR$X zm*m!nnc!eNMDOZhu2b+;RDrj6yE+UA*t&D07Ey-8Mm(bHf6!F&~u6B;Pecnj8 zGz)nrac&XZ1;K<3iqh%xb)JvXBZb@$)g3As)9r_=^}svvm<$a!p)X-=J7}tXJvdU# zf?+9F#&JGy^c9ORbR||N;f$;bXW>MFHjG6IeG+Sh9^7SJbZLpF=j4N}LV*t3TZFC! zTdEm)iBp47tUO|k#48-;B!8IZkzF1-fVToNvvbt^%~69pC&HZs9*+h@Y?<9y`lu>e z+V5txxOgF<*5gsI+6wNOnQh=>u*eh08O?JU*m{^L>iEV>h14!|eT<_zQjYnd_gLLP z2!*nzB(_LeV1@5UwqCx>)4~SN6W2)Z?kPm6*nq+NVi0aYh!12oU5Z&l_W|O(> zUKct8&iX0q*=2pqXCNL{GZk*e8N3dICy1w2o|G)je@2h}qnb2b;^3#K1$J9$ z$*t%MR?XG4dGCQIW3LS0dD z2co(cqdgQILsAdv-R@&3PRAH(x$+n@wgXtHwhVk|dI7o}{v|L2zR{Ogll)5o_~iR% z;#heO6gLkPf7RArt%qM?aiw(~FCR7N9j58>f|r9&;|8`&T-u-Kx)}ohMW$F4`R$P$ zblPH>CjUeca<J7Rklu`(=g z|KbR%307A0F;)|-Vp!hL0_b8UW*A3Zx$V(eBsrn%ekhB)LCsL0hu?rq1nUBOD^BZS z2Ehj)ld@+7h6+a1o1jqWd+Gc)tsAcDSt+WdY`i+M1+ug!m;FSX?(#oqy?0gr{^&|L z3alsgrcMvw{1<)~7$$%P^zhqA>x$)t=EEo-yCv2mlEFu~LQx7_un~MTkpf3*1RqPJJPFF|;6D;cPqWbDi4^z* zBltuj1zramF*A__$7KYcOr&5$8?%B>C6ZtzBlt8^BD+y(We(~4;5Jb8u%f=h4SEKI z;C2LQ=;LP**N%`~4qH@Dj_l>_vd%O5EfBICn8d9z5Vq<(5Wsd~kZ{zMJ19C3BrnwM zfV#+stVj=Y6xqY+97PH%K9Ms+o%qDiKvY*1 zueL>17=FmgHNhu3s#-h%`PE6ZA7@c4`Jp?xk(DeODmak`wlMKPikU&Ch@Q|hapn)0 zz}ary>yCT`brjkUmLBGGg3GNIm1Wa}Wp?MOGVWzH$+|Z=^0BBHDYBeCNX@l>#u6=i z{+8|0y`BhGCDh~|k>j+e2;rw8P_s|SDqE2~Qf*OUOl2gcq!3Er8l*2|lzKh>SI}d& z%ZSrm{+(8MMNe(AwQ5Cu!ExwZG=i{?p-(ZKZg$9TkI*FRgB2sq3&pMMLuC>i>z9Da ztJr?^D0C4M)!cd&h3erixB;*6h60!nyv3Bg~u65Q}p~CE#3Vph9|> znI^m|$6dL@qLWIpLfgNfEwY~#=wXf`|K@a#BB{%|ub9GbvBK}kw@0mL4*o+9CI)x0 zim#Ch3;~G~!MB+74N|B8vSZGN83o@4y|OkHdv1a60NOtifFhY>=f@3#r*`w60wb?J zN0IpIM^t-xFuevGA?+=(S~) zVhAyvH_87lDr9$boQ_wTE$zC~%%#$a-$6q{C;kL@P$x1`b>bc<)Wbgl2jAnyzK?)A z@dLzmC$d6x;vXEL6Te3+o!Bm&c${=1Gr1Ev?#ewh+KG}C+CGG~$giwG4|5dxnbSFn zq&o2zri7VpcVf*v=|QFhKjQqqAr)wZ22KP&X43CSp$Ao7lTq*!(BoakBs+t2*;COj zV;$UOqAS*AjNnPc`mFRXx{O&Vd&a6B>ykWoPp5I{G6o4Ap_0df9+p0MfSnaKbxAyX z#V}&Z?wuN^bEnQ+Gu?C$ygFSZU5go<*tJf;gSwW9s%!Vc5_;GH9Q>4xvJU}w?PrMX zu4RSj+7yn^wHjjS+KyP)!W%OeUCU8d?&xUON>*t59NHo-R-lJDiX?G5N0C(58cYc@ zy?fU(CHMvBcOxZT%ZcEZOiD%yrZZJ$M!|oB9`9Nv>0!yxy=$4oT`R0u*D|8e&(gK5 z^DnxVS+TD5XmkuR4LpfwBfy_@t@Oc`#I6;?h$*{wZJe&U_B8Wi>C{x{O_;A4fCqId z6IG{v1smw$bgs*OHpkZpxKqDDYzOxc@A;Q}hen ziL`l8cdDkvinAM*XE!0wu4|mHYHF9wb6cLeh!N$jLTu)LK}~Fj9jCkezk+PNc;lEu zQ9C>?4E_d;-}njsju?{!4Z@I^00t9+T?kToTz)E+@XEZ<8)$$Wgmcgy9Dn%{=hT~u ztNwr#ze?djKlgS7@h%Kr)~e}AA?;)yzbqXpI@!AUrgHNV8F{&&*dq^vLLHrkVb0}) z9@LOsHi3NWa2r(Hql+`))}fFi44^#3a_cZyMpsW6UChL-14juPK+XwW*Z|g{io2gd zzhK*@D(3?amBS7W!^NYvaeCOMT65R-Gz%a>2it%}lnvM@IQO%hc;K5W3uRArb0yBf zLiI!S&HlKVLakyLDdh!zSRBvHZ@hRCZ>X%ab)E`oyEHjD@ir$;#!0+w-KplKVqV<9 z@G}ZNkajb#gDvaiAPE7R*FbEWmove<_(d=eo7at4%sWKPJ5|ifOqiFWuH2)db60Xg zS+X9)z@qEduy(rrGtObAEH(D2ZV2_sF0S4DY}_GPKMc!z2y{s7>u)VCRG2K z*}YukUzwdV!R+`=HZglPVln$rG5ZEFJ2PQ+juOl+ImPVwwmy=>3NY6YMRGa4fRj

eAPCNxe*C;sEs)68Yki4B;=b|;1@bcE>b3tD(BHdvt}G7oSR z!deHG9*#-j7tQ2E>&A~#;C=wdE17G>i0!$?g`m^>bA;VbBjT)MH5}w|2*L5>Za66X zXe_Acb&k4nafninHY6*0y#(4KO{@UFHH#?HkJDieSR$GP!CI6~v)c`dhnxU~I2o!ib#w4I}_+{vo#rbnLe>S%m9H@<@v z==_nWGt$cG97R%f;|l5g-J3Jg7_a7kUE}McHI^qoQf2kzN2+Y%0-hX2IQYhtxd!tcr1wf5n8mDCz1 zyKa?EidA}?_!eg3Wbo&e#?RBSr3Z6Gbu-LyWFUhaMN6zT(W(u|EM_ntkBFe zPwT|IrD<0ZeLMrSiAU22oT@TGs~9=)un~wS08c2hPP((od>-%+{K5WoC;nht$_IwQ z<+Zzsz?gjauN;3){9zE{zinkq=hmOlV@j<-_el6_p;ntg z3u>8uZPB!1gI4zFUtyS(!Vx`J#Nj6rMubu==?4p0#nV09hH~>dvm#%K{anT8uTFO2ECoj>3fT`+H~4ra51$g-k>)n*Y_0# zh1b)j8lpT3BnA8ieooO{UPzMzulWpGWU#iOD9oVw&|uKBrJpny^q!9?8_gt+8p{uZ zK~C{csrAs29R-Eyw9U=M+$eQ_qiVm~pp$&8Xl%}5#U2_Z6&)sqy%+^}=xMauLz{dY zURSoyi+w*Tkxu)i5@V6}PAVIo;JOtuH=h?)6DSIi23V+w5OXhnJ-`mec!vI6R`7!>LWFjUM`-FIQ!a zv^A%kt2iC)FetNv!)JPN_<1q6tfYh`=lA6H-GhpH=*?OVmo#zc1{XgQE_Uiy!<3Qe zG7rrjTu^9wXfg}}(dIqP5S3x|cMK~J{oc;mTJyMoAxQ;=dGt^T-^Ef8F}~-gG+0$Ld~nb1~aHSbkj}ZvC^(9L|*V z{63s_b2EpR3*~v(rjGgz<`UDlxU(&_uqRvN z<`DnR4}wg(weaPJ{xMXINytdYUnb>dT~<33X$LKWa9N+rYA3=orU=jKd0FiVK&gWM zBgkXIu`Ytr@g*#pj{h0$ax0V}q8WoOtKErLmMa83n!_lc>O``v=7I8w*sC2Uycb#& zI#JL=^{eVDwOV{x!Bu;>rUNAmr`eM4%4|j>$PCjuFb@IbUnE^FXoroi5#+VewW4Oa zWE@2|C{)dAM&Y;HxQIst9YLFHEK!}%g2c|A=N)EjCh!b&FzvV?adoh;}f;jN`pG>3_dxZ8#3&2*YDO;Ng@ zW(wk~&xtVa8G=3#HMh}hLD+hOw}H+S^n>s=Qc#d8{!W^kQ0=>^Q+W4cUow#%panoC z#;l9sQ)CKriWK+)T_ETdK`+u0K>(0^iIxg-h}Hf{mk2spwCti~g6f2~4__0rWsVi} z9bGNR6hztzMkf7JGNx+R2@|(cC?ZF@UeGjYQ?7P{pwFZRSHEk+Sv zh|+rPHsQUCj4l6hZ8X6nfieFZ77#hT(9^i0Q!%dDxDl@afx#Jg>l^5va7lv~=+)&ElibA%* zYbjjodsDfsyHfc_{;o;wMEaP_B?u?9UX1WZ6s9D-^n&+t$QWLx6iYZKlWjIWjV-Yy zozq_l<>U;OS&(6Jbbcx`y3#p)Z3dg`mP`&$PQ4oH`lT`bdf`s>t_0<=OzxDr49<0t zsGE__ltt;BD_7)~N_coi9WFg7jU`8mhF3FIL(-keBcncZgo)@35&coZe+&D~%*$~N zpPO+LxSvY4HNt&K(r-%o9Pb8j9~Jp}p(`8V9l(avlVVw-jkCMIvr4=L0pluC5qY`Gw{X2?ZL3&;uwNeVg z2Ph9=hgODgqoW4lu|j#32IOH+fEF8cyMG|UZ4E>7G@9pRYfUvc{L$d?F~r4F_iEQ6 z;Qre+8sSJchhyD4@VMba=UAlY8^^LXGeO<(@+lxGrIVf0A=GJbnB-E~PKjk>2V#gD zVfizWOHrbg3xT5McU0$mNFQ~E$m8Mj`Z^Ol~A3S?K0;|WN;bRBYfWA z8PVwCwl0>i*v<4x_gaKw-M1o~XSebWr0rJP`tLuuTKvUmt@BBQc?M63bQh-=xL!bb ztLqJfzu2vRJE5X~q6m_0&d(6`w)Jp&f$KjA?{oc*Fset-k2m=KJox{E4Rx5)izfhW zwjxe1a1|kZ!c~bds;D|aQ7h7kHk<4m2FXr?!>Fl8LZ-mSLoaG?j3JYLNgi)A;AEVt zr)6j)jErBBhhVt1HH}5cDm0quoP~#nod$=|0@mXTy#&?J9M9#hnTNb}W#$1I%mY>A z(U8336I!Om`3$rp#mU~S)8Oz!=gfm-=0c{{$(?wlSZ=R`N4eN5>~%4{*v;Wc2|sks z%O6*Yy&KU|-%k943>r-;1rWqr?b(7>x_jj;hT`i5Eq6EOTnu!J&AYSy3f#5cZ=)k? zEugJ}Sm*iJh+kYr_-{L1(f>AV$~V}kWzcGD#J2*W{O$B&y#eTxz5a6FziK`Q8ZJmx z%}I;9p$7!5q(vRq;F-{pGMgzkn(GO4K1_LO|_fz>**DR#D)#@t{}Fd+t)xx;r>WEMSCx@-pGMeduEwYbUclk8W^Q))XyRkvm;6|{)% z!Ev;i*4k)j3!|^`Wl;851g)freLtrGbny`8 zEvMS%LhyPFRp<}1xq)Av zzTZag3R3rP+llSeLDNPkEi=k*qd_!+@A#nexVC!VU|MFQe^i;xzM-^iq+-6;)a)BU zzl~Dp*1BfjNLn~rp*>ZDe4{DzaD^J`n|+7V`Y{S!Q+9}NEPZ!`LY*jZJY937LLU#< zi62b<*hVi3>M>67<__3tf;q~DTZFmKMwbe5K>iy$Jfwr+Q_VD zwAV%%P1C#~`pQP3dPYAfM1KVE%LCNwBraho%`eWxx0U8N8@^Y(n$DuLZ1jSl>uhwt zpoWtrqd4ocXq=$!v>0>bEc$JRQu=HCwZ60H-cu4KuftP&qP^Nj1J{7}@#zZ99k|{% zk6t%tD)?LF8s9mzZx*9PbWY`V=XrF^8469Syu&x28fGh$QLx<^riDR;wt%;Q8s;dp zI{6M?gqGRpy!`FX^J)EAiuY2}y*`uL&sJz{T!-jZzAIb zbhRM00xYIAg4F7;nC?H9C0EkNmCyPX)4k_K(M!H1)&!3oAoVSOsKjrGYU32FQE}Oswmmyyp*O%MVHgetWD0#X!b%SxjW?@ z-!f`nq|n;(k9}9rLpHhvMO;OxixqD~vl;)RasGYZNd6vnyQ%Hz)|S7U;$p;z4s$4Dp~@7ehQ|ZjK?ZC#_(84BhVO zQE*!fy*sE+!R;|Lq_MeRqm9h%Nz?l^7u*?RZU(xW?v;A))wrhj(E2Nwy;tLk-b)`} zr4U#2K6-aKqeZm0Y*fMDDbrHO@*P!hKTWgIEkF;@{nseo?vzOdTj;TsjFy@*ogSiR z6m*}EeNw?g^pcG}$UY6|4I90kH5+KRphfP_vgQKqwRv~epHuKKeXS65E&v*JtrS6B zSq42q_uA;EEJ}WaUKg}iGu>En9;MRjL=+iI(;lU*g7#``(tl76o*r}S*`!a=2G{d(*62NlwzY%r5bL< za%_}6V88w{^{`R#0F7RzN*itNvzq=%wKjU958r=Lvkkun^A#Foqpm)gKqGB5GG)KM zla92}IJ}Cula8~|fU?!}DowM|(6UURnKpX8+E1_1TpN8+JsoJiLNfBq*J-iMEN}AD z>vWlo>aY^MPS@CIQu5UWZ_pYWotAtp(5*J=pSzmgq`Pf&Xl^FZ78|WCSxx_<$8EH! zBopXa8;xtfpZxPAVUrGON*;Md04G^Rp@@^WUkb6Ya z!0g>L%0}axO1!&iyp3k{-mmYWNj92~OVK@al8ye}cfbA~nX_#8B>Mh6>a^Tw9H1sdrk*hVIvo8@gdz{BOh$>A>F2snENBT$L4kAt)`FY zK{J{$ANRnt)kgRGA1e5mp0m*t{>OoK+UU-l{rV^LmW?*&X!HqvXrprqR?}Yk+(t_Z zGJ*bMqe}uWx;~{}ZFFtmnSxKrxz^-~x76KHcR|5EN?ohav2`y3<=SX2c%M;E8(jw8 zXH;dQx6q2usm?~9=4Ap6u+c~O7nr}G!8ZC28u$f`veB)m%$GE7t*n1b-J4OHFKLp^ zyu0bmf`8L=8$HzY0njWP%`W?Q!B-Tr(Ya+m0)-V41MjB?Y+hICYWy>6|FDr8vtmDO zw^0vN?Q41&2<>0$_M>iJ)4y!yPGtOs-m}r3(oCRzHrj-Y-_qAMdJ6fzrJrrIW{_U^ zAJSxfTI${~C=JMCqf^k{?`!_@mKl-&2LnoQ_`mo@#9L&7l4I57cBM zemegHb=W9l@P7SAI>bh0;QdHrZPdGUC;dc0g~T#H(YZG74tT_$XrUl;srw&ri9gXL zHj~}u&$Qe|>@I(%)iydGQ|1@C*+%Rwf1x{V#NP5(+H52CmcPSU8}ayDDSFr)vCg@xK#Hu4VKSXiX3vC+{j_Z0Tfw%O?SrY(iV+Q)*hDeeC` zm1x^!Pqm!-)NLs&(dOL2MJ%U7^1h`~ZL6TA?l~=fD%0Mv(I0L5O}$LpuOMagzo4K@ zOO?IYQnw4!uuSWv5cO}#1Ukz`N4HRNx%QlmO8OgAq2=7g1#Tx32a*b{=59u6t*Fq3 z2(svsl1B?GwD}11Qf@E*)fo|w=Tk>;UJ@(e#?8YjwAPqE6TX ztL1&%CRKcIEmhEB{0mZVB=y$Db>mI3d9#GKwj1v*n^!72zwE~Q-s}duY|&Sxrg?u) zEWV^0@(Wr_&*G6(Z*537-WZ!VPPB~M%vzL1duvk!MVoZWW?BChW1sO(VQ=jsVJ^l! z$_Ish?MfRxLHi2(XxG|kq_)4XTD!?cn;kzC2DIC4G#!#P+C4UUm-ZLdY7Yuh1=eX> z1@Q>NWvq7YBeMQ|pndC`0671Vczf%$C4!V_y>{F`n5QJ`waJ2%(gy8hK{%A^`wAPh zOA>gE+SNAiTJRdRhZ1;wwI_kl{>9V;W?$_GTl7xnzQTT5;PH56nzSZCsxnR5oG0Ry zY0^T1RAu^W3v3>@u)nrsTU@fgwp5UkY}T$~WXg2H#hSKldt9_x+b&3n4$xk)d8~AR z_S185$pP9gf|O*7=G>upEZL&fybzac(dq;#$yTjJkg3|#s-5*xT(ni2CrF95X$u7{ zra_M13){4^mswKr25L2el$L?oZ~u&I8K`v$Qj+bO`xV9GsB+}!QMDAat`TdLk zRfhjU9>4sCs%(}9sI;o$E>Lv(2%&?%7B16uI=KtS<&?yfi z37?Xca=NI6?V%{|m|`LYp3RMm?(4(pV=>U8qW>z1b2IUjL!%3eIUJ43sR0=6tVGK4 z0+x9~8n7Zio{myXCiO-SX|%SC!`UL_5RQA7>1%D4;9tv zD_B<}mFs}KJpK<>p^8xx@+BFDoYv`g89u67iD6=kmDv+1%iA;Yk-_lt%*^NjyuM9Q zF#hpqEe8HNomiMk?-H{sn3BDT*>TE$osP<@0j0vD;m|Z& zkJ5G|JS@Me!l6p{@pGC(jQ{y94Agur6qlmHM2aqMM1_ieaF{6bSLt76+$3-_C;=dC zZQ9jfw$hW-hQERMYsX&){s!T12>yoRZy5eY;O`LpCDYCt4PQ|5BlH4<9_oWI6Awx` zY?W}RgojBuUcyNdPDcoTk1&_kNqQ&3B9q=iRE}#cX8%ll539+cCzS@bH6figfGLA< zoXMd(YewLddM8dV1scoGL|BgZ4mrI@b})-%kMkBN$J2OyXU%k4h456om&!7I99+>w zNS}{zNy8F6CUcB$zLHuUd;o5BoRqr)=g2;|SzAsIX00aX-UvD$h!@F&{YCNwf2d^0Xhx{$Q{w1q7$t&dh-maa{AJni#=a#}@CP_7=-8_mS)yX6V`0lU$6K(_v5ujR^V+shFPhgl z+tJI;#Y#VL>?l9iQKr@PzQnOW^sIvou5+x@oXIyKEW?X|>$H+W4hMB`_)4zH(FYZH z^$(&qJ9bc4-XjjpNzLDq=KQ&Ct79YR+a1Zy=W||!Qa0uSDU$8<1}JRUC1L}w^W{O` zIlRsvJGvZ8#JmgWXum=0G=8<9!1-94&pF9aURHv0!=@C!^FD1{&($Vz%j%rmvi@Ly zQ99VUit<}_BEyk^$=(ph29c<1+d zg-Mf~XZI~lS|;|mM(nXuo87k~X}WV%-(g8>guY(rJLv1aQ<7#nFUs}PT_){Lnw4}H z-E5qhv|fyMjf8ih{}v^!)A%igRgOJ1S0&AL2B7GE84c$-?r6C&={)B!--Ai3wBdzM zBJ9!rEW)Qt-$>fwn9}hx!inWSCoOW`(%~{T63?&4MCW5t;$u?clMZuR$5`VM=Vd)l zGj`AggBBahoxS^CY^-uV-E_IJO$vL`aaHr}#)~rAU$tku@%R%^`$iC8;viBztJ*^N4XxR0lodshbgzJ0G1waHXq^IL1yU$*GA_* znkTvLbGFw{b$usFf0J+rHjC?B4?CBXZFD)|`!;B)@PGK>t23EP9LdnrqpNRH=+Rsec*h&bY${jIzPQX4EphDjf5DO-bH5ebY0832-z~qS=~3@ zD?s6KJ6(UscM;ML`8I%?8({8J@Oq7od5r|hnyfv^PhuQ=k=#S9QX^KuKP6Zk@HA;( z_Gt0ch*h|-OnTCBLGCP1yGV`@$z=WIL6>>V5hC=nb4}I;4~Iv%nqWG7B%}3CS(Nm# zOs(Zkeugjx^y{@T+Iv0xG)B9wrHPXDU)^7LmOJ@zN3#A$&5xL(|6gBM10Gdzu4iWd z|IY57-6RAOvJ2tgKtd8Akiag1#t2lDAEg$_k}QEs_)9`D1-iQdD``caG}t4Gnkb<3 ziJ}%7QPiY>S46b7dX;CNW=RNOy^UXIi-~61DojGUy zSrX4!uIRtwTNgXyUSZoHem{K;@M6X$OxAMx>WZK?J8iwXv2f-|_SWd} z_LJ=HG5L0j!I6JaH0ztwr`VhI7cxui8C<%wN#`Fr)83_T_1|pw8#2euvp4CUF1#q3 zbcca?hC|aA*sG|Z#i+oeyvU&XWA=10dDJ5;Xpoo($qRNl>%3&&AR_OeL|tsx4B=>k zLo7g9x^jbb+HF9eV~L?VYowz{e`?T!cqmHFj3LAF>0=!m5Nl*We;)Wt#Z!Pgrq2L= z>MnECU|8M-l*6(H!*aEwo+R}osVB)6UK)YY77}eC(RNbWPLk~;X`rHT-GNct@eTAp zDf-%B(XGq8;<%sc*TqJqnv`b4$8M*RK@C?-xGRBj^Xx7zcPH-Ra!=zfF84I<;&Sie z9_V0C<{mDU_K?yZQrg4i7REhXZeiR*3HDHey-09`?>5{&<#DBfSNrxVZHE1$UROc} z-}v#)c8cx7kSlR^>E;w)z$mygQ(mIvRluT?9~K`l?DzhQGiWGAb2sT9n6WP6JYsmw z_fw|@mtgEa(`D!X%GsuyJ?Sx+n4A8L^F6~A>&s5e0k~Q>>7KMnOdEdOdB!k#+*{5b zYJ&5IA-F)FH@sv`7l-(sNoSnr4cmrwBQ|4rMCm0RzxW!{t)KeAN%GA}K5AH&D{_<{ z9Gl}h&Ry8(vzzzYW`KW-zTE)%9j-A#%EyRru^(+W|F7&7uHD>FWMpqss`n|?`=l?g z8jrgg_-iHmT+MtuQniVR*0)?Aljb?n+(P!xk^TYkLCI*gB|=8G!04l#8y5{rcb}oj z!D5sv>lUM26tWoQ@{h%MASKIfG0G(!i&3uKSd60v$ym7_V=>ORWh1sDCxnczc*nTi z#%${Z_ZO7?Wy-#WvcF8(9}&B9D%{t3L{64^A#Wf2#+^eubzOW?$tE|~&&4ZQYN&8E zRJb-VGVh>!jB%Ouu-h)A&%ETD?PSyo4;8QsA#YH#g`A#y#GP2L>=8E1o7>6G_Jo~< z`6JXk<67%D^(JvJ0z(C4sDMlqlZjbm;yk`#?-A5yZ~midkuhRzQ|D5~3rT+=>HnDY zt4RN=g#N4olP73=+UoGskbXVs*Hc03DOInKE7`qb;o!&&Pq}dkmafZ>GY zSID*HdMb52mAZlZ(4r08kUiVe%xbgec;ub&d`|;!L6@v&^3t+J$U(J5$icQDcXfAJO}N9SH7!wr^@V|0st zqFp97v{Tx4O50AU+Jzjne%(XZSl*tnAP4gyvV4>ZbesxwoC*u!Oi8T*vF! z4}6_`GuxQa$+tmrR@AYBzDm7Jyp8ZF!efMI33Ub;JDjkTu##{aVJqQNgvSWa66%b1 zMUc#I{3~<$h8v}cAn{V-A>x(9w-G)?c#QBY;W^_4{ClD^$+SMxDYieuXZn*Y3P}Qx ze3B6$NhwJx3AYhG1&o~b9;3inLY|FOZ5eb2Z@J>hlt0B$B6r_ zq;DmC;z8me;vwQO$s^tv1==X0jd&;Vt^`UG-NbtmC?(t`GvGGK{lxvmgT#ZxL&QVG zW5i>`+laRjk91L>ivm5wdxWniZai2I2Li3f>?h=+*Bh{uSx5pN^jMZAl65Ah!2 z+(Gsu4$6Q6e&RvmLE<6eA>uLOG2(5++lY4&?;_qqyoWefC(An_3K5b+-3J;b?-(z?El$o8Xv z-z5zNi3f>?h=+*Bh{uSx5pN^jMZAl65Ah!2+)Wv{sc^*o#Dm0x#9O`8|2uIy?d>LH zDU$mLyHifF)XeS_Iht~+ zNRyVMgsp^~5+mMj3a~+xF=2qPf-p+hO4v!*O~}$opD;jJK^P@$CF~^ZCS-%9et@uo zFiIF{rBf$iHz6BBrU?Ut6@=Y{EQ4YR1B4ZXQNmWjPQq?NmPz`A0m3L@D`97ZPThoT zD5(+#2rCGqgsp^~gx!QJi}VQtgcXEQ!dAjg!frz5BYnaEVTCUuMXeO*Bof0Q|eG_FMO4v;p z$d{6C!a#xKt%R&l@(RM1FTQMyoU>f9IIThJL)Is)FIs!7SFMU|h;5i{jBS#w%+_k# zZ+p&m#P+)F9ovVt^R{YxlYO7P%kFWcJLWkyI+`4N9ETj8j<+2jI0h-1${3|ec|bX= zys5mae5iCQmz3*@&S`QEcg}Y%b}n@;ckXm*&exouIWIV`ICU;-x~sHs3;e}MGdL>QbClq_O zU@iE={s!PMD%Q6Y`>9Xryg~fs>D$0Bl71Mb@l~5MWHuuR#}&yM|DAj=z!MAlU4iKT z-xG5wn6-vb3Z#zui32MTrq>j|8_0Tk?C zaYM_oB^xhX#|I-h;BNs1I~8FQ5O^CXun{^B{2idc-sXJpKL7>xB+J)i{0S(qv3N50 z2S9<%!bRX80tNdBos(nrVH)_qW7&hV{{RYX%$)(=4HQ_F2!ekK#F{?tr#U;vBBcm? zhV>9UX$TbTf6&7@`y43Pc~%boXQ03f zu*+-#_%}d-jhBnSuK)%1OWpzA3l!J`xkRpFean_0aGl)+{vA+Yui{ehe*gtmn3jQa zpum>G5V#H~@K%dTa3fGK6Ay!%fr43hHMkWhn2oOjw*v)p@YUc7P%tN71MUJw1eRdd zA)o>U^Y9JeUZ7wp_}>8!*8&Ag;~RnLd=n&tfmn;@4d59-!7}+~@S#9~-F#cYeL#V2 zcd~lJfC3xqV&K_8fz4{$z()c_1beXVMPM{gVD;lZ@UcL_#_=Zbn}CAl;Efx2Y#u1s z1ilkI7l^MI=MMtQcr&n^w*VJ&Jdn-q)LA_o{b zBqp!|c1=tMUKd5^WK1_%b~RlQI+ho_h^2y0WrM+|vJCKP%m7TdkHyX^}cn;j22o^<@(k*};(9#RUOe{ha)O?JgxO|Fkz zJ+6Se+`Y=Z-u9o~1biYwLd1a$Vuvbg-yQOWrJa}*1za!p@9 zz~o;_q)aa%@w3C*iZ#;j|7es}>iswwwZj{KsSZX1wwxq?+9@&KcbpWkX7AVkq%a+1 zuuqA|%G8#*f4hB&i%nr(+0JO+RJ3a<+7r+5GhL3SOt&1zvp6o`7~w6` zZNf$^##&OZ###!mIa}Vjdb*|Hnycm4y=8n-OYSvq%O|}xE!VCLZYjG~-txrN!Kt~d zxGY?Mb7)m<>AISAwX?!?m9?wZ|MuQ%=Xl!ed+KXLmG!~(>%*bi(AvuItWbSu`tsja zUH?$;8kp(_wd>Y&OyWFW3@WcH3$G0?*tmXuZMd#3T*d0*v?Gjt(|YZ06Ss6Un&kUi zU_i^T@Y-27hw2ur4_B@V)ht-OYAqFGPPk#yy4orRoj%#jh5^#P0w<&$zqIf#_zi_x zurgGoZM5+(#jUj+OYQtR_k6$1C~C)ig{N_2d7ZSVEp_rYWWhRyy7+LeyJO|5j_Gb* zCQQ}g`ei6*N5sQRL=H4&-viI|m2F(h^ z@>AS}+DCp~WKKA}u0t8d7l>i;(kGf&W;iRn;)kI%;W}1F^;%Wiaced=Sgo+UI8?JS z43Etn&%ZX>AV}oh&@rQs|0z$k%*5-XHnK1_h}{mXVoVEEb01IBx>oSC(T@3uti`t_ z*GLt|t>7ViFLbpG*<{iX9+X{;MDJAdVcOMdK2{sMl5dZs+>Dr2&|Ze2S;N*L4NRx~ zGbt?Hpj`{?P4c^^Z;TZugCWm(+)mSr^}H)d7_wRoXxZzx0%m0L~~M0NuT zSBfI6$8Q)FVE%s71LZRj_kRmI7dch4l@XMRdHNI1f;VcVpKQzfy#d~5g5(Kb+BWsq z%T$X(pfZl?fmLvX1{OTMazJr&P@!73G+r`ptBIFK7ROT6SBL>kf=28sgyRN3Id1Td zV?f=tyKDKN#kNFU$#!1_EwX~tpKR5z9L6tv>sU`-PIM#7e5wrGVOihDq;`lkbhNMJ z*G<~z>-oon(igyGvgMZHjxJ1{ZLJJz``7cCk(4^vl&vIlLDwf_wtlDgH-Id=?1X5| zzV4Hh$?o0XeHKD%Ei5rh(hjpFHK9jdkd`*$H8U{Q-0BPF5wjUt(B-?(VEYS-FR^7H9j+N7oPkUzrzsYe!skO{n zK0*6QEuW>mQOkYWrCOe%dFps($J9Fhqv5XIe=L9gl{XuH@T=K_r~T&E`44G(f6Z%n zx#rgRJPTeDr{jtm+ox4){OI6jcdRQ#jqT*_d1~y0Jw=VaAl&nW8at_#Jd7{=dQV&R zFu#R=q8)me{~V`jyZLL8^JXX0yQ60mckF!pPj3=J7<^oK@ERAcMi04|L5+O{9W~Z0 zp!bad9WL5zMh3eP|AEoRxf<&gMx+wlZg-oEDeh<+R}_(HK)hOR@G&*^oq_R8gCcdz zW-}fcK~$!8&m(-~Y>V26RZm!Hw5TSddmi!vi2w%(7wc8)%8+eX({88@bdD?$J%CmT(X57Q`d671C5C6(ot~aWU^R&Fj z_zHfT_V8o8%D701mT2N}_-Cm$?{S{PLmitR=h>XE(ORG29~N6pMm3g)Dk-v-ilP`z zdKs{}I3J3aEN%p*nNnno1^&C?N4u{TSEL5*nN}W)#73B`YV;$K@Ln(6&c$Mo zvpGpDCX?N6ml@lc9#uBD?D99oWLBde_Zd;*X6z=b9fgYjPzm8a6jZS&h>|gpc$~{* z5YokMXuw|liFDYD6=lQ?#tLPH)L5ZZ)}!%4Xk$c6Z=*jI;ZN`585xN#5Gyn#^zAMV zv*e7S%wUx!3??12HJJ?LJFC-VP8JX`LeW;V@p0L+OsX2~R%-rJzgq^a3HHIW@Ci)P*;ROXf;c~}FdmUskmwwVzOa!fo1Cmr#1|BCiTEYrmx*82>`(FZ$h|@h!&xNS0Z+$b zH0~R_lAYjQ6RHw&H=e*imF@~DdQ2Zx(o!tm7nsGwQC2;M3OWp(Wn-Rp7!l$!N>;-x zLpwo)(QL6M6I8|1niFZ|IiaY^@f>T8t4g^Mu8v+8C>PAA(N{5Dsg0*y@M-kbqznQJ z+9J9G!X0KB!{{!WV=sRo9Rr5?J?23(`YpI3J6+=$t#dCQ!h5uj_wqsfGwqwbe8ki* z$@-Vbtg)9SLxy=%>Z^_E*cZq{hOSeVM?7 zivi0W60EXUZL`213Bya(*qV4g<0zx0$&8lvXC%#lg`}Q?@XCY=VK0Ph!KQiiVloaeWR~Mh zEyqp{H72<$;b_W53gSuCa$J|=$#A(v&vGG=9H%8*$cz06E^LXE82hdqlUXV&C(xX@ zM^Gq*L+#$`NyeJ+GZ zDrncA<^H+okyUC1n!ui%R#s9VKKyY*7d`1t%mwkQTUxWDcLTLyFWSOCZ_hjDAGWeiZyFL zJ;*nUXs>qZAb%VU_~7&W)zSI6xp}#{lcy{%Sg|6vurR-JVo^a=cv4a2q{&5<%PT|6 zmru;E42Oz3>R;gJ^l7ZB;>^p8&zmnlsJjP8%|$#j^`5r&cRba24*cAE+An^`hq)fy zH{#mj=LgT(HSxjg>rJ|VcJz0A^~8j9T2cyYQxCO>;=lXe&C(rv>)ZTG{U2M-lib(r zPZcvRX&XBDV;#PuyqIgsOMDtWMDLjM5`ReCn$L3an@2bqp8zh$C%`N4n~P6>3t2us zaF~eC1PkyFQkYEws|3nVgDas~iH^P;zY|F>j8Ks_;T8Tz3v#xjZWXy5?xXx7Z_YLS EFM4U<=l}o! delta 43266 zcmd44d0-S();D~ry1Tm5Sx6_H?u2ZemCi~6VM)Rgwm}vV6ciK{6c-R}=zv?(R3eC| zh+=^PZXk-_xDIY8D!4GBsDK-82#UBXGLFiq@%^1s)kz0+-skzg?~jj}oI1aA&OP_u zbN5@7*z$<8 zV6$vbb;@v9pTJ^R&$2Bm@FuF11UUXpg~l5NYNatr>E>SZsO9r9;~J$XfjzUkCyd9G z`~-q?{GYZM`;@}02xpIf$KgjM2hk2VOH@d?dG;Qqk1|G@f*ws>}t=HF_irPn~R)W*sNdBI}H+69URQ> zv3n9ct~TuqWFOdcf!nKOFYoMlG&?>+953IrI`IM};drZ1D~yz6pSA+#k?zKTlt!!7asTw}X)wyL>8uclG8LW)-1UaS%B1iv?D?+cs_;xD@-$D7 zv}*J=PHT(aZlyiBJ?*lNw9ioZejqhC15Ry1?V!eC&&I$hmY+M=L2wM``YEU6u8Xov zG!AF`ja_NaWE8`Y)L@=ytT2-EM-3KH__}mN zCejsRZ}3V~ddXrU#T10lCIDAcp(Nd6zh%5oE?IscNw%HP$l_!xFssm1PRd%EBRX!9Z6oGRs)Cbbw z6=ps!6$aq%3(yk7T~sp0Ec#b|SWEeWiV^#UlSk~=t%06Rnx9-Y*!xb#kKZZ&3%gFpLGHU1vlZ!9U>m3=Q<#YJ=)M|6)w^xjRE zln+$0|K8c)95&c127lkQyP}Ia@V?Fl=d!^eF4Ca`+m&47uKETg&-kd`m(&GX zHIjuSA&;RnWN9o2r5S;SAnZmoG#sA?0R z zHJ%;Wkev{h3qoH^nk~dKGmlI=*+SWyYDT3fh1e>>H#ad)x*?B3?ous$Y8B?!P%`W0 z8dFC5g51%?3?n4Q%5)w}v0PH58@G@4x&5%ns7|$q{Khk*Kh4D$*D8~3A%4n!q(bqz zwMyg%nX&cwG1@`aL=EqlKM=7 zAnZ@r{)S%@_G@Mj3wwZBdoA0(&1{aauQ1zJ*saWt7nb+h;fsa6m)VuV-oflc!Y&7E z3+vkfLK%opRkAI-Ck84Mf4bdcuS~RzF%!Y~y_lM955@r7Iy?^8nx*U~wqM88Z2LnD zur0QPu%#YcjZ|HX(*W8F5r_dcc6yvJE*E3O6NMNYQ?ui-F~GLi55v}s&l6&MMoi7N zGh={l6Fdp9U0JJhDVB)wr7=AlFN^^;c6;2FuJBTbk}J-(h3|^#*zlnkU_+iGUEwFh zu)!97EvBpLY76ge2T1jC4CtIJ$&-X+UrI8&H@Simu$4@&vC*|C*dXaPp)a{JVKlmv z6DkwJ_tWN{9+h{Q+m>@a1KZaQ-QlN z+=Fpb3@2%>So*VAX8H=@_{Aq4^4QBM8wJDehXxz>pPYH-MX*Y&I31lHLUMgajDl?yBwkx}>RXz7p&QLLTHt zAB30pG>T6N=tzr^Q<-QBW@9zQ6oa543`yZfka@bjFUBr~_keH4w1seF2XkN-%mqo5 zV@eV^Ls;u@QtNvkN}lEjVopUVNaBZ1riFgv2(Cc3yq9-NU+RW)0n2S#aK5qqltAH8 zw&6D5S&lnJF?pOSj6}iFHC{g@qnn8S&9*EuLx=;K1kpSsaR~~Hp%cd{LyZ*^Yt@52 zjh7})K6RMXQ*yvcf0t``Kyfy4w4v0!_gpt?5%gF#{zt66YgoWR=$ zf?|-E#X=S=j}x@@!B7jk`*xUI3_jcvC)m$|Z{q}G>LEA-BXRo!r`6%#xYmZC`~~>Eaiwe3s+L4vVhl?m{S)CT1*ABXA;l=Hss}^3~4wAL-?Jf zh%Ms4HV4)gjPJzocG0XA&AI26ni^|U_Fkhg_VliGhuNfJrdD|FxrYWwN?BN4VOKv^ zoTL@@?77KO@J7lN&g*B~e!5?;5q*JX&UBomY=~Upzlp*XK3ASRJEYgx3CC9&`6u(_ zt2=l0$2`e1OiFB?boOoGBAZjCwNK$0brsL3yhBR}FI4&&+oosqx&fJ_+f5sXD`vy% zYC`yS);TINT!pXh96hj2m93RCd~ZJ^aYl(U%BY>;9q}Y=5-ZMEO%tvK4h638b`g(L zxpM9CbcH_whMV9#^dStW#1^T7G=#-dKsAHzOb%EQUM?dwl2TT6tc5z%pTwzUSr2_0CyCU? zCE$zr&=-HD<)t?dr=dP3zzWU6HEptfna(>J#Z9UFyo+-ciG z@4-C=Q4w~V?=!1mH_FFVkJhna=-7}VChn>?u?csy`Eolp;mAzFunTGg)A;$KWSu9I zJUHVMdz?D58#bYyr~)?45nRx6?Sa3@`?g*mcmKPeKA2==$>84Dg_oF4_3))zAruEN%rja!NiD__ba);V1WIFBD z?#3PL&5f~xZ3t!IocY4n9n!H4GGSkac19Rj?zE&}Jp?jtJmg9ABsDj%!LOVH!i8x- z^CX5EA(NUSeC~#%-+%udK~HG&6~qNylZ}XibBs#el$ui%>;aj7NBL!snj#<@GjlC^ z`xxW?S(#;H(XHi$fV|5}?yK=Qkkg?SUId-l*L}f$#<#P&dbWt9y~77*7~juHFS44F zJ3KcQPmfi+krQKcEEp%u4k(u!vu6A3r2}b}p@jWqRx2Pw;pwar6%jFrhJ{CiivOd8NRQ@#@CE`V)+5$-CUfk!Pk z5FyVj#AO+GQA7ySUl7W}P@1yPev~@cWQ?8T>(3p`9^!u0X2+a(Jd&~K0#kOuX@x{D z4L)^xy4@Bo9>fkZl`mu}k(PUS5R)ir zx;#&f;9zU#Ck|Wk#Hq<%?kQAlQQ@FLS?uM;;Y;&IK7kyX2gB3lP_tNV#@kRW%0ATQ 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 aS@t#^^S+LU2*|+WRVn)&`hqr;8~+a#;Nu public static class ColorDescriptionService { + // Константы для повторяющихся строковых литералов + private const string Green = "Green"; + private const string Orange = "Orange"; + private const string Black = "Black"; + private const string White = "White"; + ///

/// Получает текстовое описание цвета волос /// Сначала проверяет гены цвета волос, затем использует вычисленный RimWorld цвет волос @@ -94,6 +100,35 @@ namespace AIImages.Services return GetSkinToneDescription(pawn.story.SkinColor); } + /// + /// Получает текстовое описание цвета кожи по RGB цвету (fallback метод) + /// + public static string GetSkinToneDescription(Color color) + { + // Вычисляем яркость + float brightness = (color.r + color.g + color.b) / 3f; + + // Определяем оттенок кожи + if (brightness >= 0.85f) + return "very fair skin"; + else if (brightness >= 0.75f) + return "fair skin"; + else if (brightness >= 0.65f) + return "light skin"; + else if (brightness >= 0.55f) + return "medium skin"; + else if (brightness >= 0.45f) + return "olive skin"; + else if (brightness >= 0.35f) + return "tan skin"; + else if (brightness >= 0.25f) + return "brown skin"; + else if (brightness >= 0.15f) + return "dark brown skin"; + else + return "very dark skin"; + } + /// /// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.) /// Исключает гены меланина (Melanin1-9), так как они определяют обычный цвет кожи @@ -110,30 +145,49 @@ namespace AIImages.Services return false; // Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая - return geneDefName.StartsWith("Skin_") - && ( - geneDefName.Contains("Green") - || geneDefName.Contains("Blue") - || geneDefName.Contains("Red") - || geneDefName.Contains("Yellow") - || geneDefName.Contains("Purple") - || geneDefName.Contains("Orange") - || geneDefName.Contains("Black") - || geneDefName.Contains("White") - || geneDefName.Contains("Gray") - || geneDefName.Contains("Grey") - || geneDefName.Contains("Ink") - || geneDefName.Contains("Slate") - || geneDefName.Contains("Sheer") - || geneDefName.Contains("Pale") - || geneDefName.Contains("Deep") - ); + return geneDefName.StartsWith("Skin_") && HasSpecialSkinColorKeyword(geneDefName); + } + + /// + /// Проверяет наличие ключевых слов специальных цветов кожи + /// + private static bool HasSpecialSkinColorKeyword(string geneDefName) + { + return geneDefName.Contains(Green) + || geneDefName.Contains("Blue") + || geneDefName.Contains("Red") + || geneDefName.Contains("Yellow") + || geneDefName.Contains("Purple") + || geneDefName.Contains(Orange) + || geneDefName.Contains(Black) + || geneDefName.Contains(White) + || geneDefName.Contains("Gray") + || geneDefName.Contains("Grey") + || geneDefName.Contains("Ink") + || geneDefName.Contains("Slate") + || geneDefName.Contains("Sheer") + || geneDefName.Contains("Pale") + || geneDefName.Contains("Deep"); } /// /// Получает описание для специальных генов цвета кожи /// private static string GetSpecialGeneSkinTone(string geneDefName) + { + // Сначала проверяем точные совпадения + string exactMatch = GetExactSkinColorMatch(geneDefName); + if (exactMatch != null) + return exactMatch; + + // Затем пытаемся определить по ключевым словам + return GetSkinColorByKeyword(geneDefName); + } + + /// + /// Получает точное совпадение для известных генов цвета кожи + /// + private static string GetExactSkinColorMatch(string geneDefName) { switch (geneDefName) { @@ -162,31 +216,39 @@ namespace AIImages.Services case "Skin_Green": return "green skin"; default: - // Пытаемся определить по названию (defName всегда на английском) - if (geneDefName.Contains("Green")) - return "green skin"; - if (geneDefName.Contains("Blue")) - return "blue skin"; - if (geneDefName.Contains("Red")) - return "red skin"; - if (geneDefName.Contains("Yellow")) - return "yellow skin"; - if (geneDefName.Contains("Purple")) - return "purple skin"; - if (geneDefName.Contains("Orange")) - return "orange skin"; - if (geneDefName.Contains("Black")) - return "black skin"; - if (geneDefName.Contains("White")) - return "white skin"; - if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey")) - return "gray skin"; return null; } } /// - /// /// Проверяет, подавлен ли ген другим активным геном + /// Определяет цвет кожи по ключевым словам в названии гена + /// + private static string GetSkinColorByKeyword(string geneDefName) + { + // Пытаемся определить по названию (defName всегда на английском) + if (geneDefName.Contains(Green)) + return "green skin"; + if (geneDefName.Contains("Blue")) + return "blue skin"; + if (geneDefName.Contains("Red")) + return "red skin"; + if (geneDefName.Contains("Yellow")) + return "yellow skin"; + if (geneDefName.Contains("Purple")) + return "purple skin"; + if (geneDefName.Contains(Orange)) + return "orange skin"; + if (geneDefName.Contains(Black)) + return "black skin"; + if (geneDefName.Contains(White)) + return "white skin"; + if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey")) + return "gray skin"; + return null; + } + + /// + /// Проверяет, подавлен ли ген другим активным геном /// private static bool IsGeneSuppressed(Pawn pawn, Gene gene) { @@ -201,31 +263,14 @@ namespace AIImages.Services // Проверяем все активные гены на предмет подавления данного гена foreach (var otherGene in pawn.genes.GenesListForReading) { - if (otherGene.Active && otherGene != gene && otherGene.def != null) + if ( + otherGene.Active + && otherGene != gene + && otherGene.def != null + && CheckGeneSuppression(otherGene.def, gene.def) + ) { - // Проверяем через GeneUtility, если доступен - // Или проверяем свойство suppresses через reflection, если оно есть - var suppressesField = otherGene.def.GetType().GetField("suppresses"); - if (suppressesField != null) - { - var suppresses = suppressesField.GetValue(otherGene.def); - if ( - suppresses - is System.Collections.Generic.List suppressesList - ) - { - if (suppressesList.Contains(gene.def)) - return true; - } - else if ( - suppresses - is System.Collections.Generic.IEnumerable suppressesEnum - ) - { - if (suppressesEnum.Contains(gene.def)) - return true; - } - } + return true; } } } @@ -239,6 +284,29 @@ namespace AIImages.Services return false; } + /// + /// Проверяет, подавляет ли один ген другой через reflection + /// + private static bool CheckGeneSuppression(GeneDef suppressor, GeneDef suppressed) + { + var suppressesField = suppressor.GetType().GetField("suppresses"); + if (suppressesField == null) + return false; + + var suppresses = suppressesField.GetValue(suppressor); + if (suppresses is System.Collections.Generic.List suppressesList) + { + return suppressesList.Contains(suppressed); + } + + if (suppresses is System.Collections.Generic.IEnumerable suppressesEnum) + { + return suppressesEnum.Contains(suppressed); + } + + return false; + } + /// /// Проверяет, является ли ген геном цвета волос /// @@ -261,17 +329,17 @@ namespace AIImages.Services || geneDefName.Contains("Colour") || geneDefName.Contains("Red") || geneDefName.Contains("Blue") - || geneDefName.Contains("Green") + || geneDefName.Contains(Green) || geneDefName.Contains("Blond") || geneDefName.Contains("Brown") - || geneDefName.Contains("Black") - || geneDefName.Contains("White") + || geneDefName.Contains(Black) + || geneDefName.Contains(White) || geneDefName.Contains("Light") || geneDefName.Contains("Dark") || geneDefName.Contains("Ginger") || geneDefName.Contains("Auburn") || geneDefName.Contains("Copper") - || geneDefName.Contains("Orange") + || geneDefName.Contains(Orange) ) ); } @@ -286,7 +354,20 @@ namespace AIImages.Services string geneDefName = geneDef.defName; - // Специфичные описания для известных генов цвета волос + // Сначала проверяем точные совпадения + string exactMatch = GetExactHairColorMatch(geneDefName); + if (exactMatch != null) + return exactMatch; + + // Затем пытаемся определить по ключевым словам + return GetHairColorByKeyword(geneDefName); + } + + /// + /// Получает точное совпадение для известных генов цвета волос + /// + private static string GetExactHairColorMatch(string geneDefName) + { switch (geneDefName) { case "Hair_Blond": @@ -312,71 +393,83 @@ namespace AIImages.Services case "Hair_Dark": return "dark hair"; default: - // Пытаемся определить по названию (defName всегда на английском) - // Добавляем поддержку конкретных генов из RimWorld - if (geneDefName.Contains("Blond")) - return "blond hair"; - if (geneDefName.Contains("Brown")) - return "brown hair"; - if (geneDefName.Contains("Black")) - return "black hair"; - if (geneDefName.Contains("White")) - return "white hair"; - if (geneDefName.Contains("Red")) - return "red hair"; - if (geneDefName.Contains("Ginger")) - return "ginger hair"; - if (geneDefName.Contains("Auburn")) - return "auburn hair"; - if (geneDefName.Contains("Copper")) - return "copper-brown hair"; - if (geneDefName.Contains("Orange")) - return "orange-red hair"; - if (geneDefName.Contains("Light")) - return "light hair"; - if (geneDefName.Contains("Dark")) - return "dark hair"; - if (geneDefName.Contains("Blue")) - return "blue hair"; - if (geneDefName.Contains("Green")) - return "green hair"; - if (geneDefName.Contains("Purple")) - return "purple hair"; - if (geneDefName.Contains("Pink")) - return "pink hair"; - if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey")) - return "gray hair"; return null; } } /// - /// Получает текстовое описание цвета кожи по RGB цвету (fallback метод) + /// Определяет цвет волос по ключевым словам в названии гена /// - public static string GetSkinToneDescription(Color color) + private static string GetHairColorByKeyword(string geneDefName) { - // Вычисляем яркость - float brightness = (color.r + color.g + color.b) / 3f; + // Проверяем основные цвета волос + string basicColor = GetBasicHairColor(geneDefName); + if (basicColor != null) + return basicColor; - // Определяем оттенок кожи - if (brightness >= 0.85f) - return "very fair skin"; - else if (brightness >= 0.75f) - return "fair skin"; - else if (brightness >= 0.65f) - return "light skin"; - else if (brightness >= 0.55f) - return "medium skin"; - else if (brightness >= 0.45f) - return "olive skin"; - else if (brightness >= 0.35f) - return "tan skin"; - else if (brightness >= 0.25f) - return "brown skin"; - else if (brightness >= 0.15f) - return "dark brown skin"; - else - return "very dark skin"; + // Проверяем специальные цвета + string specialColor = GetSpecialHairColor(geneDefName); + if (specialColor != null) + return specialColor; + + // Проверяем оттенки + return GetHairColorShade(geneDefName); + } + + /// + /// Получает основной цвет волос + /// + private static string GetBasicHairColor(string geneDefName) + { + if (geneDefName.Contains("Blond")) + return "blond hair"; + if (geneDefName.Contains("Brown")) + return "brown hair"; + if (geneDefName.Contains(Black)) + return "black hair"; + if (geneDefName.Contains(White)) + return "white hair"; + if (geneDefName.Contains("Red")) + return "red hair"; + if (geneDefName.Contains("Ginger")) + return "ginger hair"; + if (geneDefName.Contains("Auburn")) + return "auburn hair"; + return null; + } + + /// + /// Получает специальный цвет волос + /// + private static string GetSpecialHairColor(string geneDefName) + { + if (geneDefName.Contains("Copper")) + return "copper-brown hair"; + if (geneDefName.Contains(Orange)) + return "orange-red hair"; + if (geneDefName.Contains("Blue")) + return "blue hair"; + if (geneDefName.Contains(Green)) + return "green hair"; + if (geneDefName.Contains("Purple")) + return "purple hair"; + if (geneDefName.Contains("Pink")) + return "pink hair"; + if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey")) + return "gray hair"; + return null; + } + + /// + /// Получает оттенок волос + /// + private static string GetHairColorShade(string geneDefName) + { + if (geneDefName.Contains("Light")) + return "light hair"; + if (geneDefName.Contains("Dark")) + return "dark hair"; + return null; } ///