From 78448f953bae662872e00c13f99d7befa8c7dd92 Mon Sep 17 00:00:00 2001 From: Hsiaoming Yang Date: Tue, 25 Nov 2014 18:05:00 +0800 Subject: [PATCH] Init with audio captcha --- captcha/__init__.py | 0 captcha/audio.py | 216 +++++++++++++++++++++++++++++++++++++ captcha/data/0/default.wav | Bin 0 -> 2791 bytes captcha/data/1/default.wav | Bin 0 -> 2018 bytes captcha/data/2/default.wav | Bin 0 -> 1991 bytes captcha/data/3/default.wav | Bin 0 -> 2324 bytes captcha/data/4/default.wav | Bin 0 -> 2331 bytes captcha/data/5/default.wav | Bin 0 -> 2674 bytes captcha/data/6/default.wav | Bin 0 -> 2427 bytes captcha/data/7/default.wav | Bin 0 -> 2789 bytes captcha/data/8/default.wav | Bin 0 -> 1851 bytes captcha/data/9/default.wav | Bin 0 -> 2385 bytes captcha/data/beep.wav | Bin 0 -> 940 bytes 13 files changed, 216 insertions(+) create mode 100644 captcha/__init__.py create mode 100644 captcha/audio.py create mode 100644 captcha/data/0/default.wav create mode 100644 captcha/data/1/default.wav create mode 100644 captcha/data/2/default.wav create mode 100644 captcha/data/3/default.wav create mode 100644 captcha/data/4/default.wav create mode 100644 captcha/data/5/default.wav create mode 100644 captcha/data/6/default.wav create mode 100644 captcha/data/7/default.wav create mode 100644 captcha/data/8/default.wav create mode 100644 captcha/data/9/default.wav create mode 100644 captcha/data/beep.wav diff --git a/captcha/__init__.py b/captcha/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/captcha/audio.py b/captcha/audio.py new file mode 100644 index 0000000..1d3fe1f --- /dev/null +++ b/captcha/audio.py @@ -0,0 +1,216 @@ +# coding: utf-8 + +import os +import copy +import wave +import struct +import random + + +WAVE_SAMPLE_RATE = 8000 # HZ +WAVE_HEADER = bytearray( + b'RIFF\x00\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00' + b'@\x1f\x00\x00@\x1f\x00\x00\x01\x00\x08\x00data' +) +WAVE_HEADER_LENGTH = len(WAVE_HEADER) - 4 +DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') + + +def _read_wave_file(filepath): + w = wave.open(filepath) + data = w.readframes(-1) + w.close() + return data + + +def change_speed(body, speed=1): + """Change the voice speed of the wave body.""" + if speed == 1: + return body + + length = int(len(body) * speed) + rv = bytearray(length) + + step = 0 + for v in body: + i = int(step) + while i < int(step + speed) and i < length: + rv[i] = v + i += 1 + step += speed + return rv + + +def patch_wave_header(body): + """Patch header to the given wave body. + + :param body: the wave content body, it should be bytearray. + """ + assert isinstance(body, bytearray) + + length = len(body) + + padded = length + length % 2 + total = WAVE_HEADER_LENGTH + padded + + header = copy.copy(WAVE_HEADER) + # fill the total length position + header[4:8] = bytearray(struct.pack(' 128: + v = (v - 128) * level + 128 + v = max(int(v), 128) + v = min(v, 256) + elif v < 128: + v = 128 - (128 - v) * level + v = min(int(v), 128) + v = max(v, 0) + body[i] = v + return body + + +def mix_wave(src, dst): + """Mix two wave body into one.""" + if len(src) > len(dst): + # output should be longer + dst, src = src, dst + + for i, sv in enumerate(src): + dv = dst[i] + if sv < 128 and dv < 128: + dst[i] = sv * dv / 128 + else: + dst[i] = 2 * (sv + dv) - sv * dv / 128 - 256 + return dst + + +BEEP = bytearray(_read_wave_file(os.path.join(DATA_DIR, 'beep.wav'))) +END_BEEP = change_speed(BEEP, 1.4) +SILENCE = create_silence(WAVE_SAMPLE_RATE / 5) + + +class AudioCaptcha(object): + def __init__(self, voicedir=None): + if voicedir is None: + voicedir = DATA_DIR + self._voicedir = voicedir + self._cache = {} + + def load(self): + for n in os.listdir(self._voicedir): + if len(n) == 1 and os.path.isdir(os.path.join(self._voicedir, n)): + self._load_data(n) + + def _load_data(self, name): + dirname = os.path.join(self._voicedir, name) + data = [] + for f in os.listdir(dirname): + filepath = os.path.join(dirname, f) + if f.endswith('.wav') and os.path.isfile(filepath): + data.append(bytearray(_read_wave_file(filepath))) + self._cache[name] = data + + def twist_pick(self, key): + voice = random.choice(self._cache[key]) + + # random change speed + speed = random.randrange(90, 120) / 100.0 + voice = change_speed(voice, speed) + + # random change sound + level = random.randrange(80, 120) / 100.0 + voice = change_sound(voice, level) + return voice + + def pick_for_background(self): + key = random.choice(self._cache.keys()) + voice = random.choice(self._cache[key]) + voice = copy.copy(voice) + voice.reverse() + + speed = random.randrange(8, 16) / 10.0 + voice = change_speed(voice, speed) + + level = random.randrange(2, 6) / 10.0 + voice = change_sound(voice, level) + return voice + + def create_background_noise(self, length, chars): + noise = create_noise(length, 4) + pos = 0 + while pos < length: + sound = self.pick_for_background() + end = pos + len(sound) + 1 + noise[pos:end] = mix_wave(sound, noise[pos:end]) + pos = end + random.randint(0, WAVE_SAMPLE_RATE / 10) + return noise + + def create_wave_body(self, chars): + voices = [] + inters = [] + for key in chars: + voices.append(self.twist_pick(key)) + v = random.randint(WAVE_SAMPLE_RATE, WAVE_SAMPLE_RATE * 3) + inters.append(v) + + durations = map(lambda a: len(a), voices) + l = max(durations) * len(chars) + reduce(lambda a, b: a + b, inters) + bg = self.create_background_noise(l, chars) + + body = BEEP + SILENCE + BEEP + SILENCE + BEEP + + # begin + pos = inters[0] + for i, v in enumerate(voices): + end = pos + len(v) + 1 + bg[pos:end] = mix_wave(v, bg[pos:end]) + pos = end + inters[i] + + body += bg + END_BEEP + return body + + def generate(self, chars): + if not self._cache: + self.load() + body = self.create_wave_body(chars) + return patch_wave_header(body) diff --git a/captcha/data/0/default.wav b/captcha/data/0/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..8579958646420526a2e5a66380c283e512023495 GIT binary patch literal 2791 zcmY*b>2lo05vKp8@+)tUyh)r?EGJS)vJO&WWK!G}m&e|_xG@(77~I&4yUV3`iIhZg zNm`e6*(E!bqw*YimGpp8tPBdk0GR3H>+Y{{^Dmb!{pZ&+Gk5+l_ti>G{oQY7W@f&C zZ|W^WQ%%Lvb$DelhkH?{KNyU*CX?}KxY0=h!8rq+ocrAO zgGhM9G7Lj&!}_+;)^%0Y4Aasr6Jt!k1O$eF9n2T8A7|Zer{5oBoj6OPScHDy377et zQwP>s*tRV&$TDENWmuMFnzo57+d{~~7QuvIN*IQNx!e_Q>?U3s1*zW&Vi89|c)sU4 zf_uzyDaVX}hr}ipMsOhn5sSjzCJaegwuA_bUniyD~P$i~D#Hl;STiH$I#$Y$U$Vw7QtI(J>)jl4)iF$hfjzz+fsRB*tQ zgH|6b5XVlgS){%y6z?1?UUPuCwC1ITQ!zk#*UL3?R4kL%N(B;Gz zHX!VomTST`6PazQH%zr`RLa%ba=BG8EFwBle|vLlcW-+eLYRgjqyvMDaN{)SreWYa zh?;tF@X6Wn^Y?F`KRtTX6%J`vn@U@wQEzj9`t0QBaFV&G zT`3h7?#|E8-oAb9%H=CJ7mQF0&R!lr|KakZ!Uj*?bdR@_|sR@=@0MEp6*RDsw&F*x@r^A-#$2=o}ce;_Id0}$8VmUzI}VTH%ysYUa8b-s@oYne0qLTCCBuYCR0<(tb+m>j%*bN2l8>2~H>t@4Alwr&UGoxR7$M+XnP0adEy zTCHUgAvm*@wZ+*hm;U(W@BehQD7FqxfBM(^^Cvr9RJp%Ue6UhygRO@L)9K^wja1m} zdbOo$HpC@OBM*V-Z)a~@zjp2FmFtVz@Z{v=)rS}3(8bDH@j(rHK{h!&+#U_O5!F>q z*G=SxN!IChV#jDzN{jP%@7|f6h4a?j3VwKg`uOO(laYXG)#~eYoOHYWtw(#q7)p@n z5LHNAk@d337cx4ltE;7Ap-?C;Efot(3-=bw(e&k$$=>;N$Zdom6Lgx6C&R&b-18|i z4b#vK;>U5eG3-Sivy^&eeYI3tUWR}z6^g~B#l_{SVmO=6zkf0sP6n=J**4;Fr`sRO z9Yk+7Rl_i8G#HNtoiq~6Qd=!xCLPMxP@0v}{d<31C@dEj=I3tTytSb3e)z|m1xTwW=y zS5}LKa`@t(?+-@%M_Zm+uPY?<-FP_e24NZyqg^Xkb;_8R_Iqg@1%A$+l;ScpY z3?#uQw!l_NhK8&-&9V(u0gJ1Z3RqnSo=(nxe*1Xb5!h%{RMF}5Mx$OQM2ZHKi6{qB z1qK2>!Zzl9)axfv;1Wr$K!TF3Fu_uIyVYtoTdhV7MAzz#wt@yPe}1)}GQ#Yp>SW`| zs2j(Enu>-+Ac8pbAf;6UtfPLKMZ%$!1CIyL6|fZKY9xSX8U^ z20i@gZ_mb5L(DQrFx;JVLcthN58^?R`jjBc)D;B>38>)?F-#{&`yBzzhB0IU*HWZu zrj2a_vK@c{1rYdlv$|exu-$h*ez)n_HgrDb_clk}5SW%B+p?V?iUS8p@8v__N~n`8 zO+ro(I09Xh+K@s39)@-Zg#ai5^4+UlAJHHVIAY1hW={~}MG?0& zi-(bmO^Y~8<`;A(#}#25x*(lE;{%zpl|f`6<7G_c09Ay7!|>K{6!zRSkaUgz(dcuQF=>Xy$v~NcU$5z{#4YG7ag-XGY+$JK7NN*t$ zHpqu;Z&d4cx_xx=XaxM9b+f?1RHQ%^05tbJ4mF|WN&r3rc}`(J0_6$hBg7aQscjk- z6g~h(@<@RT7mv_lL5l$a(G418!|`y?&9ZJET8j&`0)P$c@8xQMF@>v>VT+9 z_@V#GA^Rl&2QijkK_q+u$r3PI&S1bM`3=1HpqIjc{~2J)B#xpejzEj>JdnZj?#tm0 zZhVv`!T2};#QzN$4af;eM4u0-DmOB}N$c`IDG&^HLaAP80DD21>vcv3zuAb{_?`zi&yz3`BCb~mqHljG=Gq{PlsIaX`bKz3+l64 AoB#j- literal 0 HcmV?d00001 diff --git a/captcha/data/1/default.wav b/captcha/data/1/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..2c6c74f1c1d903c72b375b64947bc4695c7bd304 GIT binary patch literal 2018 zcmX|C>2}-36;^(=Kl=vlqclI7b9%Zsb{)&MWIK|zP!vJzI|iHqFaQV;;3`rpC0nhT z*h+NLrb&I;+9&7qDf%@1hO~RZ!4R|Dxyv`-z4zPCKKt*_*4EZPeejz-$@tYT*4EZO z!Sm~1t}WXqYd>Gx*)q0%z#7_FKJ;V1`V{Zg@Be*=CPjZdIXapQ`&F+jif+c^h*B0s ztP_&Jb6v-_U7v)VFeD@h0^eVa*^X_Qrio^(#I(IIDTc@A^UI6V*$&1C}YF0*p!1Je{&WB6_T9U;UyVp>XHR95>zg;%)66q8 zD`07!#z;lPyJZQxqE6sin%rvcKi_(~x$$`Yi+guBn(_Q^@BjVnlpH*Ju4U)1Z(pBR z#89nHR#ippnVK0S_4sI9=ZttR!t7X@w7-r0j~=dnasR=V+P(h%Uw^+YjlCTup1pdr zI4wiV^5ddc@X)m!FU0u;a-PGJl(WFrRaMi~*4~o`cmMFa-`{y=_P+k{?d>#dY&C+T z#dqJ#d!C{=yg%-9U)LR)W-)PtxSpQQs>n4gpK;Dy^~U3VkT@n}{SkuB{vv}Ag{nD;|Xb@^a2;P&C}?tV*_4|ktEez?BA z*>Jiq|N8B#33KdD@91PU$T<)Nh=x&CbR$P@N){^+mVm_7bUMhHfE)#COxrefS!%Zq z8;$+l-7lX$wa#we|9H{a-Byb8tBa!3VZGt7Ai8YPyzX&dYqt%;%PwamjEnxL7x|9Q zvMlyZO}8A!G7U}B6j_#}!^ZYzYxMnp-d_jLx2?hD`G|)}H7G)@ZL)e?$DZv5Vc-I} zahk@V=aHm07*+{!#R%}|yHIEVyQ*fGmZ7v7dpkQj&1CWZr<<;{(~gJ3Jc^6qs0eMF zBss7WB~f51s!M@h&Jzmjl4>-_C+R<7b$<(v~C%O;IE*|H}`zrzwfc zDr0ePGAd%q7_m)~7J0%LC5~Y@0Zn+CX9UIs>sr;+szYkt)e8RxTwJAQUs4M#(=sk?Us0PahE9#J=+qtng-s2 z5#*)d5JlDujN3Gg^YLstJDJbV&dyIyrUN7hx444{0{Qkz97NM6l;>%8I4Fx6%)!$n z^h{k>T8BbftyWtG-@tshqKo5nq|>k|kGjXllaq_fmzNh;^V8X|s=5gr&X z*?3eT2EZ{PKA0AKiktytw&Qw1$YP$BAg;PEVw%Pv3CF?}RfPU_8)r#va3`$C2Hbz& z^8?SLjF7ZU6J)nPnw_4^juEXf=)DA5;^j%slDsX5ILP;d5R8vN@jOq3BoQ(Wehz?6 z!T<2U7K_n4AV1gjv49eM?fuqGdkBVqur48U)n?*&@icAYh*5c~SOy zRbAIr50wWb1PuV%@?7lt02xERYF*@G7Bz3;G>9&5U5!_ S%T8$h@cFUF=f{zclm7$VQQV9G literal 0 HcmV?d00001 diff --git a/captcha/data/2/default.wav b/captcha/data/2/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..95b9fac576d845e0e585547b0db24947341847d7 GIT binary patch literal 1991 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 ahUej#`+)eL5w`!y^{hrQ$Z(KIf#E+zgK8T9 literal 0 HcmV?d00001 diff --git a/captcha/data/4/default.wav b/captcha/data/4/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..ac7398019a15b9df69896c3e4275702eada15b4a GIT binary patch literal 2331 zcmY*a*>V$C5EXCaEmiq|^0a}{5TW`1fbkFaT-RIuE(Q;K;<-3jt%&jSLo?zKBe=wb-lR*s#QE1u;^d2vU?Wx` zu;La=Qn`9A^!nt@>L1{Ub72^7!H83GhKp^w0jH%awn@^bm5`wEVum><+jKyiL_*LH zT+-|^>_ZeUG6(G#eYRTrKK!6vI>*_C2A?@Rz!B|3Jn%7t0$B1rhRwipu)+<<7#-mS zCYW?#l`a;-V+NkpeIUu*FrZs-22RE~!w7TOAYSh?s|ZR+9)g$r;XLq|8~U!pL*nvm z%MHSS;m)`waWTf|3OIr=gAlWAc;^RUoaVz(G02m+PZS7N$eMabYStUgX0yI^w|sYF zeZAbUMvq<|pFBU>8zxZ@hA_x%=7m|Yvpby>SsX=C=y6L|6ecn8 zw>Uog^zQk7&NNjs;W%6g)A4+Hus4pGuIjeePx_(99NRKfskXVXcJtQS?Yk9)kB?5y zKAk?E#b!rRGz;PK!+0=R+`qp+iJh(_bqyZ&AF2wMs*E^XXzf$pfdS5_LOryVEd8HA4AFJ#>SRpr_+PO!{xmqax|$?tJYge51|UU zA=k?5Yik>u4L#g_bn@}+-OIxXylFJsijIIJ#m;m(8OB_fn~iqY4Dy}X{N6YV90Q5g zdxmM6mSq}1M7vq9B0807Rc85v;}7TWp3Wn^QESQuaO(L{zH@JHZ=5)CwY*vDvM3)8 zkeMt^;t04vWyEnm;HK8?bX85$)Q%#zTL@RZR@vUFTlxLhXCGf36&9RRZSH%H<7d0~ zj}CVGT744>GXIqp6$&hxsTYjrLJx{j5~(jk)?JEQK(e5H@B*K z{_xfLr{iVZYqfPA#UY9;-q}Aq7Ik}~>%E@VQ53i@D{@Qn9=?BfG|Y!Zg5Jb= zJQ}4@Ix0fPLKxA!&}WbZ%L)2E-T>@_o1ekqBFflBv2dEf23;-~OVf1tq zgVN#CKOgU9>0~wv0X5_f2uSiGaczc{%xs7IfsY>P1`+iRtdI#mL|=AL%_cl2btVPB z2N+U7Z4;5TF{i;aEH4`klMrQ`r)i$&84+q4tt^cCaU2Eckn|Nouv}ylfkIdqwJB1B zmO%&y83N`OW3*4XAxxu{dXNTDsDW|c^TU1w#b~rinx=`MGy}*1biyX=iiA@@necN} zK*E1A1nn>mqyirt?H8aR93WxBKf(hfffNwAEr?tYK%%Bighnm8J&iPjRXFMs2+32S z0ZO0^=DsD`Bv8`>BGwB-^ab^x1D_QlgbrFkp9eZ1PY8A}L0%FGJu8<9k|Nlj{T6o+ V_Ym+zND;{|zi+2st^Vip{sR*`d2;{& literal 0 HcmV?d00001 diff --git a/captcha/data/5/default.wav b/captcha/data/5/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..6f4b9a7c5cfa0133a8bc83d02e3ef3c85aa055bd GIT binary patch literal 2674 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 literal 0 HcmV?d00001 diff --git a/captcha/data/7/default.wav b/captcha/data/7/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..96ea53baa67243642c27b1f98ac0678949f84c79 GIT binary patch literal 2789 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 F{{SCvgXsVO literal 0 HcmV?d00001 diff --git a/captcha/data/9/default.wav b/captcha/data/9/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..2ce6ea818aa282c2ebd9382b5c49426890910328 GIT binary patch literal 2385 zcmY*bX>T0I5v9K+-|`QVFZmw{kT@0;fr@odBA2@&_uwAfYwmlddwTBKi+gZMQA<;% zZpm~aCyo(AHjn`MTY0^Va@1gY8Z*;fRj;aE_2)M}{q)99H#W9@egC($w)BgiZES3O zg6mg5-&o(DZ2V-SvM25R690Ja`tl&xGd}*$^gk~h%g_ze@%%6yPUg$gv(@?e>g@5! zVmcY7ap+UebsXEa9mgevP(nP{Hg!encUp~uYNfo-rBbQX4i4(gPG2@$mX2m8tBcF$ z&tJTFe))8DvX~5#fH=0Paan7lK^P@*6f(~?6tUZC)b>leI}aZ`c<^v%w^-V*)LNqM z<@4j!%QtVXuHL?T`~33Dv*Y;~7TKnu%8D$hs%F}@=d&P=qc{o}!CpeQRV(im3x%DX zLb144t{xo9x*d(Cr&<`Ps=Ro1QJRFdd|fhH+qPHuWr;rEwgm zX&A;KHDsYx-Yb<#g$MU;e|~TC5BD~IQ#kwE*C&I;X)Idv)$w?=T+NdpiWu?3h`BZb zLO3W{p2vaDsHMnayIQW6cXzh8w(j4#yLs!gt>xdposl3Xhtm9VH4gJxYMWj%h<%ns zp00a7VL_N=Nr14~mSw=fZs+g-rWA{X?ZR#|e(}w-TVy^-?z+50ZSo98t?*VHg2>#wcYz4VWK> zK^VHaqB_Lr)Ea_xSl)Y7EEP)5>knV0we2PuO$Sjj9Ouk(!XyrZC=QUBehB<|7^$Oc z222;b?N+^3*)MHBsK!?xUX$YeW_&V_NiaOhspC;-jM6MkBVy_nO^3rQuvJ+#Elunm z9>VY1{`TF6>dSxpbymOqP(S|S$TQeFMKP5G3%_ar`)94EgC9ima3DXg*1(>#@-1n`oLWpr)IRTD5Y}sFh2*g`$7;?W^Qq zUmjdMNn!XPkCEI2v7#RFKn0d=1%vT0p^i&~C;-8jilk_o*lyIDhwVnCdeClEVNm(# zhaawz@~$*~cAoiub~I$3!?MtINRar3)a|PlMHxqNmW9M|{U~OZ4ypjt2z>z4?sPk? zgIcrGZ8yrLO3irn;V&z#(vMHihb+lQIrXSdiD3oFAayiF(GA;mT@pqCbsdVlg5SPt z6V!!inmoPweOXgwp)Ux%cB^&R1r;;BBu&QS*hj@BuBOv8Murnx z>Gc#FFvfwS>0T6vj8_0k$43b{mZq%JNRnhpkfc7g7lckv6ndSGD6~7|^`BQ+n2iG~ zI$F*`nx?*Ex{MLRLINIk3{^86P6{CfvB78`c@DI}o~ov+iYf|1U&bg(VqX;dk}Aux zBrB4vLd?;{`SN%%%~(7+%F}d^G0LcIBR+^5@f`RrNd|%!C253OMIjLv3P9?*p@W|F z^?rgNOTC^Xb2S(-h+Ickl5Omm&lZEp>2f?6Plic0OgI>DfaA+t%OjQ!gbkDj0hIw8 zAjBB*mLOeC$JI5^{KWVm?tWC59t5fBgt z;iV6fVvg&A;&ek(4a>B_Jz)E|sM=LsQ<`S^}9UaOPWPVk_M zLLclYh)|~LhG8J_Y~D#N+`OOi6}n43HW&_$7AI$`v$ONnK~!F!cY08;=rND@Lktce$)p0v`iT;;g_A9*~buK7)QA9S(U1 z)dM&^00F1`6cC_aano?pSf4dGIM+}CbY87IF@b`z7W937h=6nW2{nGL2$PRz8tCHJ PzaJmpu3!E41E2j1zxa%U literal 0 HcmV?d00001 diff --git a/captcha/data/beep.wav b/captcha/data/beep.wav new file mode 100644 index 0000000000000000000000000000000000000000..0e7137517330038a097d267a2fc0e5de18602245 GIT binary patch literal 940 zcmY+8*?O8l6vxTen_l(}+DBNh#Ih{1c9&=W|+YV0%3{b7F=tzdCe*= zX*tZC?KkItzJ2}jW%Gujeti1=nQ6%%-cb~Fv9piwsq9=(Z>btB(`d&ags}x7g1VyN zAa;RfARsj*cRCN0mJCgyeiv`n-Yp{lDDy_LT@tRsL##`1xJhB{n#T^*?9uO`c3l*R z-!aKx9*c#7=sk8V(w}&(%aR%oePl-o;c~P&NJE7D&|>p9b~=xMNnC>|aPD#$8mdKf zwk$-?D_;=}to^)Ec8ZSBR4u*9nd6r^Zq#MVYzsL3^JL!CB#e|hGTjW6GA$Eg=-qS` z2?bhlJp|mz%;hd=J&Xu+ha;QGRbi5JEvMH5)f`JEV-MQFgGT3@{vvfv*mV@T*pAn; zuBO|zT&<|X?UYCoKr+LE^d&_t-mny|*_pqLe$^Wq(r-m~x$VmpR