From 874ca5e85e7caee8acc71a4303f9c5eae500e1ac Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 1 Mar 2022 17:17:56 +0000 Subject: [PATCH] Add RS41 Radiosonde (Weather Ballon) demodulator and feature --- doc/img/RadiosondeDemod_plugin.png | Bin 0 -> 9905 bytes doc/img/RadiosondeDemod_plugin_table.png | Bin 0 -> 38185 bytes doc/img/Radiosonde_plugin.png | Bin 0 -> 87172 bytes doc/img/Radiosonde_plugin_map.png | Bin 0 -> 400232 bytes plugins/channelrx/CMakeLists.txt | 1 + .../channelrx/demodradiosonde/CMakeLists.txt | 68 + .../demodradiosonde/radiosondedemod.cpp | 715 +++++++++++ .../demodradiosonde/radiosondedemod.h | 195 +++ .../radiosondedemodbaseband.cpp | 176 +++ .../demodradiosonde/radiosondedemodbaseband.h | 100 ++ .../demodradiosonde/radiosondedemodgui.cpp | 898 +++++++++++++ .../demodradiosonde/radiosondedemodgui.h | 155 +++ .../demodradiosonde/radiosondedemodgui.ui | 1116 +++++++++++++++++ .../demodradiosonde/radiosondedemodplugin.cpp | 92 ++ .../demodradiosonde/radiosondedemodplugin.h | 49 + .../radiosondedemodsettings.cpp | 200 +++ .../demodradiosonde/radiosondedemodsettings.h | 75 ++ .../demodradiosonde/radiosondedemodsink.cpp | 576 +++++++++ .../demodradiosonde/radiosondedemodsink.h | 143 +++ .../radiosondedemodwebapiadapter.cpp | 52 + .../radiosondedemodwebapiadapter.h | 50 + plugins/channelrx/demodradiosonde/readme.md | 106 ++ plugins/feature/CMakeLists.txt | 5 +- plugins/feature/radiosonde/CMakeLists.txt | 60 + plugins/feature/radiosonde/map/ballon.png | Bin 0 -> 990 bytes plugins/feature/radiosonde/map/parachute.png | Bin 0 -> 29710 bytes plugins/feature/radiosonde/radiosonde.cpp | 327 +++++ plugins/feature/radiosonde/radiosonde.h | 116 ++ plugins/feature/radiosonde/radiosonde.qrc | 6 + plugins/feature/radiosonde/radiosondegui.cpp | 857 +++++++++++++ plugins/feature/radiosonde/radiosondegui.h | 155 +++ plugins/feature/radiosonde/radiosondegui.ui | 444 +++++++ .../feature/radiosonde/radiosondeplugin.cpp | 79 ++ plugins/feature/radiosonde/radiosondeplugin.h | 49 + .../feature/radiosonde/radiosondesettings.cpp | 149 +++ .../feature/radiosonde/radiosondesettings.h | 70 ++ .../radiosonde/radiosondewebapiadapter.cpp | 52 + .../radiosonde/radiosondewebapiadapter.h | 50 + plugins/feature/radiosonde/readme.md | 55 + sdrbase/CMakeLists.txt | 4 + sdrbase/util/coordinates.cpp | 318 +++++ sdrbase/util/coordinates.h | 52 + sdrbase/util/radiosonde.cpp | 710 +++++++++++ sdrbase/util/radiosonde.h | 180 +++ sdrbase/util/reedsolomon.h | 650 ++++++++++ sdrbase/webapi/webapirequestmapper.cpp | 14 + sdrbase/webapi/webapiutils.cpp | 4 + sdrgui/CMakeLists.txt | 6 + sdrgui/gui/datetimedelegate.cpp | 36 + sdrgui/gui/datetimedelegate.h | 37 + sdrgui/gui/decimaldelegate.cpp | 35 + sdrgui/gui/decimaldelegate.h | 38 + sdrgui/gui/timedelegate.cpp | 36 + sdrgui/gui/timedelegate.h | 37 + .../api/swagger/include/ChannelReport.yaml | 2 + .../api/swagger/include/ChannelSettings.yaml | 2 + .../api/swagger/include/FeatureSettings.yaml | 2 + .../api/swagger/include/Radiosonde.yaml | 20 + .../api/swagger/include/RadiosondeDemod.yaml | 65 + .../code/qt5/client/SWGChannelReport.cpp | 25 + .../code/qt5/client/SWGChannelReport.h | 7 + .../code/qt5/client/SWGChannelSettings.cpp | 25 + .../code/qt5/client/SWGChannelSettings.h | 7 + .../code/qt5/client/SWGFeatureSettings.cpp | 25 + .../code/qt5/client/SWGFeatureSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 18 + .../qt5/client/SWGRadiosondeDemodReport.cpp | 131 ++ .../qt5/client/SWGRadiosondeDemodReport.h | 64 + .../qt5/client/SWGRadiosondeDemodSettings.cpp | 582 +++++++++ .../qt5/client/SWGRadiosondeDemodSettings.h | 182 +++ .../code/qt5/client/SWGRadiosondeSettings.cpp | 275 ++++ .../code/qt5/client/SWGRadiosondeSettings.h | 102 ++ 72 files changed, 10938 insertions(+), 1 deletion(-) create mode 100644 doc/img/RadiosondeDemod_plugin.png create mode 100644 doc/img/RadiosondeDemod_plugin_table.png create mode 100644 doc/img/Radiosonde_plugin.png create mode 100644 doc/img/Radiosonde_plugin_map.png create mode 100644 plugins/channelrx/demodradiosonde/CMakeLists.txt create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemod.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemod.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodbaseband.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodbaseband.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodgui.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodgui.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodgui.ui create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodplugin.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodplugin.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodsettings.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodsettings.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodsink.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodsink.h create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.cpp create mode 100644 plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.h create mode 100644 plugins/channelrx/demodradiosonde/readme.md create mode 100644 plugins/feature/radiosonde/CMakeLists.txt create mode 100644 plugins/feature/radiosonde/map/ballon.png create mode 100644 plugins/feature/radiosonde/map/parachute.png create mode 100644 plugins/feature/radiosonde/radiosonde.cpp create mode 100644 plugins/feature/radiosonde/radiosonde.h create mode 100644 plugins/feature/radiosonde/radiosonde.qrc create mode 100644 plugins/feature/radiosonde/radiosondegui.cpp create mode 100644 plugins/feature/radiosonde/radiosondegui.h create mode 100644 plugins/feature/radiosonde/radiosondegui.ui create mode 100644 plugins/feature/radiosonde/radiosondeplugin.cpp create mode 100644 plugins/feature/radiosonde/radiosondeplugin.h create mode 100644 plugins/feature/radiosonde/radiosondesettings.cpp create mode 100644 plugins/feature/radiosonde/radiosondesettings.h create mode 100644 plugins/feature/radiosonde/radiosondewebapiadapter.cpp create mode 100644 plugins/feature/radiosonde/radiosondewebapiadapter.h create mode 100644 plugins/feature/radiosonde/readme.md create mode 100644 sdrbase/util/coordinates.cpp create mode 100644 sdrbase/util/coordinates.h create mode 100644 sdrbase/util/radiosonde.cpp create mode 100644 sdrbase/util/radiosonde.h create mode 100644 sdrbase/util/reedsolomon.h create mode 100644 sdrgui/gui/datetimedelegate.cpp create mode 100644 sdrgui/gui/datetimedelegate.h create mode 100644 sdrgui/gui/decimaldelegate.cpp create mode 100644 sdrgui/gui/decimaldelegate.h create mode 100644 sdrgui/gui/timedelegate.cpp create mode 100644 sdrgui/gui/timedelegate.h create mode 100644 swagger/sdrangel/api/swagger/include/Radiosonde.yaml create mode 100644 swagger/sdrangel/api/swagger/include/RadiosondeDemod.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.h diff --git a/doc/img/RadiosondeDemod_plugin.png b/doc/img/RadiosondeDemod_plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..4998c683aa1b1ffd60349f6e9b34e2425dfd77a6 GIT binary patch literal 9905 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 literal 0 HcmV?d00001 diff --git a/doc/img/Radiosonde_plugin.png b/doc/img/Radiosonde_plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..f7def98227c8fba9394f327635faa7357bc6f804 GIT binary patch literal 87172 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
  • b zDkr)Gl{^cqSx*i`!ER##_0P!dNT}J0we>r0qsD7tvTK% zd~BIfg)5p6sh+#vwsxAv{knFqp>MU!owh}D&l|?xzPjBs_lH4;-t^+Pg|MS$Lp2?= z%)S3Vd;h`ZI+h@2f-;>CDLOtklxXwESqa+S%DNdv<@r-V1;ra6vLi1|#0f(w_4j z9tLndF7EvT057s!GB2b`QU+6U6%|A&voMp8U>}wy?|76?&xvA(v%*<+l1Vq%{|#!>JvVSE_Z3LT_13bU66v>ypq!uYyRkckuK*9Q)0e`E=TO+|9iQp6bS?@889_wrutRdLK z*WrtR+AOdxU}N@3Hv59}+&X9V#rCdh4`dxarOwtnyt4#92doHw>2T1o znv7^soKXXaHZ3(7;M|-+LM#ftImcPxUWMy#Im?{(C8f)YE%?ep23|R<@g@bjklKc? z2y~yg(!22e&9jUObtAy(Vl>Z2u|mSNV)jMJDqWBPi0)HGvXKc@qn~mlu2tx;;sXvHI@K5921a( zxCW4JIS;gxPso36Gy5yC{N+5BBx%+(tWi(vn4+PGby3tg;8iq_u>vNmgjOf@1_`7} zH%PTnQyQe)AQh8VZBDXSu1+#Km@;X>VmO0hbOPh@DSRhc*-BNml9kN_wvn!Gm6&8z z%92`<1tMZsWw;_}4KCf}xCL!sgjNJ_b`{tR5D|dXfeQh^Rig&1Hsk={i`1pKCP7;j zvQdU+W0q+PW9Vk}U! z9wiMJu3f8{Wu{eChK$swopjvCl1RQoxDP6EZCvOQQlFIj&X4H^3@9G&yv@dWPzm14 zBkRDlDsa_P_x(2T4bUV|F4g&=pX9u$5a<+Viz4+(MJg27Y?e;t8Q@--9Fxvc$s(7nDkZuBU-=9l5p#Yr3BJHJEP#(%RnWq6 zhf=$g+M^mHu5~DNkJbJyy?;vs->qHV1dKRi=)xPouApEE^&Y2pSiQ>`eW3{-v8oS_ z8t!Lnq%?p+wOADhlR*k~0xrSt(x?e03D;a`u~4UgV6{1S@hW%ys;UYM5~F}^H>$Mz z*{CuN=NU5iUTQ{a!(TxHln$?SIFJHJ2c!n13Nfl#3N_7jCN>jb5^SC=0lY+Jfh0SV zGdayfL{=u^C?2c*=4;|K%Mr@j!Ly?px30^6s{Qxw065R38&76u`Z-D*s7|D=Gl z-pZV(asiNbUJm3aPw;!%+L#O%QJfW1bAM(l_bWTOFQkhJlC9}=-ZGSysn~U?A#(~t zu$3xZJnr+T#^Lmp76DpWZ1%r|tm!fonP_T+vEc3Y%n<;|1pH3F( zBraqrrAW&8nv|oI0;`ur16P_grAbOwRkW(kvQM;N6Lh`Inia8C144i+c}&hy2Ij18 zKq);&>d|740;0n-s}wLQ6RR2JYNJ%q3ne8BZAnO`xp+a&R)K8URi;g{9m)|bg6q`y z4ha+ruG{43m((SVJ;6Sd!KXfCfyPN4QfSwB_ez-a9J_UrT%&PMW9iT_>VJSi@QFZs0WevVA5CpRcxTZXOhakK&sP<`X zz<{j5C;0CESs$_1zSugF&3yrU*MUk7;5rC$n--fC2cKbwFYsZVclZc4eEv*oGaz@? z0un~ZU8X)1fW5)T@Y|FtrXVj7)CFGTgAasB9m3e-+9yiuSh5cUV~?$mXsr)gnAG|p zI@cKT4ftwpLF>VV^39>x+Ed&6T4!IgM>4#W)nb5DnLW`3*cI#vdX?31N-o!=60KE$ zTB&WW-k0PyOX+w`t2o-kGH?xdf-^~}#i(8QI%o);m3hj+DQKAJwZ@K{{mxz4U^mwv|o7B|Q{9UK+ozFPRL_4C4H3bC; zc1Ga%RdfiBXmH4bgPJc=lklE+g~NMM#&|^yZbt@gggHaD69Abr7A7*80i0cvtbIcB zM*t+)6GNby5uBQ4U%UYUUxL*~KorU+lHDSp#kgq3vVzocDQ3A2670P3>Jll&nm`WR zav&$jgviNz7U1}^k^P06>CfLxUM*G&qRQG$V>C2JeYNFYtP&)hm33OyNX0QKMJFT; z7u5={U>rcLuo{HXaZ<%_saO{BMJ`idGnkmKDn&}ixCYJ}Rl%r=fJQ~AgIFa_E2$P? z_E@c116%kyCNwIdvuvi)BBf@Hx2mLGEQ=YkUILaQ05<}LWaDfTUOl4h3SpKp9bR)v z^N9qr6Qj3xs4egrr?(SqEGwi+YTomzCIOehY!UGCRSPbF=|04*kGOgOun`)Ss~xQ> zyx-@n?F7V2?$i3N(Abyi`=YidiUXDfat2(jOL0Ah?=!-H6^Fby;J6M&1A7An?ofP5{*RrKrx*648og?py`}Do6brQ5On|% zyEPWxJT1{ynX$^0QK~hHlu>5P3UD%DW_lkcW$sGWu55wNkz@@ey~C<4+UkqleI3x= z)y%G-HQ5Gy%v`btve}mmhel77nhXt$O2q(_UIjV@U`;CCe0vINqc!{j26FG&#srs4s&`&zRgfdm%@9oNPbKD*%n3xn)B8^}N$7@)@^ zI5HV5fIlGxKxV8Ux*Wqj{|jq{A;q@I(#~JlW^70gNj5*_+wV-c0}ER`%E9`5PsoD9D^;shyTN zXg7zg-fp|yH>{S@Y|Gug+U+ZLi)&bv-R9bT$?ozExM~r_HwfpcsUi+UN-6-CqJccw zq|&DK9;;8l$dtu||ti3>)BH!AQ4gH~09>n9O% zo74xuGX%Ly(Pjm{V#O$v7Dn4R_^i|mMKzm~QfVQP7Lyq%l@Y=BWKPatTA^lC7@OeR zq}*fl5ij={9!Qmqb4>{FC-=vCtaH;4{+bW|pbv*vah#>6fX4u}avy}}L9nK?G&y_^ zOvMp3xGX!{CV@rqUD^eFcm9N{Ly27)M-AaqXpB|C)qFunW!XfYPvTku)PnDjQjeBE9ecFUCD|6N7YALCpezj63l$YE zQ9(A!0=#Pp*L`sAKaw0cE=_n?CA$WH@(EwFT@@Pe#oLUEaXKzGYM?);HUobWXi-X& zsXNbFf$yS4NjB}?6I8o`IZ``^M(@aM@9Wl3HhO{%g4vXF-w-a~uJ_;-EUn8ca6wcy zWK==LnP`gh-P?|86G~KWe9wS?hPBDd6LX3TE3W87 z!Y{%&&8Z-{tO;cFjDQTg%LB)HWL`NVfhpvZhf@WAR$cg#!CYLC!OxG)%>8vN&rU6om5-fskV8D~K zHr41dW}meNoJ(sYb`O;9feP0p9|}s71YQNCO0cR*o2>U)y~n6sxE6qSjR)QcbDySy zSFIessnAUvP_r220;UvjwOG|kF0@er!GP9) zqQbXF!`CgtD@5?tx~HMEJ=006t@G4~0gL0Z9QgPz)eg z9`G$RpczH@6c=2GfvlIS8Yp%Ft{o58;)2VciXiTQ1E1hK2SNgz*GoIMHA#5;621}< z{;EK3Q!4x|CpcI@2WzrT0iCJ|1zIixsnT0qbEv>;S3R-b=JXb;H5nDqV)YK!=!x+1 zRbR43>fprQz0)2XTb=znh|=irK*d06D*Oo{2npIp0@VBA=crJ9afHTEAJm)zEZ{wU z7>6l3g@iwywXRGZ(IA(Z?&57+*pp6Wj@--|bi4q*7@>p{pQPr-aw`%H?=TJ)B{2M* z8^{&o0&hr4N7X+E7gCHUWh$M)BCcZvqCjR1$%nLU%;4=ym z@?r@#%L+`A8Xpc&BmX-j7-j}YnrFr9s7ME18_4;-B%6T3XW{QK^1rZ|{oGdO&unMD zkSlN3=p4^iREciLf~}}+wcb&Tu4r@xv&&mu&H^)ihtZog*{JY(nN|vPEIZuKEKeKDRMQ{dA zH=G~n0jV-DU`xQ0+#71prN-I>KEZeQmY?QaUNZMZ>p+BSJ`EYUO9`Nyz*Iny4wde0 zV|1^%d%v}JzumuOwt(~;Xx+p5;KbMi+wWM-Jz49}YKH>y#F-c&XGyIfwFsp{(v4C@ zN|%LHkxSrm2K*^BtH8SI@PZt?@z*?5I>&nJNV5-=#;&OJSg}n5q&8h22==~ekKf9t zf-OA`H?lbIFzCi%BG6#}5kljV6TDy9CPX|T?FK9KHdYd(Rf^+Lotao{!R$3># z9#uqKd;#+0DP%%O$WvJ^;+dT(Vo0Yl(W9|*1kD3}_cdiT0%-!KOH4qU&@lz#jZJ8* z0MW$95uIcMAyKC1>*hE`2*$f2Auk-KJji6TAd~7WLulsnIBS{<;^%TYXbD4PUbvo# z=oFg5MS<4NEnyU(RuirVP0NV_BF$Cdt9Q z+r>KTmGgELzN^@*3KpTXfT(fS5WbZGCN4B$e4FB0qySnBzI_?KfZ2H{9(R6bh|vZ(SS65PNlX{`B={t>g0of@kVV4%At7ie zAfRfW0UMo1rZDgYY}fkGs6c{Zn*u4zU6yZ>RHH)ZrK(;cjf&W%8haA($l*P^d8o=z z7U9}gpr-afY!1ZMQ0|V@-mV5{0Uv5{b&ILn0M=*&3m2hX*|ccXT(1&LQnDzu#Wi|T zb64vg7@hsPJycpCk%Ri+(CF^#)XA?f;hT^x{G^94=^q8Y)*HknSmoR zG@pg8CwUeUB;p(>6FoYW=_yZ_m{}mBPY9TfpKKuUQzM?v)KL`)a{-J;bEGhlDFhOn zAS1IE+~Nd7(piK_7A{EQ$lk}rxKzkI?EziHVO=`qHS#PbS$nM%B$Uo%yHn0N!1AZZ zz%7Be^9W|QI7lKMegz{S(Wl}h;z-holt`|iMSKE{URYo<2qS|HU7A-YNrAg{wGVTNOV1ZQ0 zO@ajyrWP2z$QdQ6iEABFZWCe?7h7RnI~PB5#KQsm$o@g(@O zwI}zF_1!z>{{80OJ$rP|?84PP;d)mZFu5+M3%o)GAAaw_pW}hN++r~94-%cn$=N1+ zJ&yB`6I@lxc`q_hD`xzTWLf~qQc{TBC$1*@BqL3rPU@Qj#;( zdIA2JyrzC+C;4Z*Y~P8@0n)oss!Y9 zz!`fIKc)|(j(BCnn@39XmS!Hxb>K11%|ZA}H|ISqe6vb6N;RM$ zTAt7fWF5Xq25zYr0VDuORinh17_cs-2e0k`6Vker+MyKqE@VpU(0bQ-g-e$OXdMQi zwrS45Yig0HV{)rzj)dVI6c9LIRG>)OkQKW%+QLXj zK~c^IjXuh(q=i)*#j=_$ zDVd_227vEi3k^~R%?NUD!%wkC0vQErC3N9Z5zbTU1ZCsE&)~!LJ;uWkIQYWpCVW7R zwW}a^zFBkEd?)K=rh)M$&KVV2E3rD(=&->3xXsvjer#eiAc|S37C^lSdvZ!8HP{-gIaLJ1fU_OGl_lyASDbjdkT+&PBYW+ z=FWBDPR6GbDrXR+ctMbmQM`~5DM>%?5Y?$wjcQz&aHS?KFfK_Hr)<94LEN$hO6U?S zze6Oc6>ySr^19~d7|0?>B<^hdW?6(u`YRC5_ag8+_H2-o_pEsTfQ?6rv-xkhF5S*=Zq7A}|- z(W(HKQrd(L#ia&Z3Vhc4wBDzscGY=_9?+dU*(fkpnQK;98)IyYGT{w7zC|?lg!V1H zf6pAe+O&>TvCj}jIVYylT&w`BLd#)#zM|)GAY?`f=ml^Hb;ttEg4b-?z;dbp0j_`r zSB;WDso;w3Ro(^wy~C9b)fjTtuGrj{+XqVfP-*SU)<`r4aCP!}pH-cONx3Gxw1cVn zvXU#y8KPbUi36WA52WU?Y9GnQfne+ljXl1xFBk_R{L?`lF&wBStW*Uk7ceUL=Drbc z>P^!!#<+vZ5GiR7fB|`1NeFrC6GuIB&jfCvspV4PXa__XbzK+Wi^~Z3K;=|py7k~W86w08J#2UM71jZ zRQLFSv!*|zPk^)jw4(Y|nBYh8q#=NtPDH2B6c!;=PWR6MuBk+E3NVjIY11GzFS~F7 zT-@zT;N}v{Xq@$upe0$HNxQ9uVC@zIDbK|a861`a-uSzj9RvOZf;Dz5_yuf%rvo@N zj$Nfbzm@)_SoYUb`Iqyh>lHl3G8J8>OpUQr-d4nxqO@hbrx*jp97slwH+rnQXoA^g zv?d_~Z89*yz?5dK-enwU9Zb@#n$jec7E~y;O#rEqTUB6J0I;RervZ*yQCg2uyQJI! z-s4`iax_aXkoBU{qusaZ4e#6CTMaPrlklZ9g_4p1MwORRc^Qx{Dw(pD1zts3@ZuKm z4}DKC4yF3Opp7{2r`QD=QDtqMwlK;ldsnR*CDy9A??SE*Irvcg2tE-7{sgE!8i++z z%~!Po(I^uJR&|zZuhfeby-;&A8nPgl)-BCCmKz6xGNkynyBt)Ju}eZ5m-{uj2T}T@ zHlXT5#@OZUebL+#fXV577Osx~pVk*!-V6I=8@}{LHg+X_B&xu2`mESsw#Y6H6~^A zTq?&Tb8O0aXJV1DaK2RoY6Xl6UP7yv!50M_$03kE_cxEg%LxEv*Cz{S44rNjL6GTW z9>`qf69_X-*3J6#+%J-G6#}{t0BlEG3V@`r2!1Z7;)_%eB#aN-8!WK5-OX#<{{ElK z;Ag!c!BWj8*cn#DDIQF1dX+B>w{4dMsmp}{2R%6M<)KvF%)j7K006-n19m~jdg&$z zpZ@Gd@^hQXU))LkY9jp`+3eMFVVfwYm}*(38B3IVnm*8skzVi1YKI5&sMcY%HY1t@ zqm={$S6igs0XhYZN^TO)x(S$QVUk@@T2vjQ z1a_r#Yf_uwZCq;Cj1k{HQsM6b_Z2X^gE=0)Vh^sp1aEI~9k_nFzYKcSC>E7;nvW&f z?IgRCaxP_6fN9wn3v{hp1L4_r6##FO!KFJ%wpn#9iIphly)isoHIx)P@b(-7d<&@I zkdvGR2uL7U4Ghyj7P-8XDJeN%SCowlzz9d2whK`PzssQW_$sfk>5vWR8iY$juD3UE-5fB}>)e?*!Ej?Y^J} zW;SyNe$rdIx~SQNj_5?$hj^Z{4Z)gp}1#cl5EH@Ts&KvO!-UU442M0>x^G;Ba;49 z+)R;;r{WbgN~lP42o3Qb!Kq^Hga`L0hjGOnC-9{t03uR8lXhDiC!;97k*pmjeK+4_ z38WKg6OUk+CGqPXCemV4af$~B7ABC$QlR|-5YFiQ3Ff#kNSV)*w1fLS`{MQ7FK%u9 z+0BhVpWL}pNM$&jG6kWdh#gsMi&96ByS&h(*aptl;R;o1i_*Ka(TDf`8a;Tus?md& zqs$>=k2q_@83U#c6r@dvb_J+abC>TN%H1P?0(Qxcc!4kWE^h%wd~;81AILUvsU9Q2 z%OoT~@3YpvWF1KAfN@?gQ}Z6phVQhg5RGD4$&}SB0Ml~twqV1NDj-tb8t^Ir5G=Zd z*Q|22QG^%}!YI|u5^0qw8v}mEIu9o?ErM!nmA`w7^6%#N~}>9n$^aT>)oo4?pdRI_TaW*?a3g0U{td6Gecl(BJigH z3oq=s3#c}$Lc1n)X>AB!4qYGda8-*o&`r3I63PBlPL5XDK5(yt5l)hIIXQmI#&_Q`Z7)Mznp{&;i+9v0VdpOWC%*T)A z5NVbmXyB;?%d;TC&VbJ!psnUhd;cucQph>JV3lgxIUntukSiaI<6#XlukacR6baWQ*21 zglJ)0qX-bpGT1vf(fY?Ka4E^IXi%zvgt69;2WFwd6ZFNENuKFIDGSr&?fvlWk9w_(_J+b2ovxmU`rL?RlvI32eW{9@jX)A zKFN=MK>yYprIBins!iT%r7D-uEqEW`wLP5-C*<^-E6opJhDFDw< zdaSvpbZ;4hyEeSev?r@wmNl!SUWSXN>X=~FfHT1b=v%bhq?8t|wi)M5#;QG1^bRZ8 zq}-xFED-(V(cu0&`*+{oz5V9kpj67 zgr7`b#hIckZc!1lfgoWZ!P|MruGt{TqJ}h;h~J0kTh*XLqaYIlIemViL3&s0x~lNiA*7DWYTn##$1#@A;a^um-1ACwVq_^C4!h! z6gTjCiI#sIq#Tfq0V2g%7idO{<1_`5n$PrBa<`uWB$qJjKh`tw`{ComKMkjoc5uF5 z&q9%cI#qZPQgpuLU%Zij=|;{uv(hi!Onr7U^()EDHN2b=Daw|WVcpy}nukW~P&ao) zwF~BKjI+vOvjX6OwSYh27EG`!YMWFnLaO7UR*`gEHOWSkG26V+<^cCV2)`R`&gk%U zFeSHHxk-x_DVcbq$F}$7&Vgc&ga(+@JCxk6@m7VZ7fCJ87-i@3OclU^jg4XzE)WIR zh{E8#uvAG*;lP}X5_Bx1M44r_iF2(g)2vX=)hQrbe77bI8Fi17hm6o8*$%;g0AM?m z3<{_Q2Vc^R!vzlNC5JL;R2Zu|ex)&MA85PxJGb84z5C9=owxUUC#Kv6Mn%vKoYXKv zDOROCt(66n06GPv3Mf>=S@o*DuMLh2KxbdGfSn8ky~jcNoCfdH!9~34eb))zTa&YlUI5=4ea7Auj6S2b2-&VG&8prets&Pvkb8#;`0VUS&5>X_uMC0`5S|99;JS;;xtq{FSqT!s3is;Vig_7rgKWpJ5lwk!TEs z?os{dVfXHvyN3@t{o_V!S224+1Jtg=`G8{@GAh)K79{WtlaFIRJ|V?H9L3x2n^1sp zI_UNZesl*U38gk3YXW1FKU6JFIL!+q zP}TE@meQOj~B%f<>qs;U*J1_ofQYWJ4$=*zdh^o`fv{>r_FUpzW| z&~5H1%{{eu+}OQi!$+nbbVs+X)}Eqw7_MHS)sotx+ItG1Ih5>y*xpro2U>GiZuB^< z!_<3RW57519PmhEz*!>!U=F!@j|L*eHA=iuhW^wc>m91mrOX~<4cO+81GGoN?n(Xb zYn=yg4qtnF1i1TJ@93_5aLe2~Y3v?1_KuDH6Z7D2Nn{!k=~Gq>vZIWH?$3BzkI$za{g$1AN;32C%Nwi`NsM z-$?#?JhM})QKqg9Y-86lM@GFbQ##IDHPv}*uRi33R!wXX@U<=QS#|ihy4EG7Ce9fp zwgJ}&g})hW*PttODPzD`BVZM@^DDwyy+_r1q}r)!U7~d$?7wOZ@6a#o+ynW z!`l@X#wd|`fz*pav#N9{!N%D}xzVLZw+y94l3EcyA=D-bvr=i4%Z*Y_%i(sV+Qf-w z1v3h`k*Atv0eIUk1=P*lV~u^z*k|h_S{qPe2e=@-kRx^A?MS%vz^=G^zxm*cNB7>@ zAKW(UP=C{$0C&sM!O-ebuzyCiNBsxRKFi8XZP&)7ltd zV9qKPoH^jlA#V)WMvn$91KI}wzMDX#Mto;q0V*76RsA7MO%R6x+K} zYb3UYLK6r|n^MiHZo`G$wI-o93CXGeduZ*6?S07Z-G`ZGg2Be%iMq#Mhris>PLdmC(L8M zeMf2Ru`)=!O~3`TtTNrixE2m{s<|iJd9Cx+uRr+F_rLi4Z@u;Hue|oXZ@%@lj~*PI zm{l&F#5cDqH@5KWHM7*YqZ|8zyDX~FXO$+w)k~C|6^(MeQ!{`mc4~Ty0AHFz&K__^ zm)2U&9a5tzn^naofOr`_#vbwjYsh&&p9DVFA%SZGvYd)9 zftbpz8bI$d#!#@F$Eq4b_}f7E^FZf|KH%%a@SBn&!sHV6qy_MeXPSb*KgTxX>(MOy zkZ0y`Xj2qdaY7S+0LNW?6FL>obru1p9~d11!0kw2gxPUt5*Q8LxNFDDVjjqdzbMWu zh)m3Zsx3&UBvC>+P9bPTOED$)Na9ZW%szi3=im{^`JNpi825YMaWikTqV|b*oR8*cB4MvfS)mX5je-KhpoYp+S(Ob@D0rzZDWL0%1Vg@yOo!cHKT|r8M#YZ z&LUOK18H=p(LRu^5oeG1_P(UH2p~XUV{>1$;0pw4rCU?rJx3hWqGskQ^)#lZI{Pxn z!ss(Vq2TIY&8l-%4_??)oKF>~RhQIyRAa>2`(o!<9o(t+ZfPLL#)#8;G-yD%T?0t1 znqXBq6PH`0G2qPsueM3qu4?U?37QnpXMneXKS9A{c$1L=I#}=0YKw%l;g3C)HYqg; zkPdIbXWmsHUIW1xiN>x3sE<&iLfz;TW(d#>BXP9G3xh^k4-*+$9Hfw|zDxqIiy7ICafXA_@g)Y1eSzUPFmgo+Wfa0qFbWcEIxum66kZg+%%=e7Fl1H^ z)MyPjg&F7KTf)+J@q7Z4ZVW?_!%crByt1v2V6E3mX#DXXY`>9t-jgc$wn6As*HbUuNWOGE_L=KjzZOqs zc-A}`?Z0+=bblY-5Nr$0zSP^(_fG8H+s#|Ak9x0MC||o)ys}fgO)b3~v%U8<($1q=M5gt5=+do0(5P1o2H4j;7k zZ#TL_e*aK?^+8+gl2VUS28=pn+PZ&Y(kXo2fMXp|L*q`3g7{jA1Z zVLBDmb=HV~lKYHzdHDvdWjss-H_pKc563Kja6i*XIvJZ*0!eL*Kg6$yKXolmI0d9U zvlvHr%m8tt1wkk2IiQ7nvhbQ>Szy&B+T<$fEP^2&BB@16wK6a@zvb6Vutt8Fk*+lp zzox4ZtmF9*F7RZ)xp3U9=knb3lmqwz$UJvFJHbf=DA)7X5-;6M{=#PR*E7YGq&7}Y z%;SUoSC8KM;=S%bY4wD`o_28Cf)7eNFDHfznh#lHU#RbKjYB~k)Nmu4Q{tt1itSgF zeM&u`wIfd4BZb|Xv_~lijJ!*8zHZlT<#Fo9%t-wv{l9%`7*#N#^ppxOXrPTzMe}<3EU`_wQOEUGB(~i z(VItFeI!U7k~T0xE0p+DSxDEkf+J@o-mXd=iqMNiDP2-B89q@~vryNXIDFN#jZsFC zw##g*!n7+@GmjfNP;p^UtJxrzbXiSdYP#ZpYnhUg%8H4clmcF*^eMQ=YKQFaO9vD(Q5lVs7O4E#L=2J~)ahiYPOHn{mu(4x_4)+hd&ZT-GglJe^VusC^O(w5P#lodRsv~2 zgh|M&DWoJpyyG<+7;IcMZzD_}>0{GzbDxxCS6}Z$s#Sd^{M2MrBFd(>YMH~{^J|hiDrc)uz zLd}Bfb~3Fhe346&psXscm#TG)u}Qfv2pyJhGhCCZ)hlH&TVzx9E^7^Vu~Dh==@J7? z3zJenM6gDV>QvYP!4GR}zse1&T))cqs#1^8hZL}={fE}k8|~2p!#EV=Aq94^U7YFS zWV@18QfWC^G73Z!D`~kj7b}Wsu1OesQhiqxIuvbHF(qG7^KzHD_r-%ZKDzVfSMKgV z>;RWyEu5&AN=i1x#xT85((@IgL^kniy+|8neZVviWvx$J2V#AXw~pk_-8w+%)v89J zq@;5~Jk4z7`FKUiP>lk-%W1)%NrDEc8YN(vH9arb6{U%bz|!i4_8#9olI;UQ?UOPp69EkcZ zSJm@bW~U@12w+{!@HMKjIUzvBiFnK`5J7<(C!T~5int(?#Ag_fYZCB#FfhUyv7cvSG@)VGQEr(+mSCYV`d`>m0`M^d)O1N^>5S#-0 zAo&73j^SA%<4?g(TyT_0Ay0>j*$V&r88qo5{StDwfkw-Mu zESI!2)2_7cX!QfWekg!XWkg%YBCsy&NKl3(-^Jk)qh_I?B=d4IDtXC)lC>JGkSzuSJNpJ?i)+<#pSK^WdE&<<{CnQL_1UyL`)`Wgl z8P&8=t#@1Q-Bt#7bYoX=-rPdU&YSpX8?QD>c{!aD5`Z|nli=eSC7suE1wEHjGkG;z z)bl`(@=7MnCz9+=Rs=4R0^eiQR+5Po z9^7v1-!q4|>Vw<$;a#JBtOCoa*7Id0T@aIH)mc7X$yBvGq35ewj?nVFg~O+&IwaL7 zmBchzFX}z2y)Sn51*=atx;3?3t@kO-F)F@Y5xa!gBPgI>T8=d_!LE{e5!Z4|vjW<) zW)?}itc;k}9o;-p_&!OtFx)C(MjkT@Opl5GA zTnd2X3Ad&D0POxR8``v5~Aef)*RJ`iLwZ>LmRtd=U8hWDZEwUOrQw0);`}olI%U! z+GCqXLi?87zO9TNn)WTJzRx!HS^G$|4tV>3?;Oj+J9__)K77?uMqE+O6r>DoRA>XM zX~n9NFN>KB6Nm2#6yl{up6(I+h^n7RomU$IPz|$4nI)-Dv7K6ijcpPeJLFb|Pl80s zYCbQevwSke#DF9LTguBBtWhGGINc?gKE?DXvQ6L?R&D_2fbNy#fp%VR*c=w z%4y6f0_)01De#$-(-|=dK7p&Hg+!WuqZPwt44KuemSP2XKjs5+A4P1;NJceevL7YxlloA4p;c{uYvL;dB#N zV5L&e1EboefJTLkYEiA3O)!P|AQ9&=RwC43rsCNNy4_c$AV`>1@UwGWC!hu6GZ5fz z58`Ze1O-jd$4~Q|2$d(yIE-6>alHUey^t|$7ULF(;-+(UU}`WgIB+|Ygfml~GEYpw zjj|wK)%#>(^#Gbpl`Db=gF^;qE9G<*&d-r~CaMx}gtI7bFN}1`F$!?M8 z7V%!G+%A?n?}_l5d^1{fnw zA2RxgRfmi`puq%R(zAIvRZ_D+N-7F`*>F{b%c<)l&e#{ZHjx*T87`LP<2fKPQWEG? zv7WEkSl%dLtxCF{O>3F7n%<(fZW1>f0onl$6z6sl+)hqOSK(U%F``i*^gN;EfN-c? zQt#88SuXL39J7r{sam}NY>aDH>-)SiV%QFR@T+E*$Yz;pRj78QW|y%>KCh-TQUU3rb}bnP!=5 zSHvCx4vo?!>s`9DE4BKZ-Q!fdDm2Q2BklM>>-a(Q;J(#6RLlXZbx2S)xmD#%3^YZ^ zs1T1i6(Bm}?}#nA_xG7u& z!TPQP;8M?APeQ;K_^10ERra~75a3nMT}i!oE&bxPF0J(iz>fDjr zCz7=%s9l=338}}>?OFvGj8Vj_GTwwMc2;e?X5)OH;kp#ns#c70UdzY$#0I^+$!sTu zL{3g&TDGF+%4!C$=WFoQgvFwsEod3cELK}szLCqQ>1wM2zBBzA-6ir`W{2L)ib=6c zT6?0_rKDyR0KOPQZg{)Cf8XjJD!?`r8&`l^SeVwT*4u>Dr`tec_PFLQYmOMLPpN%U z>Jogb!ZtD1h8k3@=ZaDy%Wda@(!n(s3QP;*I=DlX?^fw1hU>YCl9t;wS}%%rRqfFL zV^09>qYP+u!~%(A+f`7hno$%wgucsx?a;&8gwmtHC)dJh8zapU+pNHiUDDnck6vp% zcyIUCqwd~46I7uwV1S1K8zbOdMbJu_NDL5sZKMeWf)Cz>^yH3Vs^T+y`AjA6NxaFS(qD=^)Mwm(3 z{Q|S|=HsBvEI;LYz=$xN%MO90LTxhHz8ZlX$1QeYxUF<5kutB5K=l#Ejl3Aa{;*ae zJ$5=stVmM_fdxjQM~Ni35=bH!3sNIU^7(7dy*x4#ME@2 zkIS9f(S!CIUpjpB-u@RqI{D3SKlu0uZ+`9DuibgQ#~V1Mm4zm$^jM)wQx;xrlnDbX z$vLutH4n9W@9e$){_)XkUHeewS~c7#V-{96OVuXE^oWX)&r6A%5GzSZ+ANWcLRn4~ zq(oWIf?b%A$L&(BQ>oY`vV+szD%q+~P0UfTJl(8v9g6Fa)p`lj;A&MQd<3dgl+$@J zQIt|lvjUt(8?k&FzSJ42&n^!<2EKTwM@j>lZdY?sGEQ&C$QvnUGtF*hxUD30GsSG= zg&j;u;lO6JG||Wd@sj(bI;5381rizFGu19t5>iDWiK{tW&C?dlx*(_Bw?X5LBGamB zdwl&s6#JlAFaX!83hkOU;`nY&9x~>U3^|n50RxHzUx~;ksd|wy$`mlRW)*yQ-jkRt z3W*G}o#l3bT49Z>vtCz`YGHJ<%rz?#&?&pZ8D+L!k}UW-XG$y7)O^UOJX;ER2Hb+E z&&o`k$@rCzRQC{mjTXhp#ZCM?m|u59o`Qr!y6Hr5_Fi#*G&IpER|4WL z;mO+v1WP@8c?|gOM2r%&3cz^#^IZKi}B_{a{qk>+BQiPcA3^FW4go-r{1Sud~_*vMK3aN$i6 zO#CgJG0Rk=2(|;uVcQiFNSmIf&4S#2q-l<%VS8rxH_#hX2 z_+8Bwl}tfN14??1us|)!IJ_>Er;Rdvt+G{hR#Yd!XUM2ru^7t-^d3Zs7U48!iZT`* zR9SpbWr+|h_Bgd!gi<~gB%>)r>?F!eU2rx!VP>X-MnO++WN(0Rrd~QL0MnV|6&$A) z!W%K&$=jJ(y-pKuN-74p%wSD=rwM zd;6f}JPY9*0c%S?ob1{OHi!@0^*nGX$EcpYmV5@1dKwxP1l|gC0zjj>zWqyE@dQQh zKfFJ>dwlfZ*5Rv%&0V{FV0DfGrqbmY0~eY#eaKk{Qu9#i-O|imj?^+tBhT9yXIE;C z0uYO|5KHnqNuX20PK@8$W;b@Y%{afE65|;uk>qxE$c+TE6Qj0LT)d>`%Z)-_O=p!v zK}%H{S-y+6Z_D?;IDGWc;jOp3%_D&^@_MJ*8L@}Q%AH&F!#(NvP`Q84diYxV-fOMq zh>=^E(!qh^)O&z1ijfov8SpmbKbD5Wy&PL|y%iAk}A??13U_}2Yz{P4|>K7RGx zubu$Al5C7^6l!X=s$?0X%-cB77uqaWwJav52t5lD=UWx7g;8dKsOPGUT+IZDW6Cbw zI2ObaNp~xNij~Lh0^TfOR<78{MS_%nd4N$tse0yG0vgrTfKfUBAi*E{UEBGE z8#`Y}=i0YU9=`w1tw;CtcKzVa?rU$~eecV!zxAb85AXE(2ALyMSu)9(1lJXT zidqIU@>RQ7Yn7#4THa&09+8)mDQ-K(ZfArzP^*L#OUm(t5|2x<9e#V0*}O(vzk*-A zLEKCT$*hu1iK$I;Gs(w`TCQr9nJ&Th2o5emP98pLef@in?mTR1R;4vy?mTE7-maT% zLQr$MiFNu+f5i8O?BR)ia@XkZi$;g2x2hl{(69b3-`f)evrN?swR!>gP@ap`^t?V~ zIwz`qAVCf#xM1ms6*~mq#5q6OVeP9h=HR^jD+rlv|n`U=nwVPQ!URE6mS_kb{wpuj+9LE^ZP$IU#}04-Un*%hW;ySAARMcAOGQB{K+5w?r;C>hu`_(*T447_rCtk_rCG*2Vej8 z2k(CQ(fv114(|<(o}4F>$;wuaju(X#re>)o#`k~#QNXB_J(lm+NV`;0(^(;wWVaLi zP7EN%GI}Q8$fdQ+4!^U-ZO4RoMos6PAMU{i%$pUwiIt6Fv7XOsnY@}#3OnUSP8!ku z2ZlPLfXZNMifdu;VoxKFiHVw;7R-{?uG)RNv&-+DXeX~)Cl73MKy%Kr1wseNO$M&6 z$?g<{L`BV(q*O&o3$04)P;4Jd%>%xBA`kECts_w%Qc|a?_9<<^NL`X|Rh0p49Z2;N zCwMP%E{QhI0Y%gEl$vGhdC4v}`eg4&I(e;m`;GSAJ)?IExS9x}FgAuMnG73CP@6z5 z)7(ys+}N(&NYI-ZK9&;`MJ0{Zb7d_Hz7*tC78DX}my+;?9lX?(0hF9ugn22BscG6Q z^6+tWSOB_Sp!Gc4C~-zvY*zI?)7a(fBc3$NAbPn`D4WHSSm|#8xRf(8&MUxl{9>cHSuBP(SuTZN_*uYUVV&|SzA(<u--L_yOJHu9;!C}@I95=j%mFPMi@osdpJyzLW^ zSZ8C>S0kO|2?seVXMx0;;8*;dK(dYTAg=^_&uL6t8Jbf+q^!38i*K_bu zDtOl~{`nj68zo%sbnm|X==kC72XEc~(uZ$;?Kj{3{tv(MyTAAGU-@gl^Vk3OU;5b} z{P^P^eEoy3zWwIA_uhW*-u(x=N5`$FBwBl z=~8sPROAvFYA4So7!%{*I_ZUyoF*Ctu7xXIvU{wJ?lcA`+V1VT(WC4U2h?i!o&f|1 zUKkVN1u2yTwIFU>FJHb{xtd_MQru3G*#=*Lac(BIb&ZrksDc<1$Z58C@OZ{w6%s+t9$KERx+ z&9b^Da$Tz0D3`Td!F_sKP3P4V*2wbxs(B*n2W-tMV0xxz7K?JKQU~AjB_&&wvn4H$ zn`OL-Q9Xi#ueE^-5M=pSQB0Ecg48CYPK~v&vXsJsh^SfcB};Du@<2`aL`6fKy84H33@Bd#R@g>QqLGC-|+T zu$|<#G9uWO1o_tL1=hr*7Qvg9np!Bb$qW@skvkbCk>%4_A(IiaSvgnGi&YyJhO{ss z**0z+h)1ur!$uX6p~VS#lF!(LBJMH=KiDaZy$2PP0AoFxgKJ&Wab;x%+)=~R9k(!^ z`mBpkcC&!P7BZAa2@Wx<5Ev!bOJEfCsslGpvi1gCq&nw;H>^*4e9A2(WKysxJcGJX zl*D|HB6)aoHZtX}NYF)A$J42pzXdJxdEmQ?SB4hZAdM3R36Fvp(y{=fdJY`iOEG7>N;&ubQcr=6*Al<5k^GHJv32|Q2jBU| zcYpHz-}y^F{OMo%{$Kq4@BjWE{^0li;-gbY$KdmgcW?jZx8MEhZ@%^D&BJD!@Af4?tIO>kH;f+3G|H4w<~xLWBpIWj-t`g01#VQglOg`Z1$CA7Y-*UtEYU+?ZeAMmVHKh)P ziCJ9E<65EGD2iQ@b{6L>(lNeKZjZ#Hd-lnzt>af)dYj}LWwuc^M!eQ%IIB`%Vi=bw zv+)uePZ68j)r}avlNQsZI(#u7e2BZA!;M1KC{~REe4TTTAe-ePP#=CLBPX*;Iw2-v zeC!6fak+Z^8gXNT+}NhK;@nP3j3>o-LWsrKtrQ;v;zgNd!N#?AZE&dU->&!f#pZyq z26TI0XdMXVJ|}ev#wyb$TsTVX)_}>?8ik6Q0bZEr<2gQF5EFSZ0ls9ooiw}c0>u&d zr4EN^V#xST+xxr%3!^IR}YM@Iz3l~#JJbQKL z&+eo%qSU*8=gqHv>HfP9P97fY-{~IR?c9AheD%@p{ntmYy>;;D-QzdDbo=d(UVZb+ z_aD4_a`M{f;BI$tXtoE+Xs_}5YkRLh7(Kc_eDl@e?S12TuYS0vce)%Yq)8=3& zMjP_RfsAQ|B%9bFcQ){wTeXd>n5r1i0*j3tP^%qg3%)5&h!=zeP(2`Uw47y?oS@}R zC|Gj;P&Nj%XgiO8NpSh70vF43u>v12fha-()GJBcjN#W3#ElfWnWi=qwVUzkjd=C? zcI9e{+AK>cvR)vKBCchf$HL%)|9~X3nc;Wf!|#neTqVIMux(uEkz$|Zfxxx!npuMS z#m8dQ#&+#yjNHg_v5J}{>qXS4P*w5?+0q<5gK=j;C^r!$T8fAjjpx@Hcsdm%m{e$& z8#n|^WVWNs!acpcKLdrC0-E?zOmbX-z%aCqkto2li6M~PN;qYnRD7~)jV^`Gj^1{! z{2mF!qFmgHp9)9~aibORN;`*eMONSx-HC)>fjK6zHX@mx3#VQ2IwO8VA${rb;hzg< zAb1J~@JFWr{#n1kW1YdHzYLSwL7hUEAXyAo#S%cRo_FmEmM8w))%f$*?|Qch% z8KRLD+nBY-_Ku|Cv9fPjNeOW-}`#%32ms(Q-tifU8*`H#ugfz{ZMvqAF*ZMp^-@4psF2) zu482(Qx-D?KIz;Rgez*YohsL>)tVS?6lzwPZxdRd?t>cLs*jG)~*16$kG-@8YQA$s5v(}!r zkWoeSXg(9~IU^HoiZWIoR81l{!F*eC2&NCWc-nL-NXioeXZx7&Krl1dsrc!v4RrJY zOdB8AjfGvM=?EATbR&t2Ym>B{ym-i+NWR}Nl#@SUIj=x2Z9FaD*!@w>nOH-Gwj zfB1tR|LmLJ`Oyat-`PKKbZT(R9NxD3x2^VJowI6Hy^QH4tWho*rIJ}HTjji-!^~o( zQNWZ8spn-IH~UOyPi*fAoddCdqI8a>`YywED->W*#oMJ^JymHIq&-^RrG;MAd6#gp zKBQU)g5IlXU83G6ja^1)VpT1j7j_DAyr?8fN&-_-tW~ZL=-#n%>tXBd_YdFw;P~!q zoxy=38d!x-rpe71aecdXBgMz#+|DL>GX@MsNMwXWg4y0CH#TcGx2O%UG0Dfasm-n0 z%{aB01rFytZ!UI8xlaM}5ZVOW#H%`}RJJT<3PKWmiXC$Fs&)LRWA3uJoD^D>I$U9a zCap37UzJlTsM(^H17AoRV_G=ZhOh9e4;gcxua6k13u>CHsHvh9&v4rb>SmJJEXWDC zLRAYR?Q+#908zu8Yff|%BaA||QGlc3a-4MXKTRTj66sOz_m(puWBA}_K^V6 z=WMK|u~{z1Ev=RGyKXorxixN>GVBP~!pk zmV<0}KvF~YPVf_11yqUV6S9P}6ZDUTIQyj?;2i$!HQpE;+PqO_oZTu!>j<}d=}&+q zS%L7pJHEQ$*T~Jt2N5ZkP%$1meqBD{c!yv%|LWiWhd=(4fBldD`5*tifB298#((qo ze)q5ZbtC`)CN(ya^8?9rX74&1Fe&6%d)*SA5ym;Rs@{`oT19HJQio-% zn$TgmHbpfFx=qyV3SpIj7VsSczK>Jvi~S=Npmj*9UML6& zOv`dzLLAXdk6`-*(JU9Vbc)|ebK5CqYo~f`t9&^_ZIbmoNDZVZcWX7^9BP_s6nLx5 z=y^)cP-0rpi?WHSEkf;(dm_VM3H8pAjNZHtgNLAaxyE#;8N^TGRbU#k`$G6SxJ{5z{wKTdZuP%D_VlF@?r<8 z?^5*BGJ6MlXQXs?Rm7-J6IzOi$DGQy$w?bkqi0dvB`~;WBNzgw=2w>O$`k((F zfAa7C!$13<|KuP3-~Rc3^FREfzy5ds-tYdkzxnY`e)irsJ`M(3vKW5J$GC}{jY(n7 z223Y%#Np}SoEpgXCjtL#jSxPmXMhZVK5*|iDI~{r;w>pMwPAgoa&b0}541BVC7%Yv z<5fWXQ$4vQmi1v zDoUC%ic*`X4_K{7OHIPw6;EF4-F;(t>tS#Ij=i)|p>8w>)QV08HKCl2 z&aXglC^<(QrwI%VD=}lB_lLO)z%R+N1WWGWPpHnHFqohI43Po^!#oiLYcz|QIu)Bi zFpL-1Q4L=~&JCpGVgB#`$N%f!{>T6AU;gWV^H2ZyU;cxC@_+rKzyII=;UE3iKmNnN z_RSyv?uXy~A&@F0{7jHcSHy9zAmLp6zBdab{2Y*o?x7Ez5ub4U6MP2V2zDw+va8^T zkwat`YE*#mKQr(&fm@!s68rS!&8IHic=qy*&)wX*l+Rb|>Vq%6_5L?L`0yL=f9+fE z|MpKm{_#&g{_YRH`rAMG_Pg)D))|@@RjRUhO(bcRlWa|HH8@L^+6~@T>4r$vc}%EM z8Y49&Yh<<$nxos@Td(ciee>Y-$T?hCw)Rp85vvl;l_8@MV#(s_OyQ?qiPZX8J3 zfkbr3yoqIva<);*HA*Qp8<&zhd_2a-wz=(1dSjc}+@x-7P&c-jn`t?o(^45V9v3#Z z=xZC))f>d+4f5(u;_7w$$`*M8=u`|C6$L(bV)Rao+KJP#oRF#LB|t$;r>N~L8&8p& zJC$o`a-%FJfLd`)j5Lct%Zf^}q^2^$b`t8;RzXc-jVxgos1{bUN=zHq_xaWxO&QUo zQK*54HpUpGikt>5li|0W7b$LK8w>)QV08HKCmTK#PNF%?02MJwcE`VH$7{nNMKUm^Q4Rg-J0MAzYF* z;#KN$98oAAv?S-jxV4u8sYnPo(+715F{cQx1c^WMN&?`_6CfSLCr;<75b>v8NkG6C zbeG4|m**MP|MUO+fB*ac^q>FdfBWzL$N%Yn`5*qrfA)9(dw7BBXMg=~eg9{_|Fs|e z&PU(>t@l6v{@Y*sCK78ZlN`^F$YDb83NuZ`mICcUpIqGPOo#-S0WzK}1(K9Yuz3*z z#hYtXmt#*|-g)ZM=F^vMzI1K#&!^HvqyFlb-u~gwe)~JW{q1jk@2lVZ&X>RW@dw}f z&ig<3(bsQecRu{uw?6p##~%UZ`siC9e)z4A9=!Wn`>?O~tlr74)-@Uf z>)_R+*WZ8rtKa#`_kZ%8@BQTC@Bif6zx8|H{pnx+!EgQaTi^QL2OoU(^#_mkZ@=0< zyxrV8HjnPu2e*vF+l_~B_73kEt$n^eB>6T*HH$>6SZt)TY9cA^B*g86u$7i}a3iPf zQsx0GcPpHg*Lrw+pKb3kts&jr<%Wk+XO}a&gx^E3b&)ikfVl=wgYKmXtV_@DpxKl%6n;h+64fAWw1*&qM6 z|L`CG&HwiA|K-2+N5A#^f8`s${nM}h@W&s0??)ee{QY;o@$tj=KSHC2iR8XCs60*K zbkTu@L1WEld>Z;7$9hr5y);s!$IR&sf>e1*E#QcRjG42THekBIqyimgDw6_0!bNh! zfd2f-*3++SJp0OxU)qXiSZ;9d&ewnV@kihO%A@xlzV_ywhmVfme)rCoKYHzh4Ea7azTIr`6YMY!RojG+z?cs;J?j zj*E3%FmR?(CiHwkNEcOwqRxQja0s#Ancsjs{lGd#lC2LT0+YH%hvNb%yNTvCrmE)3~N_NqgaxX zaq{LSekCi$2&-7qGgYfdw#sC)T(e7fBcGEJa6NQ-3rGyEs? zgJ@F}zcnrrq>xitC?xoI87dJFBSe(|L6-s`djYOafkaTBScTJc3i8VKQ?G!}F>s?3 z0LG2~r~m!`_}Bm8KmPHb{HuTb&;I!D{iA>KxBuQh_=CUwcYgc_fA!lx`Mt0F;I}{e z{*S)=-5-AG+uwWlH^2SpqpzdwFrCnB9VpKl0O|WjbAoe8!v~fjP=FN))CkRP&A6^G zDgQjivBIT_1d9?1KdIWXgwsKD2@j9sK{YfKqfw@S=7Iu_4(QU)T-ti>^44drZU5>{ zswk_&SMR;`)h{1DxP9{Q*1gwnKYHi>>u=q8_4T7WukPM{b#(vrgV*1_{l1(aF8HZa;kY{yQJO@s*Fi{O#ZR&5waa{p91{`n~V{==Z++-5-DRqi?>m9T^`>ozldvL4MIkL@N zU23zeMNkI(%|Fws2t7jIWew+7a{XKCt8e#Te|PlYQTOnlS*uGL9l{<^NB51_-y6OEn|B_5aRdZwbgypiv0|qJ5ZV}~CW}%W z)6$e#R7dpifjN3;wQj5OkgAylp-V^ulI>JTs7kv3))rzJ2m2dDti zX%=d&GSjPagBsJtp=oL9Jg_1mmgcq-^k#zENVD5`Jumb~te#Kt@wAx8$SFXvkuO^% zyor^}Vn$8J`JHWgBgSqeg`KnruU(bvIl7HA9h`1sRWo1KQh7O+<+swz&7!nJTY0ey zs)I3RUTBrIevNjnU{%xVbv}Yt#Y+l!p&k)P0u$fRD+fUHKCX8oLzKsfkg2Iz;T#FUJA@=70U){ssJf-@o|p z{?R}Eul~D#@CX0Z-}#+C{A=I&$P&+J1 zq>!tCxXx6ND6{a)X$DWd5(()fj`Xn$#;ara(xzXwS-`l+=^rH$YYOgvfPRBa81I@C zHIn|~1b(11PAvr3{*-6!J5Rs7_59`S&s>ZBdOVkxG_KV#4-WQUdvN!iHy?iKokt(M z^TwCoee1*b-umdhM_+#DwfEn=|K97j-nf78@b>PjxBGW*+ee4y!M=I0XCCfrqoL4g zv#loIY4e>f+inw( zdk1@WMhAC?Cl5yVUf;WQzkhtEed}K5!Rw>Xg|&PIoc7S0TF?)vHvRg^ZSniCb}L zYe(F?$y~o&efbLh%1!E8T-eSi2|!AUCB+@^3GduV@g%>q!))x(8|6k0w@N9XQ%WkU zWpa8pqh%6uVn>X{r`OwcL?ZI zh(H(+#fkgx{^Ni87ys(t{F8tFFaG{NhC20!fBWzJWUNzP{ML8h`{sAv{l>@d{N}gc z`r0?&_~`4eeejjQ-9w*nJIo-I`x)?!(7WE|6A5`HrlpM3XgLb#2&c^B0E@_$A9xn!HJ@Gs#P(bz%He$SF2K7>r^{Og50Ud zU0fZIY_m)N9Z{1xDOT3ggbi=!l^fZ-p32wLWh-Aa^BFx2K2vI9gS~kPf8|p3(kqph zf1~^x*T}0I^!1zM)lK@w7JG9?*h(q!qM60p4sx*VJ;`pP(RGcuuD06TFpN@Y@j|Vk4Uicf&1|08@?4|(1 zxFh45K?*aE@jw~0rCIoaqf8rl*VdQ_iwM)HfJD6ZcMd@){c&|Jj`=j6agTMNn-}$`{zw-m2P=GhT`i(cg@|%x7`ugi%{_4XI zK6>?wAEL(#A!J$skixH>N!2F!?lm7T{G0^G8-qvuoCuzhQ<((zi|Vy}U>DpQCX!AR z5XMh1h<9YC<}wW=dK3^QGOVEl6P${7MqhClpPugjJT8H%#UTCwM_O4rP9?ZzDd`T0$I>#++?Yiz;;BjFDpZ(v9DW)_100{-dCFY zO6O4P9;&T9QE%0%e4cG{3eha#b`i4*MI)b( z<6GR;CbwC%ibcDW(X$CT850sae0-bT*=D!5ne8|qOUuc$l!$X%F?M4ccohSGBp4UA z5)$yISWMjB;x=zm*8#w~w%N@%e1Tx9)F{+iINc@a4&kg{g_Rolgb)MCZZVsi%*Hmi z85efaaw4au3VNofXG&V8tihMh@IapWHMvJHW}&8M_-5JK=Q<~{F`^l>SPBbm%Z^bw`8qoF_y6E;{n79I{$Kg{$3Ok@$KP}O=_`=;KYH-~N3VYA z!~0+S^1XLIxc%09lgV`%0(CqSAxrZK=jDP#oC(@EV~}8BU>2c1@R$jA$mzKKb`D5* z2(+a=CTiuLtuAgzSV7OI+*M1)z`dX_J5OKPergQ({`6(Q z4&W*H>GUy=Npm?Qo*jeE7Y=atnaq7)i(_n#v;m&G8h`F;EI|DEt0}+>S5u$4p8ou1 z_LpP%KbI_gAp@^+?bL`o&r~&$wN#<0C~d_Y*1Lz+?yc7T?biM+yT7j)ZHCnf6(OGG zH?exMVq|bTM|Ls1Rm>aNl%6Uyi{(xw-z;a$LPF2R)l5py70eRet`hBP6`D|mY*nc? zLAR?^3oGgAw78QLwzCQ_p=3sh$N8--`o>N2+I8Z}joMYfHT?2*{K^J#BSvo}*&VnF z7c++4DJdD;C{?X;)dru%vXRe&H04A>*m0z7Gs$n~JjIVx8 zsq9nmcBD)4DUXCh^6ASdlq-Pr(^oQ2UCBOm8IXJWic9vH%bBMyrQA16zj!tN($&~! zu5N$s`qnRR$A2T0zF9717?LuS#%`y3Yt+9pY96+%W4n2$)x2xVdm`1T5zPv2l}q(p zv7W`7CA?M2>Zzm>PpOHVkuBMUa<(j;ZOCYZR|rL_^K z?eW?kr|h!AfTTM(5G>5dgYx9mR7OsurC3&u=j3=nO%#-PL5}5t#<80vF~%5qbC2!c z(FgY$)}hF^a7@YMxL9WTH7du4ToG~n#+Rfh69-z2iSeupRFx1=?^zjCaUKh686&*^ z`Mf{~$mwt;;fm8+=6~on$KGGS9TSJ zyPCci#DzH46@Ti=&Zn}xf@Eri}NCNyfkb-IPIWWnBrUr!vUU)h7($)Ac z+(`XOEdO$@vO&;kQN%4>+Up2Ii|wj}$q+_O=(5cd{pii^-fLE4pP{T=wUHw2e63k1 zH8Lq_XNTR~;kOfVGOg#b^?XLl?eMV;YU6tK+BE=i{W^K$TJ6SF;@aiv)yw#mtJSO5 ziECT*MqWu*>IF>6mBkFH7PS`L87X^*#?gs=a<6@GzhxgO;(#Vwl~N;DGV*w{Ty0kX zMYE7Ia@j^Ut)~GQJyo*uWVb^1s#F`JT4lCfk@_`dNCBh)MVQ4jzmw);89o*^s-Tzn z-yMP)v@A$cYhYqXQwgch3ItEHCzl0n#{Cz~A6e#rM0_$pRA~<0+!L8*)&Me(0wPx| zoCfp?uo}VCX0e1$okFBWi{TrOkE2tL4|zrv#J8v*NElbeV00wqx8DEq$%EHgqkTqe zP)eOv0S!v6Q;JT?dQDOZQNejBSg!>tK8;Y-w*3P5wVsI+J=pB$$E36igQVc~&&VnE z^T7OyJ9z&A!kb)?vD9agK{b+c0Drt4gT!4glZ@sl5%?0^8zz+C{J!B_`f_k@J~~W# zlye0RUh8s5J$>1=y38||vSTvOUP?W8IsTdJiC@}De<4@6fmhNzO_;JgFw6tX+}D*J z%a|CUW~*wN(6eHXkVlj-Aggc%gi_JOiZ))b@Pb*%)k_&QmzFaLF_n={G1_ zqdiJeb5+tMKmOwVNl;_84cYCI1af?N+r#lHPn#BJ$&w&Pc0S|8=MYMK7UNlP4&ig^ z6G5b!QP3zW6F4Yq!X3lIAelZMLcQXdOUY+mNk8*S#^u=wX}~j=QVz)o?)EY8Ir_x2 z@WR{9GnclXyS(+%we8Pu#{PUda|17DM7nB-Y)55U0^MW@gQyu*_^KH>ml4ugDO1pj zIkk|}iWwyz=Mr%?o)VHdC0lBga2qFD@VTp!QF30@oQQF;7`MH{Y{uBFoRX}X1*V13 zc9{ZStRmmUq)wHy$~8S(mg7}DjcX}PNn&cUqNM;uIiBUWOG>gJ!7pVkMcE~>Pq6I@ z(a2$Hs;Xy6qX3|+65Xm$?J90zOBfXt5yXVfh$BW``hf!pjluJtpI>u=ztjjB(o*#;N+K6TK)-w< zMLjRPOI+}C{LU+gyAhe)(70gZrMUO(Jopnf)ET@FWlVu+)m<`Q>hyy zo>o|*rPi8K&0?$dT1CYwYN;X@s%jCFb44MQ7ZMrgURzd31I*r;bOlEzHl83z_!Z-2oEF-=$D$T)-yySPd6*5QB5OaLJ?+Osq(HT zMe)TV+|b^2sim2i%EjY#pfQu}lP+~0c#YSf$O_4w+QtTcEk#4DMT;#qMgC&r3$0#K0R zMTeZQGiE!(Z)Jt;f|9`MX~Hg)8=0b(%t$+VIWhej)!0~ZuCX`NOuY+ITIn2vq27cU7^9Isf7nA0?IL=GFph!7J^1sbq`vc9Gesh{>vwsj8WZk}gS!EDsU^niYOB z9nANhO9h;1DvOF#@Z!w`)EG_yN%LZuTh37D@H$+$Bf24xG^0dQTLk|c8xNHJDR*|< z!cW5;Yi8rueHw@=%>jwH2u{hzO>s7YW8z{==6;w$pe3IeK&c`Gs_f#|VlF}BdD1|N zdcHW#h_rKrNUW)NhhTDaBI$&u>ZR}!cW}0Z{tfVUMY4;6oN-SIfx!nU@J#$#!-`L- zyOS(3^qs;aI@0p~_Q%Skxz@~h?u#_Yf<&dtNf1iarza#nb;-SI6?^*1_A@}OF5i6N z%FWN;-2QWk)J+V_3oLD_oGqz6+1%BPk)n1v!LBil3f(9ZTE3!W3SuJ1$1p8jvx+sV zK()%sE_3Jo{WrdGfA5VR-=iyyQc=z2;QeW7XX96J84z2VN-#W9B!}q(UkHDQ9OI8` zj|Er;q=aY1ZG>~iD}PW^&Wt~QuK<$NnwcE0WpR$L3v!qOL}INBnlfZu0Jkte?Q7bAXH2|SFB0`aMbF{&9BCDSR2{z4J9xLRABj|_iW$YMk}7B!+$t37 zsiGFI8fms!)CRTokubci9o#dH?pp_UjjnUCO0+Aap3kz|c`-)WCHR}fewFW{&rt=; zDWFOV6Vj|X`hqrV7#JoPeKl5crdfDpL%Ys2{JlOHcX;X&ya^b%WaR>U%f(v~`6;-p!}fDmHa>g(=ATQ(x2jl4;n=3G z^i6eOh;5lRXtGW)W{tILlv%;l9HwSTs{~(l+$`s{WT}zC?E=v%RqR4WjwShxoVZod z5@aJIw#sS;SDO{puGCxA){yJ$3H2^XYq=u3Q;|}vT^2fc%>Zel*QgLfS{PTPJe`7D z0%jBGXA9tW&?y8HAE$p#c;!L6g$L5f79o^^`_Gx5%ZdcjM+Razlmzyo1P7Wh{zwE< z0Ko8}l1~E>rl|ySpG&wRvj7PqTUKLSO|R~gU7@Kuuze)go~(1Y}4VkC5;?5;BMz z7}+=rq-}jBN7iX@uK@G$i-(TM6M|X)mjK#Civk)7UY7#+E)^6k_wv>F3Kl{jJealN zD+_^LZ9R8o>lbduekGo|QY@udnzrlKVSjLMfB)e@|4vWq%UWMjdOU4bhLUNx%@HB=|#?d3AgFE8S!XG>4 z0|SrC=HUJrl%z#)W6c5y3;bQ20?9L0MO%}jwAE$}XGP~QC!*BBtp)R^8!2{}plzcjoSU-21 z)&dBAqs?wuh(AaM8SgzM?$13)vqX6cN|i@gm;nB5!6`V;U`+twKYc0jr!FP`^p*6d zuBJbI1z6e+5UdxkZvDArZigVbre*F8cJCeS-9PBx>NN(sU@@eIRh1&HfYgdUz zp(rQu1~95Z)yPwJiEUwg3*)R3)5ud=no?5$QcdDwti)}WgzbuwsMXW7IoqfvZZwTx zNHj1i0c#*AK+A$8wJ7NEK3^O|a31X~B`>%W-|Z#;!MU$Z={3u9d8WHivVY?T^HdNzCgycLxFpdu^tH%ZjDa_@Q|%c zm$tgg|F_oIJ)Np=}sABFOf6Oj>>pp=w4! z3ifjdGK(!tP`NzD*RkNe!cSdJed==hQ^2dhcOYt);ai`dyR`MfrH#*D-@2U1WoSz4 zwRZ0w-Fp4b{@uO)QM-F+*&|i&@^Xu!^ioyH(Po*pv6@-L>Y1XNEUR$k&x)EV@LL)B zMzVG_Lto2rH_P&NMT?h}ot&@{GOCamosnseF-?4BK5hd!-;oriGKqLGMEb;8fSqGu zXPSePTI6(Hp5Taph{%EjYlrN5a`5XIsIosbPM9{uMsS0jN+_0}X^7x~m<1B$jD$yR zBz?3s*25RJ{&WPeaY9H<0Fe~d4SJ+j;;adVy2pgzp`V3&uuj7X?9J12@H>MK62J!u z_K6|T!##qH8Lpl49SIPLK9_OJuMw|=bC^{2lM6DzErY8NiKm@cACBL{1Lp47QhZo?Z>M*(i}i6;NE!=9}lo> z$WdRF;OQ~h9%_VzK@(gUL^A$MBRt=2!lS{CF&c(3{=atext%6eZX^87pJI`F&dG7MgXRgJ6HI`4Ya((Y`^y>Y? z*Y54zKN#NbwfA(R$7(G?vN5q$5j!~B!U!W*(bGVx)LpXss=E8gXx$a1QHAN`t7iDg zbkv6yCn7)yo|H`WryzdFCyK~HU6Me@jhwfDagUF*#thtKgWmx_5hmx)7$hT~pjbRc zLM<~FB;tY~lM}KRfCM-X!jo~pAppKZyu1YiM-J2D2F}Fc@}HH!1V1LwRsbY?gkS?A zyPi;x3N8(7CG@=Z@XmeYr~v}aJ0TK%DuHpv8(so?{luM+7l1doJr+P^Lr2i5zEg2D z)Vtl^)C(GIK)AR`K4IF~d_L+>&+zSLL|8y1^Y(X7E$0gMG zXyDTsM?WKzwtYfasr@e!N2KCUzvAE@anGoLT0vkiperEQ%iGUz5V8$lh+S-?{xY{Mspz6?ONR?bPHD+WnRlON}5$OqEXP=l}5jc8WrM0XCW}( zM;P~J2(s&f@PuhP!Q#zke9R)9EW-GF@CKvFi7`oJQDD}vkdunI+g(2Zg&F6y2A7%? zHFVCbgkR;waI$ur%g3u1z%LslIQ=X@u!1hZar4OpmOR`7Vf-dqCr;Lg6|K&=3hN=* zI6vPw^+gUh#5t|pb06I`73BO{jkPB@h2WrZUW^CQAi?q90fYgac5)!#u^89gYx!je zG~ERgYTgTDTAM!>yyN>y>=_5}@!!BpSisA z(#tpgLM)l4D1Fej_dC|EX^(WPFWDX5Zqb%qGpwqt7FaPYYB{-46!l!ls1PMuiohKI zgn*tQA^e7373XM0y3t&w^zS8mn^X8n1;G{|1n%cr@K3@ZfpVUPU#~TRlq7&N)40Q2 z0Dt&96{OG>Yc8RrfQ=&rSZoQW%d zB#3|nJ`;f<2+74~PLv4VU<-+)@Tt$m(Ak#eQ#W!I}5 zsR9QD7}cfNrvR7ZpSqm*^rhsd;X_xc=dWa*c{%>npWk@?<;~As-Tt+$_%?=N5~uY{ zV_?)fa-+#vZLZbj^ajpLIbO;NY7VfpQ3Yo7$4ntMCJ%T4bvTGV39i$n9pxFfzKVQID?KRYe z6R7pnrf@-HElRNQ&%~4#TR)Ch?K}f?DuBD|)6POx4nV3>PrZ_Q=9To*Ux+{Za{R^1 z@fTj+eDMp{|IC#e*K#?=(Bw{|-mhydUbAW4CV90;OIcRV(NcP*QAPCSu@LbjpRnkh z2mWCQ5$ps3kbbrZFd~xpk_3fd4oJQZaMqbisCMT>xJau3hlBAjvGk0HG}Iy>DJ({? zU`v4J@(WWwx0gN#xpP9eBsi~&t2d83#m+2;M8GL>uXYrX6hwYFYrc*)xs-$ zMug^Kh}e=#*l*Sj($HtaIoOe2H4CSsASo<@->VjVMrsmelKXhpIUPUBOuSA%8zlU? z2@H{|{}cFsOLmrzInoMnl9o@XCacsS@4SYgyI(ObiyYi0&*fesYEI@6?oKU zR0<9w{s0&lSXKr}e-22*`Vs)Xp850J=~v3ttRhiON$&ANv%;AL-Yi_0 zQALCa;K~jBzQ|Rvi3}|W(vIg#q!Y|1)H!_6&Jo-)0h!&SOiJZO@iGmb$z#To(9*!@ ze##SqwLo^Q6-j_?o&~31SY)PO4Z9isVEzOQCd<&A?aV^~{K;tz_!hMwNc2VV z>auw%ATWAd79-q5Yavn#K;XE{!3m6{wkSxw0M7P+NUerng~yCPouK$Lhkr(_75`j& zB7l`0gX}sh;m$K1r$K^cI3u9~K>TJ8=D1#v9G^H~%eeLvXsGq$X5kZ(D(FmeqzVLh z2Fz>V=zL-8(_h$p>Xl7kR8PHp^Ql*EK7V!d7q??KumWodN}F5RsKUG#f2M{@B9H^{h)L~!SFzsH0#0{D43xF_&j{MieR?*JGPNfQEdhnae1 zL-sCDppbJ27cT-bKdlE}m{tItxo3lDM*!cbKw*&jK2adWo(Zfk+Q>*!OA%_uiy&0; z^%CjuW89N{e4?RyFC720{iNaa8GjfF{s}%OAh81Y2V!MlI!-Qb8T>na=J>@yTjvuDJQ#j&SPZ1s1_>SGv*6C$$VQiNVa7P;>iA@y$M}?vqyQ3!Cxb&| z*IfMSuNkMn&cNhN+d&IimEa`m;Cs@tAn7cHFCwrm;qM_PC7&F@3uIETwGgNjl95NC z8>4ZfOj_yUnH-lz@ap9e=;48rI<);0LU0gx(m;ypw>%PTMf?Nj<81d1G3>yht};IK zb8)-9^XcL3nptdj*Lp#+SQ|)l0gwO)NZkZ>Jl;)j3y1YBV$kQzmfdVtfrBa+m7KzJ}`2cyqsat5A-$8q+~ z#w!&ZkDTe#cd65K${)ziM$nw*0|NVV{CNP&1FJSUQfng6XtRhE=Il7tK}zD`9D1*_ zA-m9m1##1KK=KL_40d67=hQ5`-abCLki9Nmn4b^agZp!hbJV;Z>-PlMQNxFI1~8%* zJ{&7DK?L#h^->7n#9a&FYCb-Yx=#c7wJ9)`I3OTZ07t6er+53$kt)xto_hJlvzKp# zjVdBTOA#@WF@b_2^$dc>x(LE1v@(GTE{Ip_afdzyKl}oK*&5jr0X=`th*QGHic{XBpScb^EHk_UUB+ZiU^GJL$kc(MF01XCFAjZ8g0UcSK;CXA!c$7}G_ z@az6K2{c8N7{F1h0FG2SxKg$C)XQ5>zp@3q%Dq^%icv+pWEOME8X^*LjfB-_WyVc^ zcDz~#`{gn?U4KGg3p@?{jWc?!A9!tyGdh3VddCYe%B~r)>;Zt(~0VebK z#H(E3&j4NK8CAqi7A9QKS)j32Cu~0}6Kt|`z^gdYfx;kNZ2{m3Fd3$uGXVfo3w6!a z5}(I7i}m5AxhBTtblb$iA1@;K4R`?{I^}|dIUA0njO7WDDjyIg)HoN3U&w_BRxNPU zoTLJWJCOeA_}ya`p-eBB#Y%|cH^q|$a*jV?fObP0KhV3-=8Z%T46x_NqztPODLI-x z2rv$eoL}RExE7{l4e(1fA0*a!fmjrR8^)W^XGm4Zs3NAa7N#i+8s=02iJS$$0OyZ? zkOG8y*tip)0c0Q;Zx46Dv*hKTR}m(soJ*iy-U%?9VBqs1T!s0-^80OgkswCpf`kcx zNXEKAa)EdU7d^!51LlGh;&W1c3|}=L~F(aSI2J zLX_3oe|Dw(@%dEHG@l$MM{Pl7RD8zN>9^G^{E+JenA4vQ5Hu=)9}E^XDpg;&2%}n% zi2bZa;J}*$ z3xUiC^Oz%5fY8ONuvCSO3hYK5Xj#JcvoZmvIdA-?c_Kmj#0-$$2AH-B>8}of(|!)# ziS5rQaG)RW4P~(`;liu|B>hP{gaIY@N2`SiR)75^4V+<;?{SW`gH)+deNpy8DnspE7) zi8usnJq!3fHJ2_OlvctvOfxnm=j4;zgPQ z3FCnDfHULuVE;s&%Xm!p@lJKPH{6?N;GZy$l|YT=Fs_|b)8H(4K_D&_1POW0Oq$|? znbY#Dpd(wR;ill>C5s&8**LL~1ZVIYD;pKUBpswMD-rDT=Y-d`%iS zb}FY-8Ob6{pl>JR z#J&D82PFJ-BGcqLh~zS1F{7FadVHrdH}^0BodRlw?seISfCO*|nAxNqkb<2T$mz2n z@VKv+GZbbz!4dBX1sS4G!>N~l;MU8e-9AB}?YSC}cAn3tAkd|JCR6Yw=Xd);)-5m?}{TOj^4#&fKN z=nI>=+4ll02~0e4l&2Fee1LG8!3$K28WpnF zC72GttLY59!Yompbuu{t{gSMUaQcq{WSo3rL5dy5KT_unlJDvS=DwLz7!qYZNZb`c zO0_6(re4^nBD45<@zvpp2Wi9$2RYu6E)~V?CC>NB)U_yTB|LnbRB887k zZ0C&c5MvOX@_=^_Jh`|d>L&uEfM1y>o>2WCC&*D*H(r;8 z16E+f^hebw>mDTmfr0Yp1*cM>CY=h>wr3+aDIz-M6ATkz<4^sCjsMFGz%GxF8_gn= zERqz0pDZkYxJ%3it?8-w?Q;sj;}T+$yW3HbGbqaVoC@gF^z;#zazVm4AV#$!lZv>E zdnqhl;0Vqq)V4mSwc&zoe1H19>?6a$$YXAmx``{xwg z1Vf4v)G3dNX+tqC#lJpHo+^^1u(5Hew71&z({|HGA=v_kIa>`n4dKg z7$vAiryCU#c`@80bUNdrBhhE!*YL@}Z~b$|Yb%&3(jc>##EKB?#IV~TeQ~WIW93vX z_`D6{pL=U1+z4|(nqmw(z0CyCDIa$)nk-=6Jc>@7A;zABZl8dphT>)oL5eg63IDj5 zl=Dmg?La^RxI7M>T8(j;y(U8TUMTR~nVfFO8NDLNAo*Bu>NUGCf$@LN@O}#ZoPyx& z4YcaYOqz7eU0+?itblI8s{d=thOLES@ijOC3=pPZC z`v0-_-(Qj?=Y1#qlZa_oRo&w-rd@SarT5-@d((UGeP;RUYTrFGJ=5bc7+?ki50D^8 zQ6LG5lt8nDK+%atBqd5qEva3Z)t=pV_nbA7{s6oY*Ja#DQ&rv7g8_(hJ||CB+~cA5(hKbhr zNdvYj*0~g%W(NRcIE%4`;$sC{c;^GxfjM5}&PDIG*rnqEtU~BOn##B%@TKxm;k4U< zkb5h-q0a``Bg^cuftR05BsevJP&FTC`*Fd<{TN^y?Gpwz1jnGm0s);Z z6u2YHgyqp7*SmR3Aq6#o;b29hBO~}2;Wou%h0_!$OvPcFaOBjykJ~t4S_%UTcQnTR zf(LyRxNG#W0m_LsAjUzTU;^06ek=$K6o->jD3}=qb=-x4*^o@M+m91SMez1S05guW zdi;2Rt>k0S4Gz0>Jm8BJ1-IqLU}g|>Q9T~;#$h4%U$#N!!c-8;feSY-Rm%&x4u{W{T;{Od zYbL-R8|9A(H4Q#4@Vd_jZ5e#~N7`gQ)HaC;sY%ed$H|oK4KE>=i5!jzJP_H8XsaF` zT7DhS3uu*(4x^|}3-O=!W5B}AQB->RxC>>Lq8jIeg4uAHXzCvyIMb7}GE6LJKNd`{ z&V(5QwtdV2b7VlGprIccG{Yk^E*QRFLol^431&~iZG<_X(P05lFhzx5K0H|AAY{22 z1GEH3g3W;gC(t8>@!Gac@boyXzxJUZMdbQGu=`*DF4`;nNseI6P- zH%v%jV8%aDklR0^NGP!8n$06BFghPB`fLPxn(2y)&2SRT5&-gH^cl%9DJqZy^`Rt{ z8w+MO(Gfq!VAC8~VJ4Qr9}N>FJUj>01>1~f@knKu%D7+;0jCNSoC3q`9@SM34I&-@ zXb6s?!s<4Mxpg>hri8<*G#|9WpBUJ>d>oLyhOHN~zMKz6azfP;hY}lF~2<C7ggg*URAR$v`ruca*N+5t)?;ORH1Kuf_&CZQI?iK#M9&bx{CKMjv`{IrQll#YE?FnOIRjIm}$2u`0}BBEydZY!?P#g?|{( zrl28X;ezSm;EJkaRa97^4-Hm-1g3YH@jWpcA>_EH%7Aso9FSuFWW#OhV~5*cQ(-!B zDzm$FHsc#s<^wFrvGHRDvI89k-2G@!(`WW$LQ!aAEQggJXfhq&z%7 z;fm^vKsy7>3}`Qa9-erO&%J0xHKDyISbc^80PeAVm+J=wkH1wIdDPd@X07Y zXE!-Erqv4*2@qUA&F7I672DiL1gqG?!tHphY=5udHt(^+ZT4dau22(;>>RK)nt^+3 zFqBhZods(jXPo?GF{d@Az-|TyfT^gdU@p_aO8Zle#JmBonMh%oqo^>;`LNMhCh`Ov zN>OP}30UZP$}td(%S;L>7F;BeU_y!oGot{RU_uRm=S*rZ`Ezr$ATB1(9I_%zz8JQydax`8{qPwn&G7yM27zAgz7C z!PN{!#b$9tuyTBiU|oyCRO%B8w+$Z$+_rjL;Psjd=$hH9@W%-@T0YsZLge`1_5umq zDLI=ZrlO{TWqbT!P4QD68nQhnCc+$M9DM!)0GK5On&HDKDgb5)Kr>{a z5}^U2y+}Bs3hF8bAi~Bh(ij$nM!*7#2rx@p9s2Z(v-ZN}_wm39bezz;3>FSRrGHFJ zZBG*VQ$ntyLLCkP7VL3?HR2(`>inaF+is5oZgYJ+OtdxttN09nJ-)F1i1;LK)vSh? z1!hly*&tA==&-Q>b9j|eU8u}LkG?2T zb)cfcz|1Jvb1%c=9K-l(e{39~%Qe*V&^Qa&k-7~2_ zuoM(ZyI`=nVPIwyScWW^83o9MRZ%FI83me~<}{x~py8&o0DC4k*d|7jS&9mP3MmxK zjN(9v24R*I7Ocw-1fLqm#X}W_g{{tUFkZ)yRYjO8Oju&(m!4$0Wj{@Ee#{jow z9uwon`Ix}k?Gp^WOtY}-`$IzBz`@=y%R=AVLEk@%+(HWrfE8&z$Q(Onus{caG#bUY zQW#(+9zsq5FokrugDcwpNSSkt@pkxlm}t)#{J2dhl!H5k!%>=r+}E+S6op>*z!pFP z&#PE4A#x;GDT8K+!Wy7pnV?{n6ypp}llOt0=Icnb6xksNVLm?5WT0bC{`Qn35(@j=Rn zhh&@&Q#`EV2LMG3R7eOK1|*SHJkXvK0#i|wFhw1^aN&NmgkPNmHO8|Yx5mc+J0yM# zncE{rh02Z7EcjwOhgnM&n;``BECWZfOogL+5I{P06$N#~z$_`o88V8B5>=QyqQHa{ z3uZ<^D=ILsVg8)$a*~PW8iQFhXish%>Ot2fz!@{l0u|Vq*G;x}o0?{c;XpEHvEFkoR#e@_J({a%9NSV(yo?3D=Wu6cO zU>!ukwE=(9U}i^v9kib$CR<}Z*aTrg&vaQ1QERx4A&Vz=^(fFCM22Q2IC^-8W~Rd(8rgdn_PDW%tmT za6}bZn2!&(1rC6tsKzBmVd{f<&IT(A;Gwk?05c#NpGyJ2n+byhK|6ISnEe#cDnCB3 zpg)DfQ8$Cf33r)e7QTlC%lt7zuh&>yN|&J0WX>7VSWb;0Cn=_=D1haJ=$V)KL`j%3 z)5cRvj;0(j^LeLVnB^F>_a6zg4L@d>GLW^#Do(>yR0ja;@eq#_w9KT=LrOAD@Sz;~ z+=~SlRSX~XLN4rM5j=x2CI#VEUZQNM*h#(Mx=B zbE@nvwtz9u5qVl}1DP*~bXTkaktb@))@<3T&>cB%aDzbXR=p@TTr~O|x#oGj7u&_3 zRomRfwmgucx_e1tT(t%Ll^#emCo3usVB}a=lQ5d!)#{en6rkqqU%o0^BhZj}YP^V_c zBuLrlnaG&}+)W4Bmydc(g~y!<-PebQEF>z19v)1w93E~yoQiXp(W=uF)kKUV!6^#U zXRzDApKKven7*gSC<$&u0vnwj2e4n6#Nz}T6NiB*A>E+UU~PWNF#%hCyn-AJRt7y9 z>=pw59Ous&8%X*Xye@N~$0VM^@j_3iaoq8I2mj*YRxK+DO(SW>lL_{ZP-^MCzs|KQL5@(=$U^4tIXkACZ)|KWRI`#EQ!K^a@p z)dwGb1Hhfh)54@*Ds7cmCP;e(?Lix1_4*F8*nay>;#G&wuwfTG#GTU%vvH41@qVkkS9>-7o*F zuhM-=VWA5D9BKdU@BWj{^_P~!p!MLt>_GOt&X(%8e)qFq`xa3fj78O9K-%HanKi19 z2|V0UL5qj>1qmDFae(O_yp`y!4OLVeQH5zK3Pw@kqKc{}1}7XBjwLfNP*H{MRtExO zQA;0eQWiWY3n%(ixMLLy2Vr%^!-ENxV}~g!rl=GFj1+4 zn8@KcVU|=hA|*#KQ9@5Za!tpIM2Z-Y6>3jTSY!hj8)I^cg*JxvtTD8Qnd5~4`NN|x z(tffqlg4^YxbVmS@?U-M&0jPo%Ia_y5btch_Q99`d%Fn!_08!JKy_lAd(cp6czEJ!PDBm z_h0|pfB)eRf2a=SsYPr_Vo(t2&h>kL_aFWfNH1<)1D0o{#{CEH{^h^@o2{4MGQ>)? z-8=u|-~G>b-u>XB(E~0if&Gn_{_a0Q`_k5RP;B4=OZCdzuv9O<1xt0~C0MG@e&LeY zN4E?!BaQ*I#b$G;sdxOqxQ8h!T0C+}j&~NoL38ubKps^(x0PVWap4-U%LsV~*z6Df zxL!CD6{i>*prxhM0NaeTIG6zvoyitm12M+o4#(lj0AYm0BY-KBM}#cZfr^TLwmS0( z;M_wjSjxFtibe+^8;)#iY*dlWI_Ah)itU@n30vC3fcZk`($b^nr!cTB^ROU|jP=4a z4zVK4g|loO2#kdl0D_DM0JlLVjE@ue@dTV%XhcemOo|d#PEAofQ>HMxSWlB*08CC% zkeTE5(+V?Ft|73Apnvu1aQ=_}<-dCCi{Dtb_^HGf^)5%g{_p?efBwZ^|K5r%aLMF- z>x*CixnKQtO(ge}+-A!(e*U}v|(k z)j7E-+S>Tmul~k&{^{@hU;p?2qYmfDUe}z|HfM&6G(xVRM{djX$fc*p5TNY$!-Y#pVg66??KeNTbeu)wSMxSS0f<(zB}gdHe9p>VtJc;WWc zVc;}AcLAEi*zzR*umEE$+>e;?(vPMyEAlu6G%TEnv^}TMSYy=MSb29~;Q??@VilD!Q93I%o|Bn?B+9Q}{onu3|LgPL{IXHk|8M`7|D+CQsZjys*SlZ&=IHKgvID-^EHPvJ7JJyF=cV8IMnkPHE+qJp5G8{)7x!jp_YaO5g5kQH?XM)of|%N~*O zX!$q*5lMBy9{S9Z9|)|3ngix?I5>*xoWyWWYJ5^|eo}5(lE6bIO4BTeOp9U`<22Aq zn9`!q1L&w&>jRh$U?8=WV7ivVTJzC>qZSoFlZ*!+JIcvFF*6c+mpuw&cPa$lGC!tp zyX+X5=)uE-^x!l=cVHT57Nn^pYffcrUXCaBKF>cQq&#_0+ zF|(gQu*CF%Wdsby5v!Y9a zD=Kn#1oCKj`?c3T_zF;XU;2gbNPTg#>(u~UQSm87r6)`E+Jg_j{Cj@_OC|C|*bsEd zDbU@QGaXoC%$_lZ_DK3;xBoE%u1nYgh`?^Ta65zB7Tmv(FXiF6ahr<;vtdB{6mVEY zr3SBvqM9YDIA2$sQQBGH?QkGWgFF_<5R{^zVf%%ZI~Y?e56MJUEF49(qBEXXXr7m; zpO@fo@G8HMef#JnglED7{y`8pb*{;b#l&$J}QQ)0tO zvHld$Qc}}`%nV*niw&pXAk#033}?lrb7Iq3k#PzBytaOU>P}`8rL+|FlbMs>5q;Q= z78?Xd=W*|FbpCWZpyTgH4_m6^hTBI+0%^MAgOR-CHuedE93IC$0;#2$lQ?5#=j_l( z`s1<3rxev&U;MhK)K(Jd{QA|u`nUh?dq4PnORBsi0h=Gk9{d}rjTG*@ z`}rUIi$B|W^{xN+zy8$1f+y88ggnypvf{Q5uo?(hHUU+|q#u!Ht* zy$Tc+7}zV;Aamjc3p1gpU}1nrdPZRvxWYHzdjDVl&EJB;oPqZdPgPXpJuajd_>WW@ z%~Pd{bv9M7A;voC;ovBz z!+^*s07p^vuWnQaon*D-PbaORkk;do+Z{rqWkqYaAlH0aB!5~UeOe%YR-}AJq5nqB$j2pA@N1iqxmY+6Ae8QA&Q~C(;Aebxvq_N@RRmYyvzf zGMyC~fihcQ`x4$50fwMyQDiwQwl0aRi$e1mfe9W~!Jjt*y^f88@mOS;=#ojsUCROA z<}t5N6m%h}GSgtyIXqZC#|m52BZAfUlL4u0#!LSvh9m1OdTB=6ncWL1SW9FbpJvZ& z2~=N$^jY>}7ZN6MM*f(bVj;U=iap7+`~i%;I-G-w>PugLMrj4ib2OHsYYDfR}{onngKe_tg-QWMyfB8$l@tdkpdP%DPwA$9Y z`N}{4lYhDY`n$jL`+xkqfA}Zg|D!(z{Pn;4yC44Whu`_9zkTn$56{U=%yPt0R6uDZ zI@^F}ly;yPfRbxmy#q>>9_%pM0#{UP_HekdPM1ogeNID`>JR@U(c7F~UkI8$HvR9`n|FJ5t&}+q`GmeOYhvP7oO^1ggo(=&=QN8@&`h&OczVrU8pZnp-5gAVlj3;@<6Klp(Jkx2u zc|l-V6k3)bW_X|_&@BqIivrD}K)uLUE%KEMeC47*wJ20C3N?#DEntCK+2JxxflOw= z{BE8G*+W<_{+L3KHo6gx6*TjsfR*sagHPTe*3ownI32L|r#3;6o8 z1|%Jwq-Z*6iODI7Ira=lI+DLSoJABBnSUtr#c%)8KmU_IAKZTRqRA_8N51>p-~VTS z{AZ3_^F^IU=1;x((bvBBgFlFMHeUPSOaJD7`nzDQchTsU_+qbp@a5n6gFlY6)`8YZ zbaw#B-pGe;p|bL~Jy zbu@c!c@6_I)TcmisBjw|3n1_YGh<;@6b5ES0#{llPk2iVt$s))H0`Vbf(j`V%#7ku zj;TITfRY~oyK`|HnWLg+!OEsNa1_;pH+J86bMOAEn|JRG@7^1|^6K_m@7#LpGk0&_ z-&^1BZQNYndwFl?<-NhJ&GJ?&-YEoYX>TRvt7ikPLZDUh)(iGx#*mCDiGbMc7TBGu zCfl;!dQodWuQoleG(IagJSEeglj@fw`bCL;L26i(nHJ^dCAsyi%yw34TLMUIixTUC z$Z|$#0`ri(lK{*FH5d&GLd}v0pk5FtPx0g@*W}>!G+(s z&jgg&DW3VXzrgSybh@E8W2IOK}YxUj}!dj=*Q&7V^w zjy)=;02{aNf!9M)ixK>yaOK)(Fe z@BPu%%Wr-CAAOhlRvl1C;l}VA-}&zE{mGy2+<)u+um3y{VXwUZ5#JR?tI)W5=U@N3 zzXgg1D^Gf`1L9JO>P4M<t*;kBULJ)JIuNu_2pD~oDN})5qrScev0CO{Rh4}~FibR> z!D`)Ktp`fAK&I@=)`G=Oyx2?TI*DX6N>l>gg4db#*fMTg*6S<;{k3?clTVFmg{^LR zcU0aP6*h;dK{woNc#CCQCTB`!b@7ZUnv#VR0)J%L6+CbCecI@LTI+aHWjm{|EXmA^ zQuBh;d`4rMkCB-nd!6?8v2!{M-o^9Kc80#LBd`(!{3+(SZp z;e+fDu)cr4p%)8m9r?t;>{V#tXAEX$W1H9#;MAC64+aCBIRG0NtTAE_2OjHkustfO zSf<&JU6A}?2(dTz#c%(ks}J6NN@1ofK}Ce_$lh!3{POpHr+@qYdA<9h!B^hC_2pmq z<)8iKe+-Np`*&2K%z{`CTq4ck2S57@zwnR$>9>FFpKQGJx-n4#{}7`22WmZ_kmM7J z%ATu#<2%0=>uiu~h+gQ5mA7wx@!Q`4#$Wk`Uv6K2N$8HEXIiK|RfTD#N-u!*3Ognw zcLlUafTV*?JGI#8H*`y z(1msSh|wIk8KX8!!X0j8%G=$}&F$`;tChXYc(3EGl#H2-E}hY5^TtBiSgrx|#j37Q zRcA`FcvcinuKJ=Eoy7B2-_s_~IfMJG-o2#vEE&9u2JacY=d{*!O5;4KvOOU)osb$& z$;}HufhjC!<>n=cVG;auAkZ%GG>bgV5{-6=r(5L1&ET|1e@di3DKa4FPe6di(!-nR z#fH-o!)fqFq@`3BkXGcW6$wXFffTUHs3Fw<=u{8ERR9Byu*W-S*bt8hmMsJuPuSI; z@(3Jy#W@hlUj<}59k$yo)J^_64IW89Q@-;bmsK* z8K<-M05%ao+cPlfut@X249K;IE^PjA44;)6&l}upb^`s^2vq7BmGyb8W7*M{9lnYgBhH?IsBMnoe z33~vv#Pf$CK1M|~StN4AatAP?kN})ZGZoTN?CFWaRAEXhO;mv`|D-(!c2eMAZB7Aq zblAT%jPxP-1RPTx1~}eW;WcsfM+2zlLqhh;SX8la6jh<_%GDg1iY;C+g|oU~S`*A@ ziM%0PGDXT3qGa;s^^T0jmQ-7l8e2+lOB$^SfY}=&v zSBY-ZkjqG-5n(tYjK)OqgeaMkBvbNqMq4NuD>X~KZE183)wZ%w7p6*=!`bJ2iKkrA zv-a?UHFU;G02Zypk}b4k2`-uZP-$uGiz>^a+^{Isot0>xl4zclXg)2`JSSFvTBv-A zuQXXTb9srii9bW*5)LZE#D9$XntOHGS%%Yw`dq}3@X zu%H5)#cA;0BnoU)H5rWMevjLZ&IIWW|=KSYt(FD693SRi2c>m6SV^ za$7=biiwR;ks&HJ$L034#+fy^a%OkV=E*xedAGOd57p!Ojau`@`r!VJ!E1Lax30#v zhK^QUQ_RV;8BsF18jY?*!fTN*FA^5UqT*yin#rh26@9Z~>8)Fb+lJnzygpdVHqJ+j z&jixvJc%V&Y{?Zp=ZZe%3_oQLK5g+nZFD_jus>(8U9vd%PPg3a*9L;dV9*o@=)FF* z%OkP5c_!y&o&5!+`Dw9kk*7ShB0sSrKeeV>5Neks#j08R)bonw!Y}~(xu&sIo!1~5fRQawi z+xDbe&ScXOtJ^|Vv#+SLXB4J{#1Ipk6LMEhN7U@eZXn(cgsR?XBb4f=(}P@UP>6N& zfkwtt&pIkuOC@Kl6m*rMrczRtOVWH!m`V!bF=0F^O2j0oge;qp<@53)xLQ@$TZZn) zJlrvlb~T+1VX1vFUVJu?eA*j*#uNFpH}bqE^t{Xeg2S`w3o4> zwTs<)oyDGK%yWl8>D3l|htJfT}GG9E}{1~BZIbO>oVGXw>jIQ!-*%mvGT43j^t;N3d|lfEDL481_IG3=<<+1I778FWI|B^{yra5%>r%VNjSzFMOEI66xNB{D3Bib zl6`Ny>khXZfttl%wGefCtmDb8NAer-c#DWN!};}Gd8by|u4hKoU^C|^C5^ebHWOE6 zlgfNXR>(?=M22F%6Lj*f{4whB<7P6AhY1ZOW}R-9JD8=f-9{V096Fl z538$aF@*IH25W{vdWi_@aziN37}|3HV-x(!ni=j>9C>5PeVvK1(=Xi)XqU!(!l+aaTzNxvV!z3 z%e7}+DA+{W5>r$Z)9lAC4Cp1+9(BR&0qiBplG@Vf-WgY643j=~Az{-Yvs@7S86nu# zBU=(GDzZFB3PHJ$UTpeIdjM-sZ~RPXsuL$&=7m6p)_72jN8q$U$mUPSg;EkKJdi(W zkIfM(b8h~?W^RZnE*$&g3V|kK_8%xst&y%ZGL?F!*331#<=%R8>+0y%%hw;g z^XkiQzOr>=ueCAAw;F+T%INpWY_?UM{zaMc8KLwkq4a67;wiE6tVpp0Q7wtpOA?^5 zwB*m`0F4FE0qCy>a+#1>DB78-3&2P#QtQB8L6%4yraKP+{F8wWeMC-aNYsFn2STeZ z)d>O3N&Y05mV&^Ui4^8B!7LV!5fFv@FF3Vrz?}mv$;Sy+!h@lX6=_Aq{>ccbG3+JE z60-+z?K$}aOJ-$fRu%@h2cSC#yyXo7x+8lD zn6a>lfLZnc%6PKk)Xq2Q!sbuGrn8oqJ%DRJ8G?pMhc49SN4l`-kZJaSasG!7fw-{g zkXbIkk}4HhFgBeuBL~KWykIwexc4LJq$O-6G=IR<5R6b@9NG6Ib3-s7>Et+Pz-Hn! zd%)Np3jvtwf`s4{eimqvpbObMRGYAE%UIHI>=967)SjH(@KK^?QiBZ60azGaVR#qR|y zd)><(*RtEW>~^erU80armyNsXg~V33dV9P7>W$&6*PAy-mA!U(t6JGA7f0D_H&z-Z zn_Jn|M!GqOxBKy4KRFnr*N3@{QGR1o*xD#>Z&f!pD}zySuwL5QY3yC=?p^QSyu1Cz zyDz`@;hXp0e(A<5*Y{uA-@dcg-`}VV+p%iFnTTqGfT=F1{hTF&svQYyPrIeek+Q409&hiY8|(2#KicWX`h&!1lv*F9DK^$K8|&G@Al2=~`-9YA zm~M6A)q1$qO^vq8TYHW5-TKB}bN6Qd?t}feKX~=MFTM5Nm*0N>Ywvydv!DOmH$M0F zm)^bk=H1qAKiw%uYI$cSuJrp>&9>*2x+lfTC&j9#BLrnKQJ`29DuL2EE72^9 zRHu0IQ+&mu2p(%KNpt{GV*#y0K4gIwUJyojF~AgjduCyNPnrYt8h0UAR{>c4L@pw5 ziKq3`_MM|b>Y}gj&}4f!b41C@?cN9Seb^Pjeyr0t{N}M{>xvr4uR8L4u}F^f=NN z2Ha(%XFWBWho1OaYog1Hj^Yw3j;mvP-@ttpf`OTmG!mD5T?CsAz z*nRWP;H91VwSIO~iM7(HZnn5lDsNTt!(6Np^<-OO%Yt8HAXZC-Ee-Rs|eedqPh-Ff$mufG2IdoR6v^R>^v{PvgM zdHXBxzxv^Odk^l{_x9rLjyqQ{gkw^dZ`EjhL7{y{taw(Ud{(M@TC6-Lke%gAmjtqN zLiv*-AiSXVdJhdUkslY0z1zo5&s zQN)27X>>&<71a#D8bU>(N=0QtF*Sb*%9vzaV73aA6#`@mu zdfD{Z_V}EliUdo=g-r(_wcwDVmb}Z5aq81< zWy~q?TLeD4gzy@3>0rMb-PnkXHbTSoV6RVfJML=URf?yE<<`x?&g)liynAco<&D}- zHQh~yD}G?*~hxaK0DFw!EdbztIadd*N0$+!;jsqr_l6321ghxsoH9vt){PKs;lNBz3X0 zF_AN8D~@8rn{Rk>bq`Quy`6M>Gg;|{vJG#l>MFE@?X7foCs*G{R!50GQVHJx0RQw! zL_t*gMz*t8UB5lN_2#X&zx0_8zV)Rq{n9tS^bf!J*>8UFjW50b^80UJd*lB0{kx+( zH=0+sbHiS^R&k_K`cO#W_6RK2%NqR!mG**4cV4M|UZ#FpBwt(=ommkqu8D!_dQt>$ z)q;1#3zbjHbkC_wPb-XPCAtL>7&Iz)!UW!c$t={I1OpVFVCfem2Eb{t9&ko#T9Cqr zW&wF|N@SpbkChkcPYB^NOW`vefbxL)gOnfuc#{_O6nGSJaYPgk4xa@|D;nM;TKJrL zK1WDR1tl16BtB^`3-l zgHDX2!C3_k16A^Q%r6pK<}rwZp=-)9AXjjBb*4Nb52(;ftenDJ7<=e)7zGA^#>gT| zmx}GjiQNTM2V0lXtJH3UxgbkF>4M2A3NjqijIbk67c@7(%qa9yj^7GK)`fP&U6>G9 z6gC9rf|d&JYdR1oG^hx@yG(UqK?WEj+UUA)bE89GQ5a+B1weDdpxTyhVFWat4Z#h> zvH#JCuqizPCluQ$vqs~iyRi0?od^{b^Z5pKPbX*`wBmErB$`gUkRhn7>&ta~xvsxB3{^H_xj`t=@@9KPV>?w} zk5$@%a@||1x@%2;e;8ZeN^kGwcdizCqj3v_oYciz~0^MjY) z|Jqw`et7@p>sNR0ZLZ%O46b#D*Zad8gVBxA*4^zJ4{qLm>+b%mH#hF=cCL@TT}hk@}1P{69_Jtp(--{8pgm34!`kYs#NlQ+|rCfeJ%xIwdhbAu{{}p7tN` zwLc@!KLJvt){|nG_ymwyVjX$^yM{pxL2o~2ZkZzQphBk~0xpISfaIb-WQ3(%;6nbI zwHjjqAOKJ@i-nUdIZs$9$)zK2uAe9y1Ru>1YU;96dJI@ZSg=dL9-r-#Oiby+KzYpr zi-LkzjR7-*pvvY5S_hF+59xwl0?c$7Z!lQNXa4g&2D3*%)3J4&PRA4#1rmkbU9eW2 z6$R!`ujA7Xs4#l~Q>uAU&_sG?Wuo9A7|?W37t;6$QMhx2biqdElt5$@(jG9*4R;)a z9kziSSSBoKC`*QMbhbQ`r2>{@^&y9JVeJ7(`YabKVY&vSpwP&UY zIaJ67ry++2)*WJ!bQ3}uka~6D|W;DN5NcI!%oYR@II1)xnSZxg}y(xVh{*H~O z(Dv1bp}}ry>qc(0muzo@YyCi}Rdox`>&{A2}z#XH?lvlXZ}e5I-@TeM}0wnEj}=ms~h=Jsw?HuiJt z``OM`Jm2;ZS-m|hG5Yy>->S~Ls`akweQTzmz)XlNA(1UCaYW>Mp=3!QJ;Rfn;ma09N+`3$8hDxo1rYT`JfN$zPYAW}=XAvS(-PAesri(| zbV3Aw4Dksu5Lmh=#9C5UK~9LYpAu?*hOYuVAp`5#tiKROCIDAsL4h@9i3Cj{;b<>1H*_vdf)8Z~n3>3`#8pv-Q+y)=_>%%IF5^!# zrvUZJlmjhx4pZfv3+8(mW~~mG8O2z>&_d^MM@OtMdi*YQkHDo9Ejip&rgSK}RvuEg zj5~cw6iiW3%y(fx6Pa328y=^Fs47s7(_J7(iNaJLjY0C@Ok7OoOTg1!YV@rXY1kVA7!(J7A`a7Tg|ioG#E3X#uwG*qB7pAyb=c>;j{V zLr_OkY`AgytYa$rW8A3^2}6&mW)=)fWQqhsOr4J`V1$z}6(K_~i4fEnu?Ng`L23aC zz(5rV0^XBD1!Y{wj}MNb3b%+rJ>V>OY#Em`A8_P?y0BB?F$)|fk;`gLCt|%;yx$_4 zWluR_19~g#aTdMNZmharsqU4d%@9%X7S~gi&2+F}vqhBNq%K;tWa_SB+gI%eo9mIr zdZ^O(7u)V!!kuBIt6<4zz z?DeC=QDU^79Ib=b#AqWqTu<}{kxnn%8%9T4sT+6eFTXz6zE-Go{Kb~H)bRm16|Y*{ zNrl$CqHtbPd#|W{D@xC@(tAZ4`qs{^y^ZVJm3||Tj;bA&WrgGgk>Gi;=y|dDS&`^T zf#692com-&h?fLVX2An3vGS}`vqZ8Wp=H(y0pz3z=p_9q3HgDb82)_W6Es@*3V(1~ zPb1brjU`ZnR~8_)04GG_M?8S{Cqy8HRb3h&=El#vVjeNd3}U!AqB4v9?2lDiivr~& zO8`F2A_R)CxuOam#}GIt(P>EuDGWwP@hJ4CdAif^6HG1nIVJ*n(-ac4*GfDENyf=E_A_|#c^D=F=#r{ ziOg9D)!CAtW}ONa}b4xw9&fk}s!$Y#u@L#EjS4sw}Nea><;Yw)9q0NQ>s3L~l} z3&xgey4;!L0%L(b;uK(NspyK#i89ND21cR4%mC~qY_uThq$N@dPyhz1NK-y8L>L$K zvBObRzKY*f@H%o{d&X-?dW@zzJ7)>f>! z8LO^G3jJWJ=?Ugd&bZp2F~+OTT+>%>2WxGj-X>bzaDSB8*v{_k754UvyH^X_yZNo1 z?B-5(Yc~fHuU;=-yH(r0UK(wuH?QV*ZoHFxMX&xRF;TDNAT6b zHC13$9pq_4LS0y-3yJk%i7_Ix#Fh4x#+^0z3udBZC5kqpU=8NYfKb5_F4|%hN22Ns z<;~utHk>zS8lH5`6)jprIa4rW0I%TBa*t??qV3H@cPBl(n!kFdard?1otJtyZno~; z?Z5Ww*8Tfickhm_U+?T)ZQZ&(di&kGU;F0!-}&x0fAu%M{mpNG@iQO1aqZq-XQSQT z>NYpJnP$nKiCIH_wc9SX7w;g_BcJ3>-UbJBK--qKbs4BLU(`18)dJpi)TG5dIjjD}ySaoD!%`2~{UKP=|DUfu^n07(Z zA%}695``@rCZ|v^7pzA}4v4~lrlXt05nM=BL2eS9F#yN^EEgsU)@W>q!@B?ua)Dmx zCBQ?taDbB?!YV3i^Tw+WVJ*i{E+kW3Xqa^9LgqiCksrckO7*c73BANL7pw>;D;@m& zjt#`QM8Pc;0M?o<*o+p#Tv#D;co$BTsnwrk{uo06Q-cC+E&!Vj&B(TzEEruX%mo=6 zTu|S~07p?d^Db-JVb8eT`9Po?4L8!kO3IUqdh$_cmau1h?txMo{(FjN@qgjPHBm}DOq;{EtP4w(lvXw?tsTpZ4afTs{KG?6mG0X8XM8Z zMyxuDWLjRLV2)Po#eS%{ne6Rk2iw{1MzS@C)jJ_TXAmE3q=%cC;YPYUOfHtqF}irE_JBuB-{Z0@6lz#^}wO{5i8PYw~4`k+LJz z^u=qgaLERgR=8mGrS;C3%AeN9O7=`0D9B*39VoQ}wJy=@61{$8XFGd+zkK6*_4@V7 z-d=HYGqbgo+uyIf^2++>KY#bDUwz|CUwZw$_wHW5(cj#zzxTQO-~9P6y!XL_yRYtF zySuY@d;8i;`?p@Zb>r1rS6{leeq+0_*(-EwiE2KOOE}_TQ#hyz_@r*Pz~NZ6*v@MW zpO$N$k|@uLQ0L^5M((AzZK)pzX1OVOk1>@|r&0#ybjN zJp9N`VG9OeqaQ5wj>iRUfroLK-e~h&pci@xaGWmV{TrS`AYDLp3cWs1jZZfZw_3i}jz2$D|1mWtzolxjwc&2V9E!$NL# zrwwMh&>S`jY+k1N*vOm;Hei4Y%Y@|^_#enL7YH*Frhyjqn844dg0)bv8V*##!Adkx zjCis^SK8~z`9d`!+6;y2K401C%$dyzogt#shvmkw!W30lV=7ll=g%35A`nKlY};EJ z5c!TbU3cV~u5#Dc7=^mq@%~kVwH3@)J?Ww&k+nwCCL*B+#BAa?Cu z>+XZ$&HKIGJB`k6wzd(kZzTseO8XCbx8K>g@%Cu+QZ3&0nBxjnP$cv7WqyIwFO-5; zpFrjl$bCYEU!)33G=x+O1XftCk0^{$r75a1M^&Jjx}a1S07#4>xjCXTN0jD}!Vr+E z-2#=1ZzAN5n8qGa0bEhFC#DXi4avMYTe6nx?slKp*iG-R($9YQrEh)o)`xFx-rlZnb!yw);zm2(DtQYDQ!JqLIpki4%wrch ztZNqI1&!)isq{&a=&V3^PAEDjl$;YvpA^fVk|>@OE6$05>XM(~%TDv8rvQ98kO*f) zsxx8@JnBhL_PCt2z+!hkQ0?&MrpvLV&CAfcRo!4%vc6eAHWAd%oS2J@F5W> zsJc>~0Xmfg>MBxNks1p?>Mf`gDalAf3an|2kIFFB#ln8q5LV8gE>p&F0D;@5FfLx-CX_qO19@=HHY``9qQ!I=Zoew$Ez!YFN z;Az_l9gcP(Vd_qo4ZQ@Q3x=n2T#mB^xammQesqcoHY|5)vo7;?Zp5C1>>BD|4>~gY zC1lc)1Y||`CdEXEF~}uo$*PJe1)I_W^pv5P-Zgj>@|bE)6b2;ypn^?t0S(Kzkh+S! zrJcU3eU1xhKlO(l0n=UR7MLd|;J5vfJPRU+05rMr=AKaw9ra{X|oN2EG|M9Uj%xMMX}q~Zvbt)Y@7T(-ul_EgiI z>-q}408mtwVW_qqX>P_kJBi+2da$1zUds*lv%S4kdnei2PE<#cVxK5<1I1pjz7g+U z&GoM4Iy;$4FB~t~qj_t(;wrU+tx=-4l>x8yex%w77aPG$*&WMT12MfbpfI~cdI#U+ z5jjIjB5TgIg0=NTX%H>+!}YDy;AVOM_5Quj?T+r%qfM_hrBwvQVh>O38W-7t@UtcD^_0*6?(pC#q3S1TnPohlTrqAx=7KOC|h!M zXT29(-%j7T*L?TgozH*n`WHXE{n>Z-9=tMm_2vGnFAwg&G`M%Sck5RB#*NnQUadFG z*4pt>Gn%XfleJKJm~Cv8>s#gWsF3SsGVOG6Sgh|fntSc$UZ=cKPj?HETFRXbnWG+U zz^?My6dtS8Wfs^BYbNbwo$5uE?9(#wQzF4rBH_~#@zWCN(-IlrNs;tPq4XKC{5h%e zS&8BqvEpfw{7IqwoKSIAq&z29os($JNww#s<42oPQ<41X8>p7xp%)5#tb^gC$VmMz zHAG?}@2od1NQ`HIx`O|u(a^(`yDYLR5diFtCwQtS)|4jzJh-ESnMQe0vkuurfg%J8 z97q8&LPw&|yB@FES!^@3Vr4go2@D6IoQ+6U26m^Q-hF30kuI%2|$ndKo3#2IWB;yE_ijgS6LU#>v*dJIE)J(Xxg?7<~zO9 zL#8RJi6~$oVTy`cEAXX*gxo}&`hj9USR4dPL!vwkRYqa*1335@9C!~dW!v6F%^4|K134p6Faar+ zth-VTcdFrvR~?a}C6qIg_k-Iqbx)~7RC|$HKU(X@D&0t-8BCU3{)E91RGNKKolB^) z@f6lIjZDRdE~Cah2qGDScl^9dy$K9E)- z_ZoPWc;S(iJRp<@M6!TT<`>F*0-09;%oKi+HY_v7)tZn@;^s*`e3f6M^a*7yp47Rf z@`-dnbp@rGfW#b8`f{Kyj!eT-==duAU~Lp`04=o@D~^bC*GrVm&a@hmQMIAY@cMgSxW09>1k_u&Ub8CXLYr=Cp(K){4tU$UXlr0M7i||86<&s!)R;mXq zLYYPW2oLikhU5o}`V;WRc>{dVgAkrz0pOVyb(8ySIYrJNa{5uXGzm5E_pK%1UpkXmkKddx2RxUav{W zo1(ZXhlV-Cf{FnEwqyV((j?R+N^hZHk_&~Sv>0F$ahI5bq2$hC52$#@e?SGRIc4!> zR$k~bB@hFWjtZTrA`BL0TsCs#VDgBz$Fvj*G+^x^YzP2aFaUCi6XkH#0cNZV^g=H| zW2Vu_cB3Z+=5ok(JG#q3Wjllm9%#xKfc0Yc>^X`G3xr0Y%SN@&1R#GFMovM{bjBDf z-lPkAiBm9c+1P?Xko2)J)ehs_NFhauDpFTXISt|#3;@f+w%bF3u+ly<(xCD!|7WW;LS+W%B?poX5?h)NysND|qyP^HP{N3BN>-&YBti+y3G=?tS@N_uu{EwcBrW2m9$_*P8+DS+m7!)QC|1|6oo1Gd%65pm+ju z3WzGmr}zdGka9u@Ro5x-3f}V#Ck2L+?Dqso#*d_fP%;a=GM~helbpIqAB0Arg%koR zvt}{2M}!wCr`Wc_7%wz9^dmYCDW^Ev2&_S9RBo>4L4i+)J~( z<_aB5OQ9fM92W|7tWu2aq08ZFgqCeuBTU<|=uM6Zgu2jP3`qJo%Aw1~>7eP2FyV4Q zpy_)syI}(ktEkXEoooaeZU>RKz_XxR>7?ZtV9A0P41#zuagi37F|eUMrxD2e(+^fu zs0%0?+HOcXV?3?hsESZt523>j=W?J9BU_AHFl?~R8lq_8d>8QN0U*6R0jJFK;3z6* z+8E4RfsV=4T!p5m*!GnG9e=6oFZBZDK2aS|x+<9K_|q*95LL;h8)&9<$D8f@bAv#B z5XklY*`6=ia>wfSaK#cR8vO+WfGC@zbsG>*X`rG8{zTUkYrA4?XQX8hH*DdWH39@d z(+M0C4Ogt@h?K06k}civln0UC)%@n|T5m63>V~t;K&IhORNRq*!<#f2yi&P!O=ewF z*!fzw#NbzIJW{ERFS83&9;qv3$@SvZjclqFj#ho?HjsL8KyjF;ZD%{zN;|J~ufMs` zyHQDZh(N(+jcK$2iN+^Zdqn`PU+hfkB2`c-Z*CAuc6`2q*^@Iy>#kg%$PdCGFJLYcNFUI${-5-OPjdA%>I_2snQj0VWHV8Ixz*+54SB~z$u1_HOf9lQE!>;C6< zZ@xL)x>s**r?M@7rs>PK1KFl8R&s=M)=17C%{h|=f36&}5$sGWFX`q3~mft@^1NKqU18KH*!gb^evPx2KMCwOwe z6Kk?ht;(KQ1Md~!D$rO!f1KnifdT`8sGs@)GaLv7Ah4d`fmh85fet=sUSx!jPicQb z0Cbi9Q#@LA!3VgLkk4~B!$-RFO(%H9CwPV@)&Tk^c={7OD7m2O0(+Z4e-ffQDbT`O z$_~MV@S4D8g( zSh9e`1E8Wzhb`U=IErd`t+0E$vU{t%bG^8+m+fyQTcb#|7cBPzrEUO-s$wrt=mqk< zK#rp8&vbn0jwjvq0+Ey(1@r4fVV%g22=HgJFNgW1n%!<%AW_b!dqPiZdt;cKYiS|yew^wLxWlH^M zFl*JiMPlRS71awo?FFf2Md1+0?E;yN4_;L+u{UL{jxyc7N_)Fl8K&}`NVY|!>H$Eu z9cpdoAAJ7i*T3_*SKq(Z+)Nj{;ar-c|ojYfGHq##kIZ+5HwbA*6d8_jZvjKC{YGPs*pqzkpaLPgRoG}4K1@Ewy(X`>t4;~I)Q8p$SGg0<;wyM-3inOv05*ds|1o+PbTLp6oRD^QLThK z?c`{f9}ctKPQ25Jt#9OZ_p1BX8#ixvUwU=xjnCYA=ku?;{ki+EynW}|%lm`<^<1~= zN=KC*=M|mqd4=MfSbSClpYpIIk}rzn@VkdR`AMD}hy#2gkuam5S^`Mu4I6CUw6Fl0 z3FxOM)}&AHB&P)OGh)@ERDD*a1+U=!DS_eyUv`o&J1vke2o&(X`!&g#HR%FRw!o7^ z_#hEL-eM1PCMO$MAVm7pV#8^%@s!ALg8WzzypqrdS`_qw77y|S-w2>2*C~PVG{kU< zx;={r<~Gn+hSNgh8If^8Y&s(bZ@{1MHyKIEby(HK!aSdXZKb0CZzDVE=Y7=D#;${K z8z6II9T6Akg^DmFH0i=&>_r7)nB#(8VwcVX0wL*#6=Ad&rlnA3dXZd`QM+o31}*Z#=9Q?!thk9~@|!7us|mSD=XlCvxn~b%9>90-=e3nJ%=}!6Ell zI2~A!y_T|>>>zmHM9Bh@W0oL@7c2woGW{rMN;{AA?_r!Z{prYb^SG4OO zT9#nT9PZkpeMhYCjP)Fmwk_JS#oG1+plOfRtVGcm$m;_+eYj)+;c^{cc@V0t$C_K| z##RdGs$4rr&G(g-sy0^3`^cHK=w+4bHI69WjKm zj(EvSWNhxJKA5)VnxSGRoG7_sK)5u6jZtE>U%Gm)efRaz>z}>)_J=p#`S9kQ2ZP~W zKHu~?!*ZQ-6}*PC#&peD?D$hvXCQ3|qzvJ_HC}QitDaQdmu&bVRkt&3FofhvzewU* zle&2duTbq5!+Wj#VwGE<^$2ZYr6;cQ#I)XsCX_U#3Qj;gV~r$Dp@bnA*ZX7IKwKBe zn&U;gKczPZBtX4seF6g^Hbv#ugvwhmMjFmo%M)vRQ~f}GGnyHNf;GFpVhy+4v5ptK z2C6n&TB8Yxl>vd$FEB*p?wlc5u@MzJQMLsNW^dLI$eV)&voB+CB{Z&>1{BE?(Rm1+ zC!q5N^?t$-3>hO)b2jI0G(yb=(Wv`7t>B;+9t|S>F460N_n|>Q+y@M!?OvqTA}Y;r zwG(fQa?Q<3eX~~GY!=sB>0XVf77US~z-GQ|(7&M3J)_i~Q)m}u+S3xvDY5312m&AF z0RESP|4sqebr5VtDhhboL>@koA0w*Hh?J*Aic>;4`Q!qi&*UcsvJ-qMiR`pcz9fQQ zW_(tnctNT-FH>BAC;{Nl=fv`7gwiMZ(z8725?@9lUlJ&mgvv#cYC)u4ARh`3X6z~Q z9xwPTE`jz5l27p|bR_iCx!}1JDWOQ1-IRo#qqR$0q<2 z+Kan191dDffRzGGN7@-phxZ$i#$@5i#f4qJ$Yz;+Km~8@KOhhmiwc3H90pi62F|5} z0@2|P*A55Vx<1tfaEL&-7)8(aCR>9I1VGand&nVc^pNeq^+GQ}V`@||BZL9$YGap2 z4+NO%^2jxskZu^XV1l!NIo5(Rn%P{b*+DV25oRa@<|c;;FDlU3i%EyD##|S`>_C(; zS(oXJKzmKNARw0x3PgQ6$@#pJx;c#Xns8x2(?K9M%ERffaUgP3U;~2%y~J8_KstIF zOcaiyy7O}T>do@jUT(0J>~6#WZJ?;y{$j%ebX9E_f{eoTjc8*#UR{p>QI+ZVQf*JX z<%%|);f6h2x5HPGNDHVXd!+4%bR3bcJ>0d1I_6;8(MVuX&ooSbsZR?GWj*BT=x1)A}e7QWbl)=FC(b`G&jF3s!nWs^Sc#jsB$G zm(crD#z4mGO&je|_z9pRp>?GV;MEpWTO%qmM*))8A~u_^dHK1)N1zExObN9mrM0F3I%`H}&Fai4 zjVY;i7EFPLGt%`YhQZ`0lo*CW9iOvgF{L!xh+Gj6%Y8z*R|rI&Iv~{&a${I&j;d{O ztv#W$fdYq=7D8bml$L*j~IHg3K1@~a=c^Tt;{ zzxCi=ZhJ&@TaJ27S1d{rsY{-~lX}Z(x$X&}>L0Ahp8(1UOh}=20Zc-H=H!~{tI?e|S+6+Ud~ZNPL=};^Hkz~~)Bb!u zQ7L5`)ncnw?lj7sW~Nq-7P9VGMC*15^!kf(`KN`#r+NG*S9#~w1n2m|CxwzHMY1PF z@^d2jS$Mm>96mi&IDX<3`?x9cS9(Y}2%j;bTaxIP#5#Dtyof@-0RBUTGaRhHVC8~R zW4s(wOF6ZPGW#g97C^~`LH?dJP;c;7Efi#Fm;;#kWJ%zn!zQAe4R@)91!ne}LrNA< zl9`%-HlA1k!6rl*V<8U3Nkn3@P-l3|ho|(Pvt%s(g z4gN62o7zoGgClKDjRe+<<3f8eAnBYyQ;Ihw5R3%}Gvo5;?EskSax4u#%L`2ej9thH z#R#b>P)*G=_!u&UZX&kPCYug*nIk3;FPJmCfB;x~zzi1v%%62Rq-x;?LN9S#xL)X4 z-Lyc{bQoAa5igDle)z0}exNua@`FI8>rJ-Zv6d4MZ@c0h zSFGcVb{yfhjc8c{O{1@_2d|;FIoh=*`i|7Vo$k9*Jy)`Ak2h`chAm#VC7X^+$CGJ$ z(oGl8QXoXBPn7zhVn0+KMyjJ&u^&#i0XrgVvw zPO-)-HwIPakj4_y+G7S^#uhGm(hZPRJli5-WmmXh59e(_;-sqXRK*p|TZy#M7uR^A zN{VpCP-uF~oj|VU%2XV=sxw!0WXkqz#gVVM3k_es;mg$A(W1=*lv7w?2SO^U@}%^E zyd_k$MaqtRH`LoNuHUS7wzG}(@2Jv>!dYRwsJd80Y4vt$j9 zlEq!M`|2)#!{aDgb#b*is?ibEkS^E4Mq0_G_*}!Ws{H)1i1N-WXJN zuZ`}%e&_RF{LI(C_2pmq&d>eQum0jUf8iS+e(eiyy#Myi*Y0iH*sG1Y>1LHEWQ~Mh zXf`ZsR2P);=jGB*OC?W>#ZQVvO9H{7K)3)AEeOO5Lh%`)NEmC0dfSP2_d+5&^z)GMf zwGe(2aLUrp0jdh>{EvZI^1#)Jo#UW=8UeXzym*u=vFYJ_R2!*G%=2{--6Nnp&6KGDQ z&~!Qw<;%&9%zwVuLj-zwuW93!E2=2SK~DY?MUHm3^)g_V05Tmm9e}cDytwUvfLwx> zjF5E8cPeT@`J^W2!L37HV6gT}NWzN)Ft~zB||qH zx)Lo%q+;^tw86YCUbCi}@PH~>wj^ry90<|%wE$r8*N{aJmmV2anAsir4Zbwn%n%6fG7rN-5lnj6%RN@y){Suj9 zD)&oeK8e^Z6xew}J5THsNZlfpPpa|DR33@KDO5UzT93pT)5j{F>L@w9UhVAWQ#G$Q zrnUN|Mz_%96`6cuTTlixpFJqI6G~@T>rY!FB~PM8Z1Y*Id3A_0}c$Xe;$oGTov;@x&$J6Bh+% zu1L?WDV`RnUXbc}28YDr)_MtNJnhfsBIRPTQBJo@*b0orbyl%%Q=#HSE&)|3^VIH)!plz{ab_mTf^&jHtyWN`pO%(-v0c955D@| zm%sJV*M9M>~N9%Vg+%}2REU+2ZEcz9bZrP~4q}RNtRXwLx zJfoC7C6}C)2p5I?1wIdOh6h>TfjxJ1LiicBFbVP1eGmA%WpH%TUg~YTJ3R9_vYl_2oF~F4_crlI~ z7upNmav12naGDo4fArEJiZ>+|x$iQ8=2QwzrvowDA(9&ehM40;!?^^Q8VFPhbvat` z=6azilulw4)xn|)y+j!^F5E`o!d!x0WV=D;dm)#gCE|r%n&-v30FZRZgbOSf3EQ)P zu|4ZDapuH`D#mM0@z8X%Mw6px9-Ka9^b;nkSXcuJj-qO zvvs@NznbpvX94Y|jF5_nsM}&a zcXH^9_uR3zGuiWGNB;aMP#6WWJx{!D3zv<-g5ICigo*|rr{XnBtZGR%?3uPJ({jeE zwn)hwEm>j}TdL{Gc6`aED^j(E%9cpQ7OOkMRj0pbbEJ%huv+DpOI#w6LkM2w9w|WS zlNqBrThe4r7|e0KA*9myrP_eZ6jr*@hFHU$8xX0sFIIP@TAo5b2aHUK_c3cM!k_HfA@$mx7pZ6I%mRIKFlAY4F5Ig=`PMjI@d{RN{lrMATsuB6(R z*7}laPfQuf7_w!1sqU$_0*zL%TJx4Fu4>%}-q)IeO2ePbTfJeWlaM*X3RhI=im9Cm zjV-1!g%y^##*r~tfnbWMH6b~C^eA)Aq=_nls4}E<+PGE|)2L%=pr52cnIs?;c!X`X0R7|@3*AByc<&VhIR%hiKpG4^vDx3n1S8N~@u9PuS z@dSZ7iD}J*!WfVn{W42P>4<3qIcuWki&ebvu?t0asN@Y4J^pKB69vb@JJb zW^z~$HVgJbLgIHkuT^|nEq_+6cwVbMuhV^6rFvSf06Zy?L$x6gFY-i-JmC^gxVS1f zb$Rvdn(#%1nrE^q-994`3FeFC;b?f{#*GKBZQZ?D9<{@zq$B1w`b}oSXpI2$=CH;Z zRofG4M^fcVt3e+Td405KN>yyxx+~xGl-hns%U^5;@-<(s>Z`URol$1*R{Q>2SKs^S zm9PBVdmn!N?K`jS_IGOC?OJE6+SsU6ho#b>nD6B?ooup|iPcl#YBErYd-4%SCS*wl z3^A`N=n%V2e20O=2;kX`D^~roNqbSRdO@RjP9=L*A$>+Jc}gmNQX)Dh7M&FdNx&P? zS)phNAP@oVwa6DO0C=J^5b+tFgapd3MZRoNAU`Wqo&>WUEEe>=?O>$()Y3!kG~ktl zU6LTwHp7BkBDW=SIfmN_=Mo9F*s+{~x3xiq#QY`_{6R@7We&iGE+i+)oZ>N+LKC@Q za*Bnj+EJT==CHdv?M2^!g{0Ga4C4j2YIe(^w@)_K*b9k5fn1`Sg5senHO~u8r@ffH zaLNuk%?mBw97Q$TYs!JsRF{YADXe&)7gz~339COqBcQP90LGZ=XtaqiFZ2>^JmCd1 zMDz#vlf5*{1pxDBT@J6q#$M#w#U3oNca>4@bIzQQ+-Tzi0-;`rP=m1P9Pn;EEF48u z8-~b7oF{vG>E;&vW`1=&T;Gh=Hly$-iylf3^?LrBZEovgL|5o$;n4 z)^tP~cA{zxR4p-}iberIst3ObSlSHNcH;G&cy%k9Zo^+M21J22Dgoe|C=^eoM9r3N zIKXSPY>t#o5s*^1<+|SDFp%p5_2!P&t$~s;ST+-7t0!%?hV%xnR_9b}Y-+htCe=#h zI+}jR1Yyj#oJ@f;a7_3^nC4)1svuD)S zgxr=?I@2moTI0{?!g*t|Y|GbO<)*jR3D!Ho2B1r{2H|EuRP6)`4Nt6K_9fJTjE=|~ zBV}v64kV+)pEr54Mt{K)tT+JvlFbxTNnC3}$BNV=ka~q;k3a(6_(bx6L=}=#pYBQg z5+I)VEci7Ti zN1iYyy{fR2?=rlglRd2zKcy5eNd>0_t52+4KEqpmN-RDn;Gep@eCpEWvukTl@dZx_ z_)iP@PlHzh?~+n3FzU2kmnRjE*Gk1ftGdxmHOrAwCRHz#`nB?)mTMOxrKmIJ)O&S$ zpT^)<8~iFmKw%6j%ps*EEH@DnTSN-lGg-COhQtv3Kd_r>Z^cVpf2?Q;q_p0++7nfU zGR9QdQR#;IJGq@(^_#Es@4PnJzuR8lFGH@DM_0?kz0zQ>H~_D^rT%WQvz0G*7jen`7Lm)aX49@(H7geN z6^jPIa~Q;4o5X7uxGbdnGAx^QmyDY8I-tOm&#C0k%B4@spaP@imr!_4Abd(7T#%?w z3S_5*@W&ZXi_}orAnOQNjF!Y;(E$=l3q%zut;qWc=ye>f>C^*D$$Q@EC&g1KEYv0P zXRzU8S5J`N6`;Q^KmrzV>N|Si6~uz864;7(niDI^)2ph*HT5D-y~x)r@W>N2z6MA- z@UPoR9=!9KECULR$X&h<3;9rf@|ArrVx-j+pq7GiijooYc0uk&NHq(ZG6PIbp>Qo{ z1Om{lF}Y{3y9H=`sErUWx(#VKm!R?VSWL^49KI<&PA_ObKF*nFjVUe@l7)MfjWXX0 zy#$!$g}Th~!qQPMtay;INE$<)=&*o4$6%HK^eWYKlMRTBB?xi}TC)1%VdT+ay-aKlcs~;b`Jhf0 zAO&c<(;W|ZO*EachCK?@Pt68YNTLNql`94ko2~?~>HBjdqOcw+u7@g{k@|MLxtjpu zEZ+;HTkcfdnXCilW;OP#+L_mQD+X`P2=F(| zzJ>|BaaZ(?qQ;U{7?V;N}o*X5{Ya) zp>&x{JB)9l#Nuf(JCO5sOJj(N@J_NesgpG{{HPZZ{2w9T6s`%$6Z#!Z1C#b zaYw8iidVv+yw4rC8T}fSL!xqs0SfrY44%xkDz~jD9V@1Q$eU1So9^CTs=J#6|0Lv^ zo%&-cJzgJ1D!mY( z1{Cmmq`esj)CQqK%bTt`;w3APXpy2hTr|fj_C&))6s@kL-kmlDORiwq>&iOJF|*RA z;oGD_heGU9i(MMATdR%OBb|Kx`mnk`DDU-ho2_`iLNxQVwUCTxL3tl20e z6Sbuxj&wxkHe2F;XF6g}Mf736)MZ~a87^tH&&!qPRoWMo+UI2I=VY3v#p>aYk{?Ry7DUv)n1)k4!zsQI zKG};8AM14rK1Nl0QlL5`0-Fjv{i1%$=nVPo1h`M&%OwD;ZnQ$0P)-LxudtvNLVxlljG1=_%yy#fyrE!!=FV=Pq}2}r|M%O1 zX*(d0wh?(NQ8Wh%rcl`$t=U6mOCWEg9)gf*d!bhA2GVs`qHN35-NlZ-ItY=^WDkQk zl|BI%NH(Qxd1FLuU=XPtO1R63I4fq>B{QmRsM=l%$F;rK%8k!N|Q%p z32GfNohxB*r;M(&!Id$%@&;!??=BmCb&J1Y@zhKJf6E%~In!H#!qrG@=mxsVS2IRB z_E^^$XMnHGy?y z&AcqMtxDZOg;%2RNEB|d%q5b$#pbBan|JsNE`U8@RCy#4U}j&HI#%S46{Txc;}aNy zVsk_R6q_?`@E2{NnkU%_<<}F1%~WwKo8Qc2MyYr=7N`YX1&<@=wq;zVq+Js>$pd<^ zSIc*4gdUwdWQ&ce8*kt3zkaK7dndlpcGq(DLNZv(XS(&_&At2Yzx~R4Z{B(9{>z_v z?d^}=`P|n(_r-62^p$`3r8hr(aO?H`y_YsNZ+5qCb$9Oex9@ZZ`?bn2PWqF1}%mpUb;RgrN;XuKk^tg2k_$rM^QU+?An(wa=modfE;<&KuE z?u61D5Rr(@0f{9jH3cLFuh`&|nEX;pQ0__SLU|jJvjoy6U&`Q1>AgvhILuH#ark1+|3b#n< zmI^KWW!>^+-IXiGwJWAIp+l+)>Mco!uR?fA0bAN-OS#;IK(HE#cT$;QKH5$Os*yk~ z8idDPu|Oq4RKk^BtiPGr-Y;Lf-M)K&{rcVh^}E9dZ{N7{%FeYro3~!xyMAx?+TFcd zuiV_cwpHyms=Zca*ewn^`F@KiWz7*n7w{U0fZFR37!7=*QD`#p42BDG`DK+_V6v=e z4XZlSWtIMtQg>daz5vmDTBNw3)Lm5SFKLXQma3nXsGbxmo)Rga5-Xk(E1wiA&k2=h zg;1`Y6RVz-YR*YCXT|Czk@{)5;W?G@NvZm*MDdhd^`ux#|3Y_?oBnlBm6&#AP}$W_lM)F6{Zk!(?- zSdyw1CCUYfa#5;Ul4+J?x+S@ONv2Og{Gs$!w$D5VLoT1nDv?9Y&eQ4S$8IC_C(DQjt7$IRK8F;61jXal869- zZRB{-bD;Fp(UAX{+)Qgv1IDd&0Pn3|l^a4l$fRu}* zoMJ@Pc_6ATlPc=cm5V@QQ7#PN{rOAF7p|->^MyRATq0LXbvBim(AttZTUzJH>s@7_ zqRgJE*aN7~5W!^%re`}ummz!p>Za>gi#*bh}UleL{(^J=NKTPSbk za-&qT6CBDq;@-`}m?-pK5ABEyQe zp7vIf(Pq9dsCBLmckW%i_UesWuitw4-FrYnz4e6$uYUI4%kSRYe|gm3E%$bcovmDZ zGc(vLY~Cnu+$atA^QA69WQ^9JT$Po*Jr+K^7=S1LR* zwO?V3Xgzs*q8*Ag1HOXYn+NjRpXo;;b+0#XaixsDkT{z+maF!B!IVmC``y6H_Zpvl zXX}ku`}c0uUb@}5wO@YqUgx!Yy*tIG_R9LrJA?K8=8e~OKl-`Pe(;UYy#Lj= zzx4B;d;7!JUU~c0jhA;{dHeQ*&%E@~8#g}u+IwI7_D5g*#^>Mr=#y7xTpczy+u3%Zx!tL4wz~Vn{*8^zyH~55-DoXG zR8!tk)K`s#n^|W*8mwi)jl8dvaArfnYQkTMx${9!5h%!@Bk#55T+Wi;*NAxQAyd}w zZ4mBSFx*R(_UifVYHC=h?RRQdJJD9!oex=(UTezd$cNmen5!H&X9;P*BJvnC5tk`N z7*m8g>X-W60+$mguxAz8CnXy4+myORvEhseK5XKY&~RF0gg2kT<&wH@gIxj1^>@7g zaW^w+Uq@58;2RPGwN+qp3T1jMnmIf4PrZ)ai*=drg{E`84y&kWFJ^0>E(neoi)O5l zXh_LIoovB~;7=CJ5`bO>#w=5chrnE-y(r0YBrj;sR1K@qtTv>(m}x^c5MV|iz_@sm zUdIeaQ8l(=jm=m*Lqt-AWTEkJ_z5DEw#7^KWYv|fxf5kav|tVA%z>1_8`rp^DtA=n zjcI&wtv{g)ru1R>97|iK<}S7ag=Wwfvg(Z*rAj6c@s?LF0wHyA8R#CMlU@LC$Uo0t zy!;|~1-c68B=8FL6RD`6z#>)D75>^4{_6PD>JoKu1@#kjUxu2D0v=*fs*6g5!t3Ii zU{xX)D>O2-U2aWjoJGB>WB^cad{qn4bVNFCAg3Tb4?83%d*V2qH^-oE`iF)SGo8aw@~X5%WZ3X-36ZJ zyij*ZX&1O+#$+v!YZ1k6xH^p0M$uf$8!nhUNtHXH^rf}&s-rXvH@8#0YsJofv9^^d z3=_!~5dsRV;B;lI)`ZCr(rN-~m0zt2XtW`{A!fFw9j>C!Rq{K*Yb8i@67f+!*iJag zggN8ZMy25eubNh?dP{p2Tx=CE{&^Mv7`vmoFu+a(B8s1dKP$=2DU83Fg zH=EvS)lsR~yWL=+U?~*M)ta-}@ihh^f7Tc*gZ9^1B5G?$rT2)99+4-auC$0|FVgIU zQW;Z_kac^Zt*zA7RR0c7?t@!9`{j+j;_dtW zt9KifE)gr)Vr6@=AL?H#+1ZtxD8}u{kl0~8uhu*xQ=j20 zfUa7Qm`@2!XT;Vs5;OTvCw21~c^4Y|p-Igt<_D3eg&3~d^w)N%wR`#oMu9D+DCj)DY;lG-Y20_T+*u5|*Jll)eq^EfS zj^As%!E;)E-1uABv1;l+fX*C=5#CP~roHO{a^8fRudFYkYOS7jsN?^j@Ad zdhsX}WGsdwpFABNj-o2Gz1fDx8}wOxsfWhui3B3{RN0v!pYsIB)I5NA(N3g|;I-T# z>Vqht){m6h!EDWwDB3-QUTaV&R5GE6x5mG+2GkVq^2*xfE322TtX^D(LI<8sk#87i zNkr)(2>YkXY*U(T@W|@o^DkU{9=uXO)kR7x#)VQ;@RLEFaE($_msT!ZTseR7%K7EB zOFZGKOes|wr22r|oKjfQN?T6jD(d}JO9+T6_;?7QkX+H0GuCz`dfsH;M-l6|!wq|| zYVnnf-lD-*F!+i_f5{Xmn}Zb#0H~;F!x61J!evXa06!Rw*T60nXze6AJIU5oyfzHy zTi#^VkpP=(#SzY%+%c6sEOSH@?zq~Y(Gz)dxM+=*?SZV(5mi}3a$8twkEm@Sl{KgU z*n-MH%A9W!U>h4=Ep6Yb-MHU<^)p+qerEHfw}!V~>+HW&hdSm)ad55B+D=zT@mz<9 zR@{M{-IFrgqk3CZZw_mXAq~J1GdMus=3RlZFH|FldXQ)Y{Z+ra`9u5oIO?dR|c`(UJhuf(X~QvH`U!qc6So( zt!Ql!$kxG7Q9DDTKuQ%anUfV;vH~9)mZ-R6WjAnl$4!=?#^6=zJaUa&s&a~yPQKE$ zrt=AHQ8^G*$)-Eq@x^LRf8Jz|s|`VkDI_z874U%+A%#9D*Z3q#k4WVetAW5G2zM1)XL-OF0bh>uj+uDx_nuEX;rr>w2FjQ@fH2bdF6#=-7??2 zwr03;MR!SLfrvE`}ugPDdiQZ$82rfAjd zOvxQ7xjxJ{Cq(hCJvDTPTb5wmNHk2LhB4E3R<{D#mc82ZPV+g+$TN-b};=86^VshY34o^94HRkMocYvI{4#16e8UzF+hJtYB(*?1JQ7b4-dD_iVSCXx-)CKC3sJmW>KIZ zpKYN$O?`;Qezy?-loJWMq*6?75}1}kAq5<@uaF>K6I%-axr%xnQHPNm?eslqwigA6 z^;2zxdCjRBnofJsTl=(QsySXXM~sDeO=u|;N<6V53_zt&V8#HZsw{QK!-}>D@`}hCh z|Nh|*|K|VrKY!y7{>9BVK8x8<7#+b(F|mEK+S|@FM{yvV8pBw7BhlGR^|v#_oosUu zEjE0mR-n=$3U#lKFlw|4u|&ACdUGCZ>Ki)b33<6dv~kbw@T~Ra_!A{vExsa9YhAmHH|Z(v4_=;h}IQ1 zc$4Np)*dc-q7@$?0$yu@L@Si;Mzezid6#-P)*`|Uzo%$7Cv>{7QX5jJgL1h~EOzmA zQI)G;b>%JAgia6AePX3sV2|tKplq!`s_Bc@T%m%6$eU7iSF!8QG+l{`HBqsoYPJk$ znY_VEo=yR*L9x!cs&TC9+yawd>Wb-tS(_(evJh%3p>Zcn?xe{?C{!*UP*f`Sn#RjF z5@Ksq;Yg@~95IGuN{>Jvl-UwGfGMoj2INYQSmxwITmpqh1Voi4DAR`J`lv!1mZ=Ge z%*PYDmPM{BQtzrfz*mKYnutgn7U?5mM_L^!TZw|%7Ln_{0#8z#YVEZ>xwsP@)j-1fLQJqNj(CgeNE)x@vW;Wzf2R5gFu;Xq<^z&BcIa& z1gIq>2^USZ^>C_Y59RfxL7+4WR=1+Al**meMVd~3#ca>012wa+Vl<~@rliPOPy`!> z2ppm6j8Jh_tb9_UdP<^tPOjmbExKSpA0pN))@P(j z@>eP05f}M`jPTcoDBxEk$!FPvbO`y|L9=!UOir;JZeIZ~moOd1QB;@<0J%!qk9SSZ zmO$=C)4k9g`e>Wqqj_N}XSNq$rWfFlUULeGrXPzJXn#_ga2lU-=X#Al9fMvIS7*dJ zz-tVnkSHb(w^%Ss0D6@fQIr=ps5mf}XfIOYP+kmV!Pt6ntHz9cMjo+&D5eFXpzSFh zi>Tr#s;jrkdpD{9!mqUvEMUL=XMg$EKuA$q>IZ-I*MCmxD!~8vfBgS)%@Jx0FxdR@ zbZE4j?QSMpqgZno1=RcDaw|}5`hbMW*F1%qr_}I;qBgBgC6$WSc<@k)M+zzM3PlwO zrKql~Uc9n$arw#xAfYY*k#y;WiU%bo4|5)EgR z)Kc-9J=gWMb`l#v>%3II`C8}3{q{BZVAb;QYNjy^XRFR|O6LO-At3gJx&(rWp$HFv(@EwuyHUI@r3AZG_Vnf?wCxY1faRP7U$ zZm`()r)w_i(^!AX5Gy&dpo4mm>M&UuCQE}vd6;bN6xMGw2RG{7{YqmeUs+ET2GLYI z7^{2ZO<$tr^A{|Zn8F;DJ3tHM^p1?il2GcSQf)-6jY@QYh(r?-s{$fJ1lZ_Y89h)r zmat6Y;VJA_EQHjb(Yxa+8zDA&c^b#E+I~szS^@9%?p3YhiqXrr1trdi!W~n)6B~YPG=@*IHv*AgAm} zgFRs|MKrpg0*ES!gRk(2b%fFw(dZ*U5z1B6k6Q;tYC@z83S_=DiDyOZxk4dwFDra& zrijcQQ|f&}h4qTgBeaAR#(<3au+-XFz^gW*Hm3}lutFOF$aGOD=q6=g%@`3I2!Yyj1*oWW*VDb8%k~4- zgi`5U1FznqFR57JM|t3>47|mzv(Rx=hu-#fXm~Zg zc{5!dc+)jgw4e>=RI#G2I`Y=Hg4wPk+i}!}zGmOw?08#U|IXFS-nHC~+m*fR`BulD zEn2D#&uA;Lv6E^KLd|}#zZqTMO>SPxT)S6oZpSiRPqOWVzp_xb7J8oAda&GaleziJ zWk)e@Z&dw*c4F90Zw*SfuMJ**aQ*)4*Y{uEsc*H2V$v84h%ENY8q4!?LvtNF14iL?@hQeGNJ$V;#ff!1a1_wd8{%0Vbe&Y}RI9u<7lp7D;0f|Jq^8VMq1=9cXfB)}PI*Z=wi6s2hPO#P^ z>LkrUxVsS_?xaV%8TdniO@AnA)#+6dsZbzX6$n-Y!WE%#6(U;Y3s!iPx)K0&bp?L* zw|eO^5I~onC$$t5Qdd?lfpnG?`pxnR{3;*3vr1#NYpf3PQ#|tSC{lG%(h5;jP&^4G z{I7oPt6%%t*Is`4WsOb+BotIpK#E;~_iSBWIe!U2`a)?1WE{{{BA!wsa}YXTPH&CM zfMBx4Zc&&}XwPC0+iZs`O`XNd!Z?5LdRvf9KHJULHadj$hsWg4Hb^s`JF9dfLIO4)=*_5SscVt%|N*9^5<->B)nVP5KuVc z24BtwKV>U80wt%vk>u<@{yCbIZo(SIsX9tQVz@ zD@xaz!~#Um3sTE65K?-dMCTR5AD0A*$}jh%EXf8DE_uy_Mr`7(s4riTzIa)A@rq`7 zS$+Ak>JoS(Gz(-7smLN&(_dNBFR$u=(z>{;J`Y$kToRa%(iPo>^NQzq zhRZUCKxAG~I0SmHTwxQ)EWBm;^HTGg&;YfR1js2XPZv}=(-vz&Z%gV75rr-!SNcRE z$C}W-#<#7mSyzCZQb$zEkX%kkl@XadEEafIBm_?y;zl^;oCec_A)`or{k{auQ)>a5m z8~Mw9Prhxhj(oLsf3|7MG_0kbtI~Iu`|h2ana_Xm>N{@_?%%Dx_ge2upV@imrS|oW z#NKA&+O_<~ZmPWzZLEjNJ%73mV%ZBlU!m(u*PYqAGgo(&I)Tc7NH?6xnmyZc=UVPm z#hNKw%XN3X;ct|^opNxymD+7)b}FfxoznGQerFWFc{9JUlW259dpBDT-o5qym*2bl z#w(+1SL>sVRJG}h#Em|`HyMkR(?ED#fBpJ{5AMJIxmR9$=l1c9PWi#N);Xw9xr z)LR1keZy0zy9;$!rR8t-L#=+e)eDs>K7&y$m5P9nVpWs~vIgGs;T=?$fso=0SAe2g z;{%a&i9CFQLTY*C0#H{#IYIrj2Jf<>6czlG5Eu)ttO9%9z+8~ywxI=ksrs=P&#~a(}_SJlOJszuhyjhbosdL0N&V<$;1+~-pv!+NHNWdVl zEDgiijxSuY__I21TH{Kq9BHLBB{#&yx|m2C6R9IYCBXyIN*|LL;&Nk5W{N9ppiOed zV96H9TYMR#KV$NzP42kP9#Pps3QJIG2}pe@U94=6lx#%a94T6ob!WcgD-VgDF7CPzZ;NT>jwv@Vc02lEzB+5ie1D%yb-%yvRR6c+li>PEW0ov&_W zN`qv&Nkq%uL_Lt}#)`vaag-!lULbF0SZ`Ihq{ z+a-zZvc!5>YF(CDmz9n+omZ%K@r8zqYnm4n_BDe~=87ALywjhySqP2BB@r1`F3VoH zBzyi6c$L3Maanociuw{@8K`&l1)!xUIdw_-g3z+6@yU!Kl_jb*M>M9WTImt##PL_|RT3W5B!UtY1CU$tCV zGhg6aE&^TUE1J?>FZ}JPrX$yMRC=D~dH^umPxW`>?agp~5UBQj_4VNYpSeE|k{!$M zd$B((aeD6|IoxKt`);-5R%=%7`-)5;7bFsiC9wmE%tY>M?RBf}-uL$Hb%wKZ6FEaZ zQRJgY(UzW`ERvEXJz0L?utiIH@xl>uSd_!I^v9#+2w9ZmA2O@zR#o4=(=(LxUdA^N z$aC<+0S=IPJ~-!x-)T-t^$E_m5vGw~nn|&TD#JW$z)H4#K-ITPVlUH}7LOh&Cl8d# zq`bdPJ-J(Ze4-xjaXS;L*35)aYqYe6Nx@PhSvJy4JIl3Du9*=US+$QdwG<(QNg*=rvMv~3P1X7vWPv#&h; zX#cCF6CZnQ9x%|FCwZd zCZG$sm#luI2Fz^3E@WM`0$s?xX!Ro&_n+h-L7!m-x@7g7;$A>GXNFg-P7Tj=G5rT0 z|lPdE)mtk`^Npdty~`6@J2y$YXHFXzy0t3kC_q!UrC_`OGtrqNC_r$kn-Voe;HC> zIX3~h{n26>n)$p~OIPItBgO z!y}97N;StRpeS?HZ}A$e&l5pFQOni^tHWwvwcFQM9P17{Xw_zMEH5nI1l$3faz$dm zQa2Z_EdZt2mX_?6We3O#%SGGrt)&})R_}lC^zZ-uzyFv2@?ZYogAYcd5sGC^lACG9 zXS3cf%QMX|>zQDi_03g(%$cRVY0{MhkScAaX7kTL3d%tH>d#dJ1wK@gW-%%FAfQ!_ z58!fy(o=j3lez`LoUbq|ck=aNd9cqPJZK!h+uFOMjraLR59d@9Njcf+Pb^C%O}=zs(qfa;;sE8faBZF>-2Q+lSrM^mIboL>tU*HGSHG17T8l3-kMW-C?oAc8NagiCrnCxkUhVkTu zU{MNZ7+<8g5z4Ox^J}mYCje?aG29g?Y~f;3>XJ&Imb;YHsfeI9@Hgcqz&T)|>>74~oux!K^HsZH76ALcHbk7RpR)e`UKf2;Y z?4I;YDOb~9#~j*U%%yi`{w3b zH#WXv3RawN0Z}dcZaTuto2eBq<_zQBL?sl#T__t#l>M7=o5g)?(fPL3eSO*a_Ey9m zMqQrd%1U5iBWhUGv;cJF zNLbdhjt$hYnz5{8me$ba_1yAGX2F`gxsF*^vdgygf+cZtDQ3!nSXNS&<>-yo^l|`S z&s67Z&SqqLA(7i*46Y6p{BSy(DvOl(6vWLR^8sc=CGWLQ^G2^O_bUJ2s0 zaM?%{YT>NpMP-jXM%59@8!_2P7z0eH!*f@>)nKhKc{QWAOH~CaR)VaQDOKWCF0aUy zeoq-sw1!dX4p?~7fL{|l@6lqM5mT&~Ng(bd;)_JxTP}yqcFSV9;aFWS*$MG zde{}kQOc;Zy`DXpdDFh}vUL+M=p~!y3pW3c*#m!ZroUkK{{@@>A}2jhXHzSl>RA^2 zgI~d^i@Nwne@SNZFw>>Ev?*&#+$`5Y^dS>-v z?6_=r(dv1{T^K^W*zN)}T%??fR%eE%R;TbWOTTz(&p*iLl?6<2I>DH1-QS`-~ASzEJ zHa9o3PP?Ywxv_X{(Y9z=wL3O9j!y3Uqkr^|{`TMg+rRp&zxwdu!*;t(5Cm*#4)D#~ z+pn8G>F+?wynk!nUp152g9SJ>W3O9Q`|_4+GeelYDP=h}5A|LY!t-d_urkLfT#gpR zusQdR5F)h%-$JEMem2IJSK4{CQ)rIJ{vJ0v5XJ|>aJLHW1VED9K&2W22qo*L#2O-M zh|&PGD(LM3Y@iqzuccWz0W4Lmr9?fW*0Fk{&~25cJ$8R6+@8p=oV4kdR!{^)g$rabi+kd^%~;-Q6|TdF(u^=#?%r8&WAGQY<;*G zW*Ql(hf7_YZx!IMb6gZkltxHSI5?{-68pdfTEvE@CR%F9DDu7jd80E`UywT#iAGJq{>&c2c zRdL4&XT0PricuaO8#+a$Pe`32UCWfjWR?ns(2YQ5EjWWJAF}REulX|@0o3WsY`9aa z8!?+BxUlTKzUY4Emdos;TJqjl@|jwkEiHjtzMMIu4xElQVzP9^mtJ4>FRlfaJ@GZ1 z&y*!Bn)j{*7lGAW$XcxIUr$=sla@fy8L#-9X**mvS7v1kajeFdSK^kEv;vkotVX$v#w^BRzRr5mRYu>7jHzaUkkpooLX{Z?e>fn(8?0O zX^WdaWO2$#HB;)aDD_ZAj|&Y%Yyw(gYA2_4^ZF34k4j<(qx2-(Ld+NwjbuTKq*#}? zU~^^{Jq2ro-aup@S__D~IcYb~3{rX3i&QtVRcBcXiT$iJK$%t|FZ*+{pU@*^ErL*+ zNO@f{GK`j>lsGBJa_|6yZx$IJB}8Z*9v;$iEh}qTRmX@*ke4&8n5xPMTun+y;gtwe zMGS*#7!)UBWhPmvLN3bdIZns$YLpP-1v;F_yAwH2kxbHjA)54sp)~4;o*4kSe>p#7=@!ImrOUr97SvJ35b^Vyl`(uv4Uvz~2f+P690@;J}Nqe57 z=M&X4o&WV;VX2Ec-{zUjhGeE^iSUnqzJ8u^rvG_~>W3@ttj&8-bN<;@rs0JwQ!g;Q zUT{bjP0}OxI;^tOAY&X^AI(ZR_T}i)q;jR{Ufu*i! zc6Kl9+Jm|%+|edGJd#bVIDMf1?w|b+Kuh!WxrBNP zi0b`sefMJG_kQp9A<-8(wQ_m_k+>(CUM`lmlv;W?BJ+i~%e4mNFv*4C`+ zYqs?@E37*l%T}PG`XTo=V*0GSF=8<+0mY9Wz7~%`-B!Iv~#mKQV3N`v2}zq zvTP$m)zbukg%HeffwB^VT*#_6GJG>TkHl?^E4>{S)Zbj7eGJ!@MC zUAy7`%B|qr3!!&z`ro?l{kg@!Tej%+mDmkO_?^|rJCWjQSu;a4L7U3AvVw_>7)WfP z&=wLxsLY2dg6Z$V$}vGp3R((aQEQ?`r#PI@hsWBZC*8Xbjl&c5;8?kRw{~>5wsR;B zw&`XcSDIN~PqAv86eBnvBBYqoE%gti(QR#Ts7&uRo_yo*Ti<{08^8Ma8^7}S_{m7_ zkW#Ds{Rew2^qgg9N#;S!Q00(S4sn`>WQa=znDt;b7#PkPOr zUUj8cl5{Z11`9PLP6vVo=T_3@&a8ORHD}6Z3*8LiE@#HEmb9#kNZY)HuEhTO(rxtA)>tbTzt>D{V3BG+ZaqC*-`ci7il3uc=7j3Cq zYni1$c`c_!m=40W(_$CX`bD7$pp%5_TbAIu1S?8RY-9SU)ZSy1VG($`q(xEQ7q4sv za7O@N30F1{(O0NPb9xx7huH}x>=wHZg~l<(4Ki#eB@MECH_dm_Qa{VLQxz>tY2oG= z-@Pjv<1#J92rkGfak&3^CCN)kt%mgnl&WR~AyH+bRVFS=8IDWp^+LlaYg$3%5uuu* z$!M|YC(2=7%t~rrP;kJ==F4{H%l568?5;1IO@sJcy@04* zx%%(_xw*=08$j^?ej)J%I^F(UpT}_4eq1rU(5`%Hd(c_dpPQ&=?d#|FtpQzVDKBQ3 zIyd>W;c0O*eQu(uoqX$#q=M1cF(suFUz$0ba7Yp z465ct^$e=!2Y(7x&oA-p2AiMbnc=x+dp^Gem$EJ#q`8N)9sY2-cy&x&A}U@@RHZ~R z9begWgMgF%)<60`Opoup|E=%LQ@-`RU!M`x=~qE-e(!hx8hnLBSf3|4-M&b|lP^0t zDW*3I!Jub#)oL?+&ll{r1>h>6D8Q+emF3xBpZRj%jEYPyF{x$ox_x7HD;V-6Qcl0$ zvA(iwHR0(@=Eie80+UmOGF`83TCBI`0zL~Skzg_n>yWhwo5A)#MKe!xfT~;}JI5*b z{Lb(E&ey*7wVjg^)XQlo>n`UHGcni!`hp>+YGf~8Q;$OfhwIlWadT6m|4k2;n85q~rh zcls=>kGu4^&vaYmM!l$MIYB~5CX&V7(ac&Xvl`5-Mhly0HB9Q6ycAE+{s6w|M9ok} z8>roxTUkLYOVJxkv75H!B4{aob0K=&nz*%+UUX(G{+uIG-ptT$jPU|R4UdH8q--{^ zLWorpVk0Bg5nf9+x`pXJe{fr#>{R=Ma<2~}Ivw0F@|`ZeyUX9Z*SL4T0n7UjnvWi} zA3QV;j^y!_8H_5OKG6k}ai!VA;gn-pN1pNudPeV-ngg=G%inp@`}tqI``zz7{*~YS z@Vno8^7QBT@4r9(rQi7Q5B|aL{I`GixBiT6&B&Vz?fCOi9jyT|IyvQo>}>UiBKH(R6u6=jqZ9pjXA*>vafr^u}+z7{U7 zBDA|Gh2c_SoIlS8OH!n)#Lek$>Ifl43v3`=a=K%S%g_}<=#+;Ya2T=8Xh(&|my zeVG+^+U`tPS0jtd{%bc~U%s~avv05e^mXT#7XYfl3+pMHCAzSlwyYfDUk7B=6ywfUASwYnN!awZ-Ayb~y@d0Q#gkpSUL(19cs@S^L!-11lMBW<-MmY3s8w?a2=hHfk;mhBnGQha$a zzO;g_TGLib%3_0U(v~&UwvJjiF^dOx1S@NC)`>|0rjh0wh}1%bW|mUoI2SDOp{ky) z4~gcORJ#SXo+g!8MU7YBW>8}wQj2F9Z?v$6&>o_mj51rO7OC`6Zd{C zY7g!0R=T@nb6jj~6Wu+sF)A8kqSh-ga=griC?O*08MT3`wQSQU4*FEvz?*umuI9Q; zqNNubYObN?bvfT}(S};637MLh(Pgxzpqh&5dZDHlWFRUnS8L+6W=T{rMTbY1lAxeD z+#gS^7x8eF%hMFLwYd}ttr-n^JdhMI$FoR22mdZUr*G|sed(tc7k+Zt_S%B|HOu-e zcBm6{8bD$8>ffp6MD@ZBs!tQuxvt>UMVbHUv*u*h9$YnizD~D4li4bKYMbZiyr6T# zD;qpl&lGo&M0v(HLINGMftj*v-BBMoz*1h(+ByvWbWsDpI3-V@8-mM28e2P(+&FLKlzh? z{4f56KOCRyANvKh{}a)C{Bm zv*sXWt^-%W{_Tr^Q-MUvB(OQI&3dQi5SB46|U@!oj zf=@USgmNv82R85M0(iQyIPbMOeGPEFa&vL!`M!L8(Q;r3`lHYYPVSH6>EK5Y2`RA1=3o1V^D4nNdT$gHapy| z!ixEJWDQXpSff*H_DUew42X*4!ju%NYALv6GPEuYv~CnSowCs=)>RbLtmT?|zMIRHLW>bbj8>%>C&vXP z0Z4Rmr}p&y!Fx}74;~mt2hwy*_q!#dnQIyO$(X)?$#eaYJ=_^Yr8w# zctrJjM5kNo^h&KRE@^3!4YE>9)Dfv}zTQ~x790H%R9d}<>z$%8EcbV+yC>S?k0;;$ z)dwGc`{?d_y`zW5!w*Lve)ABh>sx>6;d@`(JGgHQ_QZOhW+1K6KmCclGExu%r+_HpjECsGF`mZhe z-&qX3V~Jc_48FaQwm6~-OTKs36SlRO#gpC0iK#H|S&N%<1#YBmTiB|*u)c{oR?yZIuP;Szu9=Qmc2Cak&)cKr^)&4)$w5ksNJd)k zAWzK)P$gjV80Bcrr)QVU~isfrY(;7-u9qLRtxT`1url{CtQ zFgZrHvP>Jx3856RiIg^ql-uYR_fO=(E^Ruz_b_c#RQh?Qp5l!xrN#*%ToxmoZoUIc zRwG82*x8jP)QHn;Qu?;jA&K6>x$kw{w zd41LK6N?rzn1bE&vIVfo|C+_rt5zTA6*EGW=Vcqn{j$wv>WAs0x}qyAby2hC1peGF zZV#|^u8ZlPCaTN1pJjLzj6QAn8T!viR2TPf#qhJ5$@A@BZ1rMvc!A;PE)Mj}>IWds zDNoGL-K>psqWb)Z^Wx$_pJjNZT3&RVmvzzV1;=?M{l&%2^*qC~tMCJ$>a;TFIQ5?e zsxA@LaE~6_yY%y6&_gio{P0+xa$fESR~d153QR_nQ3 zA-3sUH9MjlOY;sYQ&y9uKo+1MGu+h7acbe6Rp$mg7>3fAI~207*-!atCZHlK0GVTH zW!18}W_7GA1293#oT4n2xlERtZw9j37CoV`Cm5PD)|}hs(B|=No#PaI{?_06Tfg!v zzw+S0gJ!ciCn^-n&b^}m<8CfpTXtACeF1L*aYf^{^;N(rldER^QovQ$XYmxwcL^bV zhEwLthL#(SHCs64F<*?*Q)Tl3Jx=T9G;=}=GkvE{9jEeuQ+mIobqYWRKt(e!%9=Bc zG%%x208VvA6WnX}M{aB-76aHysJP+Juln*Uf#O=I z>;!FQtxMr|tg#!8^x|q}c?AKkTH3^HzS4Sxbf#$!RZI2{xc9y``K4cf^jCiGYv27# z_Z~d$?%tM0J8XAYZnSc04XM>K&1Pld5ja(jpF?yldM!&y=0vtQ93) zKo3xsWS~{u?4c=15p$wUvxg=@YAHfZ=EZ2X8jO){e_`E)I@S@(N^;4OSg^%!1+ud*j(tUE4z|nBbbyb*Yn!8kQEY}*_HK-9YAU`XKDkpt)!P%)7CXm%DSGm ztt6Hfd~d(K@zYMk=EHcpY@Lf#|r>AF^^ ztNC_=82759F1tMx_NU7JwtBFm84Z%65~5OES-%;GY)U#K=xiEKc@u%R9Sd*S7r$(` z{FG(+OE$+(*w$XYWqaMa@v1chdc_ug#TI(W9t3^C9{7UY|B~JJlHL2V-TR6ev>pD( zU9VfW-n49eaoH5CoCVc9``V24vo$mHbS8_kg@Y(VFK*P)F zR}JCpE^jc?Y-*shX79A|J8kXG^sLc3-{!&|&g#vqIw<9{+Q{?mKV=1aX7$4uUMlVd z=(D16xAn9zx@LB)X z)f?tav&8uZpl8KF(N}l=IdxvvC8Fw2D|)+-Ovl%qZqUy09U!U?zx5qh2}Vv6FY4aY z59E3iw)yqn`)l)*cp^F&vx!7-b=7Kjn7vbTgtEaB&}ZhBK1*2u5(3=WaJz!ZYzV=e ze!s=GIOiT9t$7y|Fca(nSZZU#v9WGnU9mXqOMqqb{mgd-U+p%t18il*0yqUGCPK}2 z0{fr$T>Vbj!N1 z?(_LmS#Lb$aBkdOGQF&>-7=$to<^=(0H`vq){H0gB34K|#zB%B@84jTqsKlP-ky=cFhqgfo0FL~J@U77u1m zvA&`jD@c)o5QH`|O>APMOKo9?_w>mDZvcP5xfsB9sNO_t^{gZ(STKzA=ZTgfOMVS)e5& zEA^ z?vXs$W+wam{)xJGq7HYfP!N=^cMI(?xqG6XJZ^0t%f_T4ck5dpToRtoQO&Ey30jd^5ut2%$tXtQTRu zIXR3t%c3Rh$1ctN#tF?+uIR4f7w_d8XOFv&H+G#dksQ6$F3! z(88Izf>Y-@Yo*Tl<}%`#5woD#xS)%mx_AqCp`4a#px!%a+3jgq*{WC~`by$Aq`@cTJtk^&QpZ+J<0CFKQk%+fDrC`uwp9Ms4 z*cSn$%+bB2>r0E*78kDp1KDh5=qZrf?~7&gi5%`SS!%%?`vbnM8bhU1S z$$@ca( z%d&H#g3p5G=G!;Ed>-fXTsN0)thimkRi0RKdCf74s1E6~5TG-_f)rQ>oLaUo08u&C ztbwpc?c+iV;|;XdFYVv2fB4P)CtsW1d%w4RtkiqBRL?+TJlJ8Iy^^G70H^d;zB43S z{W7G~jGS0Q7%_%ZzHG@^sCWoA01!6Z=XUO>{k>{)SgsEUy^puXmEk@=J`y`SOk-FE z)rW-ED@yGg*T@i3)O^E^@+9z$Fy`<=gBrc=jNNo67rm(^Ph!Cpy9rBwdN~fQFXJn4 zL0BTBD@|^t%FcW>0DGutNjMRGR5o_#&K_GEmc$lHYw;ZIK}s7!9U1Pj-7%>dsH`Kp zff=1*9bmDBG@H5Um_EL3j_V!mi@Q^H)GLpB<^5^(?cN>z(WCa`_xfM``u;Ed>O;`Ce&OV+-#mEqv=7_~WCH+d^ojPc+!FJ@^ol+|BWfPSEY7Nuxhc{z@L6e`Y&crm4q8v%n?rhapl)_~tM#IUP z9$*h>pXnF ze|W#%-C>kY9srK1r-7@gEwtLkm{zvZ%#`ctf)>Z*2qFZzK9*HNK5}ghU9u*w+mp9e zQj3<@4SQnI8ojlKSXWJ-r$t9Q&86gx#l-bn(Q6jiCcbO|ib^c4Bi6O_ zvLkwPBe|5IJe5YKTuT;&a7m6-v_yt-6}SMUCB$wHz%f|bv_@~PB9@J;!#0R=&X%ONNIk9&3xbi-dT4V}Y;Tu(dzJAKw|z$( z95DJIk8}QPWea1ydEO7qo#O)qDNNK7`1J4tQjGP`O{Wd0(>mzF_yy z`m2DeOw9U%J^Yd_{IV?s_+?HGXy1I*zG2GdG$(I1alvd_&RJ@%8K8jXZ1m!xz|(Cm zYu+AT(6jbwuFnZZKe8d5*M;0ueaZ^-9K(ycyz#}XbCZjS&-7x$v-bF^`4ubBh1?&) z@M0Dio?6ZOR4(Vf!0=*mFD8{28(z!;eU{a;e ziRVytx~my=&8)8IlGW!I>=QWZ0#S|1daD3LwYlY*t5W6uZ-4ryz)bg^z8{LlAmw-e z;19C-0<0^I#vG@1Pws5F+{t8AR?ogz&z|HbapeSG|ASzh5osG(^JJ({FTp~{d z;wi_fZQhME$Dq>=Difz}n7vcLC9_@45z3^fxqzi+IJIJSO)bv_Tbd!)Z3||n)NGjV zY;4YqhVbW;=2?Ta^;uH9O`ehZ4T+*q{UT(ZqVD%j@{t>7?jy4;(LmaYv-lVkb#ar@{| zbMKx$ITSmyI8wXE%F+G$c#k)F1hACS030zxB=Aa#WJ5W^1Ct5dyK3}sSO@Z}s>!OBlG<2(Qr5?W z*uh9OUgU$g5K?=E>4|*u*m(GU@8n@)vd49RZw5rWhqpS#hLO|sjI1OjDWS+oO-(oS zY`0YybW0s0-_*0cR&g?{Y>(;5paQV92c&fIf;v03S1yJ62kc;p>2pu#Q&TInrI>BQy6kRME2_*yqlH zIN9NVr5de5-N*x4sgPC6z)GWCX!T0{F$G68JrK8#q~RXd7?c3ZX0wkcfMcjyvI1^Tw>RQiO0f1KGH{GbMAV+HxQs`iW9L-mKgb)JU zDFEv*9#V-4{d|PnT2C);WNl7t)seESqyVHW%dy49=)ywe)^-0oZ*BeTt-w3$X^RWB zIWx=Q(i+=BCHr}*tzG~fk#p*QQ`FV2W6?%Z;ni#mfU;HO{z z-QWB0Ti^Q5_rCwf|KeXj${eR)8zhtHv~aI?3$O;@#%8@`g4E(Q%kmAYWj5+(n@u(2 zSoTJu@mwj4V5^&}r?2nL{H08snt6_!IAwNana=EBIE!C(+9`EOvkjoQ)m7`}=IWMf z-MO{C<=Sw$onD_i5cGrGUN@Y<`o`*D*#E8H`mI0uqdz)@soCdm{>{JnOTY9>_wLBAQcK*Vp{1Y$%&w^ZITqUN;B(W@u$Pe$AqT z&OO=9(^B< zMEglDBE=bE59us~z62&xY6pfChOMrwUqqfF8Y5FoxyPKEHdSjt@nkuJ)8R z#$;PEKm)L<3d31;8(3Qh{yEQNng!Ze)!)QRB64p*<>t zn!Tdl&cU)jsZ4gO<85|0stkse{(x*WF;R?Ht09gH!%`5UijvYaL{-x&tf=W)Ez@on z=kDqcAGV&pKYZ`~;p3lvfVxb~8kW1`N`FfCCUkpTX%0$iJICt?K#$bSa(bGQVMxr_2U9Iib|E zT60cIL=O&rO!Y>UR<|T5sWRoKs^O{_fIvjlTj0lmSnXg zKo!@_@GZ1zWS9oRG!Yh7j0{mr1F6!x32}?xfQv!5WTe+xoL^tawL~llZ)%g1%G};=;pN% zTyCtQL`!^tlEZmwtExsTQYg>+(~M^WS=vaO-C8SY%PL}9&#tUySM0!5DXTSUS&H1c z;eY$4|7~mZ#%g?FD{D-*Cv`Jp*A$%918VQv5;7TYb`N>9tYNog@s!mG6 zAP?Y}rrjBH;&6AAa=HpOXWp`szUf3Qv5FfLqB$;_Ecv3?RxqhD5j`8^Ebh0C}d|IpH-9ERwUq89qfBfFgCtthsh12< z_xGFcJ>L8HqdP~(14XBKwE|-0GOtyH8kH@^N_3WB&3GFnWoMO?Ok^QL?CD;tiVS+oDtiv3F~D?h!y`DM57 zOPiiAu57*G*nGp`eBHhUI0cOLiV0GlSIt?RP4BB$>~2VW*}nC%ee-4e#>+O)I>6aQ zths_y=eoGfTrYn%vuHXPJ9?vO+T`)Oo z)t;4jmhwZ%vh|w9c`EDHX&1=+TG-(#cwV-jy=P!^y>vlmZyua-*ahS|Kf=q$2{I4T zM2*kE4W|Tfs#9(_CzT8PH1&f^{2Ydtvwn2L3syg};ity_=GWyjD(8%-Ov9^01qEF& zocB@9HNR)h1qX0J&o=u3x?OfjH`VFhW}|_?PmxF{nM|ZosY0=c<0X3{PD*J2M3ZQox;@YgJhAnZoXv-aO&n;Z{K`- z#!~NGGl%xf*#NK2bbaC4rau_U;(;_~-!SRWYG1U$>Dv~}0PC|(GFZatK#JGDr5X8p zrwD3xaeyaSHsEW!Xmm?J2K_M&DM}p`)D$bmKuQB`_KDtCj=%QJ!^aP)ENF1LLs9UN;X_ZxQ~7$)HE>Pw}j2x5dh$%e{5^E{Bo@sWAg9)$*+36ET zr&w!bB{eB)DOE=lEe(Pdy^(Dgxpoil4$FgaWi+KHJJp>%{@_SHysh3osR7vS9Y~WM z4vq&{3izhoBbx1^*;mxe0YcS)X=)k0jzWbfYMK*bqMU@U09Xyc*#>4JS1aG_-~eHr zLD}fydMjTCTIv%Z&B#H`n<4&%C{+G@wnSJb*&r<8s|3dhJ2&zGY9tc`oD$@u$!%(i zmlA+htPq1O88J$WQBnw(X3+%9`BJ24MU69hiq=yVvzsbe(Lt%Q7RTjCf^{Lh7n6f| zEmEk*(xNX`b;UWipImn!w*aaffK$jVKqw%pwVZ8>SaX**ocP)bYFkd3kq#E33%8;R z098w|TbB5Obry}&mv<0aTpbkkL9yN|ss>;;A}CQ_1-kO%KvzI=tjAYe-N;ziGk{Ze zOMJP}hPA*)>s6M}FUfMTwkH9)SX1b>urn?89dt2eXa&#VQJ^%%C5 zuSC^WrNX79TCqD8hC6a+#BoYiZWKu&5y#d;DO*)RXd$UI3X-1VqzuI+X+GT@@sd_3 z(}@b3gk>HN<%*$n))R?sgre)Ij6a(TClFse?aSeio51q1B9TsJ0_kihmh{F`KCBQY z=^V@Byi{g5oEOV_lW(*og3eYLv`iwhh^~u(l?e9wM3Evp7dY_eA6}pDw0*X+{G?mJU z#k|HW#R6}8y+5_#{Nl>`n~u#l9Y9x}H|*ZmO`P(*V)MOf_rGGwd-~>}iB`~r&t4L| z#2Kcp;M7H(gU-tq*JWJ-sTauPDznGvN~;6={G3Duy4Z+3!{U71y7juv^@h!Dy5PWO^ZvrwRe0%wzF^<_g6)}Jf(tai zMi+XvE){1Uq}lMF6VfFzc!mpeUCe^RxWEmtpG$kbQYRO)pwPL=4{LaOsHeJ0DnGIz z=tndBEGy9GFY!vcX=o0w&+2wo$!A&SO*PYb%4g^jQPtWQJY*x8gqi%jPp(kV8V!cy zPQSZcNIKE);C^$k&kW#c21l5=qMy@`Da%c7B$_CcV>x_%Yt!mjw3y>!vuXR5XR$ZW zx^tE+H|A(!KYO`v76R0Ckg_|L*Ed#z!9X&Z%4SiDqGefa8tuVw+#ifUz5Wo??G1YU z0W3kCZXeX{^gyk4x83PBnoUJfs~ivHRjI%}=rTzX1aS&eXP>uCkUC|lcjhc*;?z4P zOPLb|niDYJn1xec+j1rfWD2Le;fU3~GzY{b^F-zxIg5`qn+n?Nb?xklJ9|QZSb=6< z)w6<>RJ06WLAy(6b+jtPp{XvC-ZB&5XX9>qr_kt?>OH*HErI~Bx}!?BM|9f7Ub{GG zg2ddKW60Zsy_0uh=S=eB%sw{~zx+ddEnQwFd@)-ymwvKe4AP4Gdq;wms+QVdt5 zD10rleppgcgcc(eK4i{Tt3k7u0hXG@@Jw=YoE4*HM~;@#4XiaNb%y0;w@@=Msg{N; zMu?aZ7G?pfMmy|yuL{e-lo-jaH`v=nQp0K^k1Lxhn-@JFfISW|D z0#NF8%rFZ5J~l1hw_qqynLAIk9oj1T05U|tNt5|aXH*1d%+1aL<|i_o1+P7TMa zZfDM%XWCh?xp0SvSOaa9RyT`|^}KC02eNMz*4D69N7ilzj!G^sB^Q?xi zHGVTmxu{yAcTnx^(zO<*=qXW#!wcmZHzs&1)R9tZtSJzP6TGqCP+5xBD z@xFC4aLtii-pZ|ditBDOtcGtq6+=y4lx#}oaGLofc z0-(xNE0g5|nW`^AI=!gXgV|%0D^zlNv6aolvNN_E&2L4qtr)tM!Tt3vee!778FIi< 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�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 N002ovPDHLkV1nCr+!p`< literal 0 HcmV?d00001 diff --git a/plugins/channelrx/CMakeLists.txt b/plugins/channelrx/CMakeLists.txt index 9d871f209..7c8c51318 100644 --- a/plugins/channelrx/CMakeLists.txt +++ b/plugins/channelrx/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory(demodais) add_subdirectory(demodpager) add_subdirectory(radioclock) add_subdirectory(radioastronomy) +add_subdirectory(demodradiosonde) if(DAB_FOUND AND ZLIB_FOUND AND FAAD_FOUND) add_subdirectory(demoddab) diff --git a/plugins/channelrx/demodradiosonde/CMakeLists.txt b/plugins/channelrx/demodradiosonde/CMakeLists.txt new file mode 100644 index 000000000..4301cd726 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/CMakeLists.txt @@ -0,0 +1,68 @@ +project(demodradiosonde) + +set(demodradiosonde_SOURCES + radiosondedemod.cpp + radiosondedemodsettings.cpp + radiosondedemodbaseband.cpp + radiosondedemodsink.cpp + radiosondedemodplugin.cpp + radiosondedemodwebapiadapter.cpp +) + +set(demodradiosonde_HEADERS + radiosondedemod.h + radiosondedemodsettings.h + radiosondedemodbaseband.h + radiosondedemodsink.h + radiosondedemodplugin.h + radiosondedemodwebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client +) + +if(NOT SERVER_MODE) + set(demodradiosonde_SOURCES + ${demodradiosonde_SOURCES} + radiosondedemodgui.cpp + radiosondedemodgui.ui + ) + set(demodradiosonde_HEADERS + ${demodradiosonde_HEADERS} + radiosondedemodgui.h + ) + + set(TARGET_NAME demodradiosonde) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME demodradiosondesrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${demodradiosonde_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) + +# Install debug symbols +if (WIN32) + install(FILES $ CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} ) +endif() + +# Install debug symbols +if (WIN32) + install(FILES $ CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} ) +endif() diff --git a/plugins/channelrx/demodradiosonde/radiosondedemod.cpp b/plugins/channelrx/demodradiosonde/radiosondedemod.cpp new file mode 100644 index 000000000..5e965291c --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemod.cpp @@ -0,0 +1,715 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "radiosondedemod.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "SWGChannelSettings.h" +#include "SWGChannelReport.h" + +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "device/deviceapi.h" +#include "feature/feature.h" +#include "util/db.h" +#include "maincore.h" + +MESSAGE_CLASS_DEFINITION(RadiosondeDemod::MsgConfigureRadiosondeDemod, Message) +MESSAGE_CLASS_DEFINITION(RadiosondeDemod::MsgMessage, Message) + +const char * const RadiosondeDemod::m_channelIdURI = "sdrangel.channel.radiosondedemod"; +const char * const RadiosondeDemod::m_channelId = "RadiosondeDemod"; + +RadiosondeDemod::RadiosondeDemod(DeviceAPI *deviceAPI) : + ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), + m_deviceAPI(deviceAPI), + m_basebandSampleRate(0) +{ + setObjectName(m_channelId); + + m_basebandSink = new RadiosondeDemodBaseband(this); + m_basebandSink->setMessageQueueToChannel(getInputMessageQueue()); + m_basebandSink->setChannel(this); + m_basebandSink->moveToThread(&m_thread); + + applySettings(m_settings, true); + + m_deviceAPI->addChannelSink(this); + m_deviceAPI->addChannelSinkAPI(this); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + connect(&m_channelMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleChannelMessages())); +} + +RadiosondeDemod::~RadiosondeDemod() +{ + qDebug("RadiosondeDemod::~RadiosondeDemod"); + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + m_deviceAPI->removeChannelSinkAPI(this); + m_deviceAPI->removeChannelSink(this); + + if (m_basebandSink->isRunning()) { + stop(); + } + + delete m_basebandSink; +} + +uint32_t RadiosondeDemod::getNumberOfDeviceStreams() const +{ + return m_deviceAPI->getNbSourceStreams(); +} + +void RadiosondeDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) +{ + (void) firstOfBurst; + m_basebandSink->feed(begin, end); +} + +void RadiosondeDemod::start() +{ + qDebug("RadiosondeDemod::start"); + + m_basebandSink->reset(); + m_basebandSink->startWork(); + m_thread.start(); + + DSPSignalNotification *dspMsg = new DSPSignalNotification(m_basebandSampleRate, m_centerFrequency); + m_basebandSink->getInputMessageQueue()->push(dspMsg); + + RadiosondeDemodBaseband::MsgConfigureRadiosondeDemodBaseband *msg = RadiosondeDemodBaseband::MsgConfigureRadiosondeDemodBaseband::create(m_settings, true); + m_basebandSink->getInputMessageQueue()->push(msg); +} + +void RadiosondeDemod::stop() +{ + qDebug("RadiosondeDemod::stop"); + m_basebandSink->stopWork(); + m_thread.quit(); + m_thread.wait(); +} + +bool RadiosondeDemod::handleMessage(const Message& cmd) +{ + if (MsgConfigureRadiosondeDemod::match(cmd)) + { + MsgConfigureRadiosondeDemod& cfg = (MsgConfigureRadiosondeDemod&) cmd; + qDebug() << "RadiosondeDemod::handleMessage: MsgConfigureRadiosondeDemod"; + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (DSPSignalNotification::match(cmd)) + { + DSPSignalNotification& notif = (DSPSignalNotification&) cmd; + m_basebandSampleRate = notif.getSampleRate(); + m_centerFrequency = notif.getCenterFrequency(); + // Forward to the sink + DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy + qDebug() << "RadiosondeDemod::handleMessage: DSPSignalNotification"; + m_basebandSink->getInputMessageQueue()->push(rep); + + return true; + } + else if (MsgMessage::match(cmd)) + { + MsgMessage& report = (MsgMessage&)cmd; + + // Decode the message + RS41Frame *frame = RS41Frame::decode(report.getMessage()); + RS41Subframe *subframe = nullptr; + + if (m_subframes.contains(frame->m_serial)) + { + subframe = m_subframes.value(frame->m_serial); + } + else + { + subframe = new RS41Subframe(); + m_subframes.insert(frame->m_serial, subframe); + } + subframe->update(frame); + + // Forward to GUI + if (getMessageQueueToGUI()) + { + MsgMessage *msg = new MsgMessage(report); + getMessageQueueToGUI()->push(msg); + } + + MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipes(); + + // Forward to Radiosonde feature + QList *radiosondeMessageQueues = messagePipes.getMessageQueues(this, "radiosonde"); + if (radiosondeMessageQueues) + { + QList::iterator it = radiosondeMessageQueues->begin(); + for (; it != radiosondeMessageQueues->end(); ++it) + { + MainCore::MsgPacket *msg = MainCore::MsgPacket::create(this, report.getMessage(), report.getDateTime()); + (*it)->push(msg); + } + } + + // Forward via UDP + if (m_settings.m_udpEnabled) + { + m_udpSocket.writeDatagram(report.getMessage().data(), report.getMessage().size(), + QHostAddress(m_settings.m_udpAddress), m_settings.m_udpPort); + } + + // Write to log file + if (m_logFile.isOpen()) + { + + m_logStream << report.getDateTime().date().toString() << "," + << report.getDateTime().time().toString() << "," + << report.getMessage().toHex() << ","; + + if (frame->m_statusValid) + { + m_logStream << frame->m_serial << "," + << frame->m_frameNumber << ","; + } + else + { + m_logStream << ",,"; + } + if (frame->m_posValid) + { + m_logStream << frame->m_latitude << "," + << frame->m_longitude << ","; + } + else + { + m_logStream << ",,"; + } + if (frame->m_measValid) + { + m_logStream << frame->getPressureString(subframe) << "," + << frame->getTemperatureString(subframe) << "," + << frame->getHumidityString(subframe) << ","; + } + else + { + m_logStream << ",,,"; + } + m_logStream << "\n"; + } + + delete frame; + + return true; + } + else if (MainCore::MsgChannelDemodQuery::match(cmd)) + { + qDebug() << "RadiosondeDemod::handleMessage: MsgChannelDemodQuery"; + sendSampleRateToDemodAnalyzer(); + + return true; + } + else + { + return false; + } +} + +ScopeVis *RadiosondeDemod::getScopeSink() +{ + return m_basebandSink->getScopeSink(); +} + +void RadiosondeDemod::setCenterFrequency(qint64 frequency) +{ + RadiosondeDemodSettings settings = m_settings; + settings.m_inputFrequencyOffset = frequency; + applySettings(settings, false); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureRadiosondeDemod *msgToGUI = MsgConfigureRadiosondeDemod::create(settings, false); + m_guiMessageQueue->push(msgToGUI); + } +} + +void RadiosondeDemod::applySettings(const RadiosondeDemodSettings& settings, bool force) +{ + qDebug() << "RadiosondeDemod::applySettings:" + << " m_logEnabled: " << settings.m_logEnabled + << " m_logFilename: " << settings.m_logFilename + << " m_streamIndex: " << settings.m_streamIndex + << " m_useReverseAPI: " << settings.m_useReverseAPI + << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress + << " m_reverseAPIPort: " << settings.m_reverseAPIPort + << " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex + << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex + << " force: " << force; + + QList reverseAPIKeys; + + if ((settings.m_baud != m_settings.m_baud) || force) { + reverseAPIKeys.append("baud"); + } + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) { + reverseAPIKeys.append("inputFrequencyOffset"); + } + if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { + reverseAPIKeys.append("rfBandwidth"); + } + if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) { + reverseAPIKeys.append("fmDeviation"); + } + if ((settings.m_correlationThreshold != m_settings.m_correlationThreshold) || force) { + reverseAPIKeys.append("correlationThreshold"); + } + if ((settings.m_udpEnabled != m_settings.m_udpEnabled) || force) { + reverseAPIKeys.append("udpEnabled"); + } + if ((settings.m_udpAddress != m_settings.m_udpAddress) || force) { + reverseAPIKeys.append("udpAddress"); + } + if ((settings.m_udpPort != m_settings.m_udpPort) || force) { + reverseAPIKeys.append("udpPort"); + } + if ((settings.m_logFilename != m_settings.m_logFilename) || force) { + reverseAPIKeys.append("logFilename"); + } + if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) { + reverseAPIKeys.append("logEnabled"); + } + if (m_settings.m_streamIndex != settings.m_streamIndex) + { + if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only + { + m_deviceAPI->removeChannelSinkAPI(this); + m_deviceAPI->removeChannelSink(this, m_settings.m_streamIndex); + m_deviceAPI->addChannelSink(this, settings.m_streamIndex); + m_deviceAPI->addChannelSinkAPI(this); + } + + reverseAPIKeys.append("streamIndex"); + } + + RadiosondeDemodBaseband::MsgConfigureRadiosondeDemodBaseband *msg = RadiosondeDemodBaseband::MsgConfigureRadiosondeDemodBaseband::create(settings, force); + m_basebandSink->getInputMessageQueue()->push(msg); + + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) || + (m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + + if ((settings.m_logEnabled != m_settings.m_logEnabled) + || (settings.m_logFilename != m_settings.m_logFilename) + || force) + { + if (m_logFile.isOpen()) + { + m_logStream.flush(); + m_logFile.close(); + } + if (settings.m_logEnabled && !settings.m_logFilename.isEmpty()) + { + m_logFile.setFileName(settings.m_logFilename); + if (m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) + { + qDebug() << "RadiosondeDemod::applySettings - Logging to: " << settings.m_logFilename; + bool newFile = m_logFile.size() == 0; + m_logStream.setDevice(&m_logFile); + if (newFile) + { + // Write header + m_logStream << "Date,Time,Data,Serial,Frame,Lat,Lon,P (hPa),T (C), U (%)\n"; + } + } + else + { + qDebug() << "RadiosondeDemod::applySettings - Unable to open log file: " << settings.m_logFilename; + } + } + } + + m_settings = settings; +} + +QByteArray RadiosondeDemod::serialize() const +{ + return m_settings.serialize(); +} + +bool RadiosondeDemod::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + MsgConfigureRadiosondeDemod *msg = MsgConfigureRadiosondeDemod::create(m_settings, true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureRadiosondeDemod *msg = MsgConfigureRadiosondeDemod::create(m_settings, true); + m_inputMessageQueue.push(msg); + return false; + } +} + +void RadiosondeDemod::sendSampleRateToDemodAnalyzer() +{ + QList *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(this, "reportdemod"); + + if (messageQueues) + { + QList::iterator it = messageQueues->begin(); + + for (; it != messageQueues->end(); ++it) + { + MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create( + this, + RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE + ); + (*it)->push(msg); + } + } +} + +int RadiosondeDemod::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadiosondeDemodSettings(new SWGSDRangel::SWGRadiosondeDemodSettings()); + response.getRadiosondeDemodSettings()->init(); + webapiFormatChannelSettings(response, m_settings); + return 200; +} + +int RadiosondeDemod::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + RadiosondeDemodSettings settings = m_settings; + webapiUpdateChannelSettings(settings, channelSettingsKeys, response); + + MsgConfigureRadiosondeDemod *msg = MsgConfigureRadiosondeDemod::create(settings, force); + m_inputMessageQueue.push(msg); + + qDebug("RadiosondeDemod::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue); + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureRadiosondeDemod *msgToGUI = MsgConfigureRadiosondeDemod::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatChannelSettings(response, settings); + + return 200; +} + +void RadiosondeDemod::webapiUpdateChannelSettings( + RadiosondeDemodSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response) +{ + if (channelSettingsKeys.contains("baud")) { + settings.m_baud = response.getRadiosondeDemodSettings()->getBaud(); + } + if (channelSettingsKeys.contains("inputFrequencyOffset")) { + settings.m_inputFrequencyOffset = response.getRadiosondeDemodSettings()->getInputFrequencyOffset(); + } + if (channelSettingsKeys.contains("rfBandwidth")) { + settings.m_rfBandwidth = response.getRadiosondeDemodSettings()->getRfBandwidth(); + } + if (channelSettingsKeys.contains("fmDeviation")) { + settings.m_fmDeviation = response.getRadiosondeDemodSettings()->getFmDeviation(); + } + if (channelSettingsKeys.contains("correlationThreshold")) { + settings.m_correlationThreshold = response.getRadiosondeDemodSettings()->getCorrelationThreshold(); + } + if (channelSettingsKeys.contains("udpEnabled")) { + settings.m_udpEnabled = response.getRadiosondeDemodSettings()->getUdpEnabled(); + } + if (channelSettingsKeys.contains("udpAddress")) { + settings.m_udpAddress = *response.getRadiosondeDemodSettings()->getUdpAddress(); + } + if (channelSettingsKeys.contains("udpPort")) { + settings.m_udpPort = response.getRadiosondeDemodSettings()->getUdpPort(); + } + if (channelSettingsKeys.contains("logFilename")) { + settings.m_logFilename = *response.getRadiosondeDemodSettings()->getLogFilename(); + } + if (channelSettingsKeys.contains("logEnabled")) { + settings.m_logEnabled = response.getRadiosondeDemodSettings()->getLogEnabled(); + } + if (channelSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getRadiosondeDemodSettings()->getRgbColor(); + } + if (channelSettingsKeys.contains("title")) { + settings.m_title = *response.getRadiosondeDemodSettings()->getTitle(); + } + if (channelSettingsKeys.contains("streamIndex")) { + settings.m_streamIndex = response.getRadiosondeDemodSettings()->getStreamIndex(); + } + if (channelSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getRadiosondeDemodSettings()->getUseReverseApi() != 0; + } + if (channelSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getRadiosondeDemodSettings()->getReverseApiAddress(); + } + if (channelSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getRadiosondeDemodSettings()->getReverseApiPort(); + } + if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getRadiosondeDemodSettings()->getReverseApiDeviceIndex(); + } + if (channelSettingsKeys.contains("reverseAPIChannelIndex")) { + settings.m_reverseAPIChannelIndex = response.getRadiosondeDemodSettings()->getReverseApiChannelIndex(); + } + if (settings.m_scopeGUI && channelSettingsKeys.contains("scopeConfig")) { + settings.m_scopeGUI->updateFrom(channelSettingsKeys, response.getRadiosondeDemodSettings()->getScopeConfig()); + } + if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) { + settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getRadiosondeDemodSettings()->getChannelMarker()); + } + if (settings.m_rollupState && channelSettingsKeys.contains("rollupState")) { + settings.m_rollupState->updateFrom(channelSettingsKeys, response.getRadiosondeDemodSettings()->getRollupState()); + } +} + +void RadiosondeDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const RadiosondeDemodSettings& settings) +{ + response.getRadiosondeDemodSettings()->setBaud(settings.m_baud); + response.getRadiosondeDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + response.getRadiosondeDemodSettings()->setRfBandwidth(settings.m_rfBandwidth); + response.getRadiosondeDemodSettings()->setFmDeviation(settings.m_fmDeviation); + response.getRadiosondeDemodSettings()->setCorrelationThreshold(settings.m_correlationThreshold); + response.getRadiosondeDemodSettings()->setUdpEnabled(settings.m_udpEnabled); + response.getRadiosondeDemodSettings()->setUdpAddress(new QString(settings.m_udpAddress)); + response.getRadiosondeDemodSettings()->setUdpPort(settings.m_udpPort); + response.getRadiosondeDemodSettings()->setLogFilename(new QString(settings.m_logFilename)); + response.getRadiosondeDemodSettings()->setLogEnabled(settings.m_logEnabled); + + response.getRadiosondeDemodSettings()->setRgbColor(settings.m_rgbColor); + if (response.getRadiosondeDemodSettings()->getTitle()) { + *response.getRadiosondeDemodSettings()->getTitle() = settings.m_title; + } else { + response.getRadiosondeDemodSettings()->setTitle(new QString(settings.m_title)); + } + + response.getRadiosondeDemodSettings()->setStreamIndex(settings.m_streamIndex); + response.getRadiosondeDemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getRadiosondeDemodSettings()->getReverseApiAddress()) { + *response.getRadiosondeDemodSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getRadiosondeDemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getRadiosondeDemodSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getRadiosondeDemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); + response.getRadiosondeDemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); + + if (settings.m_scopeGUI) + { + if (response.getRadiosondeDemodSettings()->getScopeConfig()) + { + settings.m_scopeGUI->formatTo(response.getRadiosondeDemodSettings()->getScopeConfig()); + } + else + { + SWGSDRangel::SWGGLScope *swgGLScope = new SWGSDRangel::SWGGLScope(); + settings.m_scopeGUI->formatTo(swgGLScope); + response.getRadiosondeDemodSettings()->setScopeConfig(swgGLScope); + } + } + + if (settings.m_channelMarker) + { + if (response.getRadiosondeDemodSettings()->getChannelMarker()) + { + settings.m_channelMarker->formatTo(response.getRadiosondeDemodSettings()->getChannelMarker()); + } + else + { + SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker(); + settings.m_channelMarker->formatTo(swgChannelMarker); + response.getRadiosondeDemodSettings()->setChannelMarker(swgChannelMarker); + } + } + + if (settings.m_rollupState) + { + if (response.getRadiosondeDemodSettings()->getRollupState()) + { + settings.m_rollupState->formatTo(response.getRadiosondeDemodSettings()->getRollupState()); + } + else + { + SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState(); + settings.m_rollupState->formatTo(swgRollupState); + response.getRadiosondeDemodSettings()->setRollupState(swgRollupState); + } + } +} + +void RadiosondeDemod::webapiReverseSendSettings(QList& channelSettingsKeys, const RadiosondeDemodSettings& settings, bool force) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgChannelSettings; +} + +void RadiosondeDemod::webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RadiosondeDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) + swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); + swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); + swgChannelSettings->setChannelType(new QString("RadiosondeDemod")); + swgChannelSettings->setRadiosondeDemodSettings(new SWGSDRangel::SWGRadiosondeDemodSettings()); + SWGSDRangel::SWGRadiosondeDemodSettings *swgRadiosondeDemodSettings = swgChannelSettings->getRadiosondeDemodSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("baud") || force) { + swgRadiosondeDemodSettings->setBaud(settings.m_baud); + } + if (channelSettingsKeys.contains("fmDeviation") || force) { + swgRadiosondeDemodSettings->setFmDeviation(settings.m_fmDeviation); + } + if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { + swgRadiosondeDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + } + if (channelSettingsKeys.contains("rfBandwidth") || force) { + swgRadiosondeDemodSettings->setRfBandwidth(settings.m_rfBandwidth); + } + if (channelSettingsKeys.contains("correlationThreshold") || force) { + swgRadiosondeDemodSettings->setCorrelationThreshold(settings.m_correlationThreshold); + } + if (channelSettingsKeys.contains("udpEnabled") || force) { + swgRadiosondeDemodSettings->setUdpEnabled(settings.m_udpEnabled); + } + if (channelSettingsKeys.contains("udpAddress") || force) { + swgRadiosondeDemodSettings->setUdpAddress(new QString(settings.m_udpAddress)); + } + if (channelSettingsKeys.contains("udpPort") || force) { + swgRadiosondeDemodSettings->setUdpPort(settings.m_udpPort); + } + if (channelSettingsKeys.contains("logFilename") || force) { + swgRadiosondeDemodSettings->setLogFilename(new QString(settings.m_logFilename)); + } + if (channelSettingsKeys.contains("logEnabled") || force) { + swgRadiosondeDemodSettings->setLogEnabled(settings.m_logEnabled); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgRadiosondeDemodSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgRadiosondeDemodSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("streamIndex") || force) { + swgRadiosondeDemodSettings->setStreamIndex(settings.m_streamIndex); + } + + if (settings.m_scopeGUI && (channelSettingsKeys.contains("scopeConfig") || force)) + { + SWGSDRangel::SWGGLScope *swgGLScope = new SWGSDRangel::SWGGLScope(); + settings.m_scopeGUI->formatTo(swgGLScope); + swgRadiosondeDemodSettings->setScopeConfig(swgGLScope); + } + + if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force)) + { + SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker(); + settings.m_channelMarker->formatTo(swgChannelMarker); + swgRadiosondeDemodSettings->setChannelMarker(swgChannelMarker); + } +} + +void RadiosondeDemod::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "RadiosondeDemod::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("RadiosondeDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} + +void RadiosondeDemod::handleChannelMessages() +{ + Message* message; + + while ((message = m_channelMessageQueue.pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemod.h b/plugins/channelrx/demodradiosonde/radiosondedemod.h new file mode 100644 index 000000000..cec2df55d --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemod.h @@ -0,0 +1,195 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMOD_H +#define INCLUDE_RADIOSONDEDEMOD_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "dsp/basebandsamplesink.h" +#include "channel/channelapi.h" +#include "util/message.h" +#include "util/radiosonde.h" + +#include "radiosondedemodbaseband.h" +#include "radiosondedemodsettings.h" + +class QNetworkAccessManager; +class QNetworkReply; +class QThread; +class DeviceAPI; +class ScopeVis; + +class RadiosondeDemod : public BasebandSampleSink, public ChannelAPI { + +public: + class MsgConfigureRadiosondeDemod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const RadiosondeDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureRadiosondeDemod* create(const RadiosondeDemodSettings& settings, bool force) + { + return new MsgConfigureRadiosondeDemod(settings, force); + } + + private: + RadiosondeDemodSettings m_settings; + bool m_force; + + MsgConfigureRadiosondeDemod(const RadiosondeDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgMessage : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QByteArray getMessage() const { return m_message; } + QDateTime getDateTime() const { return m_dateTime; } + int getErrorsCorrected() const { return m_errorsCorrected; } + int getThreshold() const { return m_threshold; } + + static MsgMessage* create(QByteArray message, int errorsCorrected, int threshold) + { + return new MsgMessage(message, QDateTime::currentDateTime(), errorsCorrected, threshold); + } + + private: + QByteArray m_message; + QDateTime m_dateTime; + int m_errorsCorrected; + int m_threshold; + + MsgMessage(QByteArray message, QDateTime dateTime, int errorsCorrected, int threshold) : + Message(), + m_message(message), + m_dateTime(dateTime), + m_errorsCorrected(errorsCorrected), + m_threshold(threshold) + { + } + }; + + RadiosondeDemod(DeviceAPI *deviceAPI); + virtual ~RadiosondeDemod(); + virtual void destroy() { delete this; } + + using BasebandSampleSink::feed; + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); + virtual void start(); + virtual void stop(); + virtual void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); } + virtual QString getSinkName() { return objectName(); } + + virtual void getIdentifier(QString& id) { id = objectName(); } + virtual const QString& getURI() const { return getName(); } + virtual void getTitle(QString& title) { title = m_settings.m_title; } + virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; } + virtual void setCenterFrequency(qint64 frequency); + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int getNbSinkStreams() const { return 1; } + virtual int getNbSourceStreams() const { return 0; } + + virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const + { + (void) streamIndex; + (void) sinkElseSource; + return 0; + } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + static void webapiFormatChannelSettings( + SWGSDRangel::SWGChannelSettings& response, + const RadiosondeDemodSettings& settings); + + static void webapiUpdateChannelSettings( + RadiosondeDemodSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response); + + ScopeVis *getScopeSink(); + double getMagSq() const { return m_basebandSink->getMagSq(); } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) { + m_basebandSink->getMagSqLevels(avg, peak, nbSamples); + } + + uint32_t getNumberOfDeviceStreams() const; + + static const char * const m_channelIdURI; + static const char * const m_channelId; + +private: + DeviceAPI *m_deviceAPI; + QThread m_thread; + RadiosondeDemodBaseband* m_basebandSink; + RadiosondeDemodSettings m_settings; + int m_basebandSampleRate; //!< stored from device message used when starting baseband sink + qint64 m_centerFrequency; + QUdpSocket m_udpSocket; + QFile m_logFile; + QTextStream m_logStream; + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + QHash m_subframes; // Hash of serial to subframes + + virtual bool handleMessage(const Message& cmd); + void applySettings(const RadiosondeDemodSettings& settings, bool force = false); + void sendSampleRateToDemodAnalyzer(); + void webapiReverseSendSettings(QList& channelSettingsKeys, const RadiosondeDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RadiosondeDemodSettings& settings, + bool force + ); + +private slots: + void networkManagerFinished(QNetworkReply *reply); + void handleChannelMessages(); +}; + +#endif // INCLUDE_RADIOSONDEDEMOD_H diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.cpp new file mode 100644 index 000000000..a2df39d1e --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.cpp @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "dsp/downchannelizer.h" + +#include "radiosondedemodbaseband.h" + +MESSAGE_CLASS_DEFINITION(RadiosondeDemodBaseband::MsgConfigureRadiosondeDemodBaseband, Message) + +RadiosondeDemodBaseband::RadiosondeDemodBaseband(RadiosondeDemod *radiosondeDemod) : + m_sink(radiosondeDemod), + m_running(false), + m_mutex(QMutex::Recursive) +{ + qDebug("RadiosondeDemodBaseband::RadiosondeDemodBaseband"); + + m_sink.setScopeSink(&m_scopeSink); + m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000)); + m_channelizer = new DownChannelizer(&m_sink); +} + +RadiosondeDemodBaseband::~RadiosondeDemodBaseband() +{ + m_inputMessageQueue.clear(); + + delete m_channelizer; +} + +void RadiosondeDemodBaseband::reset() +{ + QMutexLocker mutexLocker(&m_mutex); + m_inputMessageQueue.clear(); + m_sampleFifo.reset(); +} + +void RadiosondeDemodBaseband::startWork() +{ + QMutexLocker mutexLocker(&m_mutex); + QObject::connect( + &m_sampleFifo, + &SampleSinkFifo::dataReady, + this, + &RadiosondeDemodBaseband::handleData, + Qt::QueuedConnection + ); + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_running = true; +} + +void RadiosondeDemodBaseband::stopWork() +{ + QMutexLocker mutexLocker(&m_mutex); + disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + QObject::disconnect( + &m_sampleFifo, + &SampleSinkFifo::dataReady, + this, + &RadiosondeDemodBaseband::handleData + ); + m_running = false; +} + +void RadiosondeDemodBaseband::setChannel(ChannelAPI *channel) +{ + m_sink.setChannel(channel); +} + +void RadiosondeDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +{ + m_sampleFifo.write(begin, end); +} + +void RadiosondeDemodBaseband::handleData() +{ + QMutexLocker mutexLocker(&m_mutex); + + while ((m_sampleFifo.fill() > 0) && (m_inputMessageQueue.size() == 0)) + { + SampleVector::iterator part1begin; + SampleVector::iterator part1end; + SampleVector::iterator part2begin; + SampleVector::iterator part2end; + + std::size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end); + + // first part of FIFO data + if (part1begin != part1end) { + m_channelizer->feed(part1begin, part1end); + } + + // second part of FIFO data (used when block wraps around) + if(part2begin != part2end) { + m_channelizer->feed(part2begin, part2end); + } + + m_sampleFifo.readCommit((unsigned int) count); + } +} + +void RadiosondeDemodBaseband::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +bool RadiosondeDemodBaseband::handleMessage(const Message& cmd) +{ + if (MsgConfigureRadiosondeDemodBaseband::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + MsgConfigureRadiosondeDemodBaseband& cfg = (MsgConfigureRadiosondeDemodBaseband&) cmd; + qDebug() << "RadiosondeDemodBaseband::handleMessage: MsgConfigureRadiosondeDemodBaseband"; + + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (DSPSignalNotification::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + DSPSignalNotification& notif = (DSPSignalNotification&) cmd; + qDebug() << "RadiosondeDemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate(); + setBasebandSampleRate(notif.getSampleRate()); + m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate())); + + return true; + } + else + { + return false; + } +} + +void RadiosondeDemodBaseband::applySettings(const RadiosondeDemodSettings& settings, bool force) +{ + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) + { + m_channelizer->setChannelization(RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE, settings.m_inputFrequencyOffset); + m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); + } + + m_sink.applySettings(settings, force); + + m_settings = settings; +} + +void RadiosondeDemodBaseband::setBasebandSampleRate(int sampleRate) +{ + m_channelizer->setBasebandSampleRate(sampleRate); + m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.h b/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.h new file mode 100644 index 000000000..3ba183ca8 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodbaseband.h @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMODBASEBAND_H +#define INCLUDE_RADIOSONDEDEMODBASEBAND_H + +#include +#include + +#include "dsp/samplesinkfifo.h" +#include "dsp/scopevis.h" +#include "util/message.h" +#include "util/messagequeue.h" + +#include "radiosondedemodsink.h" + +class DownChannelizer; +class ChannelAPI; +class RadiosondeDemod; +class ScopeVis; + +class RadiosondeDemodBaseband : public QObject +{ + Q_OBJECT +public: + class MsgConfigureRadiosondeDemodBaseband : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const RadiosondeDemodSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureRadiosondeDemodBaseband* create(const RadiosondeDemodSettings& settings, bool force) + { + return new MsgConfigureRadiosondeDemodBaseband(settings, force); + } + + private: + RadiosondeDemodSettings m_settings; + bool m_force; + + MsgConfigureRadiosondeDemodBaseband(const RadiosondeDemodSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + RadiosondeDemodBaseband(RadiosondeDemod *radiosondeDemod); + ~RadiosondeDemodBaseband(); + void reset(); + void startWork(); + void stopWork(); + void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); + MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication + void getMagSqLevels(double& avg, double& peak, int& nbSamples) { + m_sink.getMagSqLevels(avg, peak, nbSamples); + } + void setMessageQueueToChannel(MessageQueue *messageQueue) { m_sink.setMessageQueueToChannel(messageQueue); } + void setBasebandSampleRate(int sampleRate); + ScopeVis *getScopeSink() { return &m_scopeSink; } + void setChannel(ChannelAPI *channel); + double getMagSq() const { return m_sink.getMagSq(); } + bool isRunning() const { return m_running; } + +private: + SampleSinkFifo m_sampleFifo; + DownChannelizer *m_channelizer; + RadiosondeDemodSink m_sink; + MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication + RadiosondeDemodSettings m_settings; + ScopeVis m_scopeSink; + bool m_running; + QMutex m_mutex; + + bool handleMessage(const Message& cmd); + void calculateOffset(RadiosondeDemodSink *sink); + void applySettings(const RadiosondeDemodSettings& settings, bool force = false); + +private slots: + void handleInputMessages(); + void handleData(); //!< Handle data when samples have to be processed +}; + +#endif // INCLUDE_RADIOSONDEDEMODBASEBAND_H diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodgui.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodgui.cpp new file mode 100644 index 000000000..a9ac324f3 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodgui.cpp @@ -0,0 +1,898 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "radiosondedemodgui.h" + +#include "device/deviceuiset.h" +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "ui_radiosondedemodgui.h" +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" +#include "util/csv.h" +#include "util/db.h" +#include "util/units.h" +#include "gui/basicchannelsettingsdialog.h" +#include "gui/devicestreamselectiondialog.h" +#include "gui/datetimedelegate.h" +#include "gui/decimaldelegate.h" +#include "gui/timedelegate.h" +#include "dsp/dspengine.h" +#include "dsp/glscopesettings.h" +#include "gui/crightclickenabler.h" +#include "channel/channelwebapiutils.h" +#include "maincore.h" +#include "feature/featurewebapiutils.h" + +#include "radiosondedemod.h" +#include "radiosondedemodsink.h" + +void RadiosondeDemodGUI::resizeTable() +{ + // Fill table with a row of dummy data that will size the columns nicely + // Trailing chars are for sort arrow + int row = ui->frames->rowCount(); + ui->frames->setRowCount(row + 1); + ui->frames->setItem(row, FRAME_COL_DATE, new QTableWidgetItem("2015/04/15-")); + ui->frames->setItem(row, FRAME_COL_TIME, new QTableWidgetItem("10:17:00")); + ui->frames->setItem(row, FRAME_COL_SERIAL, new QTableWidgetItem("S1234567")); + ui->frames->setItem(row, FRAME_COL_FRAME_NUMBER, new QTableWidgetItem("10000")); + ui->frames->setItem(row, FRAME_COL_FLIGHT_PHASE, new QTableWidgetItem("Descent")); + ui->frames->setItem(row, FRAME_COL_LATITUDE, new QTableWidgetItem("-90.00000")); + ui->frames->setItem(row, FRAME_COL_LONGITUDE, new QTableWidgetItem("-180.00000")); + ui->frames->setItem(row, FRAME_COL_ALTITUDE, new QTableWidgetItem("20000.0")); + ui->frames->setItem(row, FRAME_COL_SPEED, new QTableWidgetItem("50.0")); + ui->frames->setItem(row, FRAME_COL_VERTICAL_RATE, new QTableWidgetItem("50.0")); + ui->frames->setItem(row, FRAME_COL_HEADING, new QTableWidgetItem("359.0")); + ui->frames->setItem(row, FRAME_COL_PRESSURE, new QTableWidgetItem("100.0")); + ui->frames->setItem(row, FRAME_COL_TEMP, new QTableWidgetItem("-50.1U")); + ui->frames->setItem(row, FRAME_COL_HUMIDITY, new QTableWidgetItem("100.0")); + ui->frames->setItem(row, FRAME_COL_BATTERY_VOLTAGE, new QTableWidgetItem("2.7")); + ui->frames->setItem(row, FRAME_COL_BATTERY_STATUS, new QTableWidgetItem("Low")); + ui->frames->setItem(row, FRAME_COL_PCB_TEMP, new QTableWidgetItem("21")); + ui->frames->setItem(row, FRAME_COL_HUMIDITY_PWM, new QTableWidgetItem("1000")); + ui->frames->setItem(row, FRAME_COL_TX_POWER, new QTableWidgetItem("7")); + ui->frames->setItem(row, FRAME_COL_MAX_SUBFRAME_NO, new QTableWidgetItem("50")); + ui->frames->setItem(row, FRAME_COL_SUBFRAME_NO, new QTableWidgetItem("50")); + ui->frames->setItem(row, FRAME_COL_SUBFRAME, new QTableWidgetItem("00112233445566778899aabbccddeeff----")); + ui->frames->setItem(row, FRAME_COL_GPS_TIME, new QTableWidgetItem("2015/04/15 10:17:00")); + ui->frames->setItem(row, FRAME_COL_GPS_SATS, new QTableWidgetItem("12")); + ui->frames->setItem(row, FRAME_COL_ECC, new QTableWidgetItem("12")); + ui->frames->setItem(row, FRAME_COL_CORR, new QTableWidgetItem("-500")); + ui->frames->resizeColumnsToContents(); + ui->frames->removeRow(row); +} + +// Columns in table reordered +void RadiosondeDemodGUI::frames_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) +{ + (void) oldVisualIndex; + + m_settings.m_frameColumnIndexes[logicalIndex] = newVisualIndex; +} + +// Column in table resized (when hidden size is 0) +void RadiosondeDemodGUI::frames_sectionResized(int logicalIndex, int oldSize, int newSize) +{ + (void) oldSize; + + m_settings.m_frameColumnSizes[logicalIndex] = newSize; +} + +// Right click in table header - show column select menu +void RadiosondeDemodGUI::framesColumnSelectMenu(QPoint pos) +{ + framesMenu->popup(ui->frames->horizontalHeader()->viewport()->mapToGlobal(pos)); +} + +// Hide/show column when menu selected +void RadiosondeDemodGUI::framesColumnSelectMenuChecked(bool checked) +{ + (void) checked; + + QAction* action = qobject_cast(sender()); + if (action != nullptr) + { + int idx = action->data().toInt(nullptr); + ui->frames->setColumnHidden(idx, !action->isChecked()); + } +} + +// Create column select menu item +QAction *RadiosondeDemodGUI::createCheckableItem(QString &text, int idx, bool checked, const char *slot) +{ + QAction *action = new QAction(text, this); + action->setCheckable(true); + action->setChecked(checked); + action->setData(QVariant(idx)); + connect(action, SIGNAL(triggered()), this, slot); + return action; +} + +RadiosondeDemodGUI* RadiosondeDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) +{ + RadiosondeDemodGUI* gui = new RadiosondeDemodGUI(pluginAPI, deviceUISet, rxChannel); + return gui; +} + +void RadiosondeDemodGUI::destroy() +{ + delete this; +} + +void RadiosondeDemodGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); +} + +QByteArray RadiosondeDemodGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool RadiosondeDemodGUI::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + applySettings(true); + return true; + } else { + resetToDefaults(); + return false; + } +} + +// Add row to table +void RadiosondeDemodGUI::frameReceived(const QByteArray& frame, const QDateTime& dateTime, int errorsCorrected, int threshold) +{ + RS41Frame *radiosonde; + + // Decode the frame + radiosonde = RS41Frame::decode(frame); + + // Is scroll bar at bottom + QScrollBar *sb = ui->frames->verticalScrollBar(); + bool scrollToBottom = sb->value() == sb->maximum(); + + // Add to frames table + ui->frames->setSortingEnabled(false); + int row = ui->frames->rowCount(); + ui->frames->setRowCount(row + 1); + + QTableWidgetItem *dateItem = new QTableWidgetItem(); + QTableWidgetItem *timeItem = new QTableWidgetItem(); + QTableWidgetItem *serialItem = new QTableWidgetItem(); + QTableWidgetItem *frameNumberItem = new QTableWidgetItem(); + QTableWidgetItem *flightPhaseItem = new QTableWidgetItem(); + QTableWidgetItem *latitudeItem = new QTableWidgetItem(); + QTableWidgetItem *longitudeItem = new QTableWidgetItem(); + QTableWidgetItem *altitudeItem = new QTableWidgetItem(); + QTableWidgetItem *speedItem = new QTableWidgetItem(); + QTableWidgetItem *verticalRateItem = new QTableWidgetItem(); + QTableWidgetItem *headingItem = new QTableWidgetItem(); + QTableWidgetItem *pressureItem = new QTableWidgetItem(); + QTableWidgetItem *tempItem = new QTableWidgetItem(); + QTableWidgetItem *humidityItem = new QTableWidgetItem(); + QTableWidgetItem *batteryVoltageItem = new QTableWidgetItem(); + QTableWidgetItem *batteryStatusItem = new QTableWidgetItem(); + QTableWidgetItem *pcbTempItem = new QTableWidgetItem(); + QTableWidgetItem *humidityPWMItem = new QTableWidgetItem(); + QTableWidgetItem *txPowerItem = new QTableWidgetItem(); + QTableWidgetItem *maxSubframeNoItem = new QTableWidgetItem(); + QTableWidgetItem *subframeNoItem = new QTableWidgetItem(); + QTableWidgetItem *subframeItem = new QTableWidgetItem(); + QTableWidgetItem *gpsTimeItem = new QTableWidgetItem(); + QTableWidgetItem *gpsSatsItem = new QTableWidgetItem(); + QTableWidgetItem *eccItem = new QTableWidgetItem(); + QTableWidgetItem *thItem = new QTableWidgetItem(); + + ui->frames->setItem(row, FRAME_COL_DATE, dateItem); + ui->frames->setItem(row, FRAME_COL_TIME, timeItem); + ui->frames->setItem(row, FRAME_COL_SERIAL, serialItem); + ui->frames->setItem(row, FRAME_COL_FRAME_NUMBER, frameNumberItem); + ui->frames->setItem(row, FRAME_COL_FLIGHT_PHASE, flightPhaseItem); + ui->frames->setItem(row, FRAME_COL_LATITUDE, latitudeItem); + ui->frames->setItem(row, FRAME_COL_LONGITUDE, longitudeItem); + ui->frames->setItem(row, FRAME_COL_ALTITUDE, altitudeItem); + ui->frames->setItem(row, FRAME_COL_SPEED, speedItem); + ui->frames->setItem(row, FRAME_COL_VERTICAL_RATE, verticalRateItem); + ui->frames->setItem(row, FRAME_COL_HEADING, headingItem); + ui->frames->setItem(row, FRAME_COL_PRESSURE, pressureItem); + ui->frames->setItem(row, FRAME_COL_TEMP, tempItem); + ui->frames->setItem(row, FRAME_COL_HUMIDITY, humidityItem); + ui->frames->setItem(row, FRAME_COL_BATTERY_VOLTAGE, batteryVoltageItem); + ui->frames->setItem(row, FRAME_COL_BATTERY_STATUS, batteryStatusItem); + ui->frames->setItem(row, FRAME_COL_PCB_TEMP, pcbTempItem); + ui->frames->setItem(row, FRAME_COL_HUMIDITY_PWM, humidityPWMItem); + ui->frames->setItem(row, FRAME_COL_TX_POWER, txPowerItem); + ui->frames->setItem(row, FRAME_COL_MAX_SUBFRAME_NO, maxSubframeNoItem); + ui->frames->setItem(row, FRAME_COL_SUBFRAME_NO, subframeNoItem); + ui->frames->setItem(row, FRAME_COL_SUBFRAME, subframeItem); + ui->frames->setItem(row, FRAME_COL_GPS_TIME, gpsTimeItem); + ui->frames->setItem(row, FRAME_COL_GPS_SATS, gpsSatsItem); + ui->frames->setItem(row, FRAME_COL_ECC, eccItem); + ui->frames->setItem(row, FRAME_COL_CORR, thItem); + + dateItem->setData(Qt::DisplayRole, dateTime.date()); + timeItem->setData(Qt::DisplayRole, dateTime.time()); + + RS41Subframe *subframe = nullptr; + + frameNumberItem->setData(Qt::DisplayRole, radiosonde->m_frameNumber); + if (radiosonde->m_statusValid) + { + serialItem->setText(radiosonde->m_serial); + flightPhaseItem->setText(radiosonde->m_flightPhase); + batteryVoltageItem->setData(Qt::DisplayRole, radiosonde->m_batteryVoltage); + batteryStatusItem->setText(radiosonde->m_batteryStatus); + pcbTempItem->setData(Qt::DisplayRole, radiosonde->m_pcbTemperature); + humidityPWMItem->setData(Qt::DisplayRole, (int)round(radiosonde->m_humiditySensorHeating / 1000.0 * 100.0)); + txPowerItem->setData(Qt::DisplayRole, (int)round(radiosonde->m_transmitPower / 7.0 * 100.0)); + maxSubframeNoItem->setData(Qt::DisplayRole, radiosonde->m_maxSubframeNumber); + subframeNoItem->setData(Qt::DisplayRole, radiosonde->m_subframeNumber); + subframeItem->setText(radiosonde->m_subframe.toHex()); + if (m_subframes.contains(radiosonde->m_serial)) + { + subframe = m_subframes.value(radiosonde->m_serial); + } + else + { + subframe = new RS41Subframe(); + m_subframes.insert(radiosonde->m_serial, subframe); + } + subframe->update(radiosonde); + } + + if (radiosonde->m_posValid) + { + latitudeItem->setData(Qt::DisplayRole, radiosonde->m_latitude); + longitudeItem->setData(Qt::DisplayRole, radiosonde->m_longitude); + altitudeItem->setData(Qt::DisplayRole, radiosonde->m_height); + speedItem->setData(Qt::DisplayRole, Units::kmpsToKPH(radiosonde->m_speed/1000.0)); + verticalRateItem->setData(Qt::DisplayRole, radiosonde->m_verticalRate); + headingItem->setData(Qt::DisplayRole, radiosonde->m_heading); + gpsSatsItem->setData(Qt::DisplayRole, radiosonde->m_satellitesUsed); + } + + if (radiosonde->m_gpsInfoValid) + { + gpsTimeItem->setData(Qt::DisplayRole, radiosonde->m_gpsDateTime); + } + + if (radiosonde->m_measValid && subframe) + { + pressureItem->setData(Qt::DisplayRole, radiosonde->getPressureString(subframe)); + tempItem->setData(Qt::DisplayRole, radiosonde->getTemperatureString(subframe)); + humidityItem->setData(Qt::DisplayRole, radiosonde->getHumidityString(subframe)); + } + + eccItem->setData(Qt::DisplayRole, errorsCorrected); + thItem->setData(Qt::DisplayRole, threshold); + + ui->frames->setSortingEnabled(true); + if (scrollToBottom) { + ui->frames->scrollToBottom(); + } + filterRow(row); + + delete radiosonde; +} + +bool RadiosondeDemodGUI::handleMessage(const Message& frame) +{ + if (RadiosondeDemod::MsgConfigureRadiosondeDemod::match(frame)) + { + qDebug("RadiosondeDemodGUI::handleMessage: RadiosondeDemod::MsgConfigureRadiosondeDemod"); + const RadiosondeDemod::MsgConfigureRadiosondeDemod& cfg = (RadiosondeDemod::MsgConfigureRadiosondeDemod&) frame; + m_settings = cfg.getSettings(); + blockApplySettings(true); + ui->scopeGUI->updateSettings(); + m_channelMarker.updateSettings(static_cast(m_settings.m_channelMarker)); + displaySettings(); + blockApplySettings(false); + return true; + } + else if (RadiosondeDemod::MsgMessage::match(frame)) + { + RadiosondeDemod::MsgMessage& report = (RadiosondeDemod::MsgMessage&) frame; + frameReceived(report.getMessage(), report.getDateTime(), report.getErrorsCorrected(), report.getThreshold()); + return true; + } + + return false; +} + +void RadiosondeDemodGUI::handleInputMessages() +{ + Message* frame; + + while ((frame = getInputMessageQueue()->pop()) != 0) + { + if (handleMessage(*frame)) + { + delete frame; + } + } +} + +void RadiosondeDemodGUI::channelMarkerChangedByCursor() +{ + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); +} + +void RadiosondeDemodGUI::channelMarkerHighlightedByCursor() +{ + setHighlighted(m_channelMarker.getHighlighted()); +} + +void RadiosondeDemodGUI::on_deltaFrequency_changed(qint64 value) +{ + m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); +} + +void RadiosondeDemodGUI::on_rfBW_valueChanged(int value) +{ + float bw = value * 100.0f; + ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_channelMarker.setBandwidth(bw); + m_settings.m_rfBandwidth = bw; + applySettings(); +} + +void RadiosondeDemodGUI::on_fmDev_valueChanged(int value) +{ + ui->fmDevText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1)); + m_settings.m_fmDeviation = value * 100.0; + applySettings(); +} + +void RadiosondeDemodGUI::on_threshold_valueChanged(int value) +{ + ui->thresholdText->setText(QString("%1").arg(value)); + m_settings.m_correlationThreshold = value; + applySettings(); +} + +void RadiosondeDemodGUI::on_filterSerial_editingFinished() +{ + m_settings.m_filterSerial = ui->filterSerial->text(); + filter(); + applySettings(); +} + +void RadiosondeDemodGUI::on_clearTable_clicked() +{ + ui->frames->setRowCount(0); +} + +void RadiosondeDemodGUI::on_udpEnabled_clicked(bool checked) +{ + m_settings.m_udpEnabled = checked; + applySettings(); +} + +void RadiosondeDemodGUI::on_udpAddress_editingFinished() +{ + m_settings.m_udpAddress = ui->udpAddress->text(); + applySettings(); +} + +void RadiosondeDemodGUI::on_udpPort_editingFinished() +{ + m_settings.m_udpPort = ui->udpPort->text().toInt(); + applySettings(); +} + +void RadiosondeDemodGUI::on_channel1_currentIndexChanged(int index) +{ + m_settings.m_scopeCh1 = index; + applySettings(); +} + +void RadiosondeDemodGUI::on_channel2_currentIndexChanged(int index) +{ + m_settings.m_scopeCh2 = index; + applySettings(); +} + +void RadiosondeDemodGUI::on_frames_cellDoubleClicked(int row, int column) +{ + // Get serial in row double clicked + QString serial = ui->frames->item(row, FRAME_COL_SERIAL)->text(); + if (column == FRAME_COL_SERIAL) + { + // Search for Serial on sondehub + QDesktopServices::openUrl(QUrl(QString("https://sondehub.org/?f=%1#!mt=Mapnik&f=%1&q=%1").arg(serial))); + } + else if ((column == FRAME_COL_LATITUDE) || (column == FRAME_COL_LONGITUDE)) + { + // Find serial on Map + FeatureWebAPIUtils::mapFind(serial); + } +} + +void RadiosondeDemodGUI::filterRow(int row) +{ + bool hidden = false; + if (m_settings.m_filterSerial != "") + { + QRegExp re(m_settings.m_filterSerial); + QTableWidgetItem *fromItem = ui->frames->item(row, FRAME_COL_SERIAL); + if (!re.exactMatch(fromItem->text())) + hidden = true; + } + ui->frames->setRowHidden(row, hidden); +} + +void RadiosondeDemodGUI::filter() +{ + for (int i = 0; i < ui->frames->rowCount(); i++) + { + filterRow(i); + } +} + +void RadiosondeDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + if (widget == ui->scopeContainer) + { + if (rollDown) + { + // Make wide enough for scope controls + setMinimumWidth(716); + } + else + { + setMinimumWidth(352); + } + } + + saveState(m_rollupState); + applySettings(); +} + +void RadiosondeDemodGUI::onMenuDialogCalled(const QPoint &p) +{ + if (m_contextMenuType == ContextMenuChannelSettings) + { + BasicChannelSettingsDialog dialog(&m_channelMarker, this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex); + dialog.move(p); + dialog.exec(); + + m_settings.m_rgbColor = m_channelMarker.getColor().rgb(); + m_settings.m_title = m_channelMarker.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex(); + + setWindowTitle(m_settings.m_title); + setTitleColor(m_settings.m_rgbColor); + + applySettings(); + } + else if ((m_contextMenuType == ContextMenuStreamSettings) && (m_deviceUISet->m_deviceMIMOEngine)) + { + DeviceStreamSelectionDialog dialog(this); + dialog.setNumberOfStreams(m_radiosondeDemod->getNumberOfDeviceStreams()); + dialog.setStreamIndex(m_settings.m_streamIndex); + dialog.move(p); + dialog.exec(); + + m_settings.m_streamIndex = dialog.getSelectedStreamIndex(); + m_channelMarker.clearStreamIndexes(); + m_channelMarker.addStreamIndex(m_settings.m_streamIndex); + displayStreamIndex(); + applySettings(); + } + + resetContextMenuType(); +} + +RadiosondeDemodGUI::RadiosondeDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : + ChannelGUI(parent), + ui(new Ui::RadiosondeDemodGUI), + m_pluginAPI(pluginAPI), + m_deviceUISet(deviceUISet), + m_channelMarker(this), + m_doApplySettings(true), + m_tickCount(0) +{ + ui->setupUi(this); + m_helpURL = "plugins/channelrx/demodradiosonde/readme.md"; + + setAttribute(Qt::WA_DeleteOnClose, true); + connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); + + m_radiosondeDemod = reinterpret_cast(rxChannel); + m_radiosondeDemod->setMessageQueueToGUI(getInputMessageQueue()); + + connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms + + m_scopeVis = m_radiosondeDemod->getScopeSink(); + m_scopeVis->setGLScope(ui->glScope); + ui->glScope->connectTimer(MainCore::instance()->getMasterTimer()); + ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); + + // Scope settings to display the IQ waveforms + ui->scopeGUI->setPreTrigger(1); + GLScopeSettings::TraceData traceDataI, traceDataQ; + traceDataI.m_projectionType = Projector::ProjectionReal; + traceDataI.m_amp = 1.0; // for -1 to +1 + traceDataI.m_ofs = 0.0; // vertical offset + traceDataQ.m_projectionType = Projector::ProjectionImag; + traceDataQ.m_amp = 1.0; + traceDataQ.m_ofs = 0.0; + ui->scopeGUI->changeTrace(0, traceDataI); + ui->scopeGUI->addTrace(traceDataQ); + ui->scopeGUI->setDisplayMode(GLScopeSettings::DisplayXYV); + ui->scopeGUI->focusOnTrace(0); // re-focus to take changes into account in the GUI + + GLScopeSettings::TriggerData triggerData; + triggerData.m_triggerLevel = 0.1; + triggerData.m_triggerLevelCoarse = 10; + triggerData.m_triggerPositiveEdge = true; + ui->scopeGUI->changeTrigger(0, triggerData); + ui->scopeGUI->focusOnTrigger(0); // re-focus to take changes into account in the GUI + + m_scopeVis->setLiveRate(9600*6); + //m_scopeVis->setFreeRun(false); // FIXME: add method rather than call m_scopeVis->configure() + + ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); + ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); + ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue); + + m_channelMarker.blockSignals(true); + m_channelMarker.setColor(Qt::yellow); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setTitle("Radiosonde Demodulator"); + m_channelMarker.blockSignals(false); + m_channelMarker.setVisible(true); // activate signal on the last setting only + + setTitleColor(m_channelMarker.getColor()); + m_settings.setChannelMarker(&m_channelMarker); + m_settings.setScopeGUI(ui->scopeGUI); + m_settings.setRollupState(&m_rollupState); + + m_deviceUISet->addChannelMarker(&m_channelMarker); + m_deviceUISet->addRollupWidget(this); + + connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor())); + connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + + // Resize the table using dummy data + resizeTable(); + // Allow user to reorder columns + ui->frames->horizontalHeader()->setSectionsMovable(true); + // Allow user to sort table by clicking on headers + ui->frames->setSortingEnabled(true); + // Add context menu to allow hiding/showing of columns + framesMenu = new QMenu(ui->frames); + for (int i = 0; i < ui->frames->horizontalHeader()->count(); i++) + { + QString text = ui->frames->horizontalHeaderItem(i)->text(); + framesMenu->addAction(createCheckableItem(text, i, true, SLOT(framesColumnSelectMenuChecked()))); + } + ui->frames->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->frames->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(framesColumnSelectMenu(QPoint))); + // Get signals when columns change + connect(ui->frames->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(frames_sectionMoved(int, int, int))); + connect(ui->frames->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(frames_sectionResized(int, int, int))); + ui->frames->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->frames, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customContextMenuRequested(QPoint))); + + ui->frames->setItemDelegateForColumn(FRAME_COL_DATE, new DateTimeDelegate("yyyy/MM/dd")); + ui->frames->setItemDelegateForColumn(FRAME_COL_TIME, new TimeDelegate()); + ui->frames->setItemDelegateForColumn(FRAME_COL_LATITUDE, new DecimalDelegate(5)); + ui->frames->setItemDelegateForColumn(FRAME_COL_LONGITUDE, new DecimalDelegate(5)); + ui->frames->setItemDelegateForColumn(FRAME_COL_ALTITUDE, new DecimalDelegate(1)); + ui->frames->setItemDelegateForColumn(FRAME_COL_SPEED, new DecimalDelegate(1)); + ui->frames->setItemDelegateForColumn(FRAME_COL_VERTICAL_RATE, new DecimalDelegate(1)); + ui->frames->setItemDelegateForColumn(FRAME_COL_HEADING, new DecimalDelegate(1)); + ui->frames->setItemDelegateForColumn(FRAME_COL_GPS_TIME, new DateTimeDelegate("yyyy/MM/dd hh:mm:ss")); + + ui->scopeContainer->setVisible(false); + + displaySettings(); + applySettings(true); +} + +void RadiosondeDemodGUI::customContextMenuRequested(QPoint pos) +{ + QTableWidgetItem *item = ui->frames->itemAt(pos); + if (item) + { + int row = item->row(); + QString serial = ui->frames->item(row, FRAME_COL_SERIAL)->text(); + + QMenu* tableContextMenu = new QMenu(ui->frames); + connect(tableContextMenu, &QMenu::aboutToHide, tableContextMenu, &QMenu::deleteLater); + + // Copy current cell + QAction* copyAction = new QAction("Copy", tableContextMenu); + const QString text = item->text(); + connect(copyAction, &QAction::triggered, this, [text]()->void { + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(text); + }); + tableContextMenu->addAction(copyAction); + + // View radiosonde on various websites + QAction* mmsiRadiosondeHubAction = new QAction(QString("View %1 on sondehub.net...").arg(serial), tableContextMenu); + connect(mmsiRadiosondeHubAction, &QAction::triggered, this, [serial]()->void { + QDesktopServices::openUrl(QUrl(QString("https://sondehub.org/?f=%1#!mt=Mapnik&f=%1&q=%1").arg(serial))); + }); + tableContextMenu->addAction(mmsiRadiosondeHubAction); + + // Find on Map + tableContextMenu->addSeparator(); + QAction* findMapFeatureAction = new QAction(QString("Find %1 on map").arg(serial), tableContextMenu); + connect(findMapFeatureAction, &QAction::triggered, this, [serial]()->void { + FeatureWebAPIUtils::mapFind(serial); + }); + tableContextMenu->addAction(findMapFeatureAction); + + tableContextMenu->popup(ui->frames->viewport()->mapToGlobal(pos)); + } +} + +RadiosondeDemodGUI::~RadiosondeDemodGUI() +{ + delete ui; + qDeleteAll(m_subframes); +} + +void RadiosondeDemodGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void RadiosondeDemodGUI::applySettings(bool force) +{ + if (m_doApplySettings) + { + RadiosondeDemod::MsgConfigureRadiosondeDemod* frame = RadiosondeDemod::MsgConfigureRadiosondeDemod::create( m_settings, force); + m_radiosondeDemod->getInputMessageQueue()->push(frame); + } +} + +void RadiosondeDemodGUI::displaySettings() +{ + m_channelMarker.blockSignals(true); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setTitle(m_settings.m_title); + m_channelMarker.blockSignals(false); + m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only + + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_channelMarker.getTitle()); + + blockApplySettings(true); + + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + + ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1)); + ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0); + + ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 1000.0, 0, 'f', 1)); + ui->fmDev->setValue(m_settings.m_fmDeviation / 100.0); + + ui->thresholdText->setText(QString("%1").arg(m_settings.m_correlationThreshold)); + ui->threshold->setValue(m_settings.m_correlationThreshold); + + displayStreamIndex(); + + ui->filterSerial->setText(m_settings.m_filterSerial); + + ui->udpEnabled->setChecked(m_settings.m_udpEnabled); + ui->udpAddress->setText(m_settings.m_udpAddress); + ui->udpPort->setText(QString::number(m_settings.m_udpPort)); + + ui->channel1->setCurrentIndex(m_settings.m_scopeCh1); + ui->channel2->setCurrentIndex(m_settings.m_scopeCh2); + + ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename)); + ui->logEnable->setChecked(m_settings.m_logEnabled); + + // Order and size columns + QHeaderView *header = ui->frames->horizontalHeader(); + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) + { + bool hidden = m_settings.m_frameColumnSizes[i] == 0; + header->setSectionHidden(i, hidden); + framesMenu->actions().at(i)->setChecked(!hidden); + if (m_settings.m_frameColumnSizes[i] > 0) + ui->frames->setColumnWidth(i, m_settings.m_frameColumnSizes[i]); + header->moveSection(header->visualIndex(i), m_settings.m_frameColumnIndexes[i]); + } + + filter(); + + restoreState(m_rollupState); + blockApplySettings(false); +} + +void RadiosondeDemodGUI::displayStreamIndex() +{ + if (m_deviceUISet->m_deviceMIMOEngine) { + setStreamIndicator(tr("%1").arg(m_settings.m_streamIndex)); + } else { + setStreamIndicator("S"); // single channel indicator + } +} + +void RadiosondeDemodGUI::leaveEvent(QEvent*) +{ + m_channelMarker.setHighlighted(false); +} + +void RadiosondeDemodGUI::enterEvent(QEvent*) +{ + m_channelMarker.setHighlighted(true); +} + +void RadiosondeDemodGUI::tick() +{ + double magsqAvg, magsqPeak; + int nbMagsqSamples; + m_radiosondeDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples); + double powDbAvg = CalcDb::dbPower(magsqAvg); + double powDbPeak = CalcDb::dbPower(magsqPeak); + + ui->channelPowerMeter->levelChanged( + (100.0f + powDbAvg) / 100.0f, + (100.0f + powDbPeak) / 100.0f, + nbMagsqSamples); + + if (m_tickCount % 4 == 0) { + ui->channelPower->setText(QString::number(powDbAvg, 'f', 1)); + } + + m_tickCount++; +} + +void RadiosondeDemodGUI::on_logEnable_clicked(bool checked) +{ + m_settings.m_logEnabled = checked; + applySettings(); +} + +void RadiosondeDemodGUI::on_logFilename_clicked() +{ + // Get filename to save to + QFileDialog fileDialog(nullptr, "Select file to log received frames to", "", "*.csv"); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + if (fileDialog.exec()) + { + QStringList fileNames = fileDialog.selectedFiles(); + if (fileNames.size() > 0) + { + m_settings.m_logFilename = fileNames[0]; + ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename)); + applySettings(); + } + } +} + +// Read .csv log and process as received frames +void RadiosondeDemodGUI::on_logOpen_clicked() +{ + QFileDialog fileDialog(nullptr, "Select .csv log file to read", "", "*.csv"); + if (fileDialog.exec()) + { + QStringList fileNames = fileDialog.selectedFiles(); + if (fileNames.size() > 0) + { + QFile file(fileNames[0]); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QTextStream in(&file); + QString error; + QHash colIndexes = CSV::readHeader(in, {"Date", "Time", "Data"}, error); + if (error.isEmpty()) + { + int dateCol = colIndexes.value("Date"); + int timeCol = colIndexes.value("Time"); + int dataCol = colIndexes.value("Data"); + int maxCol = std::max({dateCol, timeCol, dataCol}); + + QMessageBox dialog(this); + dialog.setText("Reading frames"); + dialog.addButton(QMessageBox::Cancel); + dialog.show(); + QApplication::processEvents(); + int count = 0; + bool cancelled = false; + QStringList cols; + + MessagePipesLegacy& framePipes = MainCore::instance()->getMessagePipes(); + QList *radiosondeMessageQueues = framePipes.getMessageQueues(m_radiosondeDemod, "radiosonde"); + + while (!cancelled && CSV::readRow(in, &cols)) + { + if (cols.size() > maxCol) + { + QDate date = QDate::fromString(cols[dateCol]); + QTime time = QTime::fromString(cols[timeCol]); + QDateTime dateTime(date, time); + QByteArray bytes = QByteArray::fromHex(cols[dataCol].toLatin1()); + + // Add to table + frameReceived(bytes, dateTime, 0, 0); + + // Forward to Radiosonde feature + if (radiosondeMessageQueues) + { + QList::iterator it = radiosondeMessageQueues->begin(); + for (; it != radiosondeMessageQueues->end(); ++it) + { + MainCore::MsgPacket *msg = MainCore::MsgPacket::create(m_radiosondeDemod, bytes, dateTime); + (*it)->push(msg); + } + } + + if (count % 100 == 0) + { + QApplication::processEvents(); + if (dialog.clickedButton()) { + cancelled = true; + } + } + count++; + } + } + dialog.close(); + } + else + { + QMessageBox::critical(this, "Radiosonde Demod", error); + } + } + else + { + QMessageBox::critical(this, "Radiosonde Demod", QString("Failed to open file %1").arg(fileNames[0])); + } + } + } +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodgui.h b/plugins/channelrx/demodradiosonde/radiosondedemodgui.h new file mode 100644 index 000000000..053802350 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodgui.h @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMODGUI_H +#define INCLUDE_RADIOSONDEDEMODGUI_H + +#include +#include + +#include "channel/channelgui.h" +#include "dsp/channelmarker.h" +#include "util/messagequeue.h" +#include "settings/rollupstate.h" + +#include "radiosondedemodsettings.h" +#include "radiosondedemod.h" + +class PluginAPI; +class DeviceUISet; +class BasebandSampleSink; +class ScopeVis; +class ScopeVisXY; +class RadiosondeDemod; +class RadiosondeDemodGUI; +class RS41Frame; + +namespace Ui { + class RadiosondeDemodGUI; +} + +class RadiosondeDemodGUI : public ChannelGUI { + Q_OBJECT + +public: + static RadiosondeDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +public slots: + void channelMarkerChangedByCursor(); + void channelMarkerHighlightedByCursor(); + +private: + Ui::RadiosondeDemodGUI* ui; + PluginAPI* m_pluginAPI; + DeviceUISet* m_deviceUISet; + ChannelMarker m_channelMarker; + RollupState m_rollupState; + RadiosondeDemodSettings m_settings; + bool m_doApplySettings; + ScopeVis* m_scopeVis; + + RadiosondeDemod* m_radiosondeDemod; + uint32_t m_tickCount; + MessageQueue m_inputMessageQueue; + + QMenu *framesMenu; // Column select context menu + QMenu *copyMenu; + + QHash m_subframes; // Hash of serial to subframes + + explicit RadiosondeDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); + virtual ~RadiosondeDemodGUI(); + + void blockApplySettings(bool block); + void applySettings(bool force = false); + void displaySettings(); + void displayStreamIndex(); + void frameReceived(const QByteArray& frame, const QDateTime& dateTime, int errorsCorrected, int threshold); + bool handleMessage(const Message& message); + + void leaveEvent(QEvent*); + void enterEvent(QEvent*); + + void resizeTable(); + QAction *createCheckableItem(QString& text, int idx, bool checked, const char *slot); + + enum MessageCol { + FRAME_COL_DATE, + FRAME_COL_TIME, + FRAME_COL_SERIAL, + FRAME_COL_FRAME_NUMBER, + FRAME_COL_FLIGHT_PHASE, + FRAME_COL_LATITUDE, + FRAME_COL_LONGITUDE, + FRAME_COL_ALTITUDE, + FRAME_COL_SPEED, + FRAME_COL_VERTICAL_RATE, + FRAME_COL_HEADING, + FRAME_COL_PRESSURE, + FRAME_COL_TEMP, + FRAME_COL_HUMIDITY, + FRAME_COL_BATTERY_VOLTAGE, + FRAME_COL_BATTERY_STATUS, + FRAME_COL_PCB_TEMP, + FRAME_COL_HUMIDITY_PWM, + FRAME_COL_TX_POWER, + FRAME_COL_MAX_SUBFRAME_NO, + FRAME_COL_SUBFRAME_NO, + FRAME_COL_SUBFRAME, + FRAME_COL_GPS_TIME, + FRAME_COL_GPS_SATS, + FRAME_COL_ECC, + FRAME_COL_CORR + }; + +private slots: + void on_deltaFrequency_changed(qint64 value); + void on_rfBW_valueChanged(int index); + void on_fmDev_valueChanged(int value); + void on_threshold_valueChanged(int value); + void on_filterSerial_editingFinished(); + void on_clearTable_clicked(); + void on_udpEnabled_clicked(bool checked); + void on_udpAddress_editingFinished(); + void on_udpPort_editingFinished(); + void on_channel1_currentIndexChanged(int index); + void on_channel2_currentIndexChanged(int index); + void on_frames_cellDoubleClicked(int row, int column); + void on_logEnable_clicked(bool checked=false); + void on_logFilename_clicked(); + void on_logOpen_clicked(); + void filterRow(int row); + void filter(); + void frames_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex); + void frames_sectionResized(int logicalIndex, int oldSize, int newSize); + void framesColumnSelectMenu(QPoint pos); + void framesColumnSelectMenuChecked(bool checked = false); + void customContextMenuRequested(QPoint point); + void onWidgetRolled(QWidget* widget, bool rollDown); + void onMenuDialogCalled(const QPoint& p); + void handleInputMessages(); + void tick(); +}; + +#endif // INCLUDE_RADIOSONDEDEMODGUI_H diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodgui.ui b/plugins/channelrx/demodradiosonde/radiosondedemodgui.ui new file mode 100644 index 000000000..0d7ac4612 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodgui.ui @@ -0,0 +1,1116 @@ + + + RadiosondeDemodGUI + + + + 0 + 0 + 404 + 764 + + + + + 0 + 0 + + + + + 352 + 0 + + + + + 9 + + + + Qt::StrongFocus + + + Radiosonde Demodulator + + + Radiosonde Demodulator + + + + + 0 + 0 + 390 + 151 + + + + + 350 + 0 + + + + Settings + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 2 + + + + + + 16 + 0 + + + + Df + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + 12 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Demod shift frequency from center in Hz + + + + + + + Hz + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Channel power + + + Qt::RightToLeft + + + 0.0 + + + + + + + dB + + + + + + + + + + + + + dB + + + + + + + + 0 + 0 + + + + + 0 + 24 + + + + + 8 + + + + Level meter (dB) top trace: average, bottom trace: instantaneous peak, tip: peak hold + + + + + + + + + Qt::Horizontal + + + + + + + + + BW + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + RF bandwidth + + + 10 + + + 400 + + + 1 + + + 100 + + + Qt::Horizontal + + + + + + + + 30 + 0 + + + + 10.0k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + Dev + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Frequency deviation + + + 10 + + + 50 + + + 1 + + + 24 + + + Qt::Horizontal + + + + + + + + 30 + 0 + + + + ±2.4k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + TH + + + + + + + + 24 + 24 + + + + Correlation threshold + + + 200 + + + 800 + + + 1 + + + 5 + + + 400 + + + + + + + 400 + + + + + + + + + Qt::Horizontal + + + + + + + + + UDP + + + + + + + Forward received frames via UDP + + + Qt::RightToLeft + + + + + + + + + + + 120 + 0 + + + + Qt::ClickFocus + + + Destination UDP address + + + 000.000.000.000 + + + 127.0.0.1 + + + + + + + : + + + Qt::AlignCenter + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + Qt::ClickFocus + + + Destination UDP port + + + 00000 + + + 9998 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Find + + + + + + + Display only frames where the serial number matches the specified regular expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 24 + 16777215 + + + + Start/stop logging of received data to .csv file + + + + + + + :/record_off.png:/record_off.png + + + + + + + Set log .csv filename + + + ... + + + + :/save.png:/save.png + + + false + + + + + + + Read data from .csv log file + + + ... + + + + :/load.png:/load.png + + + false + + + + + + + Clear data from table + + + + + + + :/bin.png:/bin.png + + + + + + + + + + + 0 + 210 + 391 + 171 + + + + + 0 + 0 + + + + Received Frames + + + + 2 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + Received packets + + + QAbstractItemView::NoEditTriggers + + + + Date + + + Date frame was received + + + + + Time + + + Time frame was received + + + + + Serial + + + Serial number + + + + + Frame + + + Frame number + + + + + Phase + + + Flight phase + + + + + Lat (°) + + + Latitude in degrees. East positive + + + + + Lon (°) + + + Longitude in degrees. North positive + + + + + Alt (m) + + + Altitude in metres + + + + + Spd (km/h) + + + Speed in kilometres per hour + + + + + VR (m/s) + + + Vertical rate in metres per second + + + + + Hdg (°) + + + Heading in degrees + + + + + P (hPa) + + + Air pressure in hectopascals + + + + + T (°C) + + + Air temperature in degrees Celsius + + + + + U (%) + + + Relative humidity in percent + + + + + Bat (V) + + + Battery voltage + + + + + Bat + + + Battery status + + + + + PCB (°C) + + + PCB temperature in degrees Celsuis + + + + + PWM (%) + + + Humidty sensor heater PWM percentage + + + + + TX (%) + + + Transmit power percent + + + + + Max SF + + + Maximum subframe number + + + + + SF No. + + + Subframe number + + + + + Subframe + + + Subframe data + + + + + GPS Time + + + GPS Time (18 leap seconds offset from UTC) + + + + + GPS Sats + + + Number of GPS satellites used to estimate position + + + + + ECC + + + Number of errors corrected + + + + + Corr + + + Correlation + + + + + + + + + + 20 + 400 + 351 + 341 + + + + Waveforms + + + + 2 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + + Real + + + + + + + + 0 + 0 + + + + + I + + + + + Q + + + + + Mag Sq + + + + + FM demod + + + + + Gaussian + + + + + RX buf + + + + + Correlation + + + + + Threshold met + + + + + Got SOP + + + + + DC offset + + + + + CRC + + + + + + + + + 0 + 0 + + + + Imag + + + + + + + + 0 + 0 + + + + + I + + + + + Q + + + + + Mag Sq + + + + + FM demod + + + + + Gaussian + + + + + RX buf + + + + + Correlation + + + + + Threshold met + + + + + Got SOP + + + + + DC offset + + + + + CRC + + + + + + + + + + + 200 + 250 + + + + + 8 + + + + + + + + + + + + + RollupWidget + QWidget +
    gui/rollupwidget.h
    + 1 +
    + + ValueDialZ + QWidget +
    gui/valuedialz.h
    + 1 +
    + + LevelMeterSignalDB + QWidget +
    gui/levelmeter.h
    + 1 +
    + + ButtonSwitch + QToolButton +
    gui/buttonswitch.h
    +
    + + GLScope + QWidget +
    gui/glscope.h
    + 1 +
    + + GLScopeGUI + QWidget +
    gui/glscopegui.h
    + 1 +
    +
    + + deltaFrequency + rfBW + fmDev + threshold + udpEnabled + filterSerial + logEnable + logFilename + logOpen + clearTable + frames + channel1 + channel2 + + + + + + +
    diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodplugin.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodplugin.cpp new file mode 100644 index 000000000..95236dfa6 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodplugin.cpp @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include "plugin/pluginapi.h" + +#ifndef SERVER_MODE +#include "radiosondedemodgui.h" +#endif +#include "radiosondedemod.h" +#include "radiosondedemodwebapiadapter.h" +#include "radiosondedemodplugin.h" + +const PluginDescriptor RadiosondeDemodPlugin::m_pluginDescriptor = { + RadiosondeDemod::m_channelId, + QStringLiteral("Radiosonde Demodulator"), + QStringLiteral("6.20.0"), + QStringLiteral("(c) Jon Beniston, M7RCE"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +RadiosondeDemodPlugin::RadiosondeDemodPlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(0) +{ +} + +const PluginDescriptor& RadiosondeDemodPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void RadiosondeDemodPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + m_pluginAPI->registerRxChannel(RadiosondeDemod::m_channelIdURI, RadiosondeDemod::m_channelId, this); +} + +void RadiosondeDemodPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const +{ + if (bs || cs) + { + RadiosondeDemod *instance = new RadiosondeDemod(deviceAPI); + + if (bs) { + *bs = instance; + } + + if (cs) { + *cs = instance; + } + } +} + +#ifdef SERVER_MODE +ChannelGUI* RadiosondeDemodPlugin::createRxChannelGUI( + DeviceUISet *deviceUISet, + BasebandSampleSink *rxChannel) const +{ + (void) deviceUISet; + (void) rxChannel; + return 0; +} +#else +ChannelGUI* RadiosondeDemodPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const +{ + return RadiosondeDemodGUI::create(m_pluginAPI, deviceUISet, rxChannel); +} +#endif + +ChannelWebAPIAdapter* RadiosondeDemodPlugin::createChannelWebAPIAdapter() const +{ + return new RadiosondeDemodWebAPIAdapter(); +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodplugin.h b/plugins/channelrx/demodradiosonde/radiosondedemodplugin.h new file mode 100644 index 000000000..0a09a5bc2 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodplugin.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMODPLUGIN_H +#define INCLUDE_RADIOSONDEDEMODPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class DeviceUISet; +class BasebandSampleSink; + +class RadiosondeDemodPlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.channel.radiosondedemod") + +public: + explicit RadiosondeDemodPlugin(QObject* parent = NULL); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const; + virtual ChannelGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const; + virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif // INCLUDE_RADIOSONDEDEMODPLUGIN_H diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodsettings.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodsettings.cpp new file mode 100644 index 000000000..03d22fb0d --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodsettings.cpp @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" +#include "radiosondedemodsettings.h" + +RadiosondeDemodSettings::RadiosondeDemodSettings() : + m_channelMarker(nullptr), + m_scopeGUI(nullptr), + m_rollupState(nullptr) +{ + resetToDefaults(); +} + +void RadiosondeDemodSettings::resetToDefaults() +{ + m_baud = 4800; // Fixed for RS41 - may change for others + m_inputFrequencyOffset = 0; + m_rfBandwidth = 9600.0f; + m_fmDeviation = 2400.0f; + m_correlationThreshold = 450; + m_filterSerial = ""; + m_udpEnabled = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9999; + m_scopeCh1 = 5; + m_scopeCh2 = 6; + m_logFilename = "radiosonde_log.csv"; + m_logEnabled = false; + m_rgbColor = QColor(102, 0, 102).rgb(); + m_title = "Radiosonde Demodulator"; + m_streamIndex = 0; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; + m_reverseAPIChannelIndex = 0; + + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) + { + m_frameColumnIndexes[i] = i; + m_frameColumnSizes[i] = -1; // Autosize + } +} + +QByteArray RadiosondeDemodSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeS32(1, m_inputFrequencyOffset); + s.writeFloat(2, m_rfBandwidth); + s.writeFloat(3, m_fmDeviation); + s.writeFloat(4, m_correlationThreshold); + s.writeString(5, m_filterSerial); + s.writeBool(6, m_udpEnabled); + s.writeString(7, m_udpAddress); + s.writeU32(8, m_udpPort); + s.writeS32(10, m_scopeCh1); + s.writeS32(11, m_scopeCh2); + s.writeU32(12, m_rgbColor); + s.writeString(13, m_title); + + if (m_channelMarker) { + s.writeBlob(14, m_channelMarker->serialize()); + } + + s.writeS32(15, m_streamIndex); + s.writeBool(16, m_useReverseAPI); + s.writeString(17, m_reverseAPIAddress); + s.writeU32(18, m_reverseAPIPort); + s.writeU32(19, m_reverseAPIDeviceIndex); + s.writeU32(20, m_reverseAPIChannelIndex); + s.writeBlob(21, m_scopeGUI->serialize()); + s.writeString(22, m_logFilename); + s.writeBool(23, m_logEnabled); + s.writeS32(24, m_baud); + + if (m_rollupState) { + s.writeBlob(25, m_rollupState->serialize()); + } + + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) + s.writeS32(100 + i, m_frameColumnIndexes[i]); + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) + s.writeS32(200 + i, m_frameColumnSizes[i]); + + return s.final(); +} + +bool RadiosondeDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + uint32_t utmp; + QString strtmp; + + d.readS32(1, &m_inputFrequencyOffset, 0); + d.readFloat(2, &m_rfBandwidth, 16000.0f); + d.readFloat(3, &m_fmDeviation, 4800.0f); + d.readFloat(4, &m_correlationThreshold, 450); + d.readString(5, &m_filterSerial, ""); + d.readBool(6, &m_udpEnabled); + d.readString(7, &m_udpAddress); + d.readU32(8, &utmp); + + if ((utmp > 1023) && (utmp < 65535)) { + m_udpPort = utmp; + } else { + m_udpPort = 9999; + } + + d.readS32(10, &m_scopeCh1, 0); + d.readS32(11, &m_scopeCh2, 0); + d.readU32(12, &m_rgbColor, QColor(102, 0, 102).rgb()); + d.readString(13, &m_title, "Radiosonde Demodulator"); + + if (m_channelMarker) + { + d.readBlob(14, &bytetmp); + m_channelMarker->deserialize(bytetmp); + } + + d.readS32(15, &m_streamIndex, 0); + d.readBool(16, &m_useReverseAPI, false); + d.readString(17, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(18, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(19, &utmp, 0); + m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; + d.readU32(20, &utmp, 0); + m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; + + if (m_scopeGUI) + { + d.readBlob(21, &bytetmp); + m_scopeGUI->deserialize(bytetmp); + } + + d.readString(22, &m_logFilename, "radiosonde_log.csv"); + d.readBool(23, &m_logEnabled, false); + d.readS32(24, &m_baud, 9600); + + if (m_rollupState) + { + d.readBlob(25, &bytetmp); + m_rollupState->deserialize(bytetmp); + } + + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) { + d.readS32(100 + i, &m_frameColumnIndexes[i], i); + } + + for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) { + d.readS32(200 + i, &m_frameColumnSizes[i], -1); + } + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodsettings.h b/plugins/channelrx/demodradiosonde/radiosondedemodsettings.h new file mode 100644 index 000000000..76a4fe839 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodsettings.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMODSETTINGS_H +#define INCLUDE_RADIOSONDEDEMODSETTINGS_H + +#include +#include + +#include "dsp/dsptypes.h" + +class Serializable; + +// Number of columns in the tables +#define RADIOSONDEDEMOD_FRAME_COLUMNS 26 + +struct RadiosondeDemodSettings +{ + qint32 m_baud; + qint32 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_fmDeviation; + Real m_correlationThreshold; + QString m_filterSerial; + bool m_udpEnabled; + QString m_udpAddress; + uint16_t m_udpPort; + int m_scopeCh1; + int m_scopeCh2; + + QString m_logFilename; + bool m_logEnabled; + + quint32 m_rgbColor; + QString m_title; + Serializable *m_channelMarker; + int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx). + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + uint16_t m_reverseAPIChannelIndex; + Serializable *m_scopeGUI; + Serializable *m_rollupState; + + int m_frameColumnIndexes[RADIOSONDEDEMOD_FRAME_COLUMNS];//!< How the columns are ordered in the table + int m_frameColumnSizes[RADIOSONDEDEMOD_FRAME_COLUMNS]; //!< Size of the columns in the table + + static const int RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE = 57600; //!< 12x 4800 baud rate (use even multiple so Gausian filter has odd number of taps) + + RadiosondeDemodSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } + void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif /* INCLUDE_RADIOSONDEDEMODSETTINGS_H */ diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodsink.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodsink.cpp new file mode 100644 index 000000000..8a2220fd7 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodsink.cpp @@ -0,0 +1,576 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +#include "dsp/dspengine.h" +#include "dsp/datafifo.h" +#include "dsp/scopevis.h" +#include "util/db.h" +#include "util/stepfunctions.h" +#include "util/reedsolomon.h" +#include "maincore.h" + +#include "radiosondedemod.h" +#include "radiosondedemodsink.h" + +const uint8_t RadiosondeDemodSink::m_descramble[64] = { + 0x96, 0x83, 0x3E, 0x51, 0xB1, 0x49, 0x08, 0x98, + 0x32, 0x05, 0x59, 0x0E, 0xF9, 0x44, 0xC6, 0x26, + 0x21, 0x60, 0xC2, 0xEA, 0x79, 0x5D, 0x6D, 0xA1, + 0x54, 0x69, 0x47, 0x0C, 0xDC, 0xE8, 0x5C, 0xF1, + 0xF7, 0x76, 0x82, 0x7F, 0x07, 0x99, 0xA2, 0x2C, + 0x93, 0x7C, 0x30, 0x63, 0xF5, 0x10, 0x2E, 0x61, + 0xD0, 0xBC, 0xB4, 0xB6, 0x06, 0xAA, 0xF4, 0x23, + 0x78, 0x6E, 0x3B, 0xAE, 0xBF, 0x7B, 0x4C, 0xC1 +}; + +RadiosondeDemodSink::RadiosondeDemodSink(RadiosondeDemod *radiosondeDemod) : + m_scopeSink(nullptr), + m_radiosondeDemod(radiosondeDemod), + m_channelSampleRate(RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE), + m_channelFrequencyOffset(0), + m_magsqSum(0.0f), + m_magsqPeak(0.0f), + m_magsqCount(0), + m_messageQueueToChannel(nullptr), + m_rxBuf(nullptr), + m_train(nullptr), + m_sampleBufferIndex(0) +{ + m_magsq = 0.0; + + m_demodBuffer.resize(1<<12); + m_demodBufferFill = 0; + m_sampleBuffer.resize(m_sampleBufferSize); + + applySettings(m_settings, true); + applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); +} + +RadiosondeDemodSink::~RadiosondeDemodSink() +{ + delete[] m_rxBuf; + delete[] m_train; +} + +void RadiosondeDemodSink::sampleToScope(Complex sample) +{ + if (m_scopeSink) + { + Real r = std::real(sample) * SDR_RX_SCALEF; + Real i = std::imag(sample) * SDR_RX_SCALEF; + m_sampleBuffer[m_sampleBufferIndex++] = Sample(r, i); + + if (m_sampleBufferIndex == m_sampleBufferSize) + { + std::vector vbegin; + vbegin.push_back(m_sampleBuffer.begin()); + m_scopeSink->feed(vbegin, m_sampleBufferSize); + m_sampleBufferIndex = 0; + } + } +} + +void RadiosondeDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +{ + Complex ci; + + for (SampleVector::const_iterator it = begin; it != end; ++it) + { + Complex c(it->real(), it->imag()); + c *= m_nco.nextIQ(); + + if (m_interpolatorDistance < 1.0f) // interpolate + { + while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + } + else // decimate + { + if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + } + } +} + +void RadiosondeDemodSink::processOneSample(Complex &ci) +{ + Complex ca; + + // FM demodulation + double magsqRaw; + Real deviation; + Real fmDemod = m_phaseDiscri.phaseDiscriminatorDelta(ci, magsqRaw, deviation); + + // Calculate average and peak levels for level meter + Real magsq = magsqRaw / (SDR_RX_SCALED*SDR_RX_SCALED); + m_movingAverage(magsq); + m_magsq = m_movingAverage.asDouble(); + m_magsqSum += magsq; + if (magsq > m_magsqPeak) + { + m_magsqPeak = magsq; + } + m_magsqCount++; + + // Gaussian filter + Real filt = m_pulseShape.filter(fmDemod); + + // An input frequency offset corresponds to a DC offset after FM demodulation + // What frequency offset is RS41 specified too? + // We need to remove this, otherwise it may effect the sampling + // To calculate what it is, we sum the training sequence, which should be zero + + // Clip, as large noise can result in high correlation + // Don't clip to 1.0 - as there may be some DC offset (1k/4.8k max dev=0.2) + Real filtClipped; + filtClipped = std::fmax(-1.4, std::fmin(1.4, filt)); + + // Buffer filtered samples. We buffer enough samples for a max length message + // before trying to demod, so false triggering can't make us miss anything + m_rxBuf[m_rxBufIdx] = filtClipped; + m_rxBufIdx = (m_rxBufIdx + 1) % m_rxBufLength; + m_rxBufCnt = std::min(m_rxBufCnt + 1, m_rxBufLength); + + Real corr = 0.0f; + bool scopeCRCValid = false; + bool scopeCRCInvalid = false; + Real dcOffset = 0.0f; + bool thresholdMet = false; + bool gotSOP = false; + + if ((m_rxBufCnt >= m_rxBufLength)) + { + // Correlate with training sequence + corr = correlate(m_rxBufIdx); + + // If we meet threshold, try to demod + // Take abs value, to account for both initial phases + thresholdMet = fabs(corr) >= m_settings.m_correlationThreshold; + if (thresholdMet) + { + // Try to see if starting at a later sample improves correlation + int maxCorrOffset = 0; + Real maxCorr; + Real initCorr = fabs(corr); + do + { + maxCorr = fabs(corr); + maxCorrOffset++; + corr = correlate(m_rxBufIdx + maxCorrOffset); + } + while (fabs(corr) > maxCorr); + maxCorrOffset--; + + // Calculate mean of preamble as DC offset (as it should be 0 on an ideal signal) + Real trainingSum = 0.0f; + for (int i = 0; i < m_correlationLength; i++) + { + int j = (m_rxBufIdx + maxCorrOffset + i) % m_rxBufLength; + trainingSum += m_rxBuf[j]; + } + dcOffset = trainingSum/m_correlationLength; + + // Start demod after (most of) preamble + int x = (m_rxBufIdx + maxCorrOffset + m_correlationLength*3/4 + 0) % m_rxBufLength; + + // Attempt to demodulate + uint64_t bits = 0; + int bitCount = 0; + int onesCount = 0; + int byteCount = 0; + int symbolPrev = 0; + QList sampleIdxs; + for (int sampleIdx = 0; sampleIdx < m_rxBufLength; sampleIdx += m_samplesPerSymbol) + { + // Sum and slice + // Summing 3 samples seems to give a very small improvement vs just using 1 + int sampleCnt = 3; + int sampleOffset = -1; + Real sampleSum = 0.0f; + for (int i = 0; i < sampleCnt; i++) { + sampleSum += m_rxBuf[(x + sampleOffset + i) % m_rxBufLength] - dcOffset; + sampleIdxs.append((x + sampleOffset + i) % m_rxBufLength); + } + int symbol = sampleSum >= 0.0f ? 1 : 0; + + // Move to next symbol + x = (x + m_samplesPerSymbol) % m_rxBufLength; + + // Symbols map directly to bits + int bit = symbol; + + // Store in shift reg (little endian) + bits |= ((uint64_t)bit) << bitCount; + bitCount++; + + if (gotSOP) + { + if (bitCount == 8) + { + // Got a complete byte + m_bytes[byteCount] = bits; + byteCount++; + bits = 0; + bitCount = 0; + + if (byteCount >= RADIOSONDE_LENGTH_STD) + { + // Get expected length of frame + uint8_t frameType = m_bytes[RADIOSONDE_OFFSET_FRAME_TYPE] ^ m_descramble[RADIOSONDE_OFFSET_FRAME_TYPE]; + int length = RS41Frame::getFrameLength(frameType); + + // Have we received a complete frame? + if (byteCount == length) + { + int firstError; + bool ok = processFrame(length, corr, sampleIdx, &firstError); + scopeCRCValid = ok; + scopeCRCInvalid = !ok; + break; + } + } + } + } + else if (bits == 0xf812962211cab610ULL) // Scrambled header + { + // Start of packet + gotSOP = true; + bits = 0; + bitCount = 0; + m_bytes[0] = 0x10; + m_bytes[1] = 0xb6; + m_bytes[2] = 0xca; + m_bytes[3] = 0x11; + m_bytes[4] = 0x22; + m_bytes[5] = 0x96; + m_bytes[6] = 0x12; + m_bytes[7] = 0xf8; + byteCount = 8; + } + else + { + if (bitCount == 64) + { + bits >>= 1; + bitCount--; + } + if (sampleIdx >= 16 * 8 * m_samplesPerSymbol) + { + // Too many bits without receving header + break; + } + } + } + // printf("\n"); + } + } + + // Select signals to feed to scope + Complex scopeSample; + switch (m_settings.m_scopeCh1) + { + case 0: + scopeSample.real(ci.real() / SDR_RX_SCALEF); + break; + case 1: + scopeSample.real(ci.imag() / SDR_RX_SCALEF); + break; + case 2: + scopeSample.real(magsq); + break; + case 3: + scopeSample.real(fmDemod); + break; + case 4: + scopeSample.real(filt); + break; + case 5: + scopeSample.real(m_rxBuf[m_rxBufIdx]); + break; + case 6: + scopeSample.real(corr / 100.0); + break; + case 7: + scopeSample.real(thresholdMet); + break; + case 8: + scopeSample.real(gotSOP); + break; + case 9: + scopeSample.real(dcOffset); + break; + case 10: + scopeSample.real(scopeCRCValid ? 1.0 : (scopeCRCInvalid ? -1.0 : 0)); + break; + } + switch (m_settings.m_scopeCh2) + { + case 0: + scopeSample.imag(ci.real() / SDR_RX_SCALEF); + break; + case 1: + scopeSample.imag(ci.imag() / SDR_RX_SCALEF); + break; + case 2: + scopeSample.imag(magsq); + break; + case 3: + scopeSample.imag(fmDemod); + break; + case 4: + scopeSample.imag(filt); + break; + case 5: + scopeSample.imag(m_rxBuf[m_rxBufIdx]); + break; + case 6: + scopeSample.imag(corr / 100.0); + break; + case 7: + scopeSample.imag(thresholdMet); + break; + case 8: + scopeSample.imag(gotSOP); + break; + case 9: + scopeSample.imag(dcOffset); + break; + case 10: + scopeSample.imag(scopeCRCValid ? 1.0 : (scopeCRCInvalid ? -1.0 : 0)); + break; + } + sampleToScope(scopeSample); + + // Send demod signal to Demod Analzyer feature + m_demodBuffer[m_demodBufferFill++] = fmDemod * std::numeric_limits::max(); + + if (m_demodBufferFill >= m_demodBuffer.size()) + { + QList dataPipes; + MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes); + + if (dataPipes.size() > 0) + { + QList::iterator it = dataPipes.begin(); + + for (; it != dataPipes.end(); ++it) + { + DataFifo *fifo = qobject_cast((*it)->m_element); + + if (fifo) { + fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16); + } + } + } + + m_demodBufferFill = 0; + } +} + +// Correlate received signal with training sequence +// Note that DC offset doesn't matter for this +Real RadiosondeDemodSink::correlate(int idx) const +{ + Real corr = 0.0f; + for (int i = 0; i < m_correlationLength; i++) + { + int j = (idx + i) % m_rxBufLength; + corr += m_train[i] * m_rxBuf[j]; + } + return corr; +} + +bool RadiosondeDemodSink::processFrame(int length, float corr, int sampleIdx, int *firstError) +{ + // Descramble + for (int i = 0; i < length; i++) { + m_bytes[i] = m_bytes[i] ^ m_descramble[i & 0x3f]; + } + + // Reed-Solomon Error Correction + int errorsCorrected = reedSolomonErrorCorrection(); + if (errorsCorrected >= 0) + { + // Check per-block CRCs are correct + if (checkCRCs(length)) + { + if (getMessageQueueToChannel()) + { + QByteArray rxPacket((char *)m_bytes, length); + RadiosondeDemod::MsgMessage *msg = RadiosondeDemod::MsgMessage::create(rxPacket, errorsCorrected, corr); + getMessageQueueToChannel()->push(msg); + } + + // Skip over received packet, so we don't try to re-demodulate it + m_rxBufCnt -= sampleIdx; + return true; + } + } + return false; +} + +// Reed Solomon error correction +// Returns number of errors corrected, or -1 if there are uncorrectable errors +int RadiosondeDemodSink::reedSolomonErrorCorrection() +{ + ReedSolomon::RS rs; + int errorsCorrected = 0; + + for (int i = 0; (i < RADIOSONDE_RS_INTERLEAVE) && (errorsCorrected >= 0); i++) + { + // Deinterleave and reverse order + uint8_t rsData[RADIOSONDE_RS_N]; + + memset(rsData, 0, RADIOSONDE_RS_PAD); + for (int j = 0; j < RADIOSONDE_RS_DATA; j++) { + rsData[RADIOSONDE_RS_K-1-j] = m_bytes[RADIOSONDE_OFFSET_FRAME_TYPE+j*RADIOSONDE_RS_INTERLEAVE+i]; + } + for (int j = 0; j < RADIOSONDE_RS_2T; j++) { + rsData[RADIOSONDE_RS_N-1-j] = m_bytes[RADIOSONDE_OFFSET_RS+i*RADIOSONDE_RS_2T+j]; + } + + // Detect and correct errors + int errors = rs.decode(&rsData[0], RADIOSONDE_RS_K); // FIXME: Indicate 0 padding? + if (errors >= 0) { + errorsCorrected += errors; + } else { + // Uncorrectable errors + return -1; + } + + // Restore corrected data + for (int j = 0; j < RADIOSONDE_RS_DATA; j++) { + m_bytes[RADIOSONDE_OFFSET_FRAME_TYPE+j*RADIOSONDE_RS_INTERLEAVE+i] = rsData[RADIOSONDE_RS_K-1-j]; + } + + } + return errorsCorrected; +} + +// Check per-block CRCs +// We could pass partial frames that have some correct CRCs, but for now, whole frame has to be correct +bool RadiosondeDemodSink::checkCRCs(int length) +{ + for (int i = RADIOSONDE_OFFSET_BLOCK_0; i < length; ) + { + uint8_t blockID = m_bytes[i+0]; + uint8_t blockLength = m_bytes[i+1]; + uint16_t rxCrc = m_bytes[i+2+blockLength] | (m_bytes[i+2+blockLength+1] << 8); + // CRC doesn't include ID/len - so these can be wrong + m_crc.init(); + m_crc.calculate(&m_bytes[i+2], blockLength); + uint16_t calcCrc = m_crc.get(); + if (calcCrc != rxCrc) { + return false; + } + i += blockLength+4; + } + return true; +} + +void RadiosondeDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force) +{ + qDebug() << "RadiosondeDemodSink::applyChannelSettings:" + << " channelSampleRate: " << channelSampleRate + << " channelFrequencyOffset: " << channelFrequencyOffset; + + if ((m_channelFrequencyOffset != channelFrequencyOffset) || + (m_channelSampleRate != channelSampleRate) || force) + { + m_nco.setFreq(-channelFrequencyOffset, channelSampleRate); + } + + if ((m_channelSampleRate != channelSampleRate) || force) + { + m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2); + m_interpolatorDistance = (Real) channelSampleRate / (Real) RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE; + m_interpolatorDistanceRemain = m_interpolatorDistance; + } + + m_channelSampleRate = channelSampleRate; + m_channelFrequencyOffset = channelFrequencyOffset; + m_samplesPerSymbol = RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE / m_settings.m_baud; + qDebug() << "RadiosondeDemodSink::applyChannelSettings: m_samplesPerSymbol: " << m_samplesPerSymbol; +} + +void RadiosondeDemodSink::applySettings(const RadiosondeDemodSettings& settings, bool force) +{ + qDebug() << "RadiosondeDemodSink::applySettings:" + << " force: " << force; + + if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) + { + m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2); + m_interpolatorDistance = (Real) m_channelSampleRate / (Real) RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE; + m_interpolatorDistanceRemain = m_interpolatorDistance; + m_lowpass.create(301, RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE, settings.m_rfBandwidth / 2.0f); + } + if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) + { + m_phaseDiscri.setFMScaling(RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE / (2.0f * settings.m_fmDeviation)); + } + + if ((settings.m_baud != m_settings.m_baud) || force) + { + m_samplesPerSymbol = RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE / settings.m_baud; + qDebug() << "RadiosondeDemodSink::applySettings: m_samplesPerSymbol: " << m_samplesPerSymbol << " baud " << settings.m_baud; + + // What value to use for BT? RFIC is Si4032 - its datasheet only appears to support 0.5 + m_pulseShape.create(0.5, 3, m_samplesPerSymbol); + + // Recieve buffer, long enough for one max length message + delete[] m_rxBuf; + m_rxBufLength = RADIOSONDEDEMOD_MAX_BYTES*8*m_samplesPerSymbol; + m_rxBuf = new Real[m_rxBufLength]; + m_rxBufIdx = 0; + m_rxBufCnt = 0; + + // Create training sequence for correlation + delete[] m_train; + + const int correlateBits = 200; // Preamble is 320bits - leave some for AGC (and clock recovery eventually) + m_correlationLength = correlateBits*m_samplesPerSymbol; // Don't want to use header, as we want to calculate DC offset + m_train = new Real[m_correlationLength](); + + // Pulse shape filter takes a few symbols before outputting expected shape + for (int j = 0; j < m_samplesPerSymbol; j++) { + m_pulseShape.filter(-1.0f); + } + for (int j = 0; j < m_samplesPerSymbol; j++) { + m_pulseShape.filter(1.0f); + } + for (int i = 0; i < correlateBits; i++) + { + for (int j = 0; j < m_samplesPerSymbol; j++) { + m_train[i*m_samplesPerSymbol+j] = -m_pulseShape.filter((i&1) * 2.0f - 1.0f); + } + } + } + + m_settings = settings; +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodsink.h b/plugins/channelrx/demodradiosonde/radiosondedemodsink.h new file mode 100644 index 000000000..9a89fbf52 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodsink.h @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMODSINK_H +#define INCLUDE_RADIOSONDEDEMODSINK_H + +#include + +#include "dsp/channelsamplesink.h" +#include "dsp/phasediscri.h" +#include "dsp/nco.h" +#include "dsp/interpolator.h" +#include "dsp/firfilter.h" +#include "dsp/gaussian.h" +#include "util/movingaverage.h" +#include "util/doublebufferfifo.h" +#include "util/messagequeue.h" +#include "util/crc.h" + +#include "radiosondedemodsettings.h" + +// Length of preamble (40 bytes) and frame (std 320 bytes - extended 518) +#define RADIOSONDEDEMOD_MAX_BYTES (40+518) + +class ChannelAPI; +class RadiosondeDemod; +class ScopeVis; + +class RadiosondeDemodSink : public ChannelSampleSink { +public: + RadiosondeDemodSink(RadiosondeDemod *radiosondeDemod); + ~RadiosondeDemodSink(); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); + + void setScopeSink(ScopeVis* scopeSink) { m_scopeSink = scopeSink; } + void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false); + void applySettings(const RadiosondeDemodSettings& settings, bool force = false); + void setMessageQueueToChannel(MessageQueue *messageQueue) { m_messageQueueToChannel = messageQueue; } + void setChannel(ChannelAPI *channel) { m_channel = channel; } + + double getMagSq() const { return m_magsq; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + if (m_magsqCount > 0) + { + m_magsq = m_magsqSum / m_magsqCount; + m_magSqLevelStore.m_magsq = m_magsq; + m_magSqLevelStore.m_magsqPeak = m_magsqPeak; + } + + avg = m_magSqLevelStore.m_magsq; + peak = m_magSqLevelStore.m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + +private: + struct MagSqLevelsStore + { + MagSqLevelsStore() : + m_magsq(1e-12), + m_magsqPeak(1e-12) + {} + double m_magsq; + double m_magsqPeak; + }; + + ScopeVis* m_scopeSink; // Scope GUI to display baseband waveform + RadiosondeDemod *m_radiosondeDemod; + RadiosondeDemodSettings m_settings; + ChannelAPI *m_channel; + int m_channelSampleRate; + int m_channelFrequencyOffset; + int m_samplesPerSymbol; // Number of samples per symbol + + NCO m_nco; + Interpolator m_interpolator; + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + MagSqLevelsStore m_magSqLevelStore; + + MessageQueue *m_messageQueueToChannel; + + MovingAverageUtil m_movingAverage; + + Lowpass m_lowpass; // RF input filter + PhaseDiscriminators m_phaseDiscri; // FM demodulator + Gaussian m_pulseShape; // Pulse shaping filter + Real *m_rxBuf; // Receive sample buffer, large enough for one max length messsage + int m_rxBufLength; // Size in elements in m_rxBuf + int m_rxBufIdx; // Index in to circular buffer + int m_rxBufCnt; // Number of valid samples in buffer + Real *m_train; // Training sequence to look for + int m_correlationLength; + + unsigned char m_bytes[RADIOSONDEDEMOD_MAX_BYTES]; + crc16ccitt m_crc; + + QVector m_demodBuffer; + int m_demodBufferFill; + + SampleVector m_sampleBuffer; + static const int m_sampleBufferSize = RadiosondeDemodSettings::RADIOSONDEDEMOD_CHANNEL_SAMPLE_RATE / 20; + int m_sampleBufferIndex; + + static const uint8_t m_descramble[64]; + + MessageQueue *getMessageQueueToChannel() { return m_messageQueueToChannel; } + void processOneSample(Complex &ci); + Real correlate(int idx) const; + bool processFrame(int length, float corr, int sampleIdx, int *firstError); + int reedSolomonErrorCorrection(); + bool checkCRCs(int length); + void sampleToScope(Complex sample); +}; + +#endif // INCLUDE_RADIOSONDEDEMODSINK_H diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.cpp b/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.cpp new file mode 100644 index 000000000..5d5133258 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.cpp @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGChannelSettings.h" +#include "radiosondedemod.h" +#include "radiosondedemodwebapiadapter.h" + +RadiosondeDemodWebAPIAdapter::RadiosondeDemodWebAPIAdapter() +{} + +RadiosondeDemodWebAPIAdapter::~RadiosondeDemodWebAPIAdapter() +{} + +int RadiosondeDemodWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadiosondeDemodSettings(new SWGSDRangel::SWGRadiosondeDemodSettings()); + response.getRadiosondeDemodSettings()->init(); + RadiosondeDemod::webapiFormatChannelSettings(response, m_settings); + + return 200; +} + +int RadiosondeDemodWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) force; + (void) errorMessage; + RadiosondeDemod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response); + + return 200; +} diff --git a/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.h b/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.h new file mode 100644 index 000000000..22f1b0129 --- /dev/null +++ b/plugins/channelrx/demodradiosonde/radiosondedemodwebapiadapter.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB. // +// Copyright (C) 2020 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDEDEMOD_WEBAPIADAPTER_H +#define INCLUDE_RADIOSONDEDEMOD_WEBAPIADAPTER_H + +#include "channel/channelwebapiadapter.h" +#include "radiosondedemodsettings.h" + +/** + * Standalone API adapter only for the settings + */ +class RadiosondeDemodWebAPIAdapter : public ChannelWebAPIAdapter { +public: + RadiosondeDemodWebAPIAdapter(); + virtual ~RadiosondeDemodWebAPIAdapter(); + + virtual QByteArray serialize() const { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + +private: + RadiosondeDemodSettings m_settings; +}; + +#endif // INCLUDE_RADIOSONDEDEMOD_WEBAPIADAPTER_H diff --git a/plugins/channelrx/demodradiosonde/readme.md b/plugins/channelrx/demodradiosonde/readme.md new file mode 100644 index 000000000..4955997ed --- /dev/null +++ b/plugins/channelrx/demodradiosonde/readme.md @@ -0,0 +1,106 @@ +

    Radiosonde demodulator plugin

    + +

    Introduction

    + +This plugin can be used to demodulate RS41 radiosonde weather ballon signals. Radiosondes typically transmit on 400-406MHz and are in the sky around the world for around 1 hour around 00:00 UTC. + +RS41 radiosondes transmit data frames every second, containing position, velocity and PTU (Pressure, Temperature and Humidity) readings. The radios use GFSK modulation, with ±2.4kHz deviation at 4,800 baud. Reed Solomon encoding is used for ECC (Error Checking and Correction). + +The Radiosonde demodulator can forward received data to the [Radiosone feature](../../feature/radiosonde/readme.md), which can plot charts showing how altitude and PTU vary over time, and also plot the position of the radiosonde on the 2D and 3D maps. + +

    Interface

    + +![Radiosonde Demodulator plugin GUI](../../../doc/img/RadiosondeDemod_plugin.png) + +

    1: Frequency shift from center frequency of reception

    + +Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2. + +

    2: Channel power

    + +Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band. + +

    3: Level meter in dB

    + + - top bar (green): average value + - bottom bar (blue green): instantaneous peak value + - tip vertical bar (bright green): peak hold value + +

    4: BW - RF Bandwidth

    + +This specifies the bandwidth of a LPF that is applied to the input signal to limit the RF bandwidth. For RS41 radiosondes, this can be 9.6kHz. + +

    5: Dev - Frequency deviation

    + +Adjusts the expected frequency deviation in 0.1 kHz steps from 1 to 5 kHz. Typical value to RS41 is 2.4kHz. + +

    6: TH - Correlation Threshold

    + +The correlation threshold between the received signal and the preamble (training sequence). A lower value may be able to demodulate weaker signals, but increases processor usage. The default value is 450. + +

    7: UDP

    + +When checked, received receives are forwarded to the specified UDP address (12) and port (13). + +

    8: UDP address

    + +IP address of the host to forward received frames to via UDP. + +

    9: UDP port

    + +UDP port number to forward received frames to. + +

    10: Find

    + +Entering a regular expression in the Find field displays only frames where the radiosonde serial number matches the given regular expression. + +

    11: Start/stop Logging Frames to .csv File

    + +When checked, writes all received frames to a .csv file. + +

    14: .csv Log Filename

    + +Click to specify the name of the .csv file which received frames are logged to. + +

    15: Read Data from .csv File

    + +Click to specify a previously written radiosonde .csv log file, which is read and used to update the table. + +

    11: Clear Data from table

    + +Pressing this button clears all data from the table. + +

    Received Data Table

    + +The received frames table displays information about each radiosonde frame received. + +![Radiosonde Demodulator plugin table](../../../doc/img/RadiosondeDemod_plugin_table.png) + +* Date - The date the frame was received. +* Time - The time the frame was received. +* Serial - The serial number of the radiosonde. Double clicking on this column will search for the radiosone on https://sondehub.org/ +* Frame - Frame number +* Phase - Flight phase: On ground, Ascent and Descent. +* Lat (°) - Latitude in degrees, North positive. Double clicking on this column will search for the radiosonde on the Map. +* Lon (°) - Longitude in degrees, East positive. Double clicking on this column will search for the radiosonde on the Map. +* Alt (m) - Altitude in metres. +* Spd (km/h) - Speed over ground in kilometres per hour. +* VR (m/s) - Vertical climb rate in metres per second. +* Hdg (°) - Heading in degrees. +* P (hPA) - Air pressure in hectopascals. Not all RS41s include a pressure sensor. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* T (°C) - Air temperature in degrees Celsius. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* U (%) - Relative humidity in percent. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* Bat (V) - Battery voltage in Volts. +* Bat - Battery status: OK or low. +* PCB (°C) - Temperature of PCB. +* PWM (%) - Humidity sensor heater PWM (Pulse Width Modulation) setting, in percent. +* TX (%) - Transmit power in percent. +* Max SF - Maximum subframe number. +* SF No. - Subframe number of subframe data in this frame. +* Subframe - Subframe data. +* GPS Time - GPS date and time on board radiosonde. GPS time is offset 18 seconds from UTC. +* GPS Sats - Number of GPS satellites used in position estimate. +* ECC - Number of symbol errors corrected by Reed Solomon ECC. +* Corr - Premable correlation value calculated for the frame. This can be used to choose a value for TH (6). + +Right clicking on the table header allows you to select which columns to show. The columns can be reorderd by left clicking and dragging the column header. Right clicking on an item in the table allows you to copy the value to the clipboard. diff --git a/plugins/feature/CMakeLists.txt b/plugins/feature/CMakeLists.txt index 0f3280b5c..9a00b324d 100644 --- a/plugins/feature/CMakeLists.txt +++ b/plugins/feature/CMakeLists.txt @@ -31,4 +31,7 @@ else() endif() endif() -add_subdirectory(startracker) +if (Qt5Charts_FOUND) + add_subdirectory(radiosonde) + add_subdirectory(startracker) +endif() diff --git a/plugins/feature/radiosonde/CMakeLists.txt b/plugins/feature/radiosonde/CMakeLists.txt new file mode 100644 index 000000000..3a08fa765 --- /dev/null +++ b/plugins/feature/radiosonde/CMakeLists.txt @@ -0,0 +1,60 @@ +project(radiosonde) + +set(radiosonde_SOURCES + radiosonde.cpp + radiosondesettings.cpp + radiosondeplugin.cpp + radiosondewebapiadapter.cpp +) + +set(radiosonde_HEADERS + radiosonde.h + radiosondesettings.h + radiosondeplugin.h + radiosondewebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client +) + +if(NOT SERVER_MODE) + set(radiosonde_SOURCES + ${radiosonde_SOURCES} + radiosondegui.cpp + radiosondegui.ui + radiosonde.qrc + ) + set(radiosonde_HEADERS + ${radiosonde_HEADERS} + radiosondegui.h + ) + + set(TARGET_NAME featureradiosonde) + set(TARGET_LIB Qt5::Widgets Qt5::Charts) + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME featureradiosondesrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${radiosonde_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) + +# Install debug symbols +if (WIN32) + install(FILES $ CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} ) +endif() diff --git a/plugins/feature/radiosonde/map/ballon.png b/plugins/feature/radiosonde/map/ballon.png new file mode 100644 index 0000000000000000000000000000000000000000..0241f72f24e0d64b6527adc92be0fc0b0881aeb0 GIT binary patch literal 990 zcmV<410np0P)+TF(J~>g(e!23KlA&7@D$Bgnnp!bVf$2*Wx*E-^X=l=DzQJ zN4jv5n|sc=_c{Ond!BpF^E_`+mZgQHD2llrU4${*fz`Mo{QIyMJ1~JC>jpQ$R+i<0 zSB(tgWt5fcOMF)2--_jZVfR7s&ISw;`WeSEP9ULOG4@L1?8Gyhmd@UHOPDt)IVp2TG6H!TLisR%xb{rEKePlx}? zjNk>~n+W^uu&=@lei$^t+XCQj+z|T40RJ%Ts!U^d=v`CdXn*q=2PIoRlE1CTbdqUrZvI+KSHG%77SgJ-C!GY}A z5*)1=GgGk-##mXb1*IuLSQ_`)Ahl4Os&9#I=9g+HO$kn6UFcuolI+4SeZ$dq_ALcAIF zP&G8(4gG9n%4PF7Cl$yeIX+L$E?NH@}g3+{u-qZTvHOCD9fz zkJlttFKhA1;MuhS*Uj_#wM9|fUK!IHV2^F4Dql#2a7e1!6JgIt)m-B1HrS1(cplj+ z9gKdCYoAorqd{&Nerf~Imf(ePUp>e3X=&5Yx3neL*|>Ig%GC@G;rliKZ3%9d4pb|G z&?>1v{vj3M4Blu1(5MggP936;JT9F*+Dproq$3|l zRs6B;Um?43R%`455PTvCZOVLO;d|~>Ab3>$db`U%&&7Qa9K<(xw)6*P9r5<@2av&6 zrRiLk`PPQ-t=8BBAUL9XaGJmiy62I#rvgE^9G_&w_DF~Kd8G;V-;PCJxM}R3cmMzZ M07*qoM6N<$f+CUMga7~l literal 0 HcmV?d00001 diff --git a/plugins/feature/radiosonde/map/parachute.png b/plugins/feature/radiosonde/map/parachute.png new file mode 100644 index 0000000000000000000000000000000000000000..8478957b3d6ddde21829949b7fef8e2181c01b06 GIT binary patch literal 29710 zcmX6^bzGC*_kT9JQMzlCN{2KE5~E8xMTe7ALXa8=;zy)Ljue?9A|)v~ML}?c6QsL4 zrD4Cv@9&SX*K5yn?>+aNbKm!Ug8$4-_35ZNsR00>gB#qo1i!`peJIJnzppMEeZVg& ze*^mf@cHn+4@6rmHv|Akqv5x2S=+_cVSHZPxx@Ut&{2oaWAt_@i^2nhsSUHc{Vl%V z3~?{D&)qLxd?6K(P7q6%m3^s^{z)WG?378@4K6ICdq2&Bge792?nf#@{=HsqqrGLZ za?M%w)TVmC(ndtT`qAN6d|u6;F|YQsjhf-eBMdqq$+Gk|1P{q135d3sY=F`$k!}D< zQlxywfd^1&lS2kn zM^hx#$cJ?j+;Wo!%Zh2O>#%W*CsfDq{6UW`>t}e=Haz8;yV>Kg54{f;PieA;#J-Rj z{$b$G-Sa_LD!8vh+6*QN$(=G&8_14rHrZH&LlUm4<<2&nw9!}{%HK-n7!fp_hcDXO zNPRhZ7!sAql-smL8}?%6>Y}Q0$CJYFg#D{(Msx*KDPi1>)%KKENZG&GJYxM*+MlFG z8ikumX1wG#*3k23sekPNy)=uCsH2>EmUz#QzgzIcOiF8q{iEU($4=p!35Gbzg4d`n zC>2nzOF1Y=xkI&M|E=AUd+ZaXBxx{H0Tk66BTN;?(E1?#0O_782)_8x$%+GLs|Bt~A^NjaMC8Wt?96gnH01 zlCpneHm6jLZXMBk6ze8hf3tHST0L6t7ek(v(7RXUvs48%EtTtk?aH~n$mj8GTDxUc z*t!*SLk`U+$u8f1@UE~urxfY1>DEBmi2L&nlw@CI8$wrfAC|(tsJy>dgIdi_I%8?P z(nuPj`|OzPLDnW+;(?*DbxXn>)O_@Gbgs1UZyG$g?{}Bt{1M+fHc>2N&BCHBK&y}7eB@9)8)WR3x?-ysrL0w^0Lg_h_~j$l9Wi?SLS zzi{*F#u8mSGKaBuS41U=tuA?m70&_|R_Nrt)1q`?C#-Y#-y129kzDrf^*`Ha4S5dj zi6&jIE~P56DXIXZD8l(lxA$8Gu!wip{Gaguy7jUYLy>;;jduFxo{1T!M@$`y<7tO+ z`l*Xs{m`u{T_4`=of9&ZTelXK(>A_89A8L}pbTlHkLh>6re@M4c!s5tczl&q6{WfX zEL7XoW0WZiibmd2jl(}(aIZHO1ndTj81Biw+kSXu;uT9sa`57qMcMDC3|s0jL!kbd z(o7EJm(MTlU!TzgPG^;L2o`Fbo6al}6g$ga%YV`Ej)OXVtlwVP{J7G9NqogtL9Z$r z7IXRYE8U(+=V3_v=IUpQbbcIXP{CVn3kOm&Mgw$$a356 zH??sbQ(ZU8&sO2P`b$C3QIlHZR`Pi1hqMNiZFGaoiM+^Jt8Us&+3)Zh#wj0HJgtwM z6Jfrrx2pDgr0=|;cu_d~QZId_G_tn252nfFGOFvD=i;0-0h|RjCZk?0TBv->zdxK z&~}T#Jx3fGBKhG=BtO#>Q4WcH*>+E*{JD3Avqc#{Fq3J$e}(lUiMQB{s~n8S(p4&=tr}N1;`a6DYLP#06$@AaeT7?TplYmR^#JHIF_hLFS za3iB8-o}h2r}KE|O-M7eCTBDTacCviTsfCOgyN=4x8{g4RjO5U*^-x=ZU~0drQnU* zJ>}Gzz!pA$@tOzXXnFew6niB}2PLAgg-Nis(~v}7hfj|2$koD`fuj3p*0exjvtAGkaDPMc~Uppirdz8u~ha1t|jTMe(usx7XfF3O? zvt-ECbm2G5<#KatiQl9Q)cJDU=q(dwMPWWdrD>V!&&mIT^3!Hx$%LJ?n|?c&Ed}zI zzt!Nd>%lK6)Og@OmWz79xl(wgtgDT;bP<^a5F42$Ux}qbQJ}W}%95)n0FG z&CIyK%_C(7_R5$Y2B=Z?Xlnk>#4uh%rY0Zt7uC>tui}%jPOu8W) zp{|g6!QSuh$Io#?=!)Lt*V-#tV!&5+cn+MPjQuZ=%hK=Xls+l~g~5CK$ekr%A{=aG z(ZQnS?Ui@g51(Ky5~J=gHd}_i#c5kViB_{DxU+oc6_Ps}z+XNh>v8>sDnH_oPi{Q<;DwvcjGo5yR^wzRG?Mb% zk?`g76-!DX7BVe%aX2W!46jjyV~qyc1{D7Qp(#_-KAhggwxDn+3Q*WGURqcd?UzvB zZOF&aDb(mhv%s5SPsbez|Al&#I$%cKr1@f%cf<1E>!*5580-dVTlowi--5M&h=89A>}qW~1P`tfj`C`#g?fxDPL zq^cGp;e}vRD8DGh?xObLsvJ*GNk{td^$#qo=X>!}iZ$D*iY$A)g43)@HAtg5{052K znF5lI_!K)=PfwHjR6Gy;WS&+4oEe?T@1ynjst)1Dh+DAS_z3>;&(iQV8=MJ} zm8K`6rcQFh1JV8@Y1|GGtW+gly0cp=yi+2g_@nzerKC*FeRwm=Wk&6ZwJOyJZ-_BL z#3yodK+6I+kcL|ss$d3N5Y>w9=K)wAsHc35I(}nRu|2YV@lV@uD#AXjDNBBC7Zotk zDOa-(AOHKbKX01-*oe0r36pE?!Ycx8w;rxo4MkEH@7FV z7by9Oc9P8tUNwWJv)oC1q&s4}ZnuuYm{5y7VVr8+k`k%gFArO_^TBWMx{04RQ&iA6 z2_m7(jTL)q(LM&r6p<9QVc)wrv5C(Q)8u_~T~+0^m;rS?!a26!!V~(te)nx5siHvL zC-r{(Sj4cLTj=`8cywI84l$;7$mdS$zN#MY$q6fR__odmr;C>{hZMglQnlu6|@LRg$Uj6 zrySH9_Yh$UJ~1Bodtw7BSf5b!a_xsaYNY`ah708{p9rx)MF~?^qEDh#Vfif<$RY2EhLa;C?Fy`pdg$%rf^-@k~tt|{EY0fc33q{-ScPivJ68a)O7WFM-cYD1p8>nvmzZg!}eQ>2IAfTE83x6V^OJ@ z_IEa|2;bh0;x~x+jeNxxgfMJV@2TVh)^%gC^_QLiOZ$Z5^Y1;_tnp~{VY1;X=q}57WGS1(_w@EeMDi-s0Ef6 z>iMf+lEN0a6h@XQw%9y)CI+bFVXK9CC?_Czm))Nc)ZEngX$ht=m;~UY-Sl(UpRMX8 zrgfFMav3u!bj$(?Q2F-YRm=NBW@!5GW0=NogA7G5!1V ztU}oNm_eo{Sn*ovD=fyq>q7Jib*Nlb6K1H6%zL;;7p1>GBg#!c=C#Ck%HnK}6Ek1+ zJ;#2A(A3V>Y3qVEFh?s2(Va*+?i#gHdOtvT<%~vMi!85Cl@~5Oo1irn@Z(o!T^$@^ zNc2P`qxGPMFHz(91SGf7rNKj&AnGAMMR_)VGvDjHD(1`pkBHg98543lq*8S_l|%cX zy=nu-*=}~dHXpkiJ`|%tHe%x#e3^%F^iQ_K!;Jnk-Tew+M(1&Fa4UzlA!Nsq zQ=YFqF{4aai%Mry^0n~NZn&ci-}O@Gv!qzoQltLA&H~%NA_S4ol0JmfZqS|AJ4&7J zv~v&{04wF#FfO|yCOtT86SpFjQe0Dv$)CfR-P!X#V1f6yic;|QYc4NNlIw^d=?Rf+ zcl?e6xOUX#!iwjHsU%)fmlwfINSq8FwpnDHp(OSuZw>c65nP@P*d;RBH8V+Gw!)%# z86fQys#)*kYKR67yd&|0!^Iz3wKFL$MUeUDKSbn>)u0bvhu;j~8*)C62jYS0jl+bf zLpegedub7l91+~0^O5nP2ciSN@xTpkIcuFUifR@vx0&^dWd-dgjs7DPl$QJUO;$)u z;H>5#{<-x5XQBX7f*?fC0G>?+(`xPa&Qot6KeDVOe&B_e(mM$wyI#)4{~OGYjx-!| z^F&jB<=WwLy8`mYnB&B>hTDg0yHPJO7o7s8l!?K;OG_iym{g zd0utpo*8cL1E2(vLz#k-5<5J3+ zv6+e6@S%p~ni+zX?!NX9{Dz$y-RqYXk@L_fbZrD#b;kqn4CtZjg*R_6Pe$*`xrND% z|G|Hl`dgL?E2rn4VO*p7;M2;jt>05d%1W|T$$xH#6Gy8pZN)~uguXU`Z9?*162mS9 zOQkMK`yQ!2$BOURZxgAiETnumxV~y-j|O0e6g+JYuId}9e0Vcblq?2}X%UKWQr9RW zR98cZ>MY;3VERzkM=xp;Fc&{TA8`Kpj}}Y7RlRIvq}(*&qDC**t-jCERivQjqn}-) zBzn2smkR^c!lOgDit4KA2Nd9$Ru=F+U_JnS4+x{lQLQX#Wl1pV|JNjf6`z zJ~FQM+qT|vBM+Q#fV)Cp6#P^5O&p^`I-hQZfyz;+W1Rd|=}5BbFb8HJ31$LyGWp=3 zevw-nw@m`7Z*&)TFHWXHzGgZU#-v^OlPl2&$g{h3tPtJ)Ee~+D0F+YYW&C+csSgAB zb|k>7RN1!+UCX&BbYq*b|3U}6t~&7EwgiNBM_va5wC|^C1UUsb=*OK^*Xa9sI<6!i z?;$ExyEg4Y*>_;^=FK_wcftzeC1FTTxT--DoN$5m%?vESW~}v> zs%8Lv+#B?@bkDOw-G^zbAg_*Z)%YC+J0w}U@#;~iF_xA@0C{spNiVW*!j7Ph3q~B8 zJ2H7m%bk^BZ$|$_!FhE2ptPB_8JN&y*@JX;h}aXsRhrdRJGZjNmiYrAMHb))SiUHIHD(uJA9tJ|a zhSS4%yo_&y5|vm!RZ9YQ!m?Mxr|4JjGkPva~gRp)$V zN3!in`hn4Mwz?2FdLbcoIk>tII;~K%&*KqH2Tx0V?q<}YyRpYcj*xJhVoe%{Tdt~Q zRCpkgq1SB$x4Yp&>2qC+OlgINX#8yxcCN=N5#QAd_=p1}jK zY)Oc-s8qEYhnW4oD)aFp;}5hFV(OZgf{4=OJWQ(rCsoLZ%ti<{^UJ<+=LSet4xV8v z)0)mrHklub?L^2m{}6X+7~{43B;DElOIx{iW$)`e8;RnP0hTMVDhj8`(_sp6l0cG! z`UQ0^lOj*&FCkrQ^`i*4gg9ga7Z=|y^S5))9!3?aV40q#U?yqQ?yxWY80iZh#BZ3m z-3d=XVNhjz3$xOk7QidLHcDsR^|a_yPV#dczAxbAaBn27u@$=qpIlg%K-NIB;mw4c zD6{gN+fplsilZWXhU;a2jgZp<=!u~#KxF1p2ChI_cKXGpGpPN;Pd zioGfd?Pu*Au_f55qgQP{Q`*r@{}){bcq(d6X?r$E7uTxYx<{Kj>=)cnu_~bGvo418*Aia)>4v z`c6XWl4Qob#7Ub!8MbM`j<_+yA0OCMfVqgTZC-0mawoErjerbGIwt%mluG)o)eqO) zQ7Y5wCYMO!ktA)v8%*nLsu^VmW;7oc7w4|{LSgM9?TFrv;&?=S;T!HPx}|T^84N+C zRCqvq|FekmHLZU7Jt=+iqMhOVt9TaU=~&iaQ}dlSL{*wYHM!!DjRS)Q~`hzIF+ zrIeBAt9GtGumAwG&G&7iUGAzROvDOvrR@f(v914kvz9jv=Z9dW9mJPik1NFh$z4P{ zMbcy1&skU#p824U1yTU4S375MUFODtWL5Bn%1vq0Cq&Wg(Q)3BSm|q@tF2c*eKLXd zE~c1DooLQDb%m4|IgH4-=&!9p`5RVRC<}RsIw(3kJ|G~$rCR9z6XG_|b%wqAl|7&K zykX|J8qQWbU=}Le`3L7?Dj-TK*5TrrE0~RxkC8dIWEtZLk{dfAh=iXE4xa>3=?s zqtYmi9q{vn^fPm7D*B_$uC)r8?KxBI9eA?C+NyD-{Lbg^r+)cgd$mvg^z)RIPy=vBv`A_? zC#^TPglB>`L%MhBDfx~U=(G=pIB*GMU1nORj+Eu2bnO`sE~BwAaU1;=3{;C?d`!o- z?S*)v`h89LWGia=t8^D;lmay4zy~#Gh_QQiJ}hxP)vU6+SegrvQi?kdlKT5#F+*4PEOAg=dpUAj`3?!kp)@3vF8NGe@=VH4~gL}Oa%!x?r$xK(BRE3muV zcNJXBm;r3JV42dl6RA=TU9lSH+1)O^vc&;r#39vU*~{PngSQ~TZ^c!Z&a%D@kJHy* zIR(YMDaQBanYFVoJDq2bfdjW)BmcLuW0P~LFF&_Y!_-NxmIQ)J_kp0?8BeL^vv_q_ z`7Co;byE}YV_c&^_u-k{LtDAC5}iDk1|M*_>`{G5OzaFSO4Nwv_awLFYLF^4S?Svq zFf6oE`u6Z+g(P5*U!NKHV!y=6`8gCVLT(s5`;;te%+@IOZ)4y$ct1wv$NY{kc`eYpwsBSk2T z`pfCF#-N*;)GIyU-j1i>j8zKr; ze!l1b0gL9!>RjuA0>>QEg*tgWj}xllwD|O9HjukG)OzVQIm_lCR(kJP}7E z6soaT{hP4=fhN|oWdU#&xR3OYBAIjXjblLerwp(CjW zrUED%ylyIZujN2dwZHmD;$#ZQ4ugLP-wX9fT%^%W_gv@>E-bS>Wm2Gwx9 z^p746?~-Y4N!m7Dp}>{O9Bf}_aKC)b|Lr>NzUgZ0fDPi1-QVoi3kBhb-s^<`_MNYv z(l=#u0xdXjXqODA(lj5_*jILwig)_TR&K=E<2}S7b0QVkC`X;dlluv(a^Q}roc%5A ze|N?%Ua4+v1vHQMu~VbRN;{|KHKji<`l5>V^UdsCPeHNp_)DnM0^`~lIy2~nRc?|b z0M^@fX*}{CB8J0YOd6s{R=2ts#^K!2-=J*fG;(1K$6mKyC_fIUneh^x@rhSz&m62C z{*`2+<~OjD|5aM%z%`!_o#R=1O@$ceYq7@;xOrvW_)1(z%smXEtdp(+gB^#!dyo{- ztc?2cSoYJ(SZuX8SJSKRsG{5nYPCE5=S{zuUSBPNJOOvDO|YhaG*%%*0}!6}`7w7Y zsXxEGUc+iG8>S3SU*V3>8|@3U0>0xzU*7e^LCyZn0es#=_`9Y2Giv* zFrdGcQir(pBKw@JDG8&_kbb~%Qh`M)E4UAW6%>%2cw62aOCnf+mi*Fk-#uGYeEPl6 zt1&|ymaI#ExqYDAke9@mA<%^3R79r6Y-g3Oss$UwJy&be#SDBtRZsndSp>pzFkP1e z?h9>>{u|e^<<>eYdbU6zGdEu{2n=!MniBryO*hdQD5IPb&r?iz@^vh1ED zj^j36{)-(j&mz&GNlNYlhE$%{N`(LSc_l@io6{9g0_g-D_eP2-dn#iZ}72z`d zuMaR{L`diDwl1m$VPzX#@8CToeYb2n_(akClcPOY?;1{5BWF+eMAcBlhu=`{Y3?+= zHP%v*%IOH0M;;M}?GA?(g++_cdN;@#jI~z)#GzDAJ!MiCu=$92$JhN;zOczc>Z=Al zRsc;7NnnkYRtXI2G)+4aCkEeo(Rjwtx`vMNuTvAC1 zBMcElO)msP)BUU3o}ZaQ%4d#4Xa~R)ssNJf^s3x%oH~@#7BHWx-j_4PQw{j}o_`4NpPq#y3HZ zU(X!d(T`~G76WHbVRLU~$g~Rhcgw#@KRTLr0sX)htQq~&q!!{(+??>yTermeE4xx6 z^rKj5VEVX;2Q^^%yAWN69$q?3ETRJw<2P&=1)mdj3=DIiy&_2R2IH^UdDJZy?8P$0 zfXOwW%_Ss!;-X>Lfvk)E-A09ItnXtMq|QehiR}ync6GTkN~LOPd=q+U=SPWk8a1km zCaLuo-mt-smZZk=OLaqzJ@QF8W0Ur!V`Dl0ZDwHeFW2jP`=6>&Jo%5s30UaNG*-34 z=G$b{S%&u|Q*V^^@f$Q%HJIW_#kA7pS+XO_L~hJ_8-w5&n?L=vXgJ3n{+FBFfZ&8X zAQPB7iK2A1eoUXMPmuS;#9k^DeCkrPf^aD>5IUF?8b7o5j%-o7>81cG@hRKbNT~oh#R63J(YgB@kNbxWDM`}L9tBw zDrjE(5M@zv3-``c4C5~Q>x)R!v5<;8KNk=W>yXwEzzwlXVgwYA2Ym?WIY9Pk2UgI{nPBtk2{4=%e1Gh!o!X!CVI9JT zR(I1p=ojpt(NH%5c-rUtS5Mbtzs}#xk}uU4EPpU@7~8QZP;K-d$GnM^>^YHjC)QR_ zAQ01xD#DFOaH}eorae3ueo*NJzdo|$y?YEt^@_RP89?hL0kL|H)iWc_y&o4a_Ww&h z0hbnxf+Em*dyT?;C-!&s1z@o#Hu@zMO2B&gFvi1!S4;g82)Fh>k3nbd8Y1}L0F)OZ zNShu9MSTe4*A)8YRv6la>2S3M|t~q%k(7U|Px4EExrPNd|Fv-Z$Q{0gv5$ zN&-(M{=I0#%+1w76gV(DAXzakVc{i4WZn2T#efuA1iEyc5`=Zi3oA?Dh7i&T^j<9| ztx?HnuZHF<9T0xnS&Qoac6aDP7`2J%%m5Q40pxq9Qkrw#_jQ_QMSwp~3`<=9?d=Yz zPc%k-Jrhppe8W$Ezwm#S*6?KJo&MAHPdAqiEuaD?KT#IlOn(JUH~vFMhTrh*Y09s- zv3lL*q?^Y-pKfo4Hld`4G0UhQ|p}IV(zaERiJ$^ zq~Skt^L0iQzxagFg8AE(|^f!%j$|840?KT+pFdlU;d7nxS; zC3QH+lKCrd>xqJ@;{#_Hhy-ggVsc?@jqmus5zy}rdpxbdVa38ohn`^Il`u-6_8k_; zcC{?q4~|K0X9oSND$`c5_$p}Rv{0I)h#tI4&`((G)Si-b<982H@-f-e8?Ok9>FVTm zUDs1Bz(#~u-4kS8ojXyK60$X4a30`^mC;JXZ>Z0V#V~qVw^o7{ayM?X@ZX5=wT~Uh zz00fRc|DX?TDdCER#1rP-#X|ksILF%989f`N|yZXQZnE5K!N=M+3Bx<^n-8o0$^tM z*WN=Ey1p+%lHwJ(CK{~T*gL45d(0@eduy-2g~@Q&Hxr4nEfb zSfViU8l0(iT|uW>8F`_)hs9(ZbkG+qFP2A7KiJ)=MxAi~rYisZap$;44|45aBrdVa zPMDm@#dV>d8#EabZk9z}n8QHud_S!N?$ZO6gBksu9`Stou;*>1Aq~iVQ%>!-N$}EN ziC*3Wsh|?<^}E)us|~49*#LV?ayG@lNrl+I`*i;Eec6~EkSwc`M3Hx!)=R3Y%0Tv8%~|_Ip=mAb(qO zrZr~XcE|AE?K_h}+f=l*&wkOPJ1Yb+1D`-(c|R?L8(>Y&mz_?DlCUF2&R)b^>0zzd}d7e%d|zOj7e+{xB|y2^vM$k-U5Em8*g9eyoSSL{*5m+G{Xit-BZlFJlVI*e$zpr}Ew2ka|@;`?V1C2$~|GR=>%$di4=tcTk*%xFg zvU$thp~*n{#DyjjAw%&Ra+m2fBj>WN!?aDX3Y;lagvr4J(GT>q#@bDZv%Iz^!(D)m zXc@qm3&ahuBNWp=QQeaZTfF*m(#3yc&ewj%6-fUGfYwmHd#o9|6#8yv1f&Mspoa;9 z5AA@3UTRhe%H1cGPTJL=iM98?-NtSCdw!{&P8obym@l=<4Y6ZqZ~yM$0d=dv-|_c; z1;m;sdQvAPUO_E|Fo%?U_vrfiD2k#V`ug56vHJnfxR`KjM=?NI#3=(EAlu_E4Fe7F zsx~Ux6T-*@G`~Q% z|6&<0MVlbO$!I9fNAR@~c%usALCDnuI0em?@;-d;aNWfV$L^3xkrdX4Yz(4Bc8x`t z#Xm3g7WV)C-l7LAkq^#Q%Rs8^9a_)g17oNKtob!nC6R)130BvNKmaFg8JnA(hwg_h z%-#X;R{q|`fHzpi)P7L$Z+~4t?_P3@hchop2n(>!%FWeJ%zb+g>ZS&zEOMy6`Z^2* zXGtbVt~u~+pNROMA=g1eI!?Zqur6Ns^<-EL3aZ^6#HXUqhKD5CeIE{bIlyDE1E_7~udu(WRb5;}aXH72u-Ge$HM4bT{ zL<@(CKtxDH`iaUMtJ`zxGm}>?_b*J(E}mkrkB;Z2*V1w3ddH4rQ!+K~b;6@ixie!z zGj@Aj%R~UlEyp#NZ`-_}>}dtDS|;Y@9dKWipYOlJwA#8pC$ZV1e0^`&23G=zg_7>X zbgVb0%1cz;yR>J{PLe9n>QoxOMd%9Oh3(()_qz;z-AxvQEk)Tl8Y@0N)^w#@B3)YF zmm`rDCt)W`JAkZmYxxnB?=GPXKghUc>3 zlyygX=jM!yT-b-0LG>0rFEW$?TVH3=;3CbrAhz{BtLQ~Oefx-+Zqq8K)hhvP|Go*q z^OSrQ5pcZhu*d#=e4ec9k1CWO>D}`oh0VyNJr+v^XFGX&d=8uYCGPe0e828IN{Yri zlX&I^XV?q9sXEZmia&`hKB~B4xf2$3G*5_0%n28c!-*jxI)pj_pppT4){n$bTd> zp0_@{ANJRpM596Gq6Lyif5WE3vq|UHl=I-yQ8I^nDDF{p__y|fN;6+bsoWtS}fL; zL<*7x;R5DuPjcuHq=zKD8G(h^LW76P_{q*>FuP|@(8baaBLh3hMXgB2fvBv&25fIj z{r(0yx-+Y`2>TPh9LMB8vEL#H1$$Zmm(;){?9e`s?~q}EdxHwajHYc}MAB$&_dqv^BcJtnD!bP4y+^r8_@ zB!NFg7s-oi#F66|U7I@dC)I0T7WW@+9^K~pi>x>m49Y7FRQ?;BKzOLs zWOHSNqV`c?!sQ#>&G#hXze0=WL6Wk+2oG#X-KuCB3c>Z^tkCp_D#PVQ6WTpHoFpSh$Uf(Wm5T%9)X`Qy@nZ-D{hyhAsPNx#=ZK#Ip00* zfxzbt$1q^0#*0t;`X%;h))V={r3Y#(LcoPEQX8(1-V&@Y3MeGY%1M&fpLqmdSN{I- zpNkCd1#~p8Y^CPOV6G_T$`3Z)o9s?U*S^Q98ZbR_K9t@zzn-e`n+Dcv&AvVf-d&P} zle~SU)kpf3zOrCP82p3@os==S7IsGckN+Ai%?AAeZFmP>13wZ~7^jlv@=wJk1k|Ko z_2GkVr*J0(N*Z-56eE-qN zL8H;?%g!T5(53-tOTKy9Pc)bPhU~BkyU7L)UdF^maacLI8tI1acG5s%9~S$oSv4bv zht3*KQYTYS;K4Y(-`0Bgtkw6+`jZ+=bQ$czo)Ac)RzIXa$7J;Ivk;=2Qp@oVpxZ@Ld`4*nLVOj2B<-&F4IxXRH#W45fcaW&sH(s0DmRm!pB3Rlc{#biaX0oj z6O5O^RDX^=;SLs4+j{z{^v*QtrTA)9be`RV2-4TnPl)I?s`E7YRGFMvTD%CB>F1vy zQNl1~+-YXeGQqu5SRyXmoUlitR54_MiXK)7iI*}+y8ZO#PUt7;%*{%n`A`%84H{NTomC}J5@#!CaZqvzO_;VzekCwM++Vc8w4W|=|S&;G` zbd<^R9vIxC)Ph6IAKPjWuAo{f_Kr})k1^4l#+;dwQ{`ak5=(DqG}k;nqeZvy&9WQx z-Js}cb62i`Bb4J_zsEwtr53Lvjut~*RLONw=|Yu z`nnm2x0;66Z~I0ZVMe*iNqgk>_0Juh^FG~?k$4O7rlCdG)?l2Ka-zo9ZsVw6iT8^~ z@;(T}oyvvp23*9~RXuXL49idG*Zloo2Vcaq_|mg)Nocboqp;#DcPfK z9$ow@JfCCyA}msS?ENCqpx?f$;y55bA#hHkJ%wkceJ&ZN_)Rh$n|h?i*{9m6 z;QfJ>*o(OS`#9r>Jxmk-lu5*0s*wVDwc)<$b+{XYTMwt^@PDXsgS2;JC(R537bb`5 z)r~B`pzV8Nel6!4LP7_-#;`JKc5(}R-mbq^QKE4&VZj*Cq*1*lHW&{Kr;O#9Sd5iEZP%U7e4CUVORT4SNyCXrJMFQg&)Cu#!hGC5 zwN3w_gqlsC`x5#nD0ce3?^xI_m-g6aFNM=Q*!rb_dZcpFL3pL}c9$HkLI1~>x4`R* zxYJzhU5}|I&92n&ifO3n+t%@fY2~@FTVo;bhwN&W*n^nYh$1YjuH|O|8~d0fqb5bC zvCgBf$KmL+a59;`hbKppAsu~E1|bZDk6pp7-3?Hqp$p;lt}qqFDxOmD+s#wCVJI>K zuFYD``F?Cs-LnVN@LeW?`ItexLGFQ0Q@~X6p$0E|2B70QC`r^yo{NbdKVFQ>PC1Nv%3Djhs#2VlJ)ZuvV_}z+S#~?qGPu2qqMF$=&5YK z?$*SfI1nGsFORMD2T2f<$ox#33m?%hER)T|TdSRv(YfM~aGnkgFI?DIY@sSjcm2|d zTVvP{$daGA@b2j+!#M>-NzxatH;9EPPMc^xgC{=YR2ZE8>Z!t7N;Mfk7hz&WO zx6VW}6jqmc-J+W`DVF;KwP)DZ>`N8j6-L#ahGhgoy+0HEbuZyh``W?NjHvC#Z&-l+ zIC8Z|4^2xZ`zV%VYUI{TzvW__jW{(f$yR^qRk9m{FTci2S_VjN;WxYqa)$wHeQ$d; z_)QR(?=b4tPh<=58y<4wS%bxhd+W#RgL`#$pPM+2qX}N}#k$-2*!oZH@--Ej{~4Zg zt}1^TX2qHORjVq-INLuF+~h}ESTcRoUGIB)_Xs+kGupmpisgZo-{PdMET*zkb%ucL z?)}6021A?#Qm@;7+4e@mbEbTdM*8e&eA0Scf+h;ndJnNqvi|#&6>XyUs+3+3W9IjA*@Ue1ug5` z>gve^Q9IEnC)*}#I9eV5arpU28-K&5+Vk4X2C9p{M(VelRL>nJ{~Lr8K4Lj`%ZBq4 z(#i~qmHUVC4f0_UdYp^)*exe+cBDez6yh*=vKxHy9gYecDH+63l94-OqYtdLoDqdq zG5%(*=MXTtCO4icuQ^lQv@gCxRjROjw>9#g>?OV4bQ*=me@b0Q+WZh+N2lNUaQH1z zb)BjBKHkO9t9IS^$ia2CC_qj%s}@P%duUwz)&gZigHj2;eI`})0pkO98vWThO}vkI z0;Ne?(jHWn{r%F>Ani+%e9f02(ciGoKk~Vh%C?*w{6$L5H5;~W=fD{F`1BvP1w~Ar z&yepIvH}Ye2KJYom2kpXbK|niTYMHOb>U zPkBrTYFNd$KmX+aWN$Iy)KF{Px~&q8y%RkRsTl%)JI|^$*-Zp*d@7g^+@VP=X!7%` zFY4H?00z*!zu`HkL6#uDp5O_d7vlJh$!Oj|0;QG<;wbQX7yUph)_wM3er{S5%*`Vc z#&`_MJ#$x}gh_X&^RsTeFTaV1YNj>w&0a=JUz%^<+rbw98w9cb!nMBp%u}M99DC)B z$4AMSh`R_1AR)EF{Z3d>MuKK~IrLcnOSK0fP40QC-JU8Tpfq8v&y%!2%|Xu38&UZu z-?#+15W!^=PE0FU&Ib6wS(b5s7&Nuofn6tUn~RIc-`!v zUWEnTuZ>ReV5KH2=ZtJS@h<=V-{vWKi=D?cA<50=H=SxtF&K5=hRK+9S>HQbK1f(9 zr~gF___OviPMub$_dUe4Oby#ZeDOSHR9a3owZHkZ&Fohjh8svykjkEoDLY2&T7)Fj z<|9>~n?BWZkqu$4654c@Wj8vz216n&i!pu;CvPi-eAp(E^rO{F-U&a`8(WG1`_W1g zE64xBB;act(is6OqVQxZ$0mETrRSi zhjq~ybuWY$WLi|BxonIJmx-v?b2=|e%c7NpJIIbCbzL({IlMn2DS6qpSGS>eE_K;~ znl#euG2#VlG`6V-)u*|njfRBR)OU~M<(d-$Z67frqjs-NXy4fMDpM@i)rb#lcoZC0 zc|}%^3!O#V$1q|3>nE*9U9IyEyl>fx!c&{J=gzvf8rpu1Xu3Xg{Ie&7k|Iq#6!h7W z@qJV!#i`vi{-W+1OUeNqL3;jilKT^KQ`uxGn+Nc=`D32QKS|;O<-&`;gbz7M3+hzEe5*^m-~BDjP@_DbTcOCG0k{|0P+bzw}mBa zc}`={n81t`F?zc^WE5TaZR2vyU@X2?KcS=nwT;<79F-ITgk)=S4W49FD#dH)5&H8y zp5Kt-m|z@fk{-NgEhh!5eRmIPpW&6&f#cRX`5vV&=Xg`{aws(rcF9J}ie_n%x-`E9 z0a8@;Bod;m5=dYddX_gg!iNnI!6N!g{(Y4a6;kI*gE$26teh$B;5huPnJ*B7$Z+mX@jsOKL3%v-e|4sQYw$nIao`}$1 zUMBCA$0hF@z+!oWZ`{vUjR($@7q9B2RI1yeD|8EdDQq5g-CpaV0Z=Vgzc_IUeMPnq z-xT?`0TTsT%`N%X>5`n$G_dQdf6=Rt4(pXt;)PNGL3_DT zXejfa{2GFH3?=-Wq^XTa8VpWf227+BsJB_M&$GilR2Qyl_x}hhPwx|n;!_#~3;!|U z<)7mMH+K)%W>hyPENXoIDKLWE8=5!E{q)w%p_-$jl1xp50S~Vcp6+}=AfNGRH!Ds% zP9{mNCU}G4m)zcxV?$bnazP)U=<{U#pq>=~5Q@ylSNvlFR+OVvABT<4EDz%X;$-L( zKXVEkBx9)zE>4VEjK^%0l)8sA$9Jb8Mw-H<1W-{5$ENc*?#h z!ZGaERoc|CftwB{M?Q92ZQ8$LLh2-djOfZ%|B0^{(qbMR!L%$<*r84r`X(9nr#CsFgA? zAyTr*$z`ENx=0^w%q--jNW|9rG@VHRQzWhOF;tnwDsgAlevb)vUjldw;M6k9vWhpX zp9Pp`Yg7*Lzt`e@T&f;Hd89+)AzMwJ8O&7*8J8`e7gUNqS;O};akp5EP^sg$^QoU zr~3R3Y0)aoH)L($Ixp_=oISHgf-S{3y+_NVXjAEm_Rq(06bx(luRqrZa$h)}lWbd~ z1THitF1Muwjq(-571_P$+k`>(Diu3VP&>QG{jkEAs2=L%i!2j)gc;x5Ebv-c_k|q) zG>LId;YXbyGG>ND{u{$xS^9LJL_&XHT<>c%z_sIu8N|sf0|&u^q@wExGC*W(j<=}KvW4IU>oswQ$W_7u z=RFSG9(sKD_>Rk1M2`z8F~)7GS^4d8fQC#WAO2Izy?&Vn)xf<+s19j%b#GuW?472O)@ zy{cWvIyFw%3hBuXmp|z*0K+ikLd|GHqWjd(5|I;O=8x3#l<@fx2b4m%F46-jQTqj5 zl5cM0yyE+9)P2NiX`n%?@!FmI1mj!_C8$S>&D{-cI;7={t zI7R1RmPekT!iF%*1H9X2mJ$o9oTM{QWllLy{%ytL3k`if;f0DUmt*PZPW47iRZ%KF z4r{l}nPAs-C$l=SvO07ga)z4_?UvXC_g}nzp&Sm)u%LKXrU((sS2SL``dnv$M$W?W zp%2j!2tLj0^lU&|_?Aaa0G>8cJ={PU*{e(t*LkZ-`$}0Kc2bv_7uXRTcO4$4zS|n2 zU$6PQX92{+p*H|C_%{7}ms+ifJzs5zQ)=Fl!{`BhyLIU6lhKdPdo&^pFVGKATH~_q zW!KjBGrUI(0Th;H>>Q`K&dtLAoX5zwxUF49l|~V3d7I}>&CG(}bR}iPuh1uBaNF3u zve{T+OJg!1VRh|PF;EKl39nSEsbK9~NWwov`AmaF{vG7vB*L(;>}nhPCrKuG1!3}l zV0R~H1dm>g@BSFV9{dCThll=oU$5(tL~cGSQr^XCF`&#IJ&5wNqqEX3SVBDZd-A|- zdJ|xF^x&(vNBY8@3RO#O;q)18QVW-|OnJn{s)eH#D&V7*$AnK1YxRl}rr1Yj;Qm1j zUQF)c;L4%c4`cjI`)T&v^IrUUoxb@I2Z!&)CQ_bb0^$n5M9m#@13RbvbpRAUb+DHD zi@3olo)7JBEm%`QmC9rCVI~D~IA4JNzMnD@>M`G>8uFieMKkwu^}4^~b!JaLG@t2u z$pS#R!Q$z{IH5;n9r-|H5I0A9rfA|YxV%*ogW zkh0{_YzkRDWsNf3?m7mZ3G#1}Jig7UJ*sdu{v$V&*0{0rPN%bA^)+Q;Es(WgjqDX1 z5n2&h2dgg7PsFI9ttIaa7pc;IezKn?SFg*Lmni=eKaATrhslq}PFZ{x!;2NW>oPa$ z6dJ+&6l#gf{2J=xb6%W70dNbA;=Dwl&s@L{y)w{IcK&*qiTH zasZvj(eZ0wq0mL>5(gF!%`5rT8spT;rJN{II*?EwN^^KT|>X>49IO7xs4ZIA~subpo~O~A+rKp_Wy@Ry? zrfrmI@K7jI8V3i*|_xqvD<%+V_Dg2<05xt61~<6c$pClJP17aUm2~$Lb>MU!Cn-F+PGkOKeZ@8$ zw3$Nl6~~pUi)@M4m#ei`0hEX>Zri(v=Qi*OvJ68^uH7f?FN4%ZkV77_1%tQEzcqE4 z*MseRL}ta1#%nW-rQc;2vNs?C6!kp{2c(!y(}a5D`BT}{u#Kx6;z8z?blk(qhhx*;hYNKan_}LSaP%4dwLLa ziF&T+~((px03m#0^PFKpk246HzMzL+fKJ&hDXm zJ0T--xU0-6P@man-vifkrvkLDvppEizo z)cEYj5ELH5dk@IC^WWCjCircM3`pfTKTQB*rwx9lOz9rejz9=$TF}qLs7bWZ#-JvV z8&ge<_4lXkY^`(yb`?-3mE0sOz!iPHVM04%SNLWtP5DvuQGg`@cBzAlEGEF4V+1ng zaA#Xn&3q3oU3Q8#@Gq&ovy?P^ImM%I;`jah-!k(Un`EY+ogdfDPMS#y56i+{9>?O( z&ZLoIECS&#gy4ZqDCTuI`bW()92fQeW2 z#5$#3ASHviw+g|Gv-hd+d*jdQHYTfccp_%bP0eu9-S!EY6A@p)vH=RAfg{556~9FX z>?|g|Ma$z5oIUWi*hH0bj{4D^#EOJH_DukjH6zJi8siTH0roS+cQ3o%isf3aJguX- zvr%jFzx_*{Ct*EfY)_&B4rn&0(nu8L7f65^TvKeM?zYqFZtV4%&@WTw1CQVZgG7s+ zbmb$?M8RIl0Weq@fk<$et;P)Vbc6TzXoVCVY0>;(D}On{t2$`)YPi#w&$BNIq$wG9 zCOXA?dOXg5J76K_Aj?09-}-=>eE)DeJ^UIwZ4q912D>il`PeCSFcg8H^Nixq?J8bI zAT5z>QxBzZUCi_ttP*WbkU?)!wVmQICr4t^kANx_Z4!&m zH`4VbtvWMeDGO=#V_bbSW?7HwRfu|G+9<3*-^Tjqy;F?4m~HKrf{tKn9Jrbvw_%T5 zMJQA=1akSN5{kKO1=O8typlDWX_9OIy-_B`d=61u?x6B+!9`gbN)f11BV+gA9B{8|q$Ft9=`0|r zT%h(czqBD$CKWOTZo_(%z!^t(Rv0EEcIVB^;v5G97kC9kInJ|6_CO=Vxrg{4m<8kbKUzyBPSMiZn;SxGiNhCCbYTGkn&8Y-B&b7iY}sa62ICgu>mi_4 z`_>q!qI{x_L997Fyajjd80~f41fw?eGXy~7V;z~xZu*e}JgM(hTaZ}mKbv{;Uaigf ziaFao{qEHEE%;$=u;U21jZY2#sD$m2xm>1!2BWV zB7zR&(Lj+Hc2YaCA-$}35!AxScK|e53bmc;)4wq4=Y|8KaAWn2C+}em6deB1kX;G^ z#}+%B(<@k`V7S-i8$B|=bf%rDv+4_78Vxk(MaY5qCvE?DXtHHl)ga35k)mD-#EjAg zb18NmCOa4Dr@-@^?EyoJHeyresM-PP9DKa`NgR57E7Kr{(=EOG5}6Goe;-*IWxL#) zxu6&Z!t&Y73G4ShT3C&gp@ZL}3*Q{3|z5wZmZixH2)^KnN$Z zhilT?eA*Mtp9h7GRMz;A-w4mc&(YMOk6o$>dyt;7tezvnBdfdK{k^V8HBXr zp04)oJ$_S(^*SN=uQ>Bb8TX4rir)II#W_%kNpI8X`9{wupOw=B*J*yL$K+sG`W!5(hCWUGn-4Cq1HK|jFGi?sOymdo5u1d#7^2^Ddji=3GT@yY9%r zcnGp^PG#IuSapzsYn-~WXQGud*Qm7A=5o2txTH>rZ2xeC}CpLE}e4)2r;l_h(u_qgt&;yKD>7>&^Pvt zMCiBWYUFC10tAQ~1f8#ObeMws`?1pSVW6wCPqg53z8J-rLdTR@=3dYFLUkw0n(>YB zKdzi?5V?uYIiw#8qMT9M;2Vn5C+|!H74xBs)2>~QfCwUriV1g0PFO{NG9ZV{dw~K_ zhCPd2FEh~gkm)oY`ttAqvxfQ(HzGcb28bsr$y0|P~5NO6w$KoPWZ z>iI3R->xrx(!L@|a_h!&i5;j3Ay5>6&(wb5CM9!vKpTF*{Tp{GC4o%FcW*47zgSw8 zrZ(40H3N*`=)n&=bt}{+RR@lBFJt-5fvjt8$(lVh-QUKq6Dik;v!RNJWdGMFZzT-fa_YA{BL|TENI!!JqMQodG2@l0G`3BP2>0idMc55kf@TB) z<`%zSVX&D4s1!h;2UHWG-ROULh*7fcb7G~kTZ1mRCGIttha9#xx~_fj6Yr4fvJa`>*tC!eIQZy-kFx1Iw(Lb4|fWdX$!#PK}*mZHhegu z`b@}?2eLSM#wkZQuyu&*WaFf81JKn|HDNWsco|wK|5J=>7_-L_4MO);5G{Y}=KLd9 zDgS=BE}3!Za6*}0p3x-?+pC5#m~~r7Gcx)bppTT%=IkxKlWu@(viyuEGZiQ(>>nTX zO}cr5{sC07_7ckYCwG^+yT(I@jJ4C3bMu1gVFhvfcmuIqmda$>paHOS6tMI}pMPb# z(K(@i6qg=3Mc+R#5}doZ)tXquiA$rD$YfpKVsB~4M!GY%i@ir!GH~4Bp1hAd42=a5 z_NZoQ;etPQ9k!I;q-tt9M3v4_#gh77)yeM_ExU~4NiEPWPQ0h!uI9{-eFqTVfR_>e zqm-kX!nFrFHK6L?m$RY`7pMazLj{a%_bUUvpHVKj{`RwZxP=G`*cRdHuRt)4Hj%P5s?V2nix9kv`hvcI&GR+&V>5c7!_ zy2y(V>#mRtSX+i9Pk-b%)zMc)ukTqk%31A;kFUySnl&L%3 zx^-kYV|i?o>t}b3yG+pGs>3(wTC3qy!pis^ZWc%E{w>{j4{#A@)xfgYUA$t@az`M! zrf={m*M?GbSCKe>$L=Oo0MO=;+*(bc+%h&;T|r0cvJFs1KVP0!28Rw{oJBT~tS(hG z5$#o3S@GYzBTxXDC_&k6elQ57Zy|GY=84AX8Ng6SwN`nkvCHH3+)7a}DUs5<1UhEu zYd=OB%BS6mkVVxBD7a_Ul*=rl8?t3_l8zZoswvFw3MCmO-Vs3>1ODdv19HQ4{fHJ&^NqUxl!TfHqaJqADnDeWK_>XSG}4Sx-ZSKuUGPJ7XdydAydM z+<45g!Kc{4>+FA~p*)D@V8ise8#ZwfOR`|mOi~9Oj62v(x94K-2U@mLmEg`XiD~ux zJHW@?pOUv1?92N$wD;CLC+_L%Q2Dmh{ z0kNG}gmX-L3Dq@RE!f&QY9c0Syp(RYY@aJ2p@A7fXukO1#~W17Rgk?Oq5l@7gk%uZ z(Rtg05;0C3JBF6HiR>?ctW7lFZKm;-y}CJb1`R7c+@dKH5|I?|!;Pc-w{o>xf@*@D z8udVjsXT*8UF-UvCe7qz*IT*=kdX8XAYRLeureE(A|_d#J$mcdT-%`|1j z?x~LDk+2ow`z!;!%ODw_fS(P!`VUO1?0U9cBWzM}lepuI(~fM+o(ZLntd zplufg3=1jv6`rDl`;%9zCEi?|e{M0cW8XME*@tWo!saB^=6caJZYLHOupHDhh-;zV zSq3T>hV&f$yI+EgkwFM|vQ8+gG148Csq|B>uieW^+ijK3`M#VPHcY&94v4OC_H~D_ zA$x(K=au|(Rsr7aDg{BE7DE_MQD#*nbP-&eE8bn_%TlP^Q9>N`6Jolj%647=q1>ap ziVE6N*WX)mlN*1?h&*s%NquqcM7FwcE&Mm!R-;^F=# z&(mR`FLlaZt<<^G%?Kqi1(qEOj9onf9ojdNbk+r2lLcj6PsA#y>ZHi9|I&a zK}0@2xqSwR{pJ#FiADaOX@dWa{}vVp5H=)U$iTX|-i>Y(^gU;ST;P=RHFR#*!lU8*Oi z+3^+#1Wt?LZ!_xZLIQvY;gi*Zs!!%56GHv0rk`(%1#k1nUF;35pC8yf&*1WLD#u{1 z%tcS`7eE&LK7i94xOw>Tu-e>BD$eiNhGl@&83(6x?eZUe|ILXH-mpGeY=JvSTIVot z*|@!Vruf0$LPXC^;9pug-rL<^xA)~g$w=|j+eikQ0--B>-h(&k2gB90BPgGZ1I{LD z_R|(rXcG#I>85jk{14wO`3L_A`55e#4?Al62u}VZ6GZY;Ghrjqudj1Kat_1CU6r21 zO7C{P|C6X5@>13$*mMgX(~!-U+%f)5SX>2cm73Sdv3sGcRupe$_J-dvRaAhuLe^wG zD3tR$t7lWniAlW8nZ3U%s{J~qOG6QS-qW)@bbP};K1M?S9$0TyX`L&XOVU%YUIV}Y z^1E|mA!ACk@2S>NaprNu#{e;Z%H3wfTI($0&&j-%mv6X;lPd&NSPUp^O>0&o7XP8z zflOOU=}_j|@XRrG6N!47>4}Rq->fM*;wEq$mMvTO1nwZ?1OpvjG~RDVaoH=6ew;^1Tya*w zIBE;Bgq6;#zkh2cS6OXY-dO{|Erxl zXB9oKI7Q28Ju5q6@VvgWU|b+Yrc+=9y1HFD`{q#S`xSz6SPV!5rg@X+c;O3he=K9Y zPA@RTyIQcSVac~LMcu_IdT8XKT zZB7a_FN(p`+O|J!^y{8)lhc@BjOP{#8pW?W-2bNPIKH>%j2VY{aB`}LygIhtJ`S`9 z3_&28O&wGrx+~T~HZ%@<8jPtl=xLp!LUL}!e)>a7R*b$XfiX=;wocZ}Z_HW)(9!g? z@pj&rt4BHAG8(OrK1pEZZ=5duN?c_7-z70c+!ek3-B7B0c#+@j@4tOdbnZGc-t2Bg zk{Y;fb3Rrk!};CP8%>cuS>Vb3)1@n+zL+BiRSrRpOzuv!uKwx1s;lh2P{fpd;6ob7TFFH4C27*Zz4>=zM6aOb^yIEz= zdrScYpliE5whKf38eZgWyx=l^U#k@a@|`1^e(FU?Oe4FXQeakt{c-nSD+Fd0Qr!}) zx=ZTdD+-ftp%po1L4PRwV%1!o5bf%>|Hn4GJCZn7<^|ZvR(&a z(q8guOnUp6tQq%hUbmZKjYW-YCx0$pn@?*|JnU3Hq9Ff9M|lJjpVvYUPZQ<_k*lJ!Ov@6gC~ zM&jFvr^5a~*8mAXVKiC=TQIOyLCXV6jV+pfO@qI~AEkT>(H|jVh7_2VKbY9{c5XE$ zmj@SCF&h1$f3S;o?(B13vNIUGiJRv3@J}_g6GG!2$==92wjjn>YpOEBEYF4LN%`Fx zV>PYsh5c(vCsEq`#ySuo>3YM$`oKqU2c-@kpehqV92Tw8TD+kb2>am_uI3`WcI<6O z40R4%S=35}ATsZP!1s{{bs`eFE%Ej0Y&t7azWdTHj8GSDDj)ZSC(NmKK{* z^^(;6oT8x}rYj~!CX!s{9l!gag`9Fq(OLi!2DGLmT2qleFId08fkH>EX72t^8SIaJ z_Opr*r@FkOZOheX282>ygZx4uzD&_m4VQmU1=PQ$x>dte4+5{QDvrgg6$|2C*Q5Zo zd|7~<4&hi(j;_q797QbuO4+fg1s7tFFea7hcnad8?tuV2`?Fg)OqG}QFiL#kJw@TN1?woPeaR%zQ(gD@fn2xSEwL$mM`4_7*qeUh;T4y|`eL93r#~$ZFlN1^bw6fL zBy_^^%y-XIJ1TFby-(d^z93WYQlYvtJKZZ3#IB?dh?V`o1jC@9z7={;F{ggKe<*Q{ z&IR;t-buDaM^mmF2goOiWvps`{@NINZ^h-1{`4ExB1)kGV$=`ze5&nq&cA;k(>b|f z=Y7*t3VNUU%UmYR92f_;l4|JUY_rF&&#eTkI}8RSdh#r&vKntr|C<(?g_xMnbUyQ0 z_HP&HsQ$DTSfnfe(R4Y^K)Qf<^Z_7_)J~Vuir9$WJ?O$F@pI!`*cDJX7lx+}USV)i zF}_Ta8P5*Te%tRTNoU9~xVGvAks{z#*yWRV!j_f1>UY>va~YeryrSha>9pWG*le_V zM9)`|5DVmHLK(Qan~&rjeRM9&wHY>Kd_L+$9=6M#~};yp%zgvxu?6L&~`(7h*%!5gDyVT{adTu1E`i<=UpZ-A+Iz@a0zzoNq zg8yaB#t`(ria9+2SikJcH>&s+K?vCk%0R*ouvmb*;81>xPB~Kr+4R`UGT_!=?L4O{ z5D$4xo$+N_lD~$Utt^V`vl?4S^{_MnROvBjV*xsa7xY4c?_!%-M=Fl>TFt40+0>7| z%IsI034kw2BF8& z2GdyQPOO@>keZlrwmtsn8wBOu)uTWQcH5Qpm?6-n5!NPx54J=Rp959^zb>rrY^m!k z7+=+&wKYhYAik=DsdWpt4Zqttx}$1K!LD&TvwRxjBKUMdIkgNdbL%W+A$Y$4oB{oP z)@w(`uL>|Y9b0O=+w39M8m02A3H5}0;gSjyOi(H7fbHj@k5~$Jw0zbJ>tdM>;y+q8 zM>3n_JGB>)#7Qq@WSHO~pq4T1NP5jB`D*tNSW!U0Ng3X$L9)xM!N3TlGMFddS^;k= z95fS8Xw>1kKVAT<=_7`*GS(KTI+~i_a&3y;BhIISlIKd34(oaHm|a+(tL-F2S>7%% z<0sA$feI*NO=kBHP)hLO#^keY^wdS^Q40XMweSDUg)0tJ_D?welWui1tBrWls}LC$ z5oHASEtB#BlL7TL`KTLRcC=^f?^2humb$o(r)QE{1-|HW{%Poi62&Xrogiu97LdhV zW#H2r*%)sFFFp`ijRl7f8Tj`I#8G%cLm=M$S*GOH&`X_j6Mz47_02geescd#W>@2; z!5>7hJ>eiSOeG4)gNPdfov)5s)?KgpPAqbGCTXzUxuy*&;wTh7@5r9?tkOCC_(ORZi42 z>V;P|)3I`~M**?bliC=X25;I$0C_1%Wg1W^=6A$J zW@d9ush3(H?t}~TewLvE6_d!#+dJJ{$tv}mY^j6J)PJahxh2Mpwmv-kto8^uS*rs7 z>``W#`;Y3mE}E`JsZyvkyovSt1}p^(ajC`S4bWfa3w=@0r1t>Bgn@#6nhIWkpB&6O z1SmJ_$2)qV$FBMP?yf*;D4ZzCH9C$AJI(qVo3TH9(=aMhqWE#G&BB!E=Mb*mJI`Eb zZq}`dEKdto@qrxfflcEkTjp?A@b*@DmlC&H6lJDk$@bOunp_HuANkbESxTNsXI7Rw3AK{4Pz}J5TO^=-%VD~Tt8iTigV!yP&4xG zI3CtR0*B)5_zj>b)}#~_T3f~#AdPE+`Xe zCfKU%@rbMMLSagPAWM|QDqsrOauw^h;wdG>HrsQ7=g~XYeW+*%i7SVsp%5i!- z?gxq0^Mo|MpHhwfa4!rQrf;Sh8rD;~too-zNmBQzi?Y%K-_zsyzPb(EKy^r1|4^9? zdmjUV z@OyRKVE~cCzX~v=tXFer8(kudd=RTz19B<ec=)TjjRD)n*8S$X?b#WBF2O|B)~;8Ju5HV2eznb=%0(*_B1O zKI_vhNOgm@7H!BI%mZJGQ1C4$jwNu@%58Mz{upX`j3lg|C1Ym#Am7$9ah$v0*7c_d z(5Jcqa}^0Y${F|#)LYt40L@x4C^s3p%<;RcNi`qRn4%tIVB!#`ve%e9_e03j<@S!j z{Royt$Bb)!8sM$!TX{qTpp%otd3aOSPhn}Whmz2+9$^wY__jt9awLQ}Pn(-+%1j2| z$Dz%~ech!V6qU~cl^B*z%d=UCl4o^avd<-?SUpS}Q`8(zn=<>_#l_tV){VlB5hB zs3C0CAr|?mKMyw~L!;6L^-c!90Dj;z%Z6HLlAPvmH}A=DO?B#Bx8H#V{~heFcFfDV zxrGOg-9YP-0wjVBP^obZexLCsz58rdiTgpI&JJ7aP3Vge}Au?Hik57 z52&2FX7gK8RY7?VsLZf717LcfZZQ7$=oF|JuiG6gh_c4qPQ9$N@*UJ$L79^9z&uxP z4BB_5H2;4G7&TTrK+Z@|?*ZN?^E9soY`pE2D9gVB>(sv3P^`>x+m@g#{Ya_!8rX|z zIBU)qmOoL;LnrRH)Dg*)+kIWt;ox6c0z3wobS}+*dTS~LQ()VzcN>MZtylp;6VpLj zXiD+;YC6U?=Z+SlqeN&G$&RgTI-v57`{{dxQW0 literal 0 HcmV?d00001 diff --git a/plugins/feature/radiosonde/radiosonde.cpp b/plugins/feature/radiosonde/radiosonde.cpp new file mode 100644 index 000000000..b16f9ecb0 --- /dev/null +++ b/plugins/feature/radiosonde/radiosonde.cpp @@ -0,0 +1,327 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "SWGFeatureSettings.h" +#include "SWGFeatureReport.h" +#include "SWGFeatureActions.h" +#include "SWGDeviceState.h" + +#include "dsp/dspengine.h" +#include "device/deviceset.h" +#include "channel/channelapi.h" +#include "feature/featureset.h" +#include "settings/serializable.h" +#include "maincore.h" + +#include "radiosonde.h" + +MESSAGE_CLASS_DEFINITION(Radiosonde::MsgConfigureRadiosonde, Message) + +const char* const Radiosonde::m_featureIdURI = "sdrangel.feature.radiosonde"; +const char* const Radiosonde::m_featureId = "Radiosonde"; + +Radiosonde::Radiosonde(WebAPIAdapterInterface *webAPIAdapterInterface) : + Feature(m_featureIdURI, webAPIAdapterInterface) +{ + qDebug("Radiosonde::Radiosonde: webAPIAdapterInterface: %p", webAPIAdapterInterface); + setObjectName(m_featureId); + m_state = StIdle; + m_errorMessage = "Radiosonde error"; + connect(&m_updatePipesTimer, SIGNAL(timeout()), this, SLOT(updatePipes())); + m_updatePipesTimer.start(1000); + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); +} + +Radiosonde::~Radiosonde() +{ + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; +} + +void Radiosonde::start() +{ + qDebug("Radiosonde::start"); + m_state = StRunning; +} + +void Radiosonde::stop() +{ + qDebug("Radiosonde::stop"); + m_state = StIdle; +} + +bool Radiosonde::handleMessage(const Message& cmd) +{ + if (MsgConfigureRadiosonde::match(cmd)) + { + MsgConfigureRadiosonde& cfg = (MsgConfigureRadiosonde&) cmd; + qDebug() << "Radiosonde::handleMessage: MsgConfigureRadiosonde"; + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (MainCore::MsgPacket::match(cmd)) + { + MainCore::MsgPacket& report = (MainCore::MsgPacket&) cmd; + if (getMessageQueueToGUI()) + { + MainCore::MsgPacket *copy = new MainCore::MsgPacket(report); + getMessageQueueToGUI()->push(copy); + } + return true; + } + else + { + return false; + } +} + +void Radiosonde::updatePipes() +{ + QList availablePipes = updateAvailablePipeSources("radiosonde", RadiosondeSettings::m_pipeTypes, RadiosondeSettings::m_pipeURIs, this); + + if (availablePipes != m_availablePipes) { + m_availablePipes = availablePipes; + } +} + +QByteArray Radiosonde::serialize() const +{ + return m_settings.serialize(); +} + +bool Radiosonde::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + MsgConfigureRadiosonde *msg = MsgConfigureRadiosonde::create(m_settings, true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureRadiosonde *msg = MsgConfigureRadiosonde::create(m_settings, true); + m_inputMessageQueue.push(msg); + return false; + } +} + +void Radiosonde::applySettings(const RadiosondeSettings& settings, bool force) +{ + qDebug() << "Radiosonde::applySettings:" + << " m_title: " << settings.m_title + << " m_rgbColor: " << settings.m_rgbColor + << " m_useReverseAPI: " << settings.m_useReverseAPI + << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress + << " m_reverseAPIPort: " << settings.m_reverseAPIPort + << " m_reverseAPIFeatureSetIndex: " << settings.m_reverseAPIFeatureSetIndex + << " m_reverseAPIFeatureIndex: " << settings.m_reverseAPIFeatureIndex + << " force: " << force; + + QList reverseAPIKeys; + + if ((m_settings.m_title != settings.m_title) || force) { + reverseAPIKeys.append("title"); + } + if ((m_settings.m_rgbColor != settings.m_rgbColor) || force) { + reverseAPIKeys.append("rgbColor"); + } + + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIFeatureSetIndex != settings.m_reverseAPIFeatureSetIndex) || + (m_settings.m_reverseAPIFeatureIndex != settings.m_reverseAPIFeatureIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + + m_settings = settings; +} + +int Radiosonde::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadiosondeSettings(new SWGSDRangel::SWGRadiosondeSettings()); + response.getRadiosondeSettings()->init(); + webapiFormatFeatureSettings(response, m_settings); + return 200; +} + +int Radiosonde::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + RadiosondeSettings settings = m_settings; + webapiUpdateFeatureSettings(settings, featureSettingsKeys, response); + + MsgConfigureRadiosonde *msg = MsgConfigureRadiosonde::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureRadiosonde *msgToGUI = MsgConfigureRadiosonde::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatFeatureSettings(response, settings); + + return 200; +} + +void Radiosonde::webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const RadiosondeSettings& settings) +{ + if (response.getRadiosondeSettings()->getTitle()) { + *response.getRadiosondeSettings()->getTitle() = settings.m_title; + } else { + response.getRadiosondeSettings()->setTitle(new QString(settings.m_title)); + } + + response.getRadiosondeSettings()->setRgbColor(settings.m_rgbColor); + response.getRadiosondeSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getRadiosondeSettings()->getReverseApiAddress()) { + *response.getRadiosondeSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getRadiosondeSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getRadiosondeSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getRadiosondeSettings()->setReverseApiFeatureSetIndex(settings.m_reverseAPIFeatureSetIndex); + response.getRadiosondeSettings()->setReverseApiFeatureIndex(settings.m_reverseAPIFeatureIndex); + + if (settings.m_rollupState) + { + if (response.getRadiosondeSettings()->getRollupState()) + { + settings.m_rollupState->formatTo(response.getRadiosondeSettings()->getRollupState()); + } + else + { + SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState(); + settings.m_rollupState->formatTo(swgRollupState); + response.getRadiosondeSettings()->setRollupState(swgRollupState); + } + } +} + +void Radiosonde::webapiUpdateFeatureSettings( + RadiosondeSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response) +{ + if (featureSettingsKeys.contains("title")) { + settings.m_title = *response.getRadiosondeSettings()->getTitle(); + } + if (featureSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getRadiosondeSettings()->getRgbColor(); + } + if (featureSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getRadiosondeSettings()->getUseReverseApi() != 0; + } + if (featureSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getRadiosondeSettings()->getReverseApiAddress(); + } + if (featureSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getRadiosondeSettings()->getReverseApiPort(); + } + if (featureSettingsKeys.contains("reverseAPIFeatureSetIndex")) { + settings.m_reverseAPIFeatureSetIndex = response.getRadiosondeSettings()->getReverseApiFeatureSetIndex(); + } + if (featureSettingsKeys.contains("reverseAPIFeatureIndex")) { + settings.m_reverseAPIFeatureIndex = response.getRadiosondeSettings()->getReverseApiFeatureIndex(); + } + if (settings.m_rollupState && featureSettingsKeys.contains("rollupState")) { + settings.m_rollupState->updateFrom(featureSettingsKeys, response.getRadiosondeSettings()->getRollupState()); + } +} + +void Radiosonde::webapiReverseSendSettings(QList& featureSettingsKeys, const RadiosondeSettings& settings, bool force) +{ + SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = new SWGSDRangel::SWGFeatureSettings(); + // swgFeatureSettings->setOriginatorFeatureIndex(getIndexInDeviceSet()); + // swgFeatureSettings->setOriginatorFeatureSetIndex(getDeviceSetIndex()); + swgFeatureSettings->setFeatureType(new QString("Radiosonde")); + swgFeatureSettings->setRadiosondeSettings(new SWGSDRangel::SWGRadiosondeSettings()); + SWGSDRangel::SWGRadiosondeSettings *swgRadiosondeSettings = swgFeatureSettings->getRadiosondeSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (featureSettingsKeys.contains("title") || force) { + swgRadiosondeSettings->setTitle(new QString(settings.m_title)); + } + if (featureSettingsKeys.contains("rgbColor") || force) { + swgRadiosondeSettings->setRgbColor(settings.m_rgbColor); + } + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIFeatureSetIndex) + .arg(settings.m_reverseAPIFeatureIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgFeatureSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgFeatureSettings; +} + +void Radiosonde::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "Radiosonde::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("Radiosonde::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} diff --git a/plugins/feature/radiosonde/radiosonde.h b/plugins/feature/radiosonde/radiosonde.h new file mode 100644 index 000000000..efbb344a6 --- /dev/null +++ b/plugins/feature/radiosonde/radiosonde.h @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_RADIOSONDE_H_ +#define INCLUDE_FEATURE_RADIOSONDE_H_ + +#include +#include +#include + +#include "feature/feature.h" +#include "util/message.h" + +#include "radiosondesettings.h" + +class WebAPIAdapterInterface; +class QNetworkAccessManager; +class QNetworkReply; + +namespace SWGSDRangel { + class SWGDeviceState; +} + +class Radiosonde : public Feature +{ + Q_OBJECT +public: + class MsgConfigureRadiosonde : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const RadiosondeSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureRadiosonde* create(const RadiosondeSettings& settings, bool force) { + return new MsgConfigureRadiosonde(settings, force); + } + + private: + RadiosondeSettings m_settings; + bool m_force; + + MsgConfigureRadiosonde(const RadiosondeSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + Radiosonde(WebAPIAdapterInterface *webAPIAdapterInterface); + virtual ~Radiosonde(); + virtual void destroy() { delete this; } + virtual bool handleMessage(const Message& cmd); + + virtual void getIdentifier(QString& id) const { id = objectName(); } + virtual void getTitle(QString& title) const { title = m_settings.m_title; } + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + static void webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const RadiosondeSettings& settings); + + static void webapiUpdateFeatureSettings( + RadiosondeSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response); + + static const char* const m_featureIdURI; + static const char* const m_featureId; + +private: + RadiosondeSettings m_settings; + QList m_availablePipes; + QTimer m_updatePipesTimer; + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + void start(); + void stop(); + void applySettings(const RadiosondeSettings& settings, bool force = false); + void webapiReverseSendSettings(QList& featureSettingsKeys, const RadiosondeSettings& settings, bool force); + +private slots: + void updatePipes(); + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // INCLUDE_FEATURE_RADIOSONDE_H_ diff --git a/plugins/feature/radiosonde/radiosonde.qrc b/plugins/feature/radiosonde/radiosonde.qrc new file mode 100644 index 000000000..047083d71 --- /dev/null +++ b/plugins/feature/radiosonde/radiosonde.qrc @@ -0,0 +1,6 @@ + + + map/ballon.png + map/parachute.png + + diff --git a/plugins/feature/radiosonde/radiosondegui.cpp b/plugins/feature/radiosonde/radiosondegui.cpp new file mode 100644 index 000000000..1f37fbd91 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondegui.cpp @@ -0,0 +1,857 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +#include "feature/featureuiset.h" +#include "feature/featurewebapiutils.h" +#include "gui/basicfeaturesettingsdialog.h" +#include "gui/datetimedelegate.h" +#include "gui/decimaldelegate.h" +#include "mainwindow.h" +#include "device/deviceuiset.h" + +#include "ui_radiosondegui.h" +#include "radiosonde.h" +#include "radiosondegui.h" + +#include "SWGMapItem.h" + +RadiosondeGUI* RadiosondeGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature) +{ + RadiosondeGUI* gui = new RadiosondeGUI(pluginAPI, featureUISet, feature); + return gui; +} + +void RadiosondeGUI::destroy() +{ + delete this; +} + +void RadiosondeGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); +} + +QByteArray RadiosondeGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool RadiosondeGUI::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + displaySettings(); + applySettings(true); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +bool RadiosondeGUI::handleMessage(const Message& message) +{ + if (Radiosonde::MsgConfigureRadiosonde::match(message)) + { + qDebug("RadiosondeGUI::handleMessage: Radiosonde::MsgConfigureRadiosonde"); + const Radiosonde::MsgConfigureRadiosonde& cfg = (Radiosonde::MsgConfigureRadiosonde&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + + return true; + } + else if (MainCore::MsgPacket::match(message)) + { + MainCore::MsgPacket& report = (MainCore::MsgPacket&) message; + + // Decode the message + RS41Frame *frame = RS41Frame::decode(report.getPacket()); + // Update table + updateRadiosondes(frame, report.getDateTime()); + } + + return false; +} + +void RadiosondeGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop())) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +void RadiosondeGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + (void) widget; + (void) rollDown; + + saveState(m_rollupState); + applySettings(); +} + +RadiosondeGUI::RadiosondeGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) : + FeatureGUI(parent), + ui(new Ui::RadiosondeGUI), + m_pluginAPI(pluginAPI), + m_featureUISet(featureUISet), + m_doApplySettings(true), + m_lastFeatureState(0) +{ + ui->setupUi(this); + m_helpURL = "plugins/feature/radiosonde/readme.md"; + setAttribute(Qt::WA_DeleteOnClose, true); + setChannelWidget(false); + connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + m_radiosonde = reinterpret_cast(feature); + m_radiosonde->setMessageQueueToGUI(&m_inputMessageQueue); + + m_featureUISet->addRollupWidget(this); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + + // Intialise chart + ui->chart->setRenderHint(QPainter::Antialiasing); + + // Resize the table using dummy data + resizeTable(); + // Allow user to reorder columns + ui->radiosondes->horizontalHeader()->setSectionsMovable(true); + // Allow user to sort table by clicking on headers + ui->radiosondes->setSortingEnabled(true); + // Add context menu to allow hiding/showing of columns + radiosondesMenu = new QMenu(ui->radiosondes); + for (int i = 0; i < ui->radiosondes->horizontalHeader()->count(); i++) + { + QString text = ui->radiosondes->horizontalHeaderItem(i)->text(); + radiosondesMenu->addAction(createCheckableItem(text, i, true, SLOT(radiosondesColumnSelectMenuChecked()))); + } + ui->radiosondes->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->radiosondes->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(radiosondesColumnSelectMenu(QPoint))); + // Get signals when columns change + connect(ui->radiosondes->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(radiosondes_sectionMoved(int, int, int))); + connect(ui->radiosondes->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(radiosondes_sectionResized(int, int, int))); + // Context menu + ui->radiosondes->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->radiosondes, SIGNAL(customContextMenuRequested(QPoint)), SLOT(radiosondes_customContextMenuRequested(QPoint))); + + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_LATITUDE, new DecimalDelegate(5)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_LONGITUDE, new DecimalDelegate(5)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_ALTITUDE, new DecimalDelegate(1)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_SPEED, new DecimalDelegate(1)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_VERTICAL_RATE, new DecimalDelegate(1)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_HEADING, new DecimalDelegate(1)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_ALT_MAX, new DecimalDelegate(1)); + ui->radiosondes->setItemDelegateForColumn(RADIOSONDE_COL_LAST_UPDATE, new DateTimeDelegate()); + + m_settings.setRollupState(&m_rollupState); + + displaySettings(); + applySettings(true); + + plotChart(); +} + +RadiosondeGUI::~RadiosondeGUI() +{ + qDeleteAll(m_radiosondes); + delete ui; +} + +void RadiosondeGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void RadiosondeGUI::displaySettings() +{ + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_settings.m_title); + blockApplySettings(true); + + // Order and size columns + QHeaderView *header = ui->radiosondes->horizontalHeader(); + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) + { + bool hidden = m_settings.m_radiosondesColumnSizes[i] == 0; + header->setSectionHidden(i, hidden); + radiosondesMenu->actions().at(i)->setChecked(!hidden); + if (m_settings.m_radiosondesColumnSizes[i] > 0) { + ui->radiosondes->setColumnWidth(i, m_settings.m_radiosondesColumnSizes[i]); + } + header->moveSection(header->visualIndex(i), m_settings.m_radiosondesColumnIndexes[i]); + } + + ui->y1->setCurrentIndex((int)m_settings.m_y1); + ui->y2->setCurrentIndex((int)m_settings.m_y2); + + restoreState(m_rollupState); + blockApplySettings(false); + arrangeRollups(); +} + +void RadiosondeGUI::leaveEvent(QEvent*) +{ +} + +void RadiosondeGUI::enterEvent(QEvent*) +{ +} + +void RadiosondeGUI::onMenuDialogCalled(const QPoint &p) +{ + if (m_contextMenuType == ContextMenuChannelSettings) + { + BasicFeatureSettingsDialog dialog(this); + dialog.setTitle(m_settings.m_title); + dialog.setColor(m_settings.m_rgbColor); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIFeatureSetIndex(m_settings.m_reverseAPIFeatureSetIndex); + dialog.setReverseAPIFeatureIndex(m_settings.m_reverseAPIFeatureIndex); + + dialog.move(p); + dialog.exec(); + + m_settings.m_rgbColor = dialog.getColor().rgb(); + m_settings.m_title = dialog.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIFeatureSetIndex = dialog.getReverseAPIFeatureSetIndex(); + m_settings.m_reverseAPIFeatureIndex = dialog.getReverseAPIFeatureIndex(); + + setWindowTitle(m_settings.m_title); + setTitleColor(m_settings.m_rgbColor); + + applySettings(); + } + + resetContextMenuType(); +} + +void RadiosondeGUI::applySettings(bool force) +{ + if (m_doApplySettings) + { + Radiosonde::MsgConfigureRadiosonde* message = Radiosonde::MsgConfigureRadiosonde::create(m_settings, force); + m_radiosonde->getInputMessageQueue()->push(message); + } +} + +void RadiosondeGUI::resizeTable() +{ + // Fill table with a row of dummy data that will size the columns nicely + int row = ui->radiosondes->rowCount(); + ui->radiosondes->setRowCount(row + 1); + ui->radiosondes->setItem(row, RADIOSONDE_COL_SERIAL, new QTableWidgetItem("123456789")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_TYPE, new QTableWidgetItem("RS41-SGP")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LATITUDE, new QTableWidgetItem("90.000000-")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LONGITUDE, new QTableWidgetItem("180.00000-")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_ALTITUDE, new QTableWidgetItem("10000")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_SPEED, new QTableWidgetItem("120")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_VERTICAL_RATE, new QTableWidgetItem("120")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_HEADING, new QTableWidgetItem("360")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_STATUS, new QTableWidgetItem("Ascent")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_PRESSURE, new QTableWidgetItem("1234")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_TEMPERATURE, new QTableWidgetItem("-50.0")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_HUMIDITY, new QTableWidgetItem("100.0")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_ALT_MAX, new QTableWidgetItem("10000")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_FREQUENCY, new QTableWidgetItem("400.000")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_BURSTKILL_STATUS, new QTableWidgetItem("0")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_BURSTKILL_TIMER, new QTableWidgetItem("00:00")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LAST_UPDATE, new QTableWidgetItem("2022/12/12 12:00:00")); + ui->radiosondes->setItem(row, RADIOSONDE_COL_MESSAGES, new QTableWidgetItem("1000")); + ui->radiosondes->resizeColumnsToContents(); + ui->radiosondes->removeRow(row); +} + +// Columns in table reordered +void RadiosondeGUI::radiosondes_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) +{ + (void) oldVisualIndex; + + m_settings.m_radiosondesColumnIndexes[logicalIndex] = newVisualIndex; +} + +// Column in table resized (when hidden size is 0) +void RadiosondeGUI::radiosondes_sectionResized(int logicalIndex, int oldSize, int newSize) +{ + (void) oldSize; + + m_settings.m_radiosondesColumnSizes[logicalIndex] = newSize; +} + +// Right click in table header - show column select menu +void RadiosondeGUI::radiosondesColumnSelectMenu(QPoint pos) +{ + radiosondesMenu->popup(ui->radiosondes->horizontalHeader()->viewport()->mapToGlobal(pos)); +} + +// Hide/show column when menu selected +void RadiosondeGUI::radiosondesColumnSelectMenuChecked(bool checked) +{ + (void) checked; + + QAction* action = qobject_cast(sender()); + if (action != nullptr) + { + int idx = action->data().toInt(nullptr); + ui->radiosondes->setColumnHidden(idx, !action->isChecked()); + } +} + +// Create column select menu item +QAction *RadiosondeGUI::createCheckableItem(QString &text, int idx, bool checked, const char *slot) +{ + QAction *action = new QAction(text, this); + action->setCheckable(true); + action->setChecked(checked); + action->setData(QVariant(idx)); + connect(action, SIGNAL(triggered()), this, slot); + return action; +} + +// Send to Map feature +void RadiosondeGUI::sendToMap(const QString &name, const QString &label, + const QString &image, const QString &text, + const QString &model, float labelOffset, + float latitude, float longitude, float altitude, QDateTime positionDateTime, + float heading + ) +{ + MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipes(); + QList *mapMessageQueues = messagePipes.getMessageQueues(m_radiosonde, "mapitems"); + if (mapMessageQueues) + { + QList::iterator it = mapMessageQueues->begin(); + + for (; it != mapMessageQueues->end(); ++it) + { + SWGSDRangel::SWGMapItem *swgMapItem = new SWGSDRangel::SWGMapItem(); + swgMapItem->setName(new QString(name)); + swgMapItem->setLatitude(latitude); + swgMapItem->setLongitude(longitude); + swgMapItem->setAltitude(altitude); + swgMapItem->setAltitudeReference(0); // ABSOLUTE + + if (positionDateTime.isValid()) { + swgMapItem->setPositionDateTime(new QString(positionDateTime.toString(Qt::ISODateWithMs))); + } + + swgMapItem->setImageRotation(heading); + swgMapItem->setText(new QString(text)); + + if (image.isEmpty()) { + swgMapItem->setImage(new QString("")); + } else { + swgMapItem->setImage(new QString(QString("qrc:///radiosonde/map/%1").arg(image))); + } + swgMapItem->setModel(new QString(model)); + swgMapItem->setModelAltitudeOffset(0.0f); + swgMapItem->setLabel(new QString(label)); + swgMapItem->setLabelAltitudeOffset(labelOffset); + swgMapItem->setFixedPosition(false); + swgMapItem->setOrientation(1); + swgMapItem->setHeading(heading); + swgMapItem->setPitch(0.0); + swgMapItem->setRoll(0.0); + + MainCore::MsgMapItem *msg = MainCore::MsgMapItem::create(m_radiosonde, swgMapItem); + (*it)->push(msg); + } + } +} + +// Update table with received message +void RadiosondeGUI::updateRadiosondes(RS41Frame *message, QDateTime dateTime) +{ + QTableWidgetItem *serialItem; + QTableWidgetItem *typeItem; + QTableWidgetItem *latitudeItem; + QTableWidgetItem *longitudeItem; + QTableWidgetItem *alitutudeItem; + QTableWidgetItem *speedItem; + QTableWidgetItem *verticalRateItem; + QTableWidgetItem *headingItem; + QTableWidgetItem *statusItem; + QTableWidgetItem *pressureItem; + QTableWidgetItem *temperatureItem; + QTableWidgetItem *humidityItem; + QTableWidgetItem *altMaxItem; + QTableWidgetItem *frequencyItem; + QTableWidgetItem *burstKillStatusItem; + QTableWidgetItem *burstKillTimerItem; + QTableWidgetItem *lastUpdateItem; + QTableWidgetItem *messagesItem; + + if (!message->m_statusValid) + { + // Nothing to display if no serial number + return; + } + + RadiosondeData *radiosonde; + + // See if radiosonde is already in table + QString messageSerial = message->m_serial; + bool found = false; + for (int row = 0; row < ui->radiosondes->rowCount(); row++) + { + QString itemSerial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + if (messageSerial == itemSerial) + { + // Update existing item + serialItem = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL); + typeItem = ui->radiosondes->item(row, RADIOSONDE_COL_TYPE); + latitudeItem = ui->radiosondes->item(row, RADIOSONDE_COL_LATITUDE); + longitudeItem = ui->radiosondes->item(row, RADIOSONDE_COL_LONGITUDE); + alitutudeItem = ui->radiosondes->item(row, RADIOSONDE_COL_ALTITUDE); + speedItem = ui->radiosondes->item(row, RADIOSONDE_COL_SPEED); + verticalRateItem = ui->radiosondes->item(row, RADIOSONDE_COL_VERTICAL_RATE); + headingItem = ui->radiosondes->item(row, RADIOSONDE_COL_HEADING); + statusItem = ui->radiosondes->item(row, RADIOSONDE_COL_STATUS); + pressureItem = ui->radiosondes->item(row, RADIOSONDE_COL_PRESSURE); + temperatureItem = ui->radiosondes->item(row, RADIOSONDE_COL_TEMPERATURE); + humidityItem = ui->radiosondes->item(row, RADIOSONDE_COL_HUMIDITY); + altMaxItem = ui->radiosondes->item(row, RADIOSONDE_COL_ALT_MAX); + frequencyItem = ui->radiosondes->item(row, RADIOSONDE_COL_FREQUENCY); + burstKillStatusItem = ui->radiosondes->item(row, RADIOSONDE_COL_BURSTKILL_STATUS); + burstKillTimerItem = ui->radiosondes->item(row, RADIOSONDE_COL_BURSTKILL_TIMER); + lastUpdateItem = ui->radiosondes->item(row, RADIOSONDE_COL_LAST_UPDATE); + messagesItem = ui->radiosondes->item(row, RADIOSONDE_COL_MESSAGES); + radiosonde = m_radiosondes.value(messageSerial); + found = true; + break; + } + } + if (!found) + { + // Add new radiosonde + ui->radiosondes->setSortingEnabled(false); + int row = ui->radiosondes->rowCount(); + ui->radiosondes->setRowCount(row + 1); + + serialItem = new QTableWidgetItem(); + typeItem = new QTableWidgetItem(); + latitudeItem = new QTableWidgetItem(); + longitudeItem = new QTableWidgetItem(); + alitutudeItem = new QTableWidgetItem(); + speedItem = new QTableWidgetItem(); + verticalRateItem = new QTableWidgetItem(); + headingItem = new QTableWidgetItem(); + statusItem = new QTableWidgetItem(); + temperatureItem = new QTableWidgetItem(); + humidityItem = new QTableWidgetItem(); + pressureItem = new QTableWidgetItem(); + altMaxItem = new QTableWidgetItem(); + frequencyItem = new QTableWidgetItem(); + burstKillStatusItem = new QTableWidgetItem(); + burstKillTimerItem = new QTableWidgetItem(); + lastUpdateItem = new QTableWidgetItem(); + messagesItem = new QTableWidgetItem(); + ui->radiosondes->setItem(row, RADIOSONDE_COL_SERIAL, serialItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_TYPE, typeItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LATITUDE, latitudeItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LONGITUDE, longitudeItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_ALTITUDE, alitutudeItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_SPEED, speedItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_VERTICAL_RATE, verticalRateItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_HEADING, headingItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_STATUS, statusItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_PRESSURE, pressureItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_TEMPERATURE, temperatureItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_HUMIDITY, humidityItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_ALT_MAX, altMaxItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_FREQUENCY, frequencyItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_BURSTKILL_STATUS, burstKillStatusItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_BURSTKILL_TIMER, burstKillTimerItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_LAST_UPDATE, lastUpdateItem); + ui->radiosondes->setItem(row, RADIOSONDE_COL_MESSAGES, messagesItem); + messagesItem->setData(Qt::DisplayRole, 0); + + radiosonde = new RadiosondeData(); + m_radiosondes.insert(messageSerial, radiosonde); + } + + serialItem->setText(message->m_serial); + lastUpdateItem->setData(Qt::DisplayRole, dateTime); + messagesItem->setData(Qt::DisplayRole, messagesItem->data(Qt::DisplayRole).toInt() + 1); + + if (message->m_posValid) + { + latitudeItem->setData(Qt::DisplayRole, message->m_latitude); + longitudeItem->setData(Qt::DisplayRole, message->m_longitude); + alitutudeItem->setData(Qt::DisplayRole, message->m_height); + float altMax = altMaxItem->data(Qt::DisplayRole).toFloat(); + if (message->m_height > altMax) { + altMaxItem->setData(Qt::DisplayRole, message->m_height); + } + speedItem->setData(Qt::DisplayRole, Units::kmpsToKPH(message->m_speed/1000.0)); + verticalRateItem->setData(Qt::DisplayRole, message->m_verticalRate); + headingItem->setData(Qt::DisplayRole, message->m_heading); + } + statusItem->setText(message->m_flightPhase); + + radiosonde->m_subframe.update(message); + + if (message->m_measValid) + { + pressureItem->setData(Qt::DisplayRole, message->getPressureString(&radiosonde->m_subframe)); + temperatureItem->setData(Qt::DisplayRole, message->getTemperatureString(&radiosonde->m_subframe)); + humidityItem->setData(Qt::DisplayRole, message->getHumidityString(&radiosonde->m_subframe)); + } + + if (message->m_measValid && message->m_posValid) { + radiosonde->addMessage(dateTime, message); + } + + typeItem->setText(radiosonde->m_subframe.getType()); + frequencyItem->setText(radiosonde->m_subframe.getFrequencyMHz()); + burstKillStatusItem->setText(radiosonde->m_subframe.getBurstKillStatus()); + burstKillTimerItem->setText(radiosonde->m_subframe.getBurstKillTimer()); + + ui->radiosondes->setSortingEnabled(true); + + if (message->m_posValid) + { + // Text to display in info box + QStringList text; + QString type = typeItem->text(); + QVariant altitudeV = alitutudeItem->data(Qt::DisplayRole); + QVariant speedV = speedItem->data(Qt::DisplayRole); + QVariant verticalRateV = verticalRateItem->data(Qt::DisplayRole); + QVariant headingV = headingItem->data(Qt::DisplayRole); + QString pressure = pressureItem->text(); + QString temperature = temperatureItem->text(); + QString humidity = humidityItem->text(); + QString status = statusItem->text(); + QString frequency = frequencyItem->text(); + text.append(QString("Serial: %1").arg(serialItem->text())); + if (!type.isEmpty()) { + text.append(QString("Type: %1").arg(type)); + } + if (!altitudeV.isNull()) { + text.append(QString("Altitude: %1m").arg(altitudeV.toDouble(), 0, 'f', 1)); + } + if (!speedV.isNull()) { + text.append(QString("Speed: %1km/h").arg(speedV.toDouble(), 0, 'f', 1)); + } + if (!verticalRateV.isNull()) { + text.append(QString("Vertical rate: %1m/s").arg(verticalRateV.toDouble(), 0, 'f', 1)); + } + if (!headingV.isNull()) { + text.append(QString("Heading: %1%2").arg(headingV.toDouble(), 0, 'f', 1).arg(QChar(0xb0))); + } + if (!status.isEmpty()) { + text.append(QString("Status: %1").arg(status)); + } + if (!pressure.isEmpty()) { + text.append(QString("Pressure: %1hPa").arg(pressure)); + } + if (!temperature.isEmpty()) { + text.append(QString("Temperature: %1C").arg(temperature)); + } + if (!humidity.isEmpty()) { + text.append(QString("Humidity: %1%").arg(humidity)); + } + if (!frequency.isEmpty()) { + text.append(QString("Frequency: %1MHz").arg(frequency)); + } + + QString image = message->m_flightPhase == "Descent" ? "parachute.png" : "ballon.png"; + QString model = message->m_flightPhase == "Descent" ? "radiosondeparachute.glb" : "radiosondeballon.glb"; + // Send to map feature + sendToMap(serialItem->text(), serialItem->text(), + image, text.join("
    "), + model, 0.0, + message->m_latitude, message->m_longitude, message->m_height, dateTime, + 0.0f); + } + + // If this is the first row in the table, select it, so that the chart is plotted + QList selectedItems = ui->radiosondes->selectedItems(); + if (selectedItems.size() == 0) + { + QTableWidgetSelectionRange r(0, 0, 0, RADIOSONDES_COLUMNS); + ui->radiosondes->setRangeSelected(r, true); + } + + plotChart(); +} + +void RadiosondeGUI::on_radiosondes_itemSelectionChanged() +{ + plotChart(); +} + +void RadiosondeGUI::on_radiosondes_cellDoubleClicked(int row, int column) +{ + if (column == RADIOSONDE_COL_SERIAL) + { + // Get serial of Radiosonde in row double clicked + QString serial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + // Search for MMSI on www.radiosondefinder.com + QDesktopServices::openUrl(QUrl(QString("https://sondehub.org/?f=%1#!mt=Mapnik&f=%1&q=%1").arg(serial))); + } + else if ((column == RADIOSONDE_COL_LATITUDE) || (column == RADIOSONDE_COL_LONGITUDE)) + { + // Get serial of Radiosonde in row double clicked + QString serial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + // Find serial on Map + FeatureWebAPIUtils::mapFind(serial); + } +} + +// Table cells context menu +void RadiosondeGUI::radiosondes_customContextMenuRequested(QPoint pos) +{ + QTableWidgetItem *item = ui->radiosondes->itemAt(pos); + if (item) + { + int row = item->row(); + QString serial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + QVariant latitudeV = ui->radiosondes->item(row, RADIOSONDE_COL_LATITUDE)->data(Qt::DisplayRole); + QVariant longitudeV = ui->radiosondes->item(row, RADIOSONDE_COL_LONGITUDE)->data(Qt::DisplayRole); + + QMenu* tableContextMenu = new QMenu(ui->radiosondes); + connect(tableContextMenu, &QMenu::aboutToHide, tableContextMenu, &QMenu::deleteLater); + + // Copy current cell + QAction* copyAction = new QAction("Copy", tableContextMenu); + const QString text = item->text(); + connect(copyAction, &QAction::triggered, this, [text]()->void { + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(text); + }); + tableContextMenu->addAction(copyAction); + tableContextMenu->addSeparator(); + + // View radiosonde on various websites + QAction* mmsiRadiosondeHubAction = new QAction(QString("View %1 on sondehub.net...").arg(serial), tableContextMenu); + connect(mmsiRadiosondeHubAction, &QAction::triggered, this, [serial]()->void { + QDesktopServices::openUrl(QUrl(QString("https://sondehub.org/?f=%1#!mt=Mapnik&f=%1&q=%1").arg(serial))); + }); + tableContextMenu->addAction(mmsiRadiosondeHubAction); + + // Find on Map + tableContextMenu->addSeparator(); + QAction* findMapFeatureAction = new QAction(QString("Find %1 on map").arg(serial), tableContextMenu); + connect(findMapFeatureAction, &QAction::triggered, this, [serial]()->void { + FeatureWebAPIUtils::mapFind(serial); + }); + tableContextMenu->addAction(findMapFeatureAction); + + tableContextMenu->popup(ui->radiosondes->viewport()->mapToGlobal(pos)); + } +} + +void RadiosondeGUI::on_y1_currentIndexChanged(int index) +{ + m_settings.m_y1 = (RadiosondeSettings::ChartData)index; + applySettings(); + plotChart(); +} + +void RadiosondeGUI::on_y2_currentIndexChanged(int index) +{ + m_settings.m_y2 = (RadiosondeSettings::ChartData)index; + applySettings(); + plotChart(); +} + +float RadiosondeGUI::getData(RadiosondeSettings::ChartData dataType, RadiosondeData *radiosonde, RS41Frame *message) +{ + float data; + switch (dataType) + { + case RadiosondeSettings::ALTITUDE: + data = message->m_height; + break; + case RadiosondeSettings::TEMPERATURE: + data = message->getTemperatureFloat(&radiosonde->m_subframe); + break; + case RadiosondeSettings::HUMIDITY: + data = message->getHumidityFloat(&radiosonde->m_subframe); + break; + case RadiosondeSettings::PRESSURE: + data = 0.0f; + break; + case RadiosondeSettings::SPEED: + data = Units::kmpsToKPH(message->m_speed/1000.0); + break; + case RadiosondeSettings::VERTICAL_RATE: + data = message->m_verticalRate; + break; + case RadiosondeSettings::HEADING: + data = message->m_speed; + break; + case RadiosondeSettings::BATTERY_VOLTAGE: + data = message->m_batteryVoltage; + break; + default: + data = 0.0f; + break; + } + return data; +} + +static QString getAxisTitle(RadiosondeSettings::ChartData dataType) +{ + switch (dataType) + { + case RadiosondeSettings::ALTITUDE: + return "Altitude (m)"; + break; + case RadiosondeSettings::TEMPERATURE: + return QString("Temperature (%1C)").arg(QChar(0xb0)); + break; + case RadiosondeSettings::HUMIDITY: + return "Relative humidty (%)"; + break; + case RadiosondeSettings::PRESSURE: + return "Pressure (hPa)"; + break; + case RadiosondeSettings::SPEED: + return "Speed (km/h)"; + break; + case RadiosondeSettings::VERTICAL_RATE: + return "Vertical rate (m/s)"; + break; + case RadiosondeSettings::HEADING: + return QString("Heading (%1)").arg(QChar(0xb0)); + break; + case RadiosondeSettings::BATTERY_VOLTAGE: + return "Battery Voltage (V)"; + break; + default: + return ""; + } +} + +void RadiosondeGUI::plotChart() +{ + QChart *oldChart = ui->chart->chart(); + QChart *m_chart; + + m_chart = new QChart(); + m_chart->layout()->setContentsMargins(0, 0, 0, 0); + m_chart->setMargins(QMargins(1, 1, 1, 1)); + m_chart->setTheme(QChart::ChartThemeDark); + + // Get selected radiosonde + QList selectedItems = ui->radiosondes->selectedItems(); + if (selectedItems.size() >= 1) + { + int row = selectedItems[0]->row(); + QString serial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + RadiosondeData *radiosonde = m_radiosondes.value(serial); + if (radiosonde) + { + // Plot selected data + QDateTimeAxis *m_chartXAxis; + QValueAxis *m_chartY1Axis; + QValueAxis *m_chartY2Axis; + + m_chartXAxis = new QDateTimeAxis(); + if (m_settings.m_y1 != RadiosondeSettings::NONE) { + m_chartY1Axis = new QValueAxis(); + } + if (m_settings.m_y2 != RadiosondeSettings::NONE) { + m_chartY2Axis = new QValueAxis(); + } + + m_chart->legend()->hide(); + m_chart->addAxis(m_chartXAxis, Qt::AlignBottom); + + QLineSeries *y1Series = new QLineSeries(); + QLineSeries *y2Series = new QLineSeries(); + + int idx = 0; + for (auto message : radiosonde->m_messages) + { + float y1, y2; + if (m_settings.m_y1 != RadiosondeSettings::NONE) + { + y1 = getData(m_settings.m_y1, radiosonde, message); + y1Series->append(radiosonde->m_messagesDateTime[idx].toMSecsSinceEpoch(), y1); + } + if (m_settings.m_y2 != RadiosondeSettings::NONE) + { + y2 = getData(m_settings.m_y2, radiosonde, message); + y2Series->append(radiosonde->m_messagesDateTime[idx].toMSecsSinceEpoch(), y2); + } + idx++; + } + if (m_settings.m_y1 != RadiosondeSettings::NONE) + { + m_chart->addSeries(y1Series); + m_chart->addAxis(m_chartY1Axis, Qt::AlignLeft); + y1Series->attachAxis(m_chartXAxis); + y1Series->attachAxis(m_chartY1Axis); + m_chartY1Axis->setTitleText(getAxisTitle(m_settings.m_y1)); + } + if (m_settings.m_y2 != RadiosondeSettings::NONE) + { + m_chart->addSeries(y2Series); + m_chart->addAxis(m_chartY2Axis, Qt::AlignRight); + y2Series->attachAxis(m_chartXAxis); + y2Series->attachAxis(m_chartY2Axis); + m_chartY2Axis->setTitleText(getAxisTitle(m_settings.m_y2)); + } + } + } + ui->chart->setChart(m_chart); + delete oldChart; +} + +void RadiosondeGUI::on_deleteAll_clicked() +{ + for (int row = ui->radiosondes->rowCount() - 1; row >= 0; row--) + { + QString serial = ui->radiosondes->item(row, RADIOSONDE_COL_SERIAL)->text(); + // Remove from map + sendToMap(serial, "", + "", "", + "", 0.0f, + 0.0f, 0.0f, 0.0f, QDateTime(), + 0.0f); + // Remove from table + ui->radiosondes->removeRow(row); + // Remove from hash + m_radiosondes.remove(serial); + } +} diff --git a/plugins/feature/radiosonde/radiosondegui.h b/plugins/feature/radiosonde/radiosondegui.h new file mode 100644 index 000000000..ace1b973b --- /dev/null +++ b/plugins/feature/radiosonde/radiosondegui.h @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_RADIOSONDEGUI_H_ +#define INCLUDE_FEATURE_RADIOSONDEGUI_H_ + +#include +#include +#include +#include +#include + +#include "feature/featuregui.h" +#include "util/messagequeue.h" +#include "util/radiosonde.h" +#include "pipes/pipeendpoint.h" +#include "settings/rollupstate.h" + +#include "radiosondesettings.h" + +class PluginAPI; +class FeatureUISet; +class Radiosonde; + +namespace Ui { + class RadiosondeGUI; +} + +using namespace QtCharts; + +class RadiosondeGUI : public FeatureGUI { + Q_OBJECT + + // Holds information not in the table + struct RadiosondeData { + + QList m_messagesDateTime; + QList m_messages; + + RS41Subframe m_subframe; + + ~RadiosondeData() + { + qDeleteAll(m_messages); + } + + void addMessage(QDateTime dateTime, RS41Frame *message) + { + m_messagesDateTime.append(dateTime); + m_messages.append(message); + } + + }; + +public: + static RadiosondeGUI* create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +private: + Ui::RadiosondeGUI* ui; + PluginAPI* m_pluginAPI; + FeatureUISet* m_featureUISet; + RadiosondeSettings m_settings; + RollupState m_rollupState; + bool m_doApplySettings; + + Radiosonde* m_radiosonde; + MessageQueue m_inputMessageQueue; + int m_lastFeatureState; + + QHash m_radiosondes; // Hash of serial to radiosondes + + QMenu *radiosondesMenu; // Column select context menu + + explicit RadiosondeGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr); + virtual ~RadiosondeGUI(); + + void blockApplySettings(bool block); + void applySettings(bool force = false); + void displaySettings(); + bool handleMessage(const Message& message); + + void leaveEvent(QEvent*); + void enterEvent(QEvent*); + + void sendToMap(const QString &name, const QString &label, + const QString &image, const QString &text, + const QString &model, float labelOffset, + float latitude, float longitude, float altitude, QDateTime positionDateTime, + float heading + ); + void updateRadiosondes(RS41Frame *radiosonde, QDateTime dateTime); + void resizeTable(); + QAction *createCheckableItem(QString& text, int idx, bool checked, const char *slot); + void plotChart(); + float getData(RadiosondeSettings::ChartData dataType, RadiosondeData *radiosonde, RS41Frame *message); + + enum RadiosondeCol { + RADIOSONDE_COL_SERIAL, + RADIOSONDE_COL_TYPE, + RADIOSONDE_COL_LATITUDE, + RADIOSONDE_COL_LONGITUDE, + RADIOSONDE_COL_ALTITUDE, + RADIOSONDE_COL_SPEED, + RADIOSONDE_COL_VERTICAL_RATE, + RADIOSONDE_COL_HEADING, + RADIOSONDE_COL_STATUS, + RADIOSONDE_COL_PRESSURE, + RADIOSONDE_COL_TEMPERATURE, + RADIOSONDE_COL_HUMIDITY, + RADIOSONDE_COL_ALT_MAX, + RADIOSONDE_COL_FREQUENCY, + RADIOSONDE_COL_BURSTKILL_STATUS, + RADIOSONDE_COL_BURSTKILL_TIMER, + RADIOSONDE_COL_LAST_UPDATE, + RADIOSONDE_COL_MESSAGES + }; + +private slots: + void onMenuDialogCalled(const QPoint &p); + void onWidgetRolled(QWidget* widget, bool rollDown); + void handleInputMessages(); + void on_radiosondes_itemSelectionChanged(); + void on_radiosondes_cellDoubleClicked(int row, int column); + void radiosondes_customContextMenuRequested(QPoint pos); + void radiosondes_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex); + void radiosondes_sectionResized(int logicalIndex, int oldSize, int newSize); + void radiosondesColumnSelectMenu(QPoint pos); + void radiosondesColumnSelectMenuChecked(bool checked = false); + void on_y1_currentIndexChanged(int index); + void on_y2_currentIndexChanged(int index); + void on_deleteAll_clicked(); +}; + +#endif // INCLUDE_FEATURE_RADIOSONDEGUI_H_ diff --git a/plugins/feature/radiosonde/radiosondegui.ui b/plugins/feature/radiosonde/radiosondegui.ui new file mode 100644 index 000000000..14a31362f --- /dev/null +++ b/plugins/feature/radiosonde/radiosondegui.ui @@ -0,0 +1,444 @@ + + + RadiosondeGUI + + + + 0 + 0 + 484 + 732 + + + + + 0 + 0 + + + + + 320 + 100 + + + + + 16777215 + 16777215 + + + + + 9 + + + + Radiosonde + + + Qt::LeftToRight + + + + + 10 + 10 + 336 + 508 + + + + + 0 + 0 + + + + Radiosondes + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + 0 + 0 + + + + Qt::Vertical + + + + Radiosondes + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + Serial + + + Serial number of the Radiosonde + + + + + Type + + + Type of Radiosonde + + + + + Lat (°) + + + Latitude in degrees. East positive + + + + + Lon (°) + + + Longitude in degrees. North positive. + + + + + Alt (m) + + + Altitude in metres + + + + + Spd (km/h) + + + Speed in kilometers per second + + + + + VR (m/s) + + + Vertical climb rate in metres per second + + + + + Hd (°) + + + Heading in degrees. + + + + + Status + + + + + P (hPa) + + + Pressure in hectpascals + + + + + T (C) + + + Temperature in degrees Celsius + + + + + U (%) + + + Relative humidity in percent + + + + + Alt Max (m) + + + Maximum altitude seen in metres + + + + + Freq (MHz) + + + Transmission frequency in MHz + + + + + BurstKill Status + + + + + BurstKill Timer + + + Time last position was received + + + + + Updated + + + Time last message was received + + + + + Messages + + + Number of messages received + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Y1 + + + + + + + + 0 + 0 + + + + Select data to plot on left Y axis + + + 0 + + + + None + + + + + Altitude + + + + + Temperature + + + + + Humidity + + + + + Pressure + + + + + Speed + + + + + Vertical rate + + + + + Heading + + + + + Battery Voltage + + + + + + + + Y2 + + + + + + + + 0 + 0 + + + + Select data to plot on right Y axis + + + + None + + + + + Altitude + + + + + Temperature + + + + + Humidity + + + + + Pressure + + + + + Speed + + + + + Vertical rate + + + + + Heading + + + + + Battery Voltage + + + + + + + + Delete all data + + + + + + + :/bin.png:/bin.png + + + + + + + + + + 300 + 100 + + + + + + + + + + + + + + RollupWidget + QWidget +
    gui/rollupwidget.h
    + 1 +
    + + QChartView + QGraphicsView +
    QtCharts
    +
    +
    + + + + +
    diff --git a/plugins/feature/radiosonde/radiosondeplugin.cpp b/plugins/feature/radiosonde/radiosondeplugin.cpp new file mode 100644 index 000000000..2445e2635 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondeplugin.cpp @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include "plugin/pluginapi.h" + +#ifndef SERVER_MODE +#include "radiosondegui.h" +#endif +#include "radiosonde.h" +#include "radiosondeplugin.h" +#include "radiosondewebapiadapter.h" + +const PluginDescriptor RadiosondePlugin::m_pluginDescriptor = { + Radiosonde::m_featureId, + QStringLiteral("Radiosonde"), + QStringLiteral("6.20.0"), + QStringLiteral("(c) Jon Beniston, M7RCE"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +RadiosondePlugin::RadiosondePlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(nullptr) +{ +} + +const PluginDescriptor& RadiosondePlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void RadiosondePlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + m_pluginAPI->registerFeature(Radiosonde::m_featureIdURI, Radiosonde::m_featureId, this); +} + +#ifdef SERVER_MODE +FeatureGUI* RadiosondePlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + (void) featureUISet; + (void) feature; + return nullptr; +} +#else +FeatureGUI* RadiosondePlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + return RadiosondeGUI::create(m_pluginAPI, featureUISet, feature); +} +#endif + +Feature* RadiosondePlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const +{ + return new Radiosonde(webAPIAdapterInterface); +} + +FeatureWebAPIAdapter* RadiosondePlugin::createFeatureWebAPIAdapter() const +{ + return new RadiosondeWebAPIAdapter(); +} diff --git a/plugins/feature/radiosonde/radiosondeplugin.h b/plugins/feature/radiosonde/radiosondeplugin.h new file mode 100644 index 000000000..c5e5a5ae7 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondeplugin.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_RADIOSONDEPLUGIN_H +#define INCLUDE_FEATURE_RADIOSONDEPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class FeatureGUI; +class WebAPIAdapterInterface; + +class RadiosondePlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.feature.radiosonde") + +public: + explicit RadiosondePlugin(QObject* parent = nullptr); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual FeatureGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const; + virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const; + virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif // INCLUDE_FEATURE_RADIOSONDEPLUGIN_H diff --git a/plugins/feature/radiosonde/radiosondesettings.cpp b/plugins/feature/radiosonde/radiosondesettings.cpp new file mode 100644 index 000000000..565d44877 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondesettings.cpp @@ -0,0 +1,149 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "util/simpleserializer.h" +#include "settings/serializable.h" + +#include "radiosondesettings.h" + +const QStringList RadiosondeSettings::m_pipeTypes = { + QStringLiteral("RadiosondeDemod") +}; + +const QStringList RadiosondeSettings::m_pipeURIs = { + QStringLiteral("sdrangel.channel.radiosondedemod") +}; + +RadiosondeSettings::RadiosondeSettings() : + m_rollupState(nullptr) +{ + resetToDefaults(); +} + +void RadiosondeSettings::resetToDefaults() +{ + m_title = "Radiosonde"; + m_rgbColor = QColor(102, 0, 102).rgb(); + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIFeatureSetIndex = 0; + m_reverseAPIFeatureIndex = 0; + + m_y1 = ALTITUDE; + m_y2 = TEMPERATURE; + + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) + { + m_radiosondesColumnIndexes[i] = i; + m_radiosondesColumnSizes[i] = -1; // Autosize + } +} + +QByteArray RadiosondeSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeString(1, m_title); + s.writeU32(2, m_rgbColor); + s.writeBool(3, m_useReverseAPI); + s.writeString(4, m_reverseAPIAddress); + s.writeU32(5, m_reverseAPIPort); + s.writeU32(6, m_reverseAPIFeatureSetIndex); + s.writeU32(7, m_reverseAPIFeatureIndex); + + if (m_rollupState) { + s.writeBlob(8, m_rollupState->serialize()); + } + + s.writeS32(10, (int)m_y1); + s.writeS32(11, (int)m_y2); + + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { + s.writeS32(300 + i, m_radiosondesColumnIndexes[i]); + } + + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { + s.writeS32(400 + i, m_radiosondesColumnSizes[i]); + } + + return s.final(); +} + +bool RadiosondeSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + QByteArray bytetmp; + uint32_t utmp; + QString strtmp; + QByteArray blob; + + d.readString(1, &m_title, "Radiosonde"); + d.readU32(2, &m_rgbColor, QColor(102, 0, 102).rgb()); + d.readBool(3, &m_useReverseAPI, false); + d.readString(4, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(5, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(6, &utmp, 0); + m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp; + d.readU32(7, &utmp, 0); + m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp; + + if (m_rollupState) + { + d.readBlob(8, &bytetmp); + m_rollupState->deserialize(bytetmp); + } + + d.readS32(10, (int *)&m_y1, (int)ALTITUDE); + d.readS32(11, (int *)&m_y2, (int)TEMPERATURE); + + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { + d.readS32(300 + i, &m_radiosondesColumnIndexes[i], i); + } + + for (int i = 0; i < RADIOSONDES_COLUMNS; i++) { + d.readS32(400 + i, &m_radiosondesColumnSizes[i], -1); + } + + return true; + } + else + { + resetToDefaults(); + return false; + } +} diff --git a/plugins/feature/radiosonde/radiosondesettings.h b/plugins/feature/radiosonde/radiosondesettings.h new file mode 100644 index 000000000..4c199c731 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondesettings.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_RADIOSONDESETTINGS_H_ +#define INCLUDE_FEATURE_RADIOSONDESETTINGS_H_ + +#include +#include + +#include "util/message.h" + +class Serializable; + +// Number of columns in the table +#define RADIOSONDES_COLUMNS 16 + +struct RadiosondeSettings +{ + QString m_title; + quint32 m_rgbColor; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIFeatureSetIndex; + uint16_t m_reverseAPIFeatureIndex; + Serializable *m_rollupState; + + enum ChartData { + NONE, + ALTITUDE, + TEMPERATURE, + HUMIDITY, + PRESSURE, + SPEED, + VERTICAL_RATE, + HEADING, + BATTERY_VOLTAGE + }; + ChartData m_y1; + ChartData m_y2; + + int m_radiosondesColumnIndexes[RADIOSONDES_COLUMNS]; + int m_radiosondesColumnSizes[RADIOSONDES_COLUMNS]; + + RadiosondeSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } + + static const QStringList m_pipeTypes; + static const QStringList m_pipeURIs; +}; + +#endif // INCLUDE_FEATURE_RADIOSONDESETTINGS_H_ diff --git a/plugins/feature/radiosonde/radiosondewebapiadapter.cpp b/plugins/feature/radiosonde/radiosondewebapiadapter.cpp new file mode 100644 index 000000000..ef0f51127 --- /dev/null +++ b/plugins/feature/radiosonde/radiosondewebapiadapter.cpp @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGFeatureSettings.h" +#include "radiosonde.h" +#include "radiosondewebapiadapter.h" + +RadiosondeWebAPIAdapter::RadiosondeWebAPIAdapter() +{} + +RadiosondeWebAPIAdapter::~RadiosondeWebAPIAdapter() +{} + +int RadiosondeWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadiosondeSettings(new SWGSDRangel::SWGRadiosondeSettings()); + response.getRadiosondeSettings()->init(); + Radiosonde::webapiFormatFeatureSettings(response, m_settings); + + return 200; +} + +int RadiosondeWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) force; // no action + (void) errorMessage; + Radiosonde::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response); + + return 200; +} diff --git a/plugins/feature/radiosonde/radiosondewebapiadapter.h b/plugins/feature/radiosonde/radiosondewebapiadapter.h new file mode 100644 index 000000000..9b402e8ae --- /dev/null +++ b/plugins/feature/radiosonde/radiosondewebapiadapter.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Jon Beniston, M7RCE // +// Copyright (C) 2020 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_Radiosonde_WEBAPIADAPTER_H +#define INCLUDE_Radiosonde_WEBAPIADAPTER_H + +#include "feature/featurewebapiadapter.h" +#include "radiosondesettings.h" + +/** + * Standalone API adapter only for the settings + */ +class RadiosondeWebAPIAdapter : public FeatureWebAPIAdapter { +public: + RadiosondeWebAPIAdapter(); + virtual ~RadiosondeWebAPIAdapter(); + + virtual QByteArray serialize() const { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + +private: + RadiosondeSettings m_settings; +}; + +#endif // INCLUDE_Radiosonde_WEBAPIADAPTER_H diff --git a/plugins/feature/radiosonde/readme.md b/plugins/feature/radiosonde/readme.md new file mode 100644 index 000000000..992754e67 --- /dev/null +++ b/plugins/feature/radiosonde/readme.md @@ -0,0 +1,55 @@ +

    Radiosonde Feature Plugin

    + +

    Introduction

    + +The Radiosonde feature displays a table containing the most recent information received from radiosondes +based on data received via [Radiosonde Demodulators](../../channelrx/demodradiasonde/readme.md). + +The chart can plot two data series vs time for the radiosonde selected in the table. + +The Radiosonde feature can draw ballons objects on the [Map](../../feature/map/readme.md) feature in 2D and 3D. + +

    Interface

    + +![Radiosonde feature plugin GUI](../../../doc/img/Radiosonde_plugin.png) + +

    Radiosonde Table

    + +The Radiosonde table displays the current status of each radiosonde, based on the latest received data from all Radiosonde Demodulators. + +* Serial - The serial number that uniquely identifiers each radiosonde. +* Type - The type of radiosonde. +* Lat (°) - Latitude in degrees. East positive. Double clicking on this column will center the map on this object. +* Lon (°) - Longitude in degrees. West positive. Double clicking on this column will center the map on this object. +* Alt (m) - The altitude of the radiosonde in metres. +* Spd (km/h) - Speed over ground in kilometres per hour. +* VR (m/s) - Vertical climb rate in metres per second. +* Hdg (°) - Heading in degrees. +* Status - Flight status of the radiosonde (E.g. On ground, ascent or descent). +* P (hPA) - Air pressure in hectopascals. Not all RS41s include a pressure sensor. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* T (°C) - Air temperature in degrees Celsius. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* U (%) - Relative humidity in percent. A value ending with 'U' indicates a uncalibrated estimate and may be inaccurate. +* Alt Max (m) - The maximum altitude seen for the radiosonde in metres. +* Freq (MHz) - The transmission frequency in megahertz as indicated by the radiosonde. +* BurstKill status - Whether the BurstKill timer is active. +* BurstKill timer - BurstKill timer. +* Updated - Gives the date and time the last message was received. +* Messages - Displays the number of messages received. + +Right clicking on the table header allows you to select which columns to show. The columns can be reorderd by left clicking and dragging the column header. + +Right clicking on a table cell allows you to copy the cell contents, or find the radiosonde on the map. + +

    Map

    + +The Radiosonde feature can plot ballons (during ascent) and parachutes (during descent) on the [Map](../../feature/map/readme.md). +To use, simply open a Map feature and the Radiosonde plugin will display objects based upon the data it receives from that point. +Selecting a radiosonde item on the map will display a text bubble containing information from the above table. +To centre the map on an item in the table, double click in the Lat or Lon columns. + +![Radiosonde on map](../../../doc/img/Radiosonde_plugin_map.png) + +

    Attribution

    + +Hot-air-balloon icons created by Freepik - https://www.flaticon.com/free-icons/hot-air-balloon +Parachute icons created by Freepik - https://www.flaticon.com/free-icons/parachute diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index d190b530b..5d5d3a468 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -191,6 +191,7 @@ set(sdrbase_SOURCES util/aprs.cpp util/astronomy.cpp util/azel.cpp + util/coordinates.cpp util/crc.cpp util/CRC64.cpp util/csv.cpp @@ -210,6 +211,7 @@ set(sdrbase_SOURCES util/planespotters.cpp util/png.cpp util/prettyprint.cpp + util/radiosonde.cpp util/rtpsink.cpp util/syncmessenger.cpp util/samplesourceserializer.cpp @@ -406,6 +408,7 @@ set(sdrbase_HEADERS util/aprs.h util/astronomy.h util/azel.h + util/coordinates.h util/CRC64.h util/csv.h util/db.h @@ -430,6 +433,7 @@ set(sdrbase_HEADERS util/planespotters.h util/png.h util/prettyprint.h + util/radiosonde.h util/rtpsink.h util/syncmessenger.h util/samplesourceserializer.h diff --git a/sdrbase/util/coordinates.cpp b/sdrbase/util/coordinates.cpp new file mode 100644 index 000000000..b5e6c23ed --- /dev/null +++ b/sdrbase/util/coordinates.cpp @@ -0,0 +1,318 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2011-2020 Cesium Contributors // +// Copyright (C) 2022 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "coordinates.h" +#include "units.h" + +// Scale cartesian position on to surface of ellipsoid +QVector3D Coordinates::scaleToGeodeticSurface(QVector3D cartesian, QVector3D oneOverRadii, QVector3D oneOverRadiiSquared) +{ + float centerToleranceSquared = 0.1; + + double x2 = cartesian.x() * cartesian.x() * oneOverRadii.x() * oneOverRadii.x(); + double y2 = cartesian.y() * cartesian.y() * oneOverRadii.y() * oneOverRadii.y(); + double z2 = cartesian.z() * cartesian.z() * oneOverRadii.z() * oneOverRadii.z(); + + double squaredNorm = x2 + y2 + z2; + double ratio = sqrt(1.0 / squaredNorm); + + QVector3D intersection = cartesian * ratio; + + if (squaredNorm < centerToleranceSquared) { + return intersection; + } + + QVector3D gradient( + intersection.x() * oneOverRadiiSquared.x() * 2.0, + intersection.y() * oneOverRadiiSquared.y() * 2.0, + intersection.z() * oneOverRadiiSquared.z() * 2.0 + ); + + double lambda = ((1.0 - ratio) * cartesian.length()) / (0.5 * gradient.length()); + + double correction = 0.0; + double func; + double denominator; + double xMultiplier; + double yMultiplier; + double zMultiplier; + double xMultiplier2; + double yMultiplier2; + double zMultiplier2; + double xMultiplier3; + double yMultiplier3; + double zMultiplier3; + + do + { + lambda -= correction; + + xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquared.x()); + yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquared.y()); + zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquared.z()); + + xMultiplier2 = xMultiplier * xMultiplier; + yMultiplier2 = yMultiplier * yMultiplier; + zMultiplier2 = zMultiplier * zMultiplier; + + xMultiplier3 = xMultiplier2 * xMultiplier; + yMultiplier3 = yMultiplier2 * yMultiplier; + zMultiplier3 = zMultiplier2 * zMultiplier; + + func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0; + + denominator = + x2 * xMultiplier3 * oneOverRadiiSquared.x() + + y2 * yMultiplier3 * oneOverRadiiSquared.y() + + z2 * zMultiplier3 * oneOverRadiiSquared.z(); + + double derivative = -2.0 * denominator; + + correction = func / derivative; + } + while (abs(func) > 0.000000000001); + + QVector3D result( + cartesian.x() * xMultiplier, + cartesian.y() * yMultiplier, + cartesian.z() * zMultiplier + ); + return result; +} + +// QVector3D.normalized doesn't work with small numbers +QVector3D Coordinates::normalized(QVector3D vec) +{ + QVector3D result; + float magnitude = vec.length(); + result.setX(vec.x() / magnitude); + result.setY(vec.y() / magnitude); + result.setZ(vec.z() / magnitude); + return result; +} + +// Convert ECEF position to geodetic coordinates +void Coordinates::ecefToGeodetic(double x, double y, double z, double &latitude, double &longitude, double &height) +{ + QVector3D wgs84OneOverRadix(1.0 / 6378137.0, + 1.0 / 6378137.0, + 1.0 / 6356752.3142451793); + QVector3D wgs84OneOverRadiiSquared(1.0 / (6378137.0 * 6378137.0), + 1.0 / (6378137.0 * 6378137.0), + 1.0 / (6356752.3142451793 * 6356752.3142451793)); + + QVector3D cartesian(x, y, z); + + QVector3D p = scaleToGeodeticSurface(cartesian, wgs84OneOverRadix, wgs84OneOverRadiiSquared); + + QVector3D n = p * wgs84OneOverRadiiSquared; + n = normalized(n); + + QVector3D h = cartesian - p; + + longitude = atan2(n.y(), n.x()); + latitude = asin(n.z()); + + longitude = Units::radiansToDegrees(longitude); + latitude = Units::radiansToDegrees(latitude); + + double t = QVector3D::dotProduct(h, cartesian); + double sign = t >= 0.0 ? 1.0 : 0.0; + height = sign * h.length(); +} + +// Convert ECEF velocity to speed and heading +void Coordinates::ecefVelToSpeedHeading(double latitude, double longitude, + double velX, double velY, double velZ, + double &speed, double &verticalRate, double &heading) +{ + if ((velX == 0.0) && (velY == 0.0) && (velZ == 0.0)) + { + speed = 0.0; + heading = 0.0; + verticalRate = 0.0; + return; + } + + double latRad = Units::degreesToRadians(latitude); + double lonRad = Units::degreesToRadians(longitude); + + double sinLat = sin(latRad); + double cosLat = cos(latRad); + double sinLon = sin(lonRad); + double cosLon = cos(lonRad); + + double velEast = -velX * sinLon + velY * cosLon; + double velNorth = -velX * sinLat * cosLon - velY * sinLat * sinLon + velZ * cosLat; + double velUp = velX * cosLat * cosLon + velY * cosLat * sinLon + velZ * sinLat; + + speed = sqrt(velNorth * velNorth + velEast * velEast); + verticalRate = velUp; + + double headingRad = atan2(velEast, velNorth); + heading = Units::radiansToDegrees(headingRad); + if (heading < 0.0) { + heading += 360.0; + } else if (heading >= 360.0) { + heading -= 360.0; + } +} + +// Convert a position specified in longitude, latitude in degrees and height in metres above WGS84 ellipsoid in to +// Earth Centered Earth Fixed frame cartesian coordinates +// See Cesium.Cartesian3.fromDegrees +QVector3D Coordinates::geodeticToECEF(double longitude, double latitude, double height) +{ + return geodeticRadiansToECEF(Units::degreesToRadians(longitude), Units::degreesToRadians(latitude), height); +} + +// FIXME: QVector3D is only float! +// See Cesium.Cartesian3.fromRadians +QVector3D Coordinates::geodeticRadiansToECEF(double longitude, double latitude, double height) +{ + QVector3D wgs84RadiiSquared(6378137.0 * 6378137.0, 6378137.0 * 6378137.0, 6356752.3142451793 * 6356752.3142451793); + + double cosLatitude = cos(latitude); + QVector3D n; + n.setX(cosLatitude * cos(longitude)); + n.setY(cosLatitude * sin(longitude)); + n.setZ(sin(latitude)); + n.normalize(); + QVector3D k; + k = wgs84RadiiSquared * n; + double gamma = sqrt(QVector3D::dotProduct(n, k)); + k = k / gamma; + n = n * height; + return k + n; +} + +// Convert heading, pitch and roll in degrees to a quaternoin +// See: Cesium.Quaternion.fromHeadingPitchRoll +QQuaternion Coordinates::fromHeadingPitchRoll(double heading, double pitch, double roll) +{ + QVector3D xAxis(1, 0, 0); + QVector3D yAxis(0, 1, 0); + QVector3D zAxis(0, 0, 1); + + QQuaternion rollQ = QQuaternion::fromAxisAndAngle(xAxis, roll); + + QQuaternion pitchQ = QQuaternion::fromAxisAndAngle(yAxis, -pitch); + + QQuaternion headingQ = QQuaternion::fromAxisAndAngle(zAxis, -heading); + + QQuaternion temp = rollQ * pitchQ; + + return headingQ * temp; +} + +// Calculate a transformation matrix from a East, North, Up frame at the given position to Earth Centered Earth Fixed frame +// See: Cesium.Transforms.eastNorthUpToFixedFrame +QMatrix4x4 Coordinates::eastNorthUpToECEF(QVector3D origin) +{ + // TODO: Handle special case at centre of earth and poles + QVector3D up = origin.normalized(); + QVector3D east(-origin.y(), origin.x(), 0.0); + east.normalize(); + QVector3D north = QVector3D::crossProduct(up, east); + QMatrix4x4 result( + east.x(), north.x(), up.x(), origin.x(), + east.y(), north.y(), up.y(), origin.y(), + east.z(), north.z(), up.z(), origin.z(), + 0.0, 0.0, 0.0, 1.0 + ); + return result; +} + +// Convert 3x3 rotation matrix to a quaternoin +// Although there is a method for this in Qt: QQuaternion::fromRotationMatrix, it seems to +// result in different signs, so the following is based on Cesium code +QQuaternion Coordinates::fromRotation(QMatrix3x3 mat) +{ + QQuaternion q; + + double trace = mat(0, 0) + mat(1, 1) + mat(2, 2); + + if (trace > 0.0) + { + double root = sqrt(trace + 1.0); + q.setScalar(0.5 * root); + root = 0.5 / root; + + q.setX((mat(2,1) - mat(1,2)) * root); + q.setY((mat(0,2) - mat(2,0)) * root); + q.setZ((mat(1,0) - mat(0,1)) * root); + } + else + { + double next[] = {1, 2, 0}; + int i = 0; + if (mat(1,1) > mat(0,0)) { + i = 1; + } + if (mat(2,2) > mat(0,0) && mat(2,2) > mat(1,1)) { + i = 2; + } + int j = next[i]; + int k = next[j]; + + double root = sqrt(mat(i,i) - mat(j,j) - mat(k,k) + 1); + double quat[] = {0.0, 0.0, 0.0}; + quat[i] = 0.5 * root; + root = 0.5 / root; + + q.setScalar((mat(j,k) - mat(k,j)) * root); + quat[j] = (mat(i,j) + mat(j,i)) * root; + quat[k] = (mat(i,k) + mat(k,i)) * root; + q.setX(-quat[0]); + q.setY(-quat[1]); + q.setZ(-quat[2]); + } + return q; +} + +// Calculate orientation quaternion for a model (such as an aircraft) based on position and (HPR) heading, pitch and roll (in degrees) +// While Cesium supports specifying orientation as HPR, CZML doesn't currently. See https://github.com/CesiumGS/cesium/issues/5184 +// CZML requires the orientation to be in the Earth Centered Earth Fixed (geocentric) reference frame (https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates) +// The orientation therefore depends not only on HPR but also on position +// +// glTF uses a right-handed axis convention; that is, the cross product of right and forward yields up. glTF defines +Y as up, +Z as forward, and -X as right. +// Cesium.Quaternion.fromHeadingPitchRoll Heading is the rotation about the negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about the positive x axis. +QQuaternion Coordinates::orientation(double longitude, double latitude, double altitude, double heading, double pitch, double roll) +{ + // Forward direction for gltf models in Cesium seems to be Eastward, rather than Northward, so we adjust heading by -90 degrees + heading = -90 + heading; + + // Convert position to Earth Centered Earth Fixed (ECEF) frame + QVector3D positionECEF = geodeticToECEF(longitude, latitude, altitude); + + // Calculate matrix to transform from East, North, Up (ENU) frame to ECEF frame + QMatrix4x4 enuToECEFTransform = eastNorthUpToECEF(positionECEF); + + // Calculate rotation based on HPR in ENU frame + QQuaternion hprENU = fromHeadingPitchRoll(heading, pitch, roll); + + // Transform rotation from ENU to ECEF + QMatrix3x3 hprENU3 = hprENU.toRotationMatrix(); + QMatrix4x4 hprENU4(hprENU3); + QMatrix4x4 transform = enuToECEFTransform * hprENU4; + + // Convert from 4x4 matrix to 3x3 matrix then to a quaternion + QQuaternion oq = fromRotation(transform.toGenericMatrix<3,3>()); + + return oq; +} diff --git a/sdrbase/util/coordinates.h b/sdrbase/util/coordinates.h new file mode 100644 index 000000000..1876dec6f --- /dev/null +++ b/sdrbase/util/coordinates.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_COORDINATES_H +#define INCLUDE_COORDINATES_H + +#include "export.h" + +#include +#include +#include +#include +#include + +// Functions for transformations between geodetic and ECEF coordinates +class SDRBASE_API Coordinates { + +public: + + static QVector3D geodeticToECEF(double longitude, double latitude, double height=0.0); + static QVector3D geodeticRadiansToECEF(double longitude, double latitude, double height=0.0); + static QMatrix4x4 eastNorthUpToECEF(QVector3D origin); + static void ecefToGeodetic(double x, double y, double z, double &latitude, double &longitude, double &height); + static void ecefVelToSpeedHeading(double latitude, double longitude, + double velX, double velY, double velZ, + double &speed, double &verticalRate, double &heading); + static QQuaternion orientation(double longitude, double latitude, double altitude, double heading, double pitch, double roll); + +protected: + + static QVector3D scaleToGeodeticSurface(QVector3D cartesian, QVector3D oneOverRadii, QVector3D oneOverRadiiSquared); + static QVector3D normalized(QVector3D vec); + static QQuaternion fromHeadingPitchRoll(double heading, double pitch, double roll); + static QQuaternion fromRotation(QMatrix3x3 mat); + +}; + +#endif // INCLUDE_COORDINATES_H diff --git a/sdrbase/util/radiosonde.cpp b/sdrbase/util/radiosonde.cpp new file mode 100644 index 000000000..7b3b46851 --- /dev/null +++ b/sdrbase/util/radiosonde.cpp @@ -0,0 +1,710 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// Based on code and docs by einergehtnochrein, rs1729 and bazjo // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "util/radiosonde.h" +#include "util/coordinates.h" + +RS41Frame::RS41Frame(const QByteArray ba) : + m_statusValid(false), + m_batteryVoltage(0.0), + m_pcbTemperature(0), + m_humiditySensorHeating(0), + m_transmitPower(0), + m_maxSubframeNumber(0), + m_subframeNumber(0), + m_measValid(false), + m_gpsInfoValid(false), + m_posValid(false), + m_latitude(0.0), + m_longitude(0.0), + m_height(0.0), + m_bytes(ba), + m_temperatureCalibrated(false), + m_pressureCalibrated(false), + m_humidityTemperatureCalibrated(false), + m_humidityCalibrated(false) +{ + int length = getFrameLength(ba[RS41_OFFSET_FRAME_TYPE]); + for (int i = RS41_OFFSET_BLOCK_0; i < length; ) + { + uint8_t blockID = ba[i+0]; + uint8_t blockLength = ba[i+1]; + switch (blockID) + { + case RS41_ID_STATUS: + decodeStatus(ba.mid(i+2, blockLength)); + break; + case RS41_ID_MEAS: + decodeMeas(ba.mid(i+2, blockLength)); + break; + case RS41_ID_GPSINFO: + decodeGPSInfo(ba.mid(i+2, blockLength)); + break; + case RS41_ID_GPSRAW: + break; + case RS41_ID_GPSPOS: + decodeGPSPos(ba.mid(i+2, blockLength)); + break; + case RS41_ID_EMPTY: + break; + } + i += 2 + blockLength + 2; // ID, length, data, CRC + } +} + +QString RS41Frame::toHex() +{ + return m_bytes.toHex(); +} + +uint16_t RS41Frame::getUInt16(const QByteArray ba, int offset) const +{ + return (ba[offset] & 0xff) + | ((ba[offset+1] & 0xff) << 8); +} + +uint32_t RS41Frame::getUInt24(const QByteArray ba, int offset) const +{ + return (ba[offset] & 0xff) + | ((ba[offset+1] & 0xff) << 8) + | ((ba[offset+2] & 0xff) << 16); +} + +uint32_t RS41Frame::getUInt32(const QByteArray ba, int offset) const +{ + return (ba[offset] & 0xff) + | ((ba[offset+1] & 0xff) << 8) + | ((ba[offset+2] & 0xff) << 16) + | ((ba[offset+3] & 0xff) << 24); +} + +void RS41Frame::decodeStatus(const QByteArray ba) +{ + m_statusValid = true; + m_frameNumber = getUInt16(ba, 0); + m_serial = QString(ba.mid(0x2, 8)); + m_batteryVoltage = (ba[0xa] & 0xff) / 10.0; + QStringList phases = {"Ground", "Ascent", "0x2", "Descent"}; + int phase = ba[0xd] & 0x3; + m_flightPhase = phases[phase]; + m_batteryStatus = (ba[0xe] & 0x10) == 0 ? "OK" : "Low"; + m_pcbTemperature = (ba[0x10] & 0xff); + m_humiditySensorHeating = getUInt16(ba, 0x13); + m_transmitPower = ba[0x15] & 0xff; + m_maxSubframeNumber = ba[0x16] & 0xff; + m_subframeNumber = ba[0x17] & 0xff; + m_subframe = ba.mid(0x18, 16); +} + +void RS41Frame::decodeMeas(const QByteArray ba) +{ + m_measValid = true; + m_tempMain = getUInt24(ba, 0x0); + m_tempRef1 = getUInt24(ba, 0x3); + m_tempRef2 = getUInt24(ba, 0x6); + m_humidityMain = getUInt24(ba, 0x9); + m_humidityRef1 = getUInt24(ba, 0xc); + m_humidityRef2 = getUInt24(ba, 0xf); + m_humidityTempMain = getUInt24(ba, 0x12); + m_humidityTempRef1 = getUInt24(ba, 0x15); + m_humidityTempRef2 = getUInt24(ba, 0x18); + m_pressureMain = getUInt24(ba, 0x1b); + m_pressureRef1 = getUInt24(ba, 0x1e); + m_pressureRef2 = getUInt24(ba, 0x21); + m_pressureTemp = getUInt16(ba, 0x26) / 100.0f; +} + +void RS41Frame::decodeGPSInfo(const QByteArray ba) +{ + m_gpsInfoValid = true; + uint16_t gpsWeek = getUInt16(ba, 0x0); + uint32_t gpsTimeOfWeek = getUInt32(ba, 0x2); // Milliseconds + QDateTime epoch(QDate(1980, 1, 6), QTime(0, 0, 0), Qt::OffsetFromUTC, 18); // GPS doesn't count leap seconds + m_gpsDateTime = epoch.addDays(gpsWeek*7).addMSecs(gpsTimeOfWeek); +} + +void RS41Frame::decodeGPSPos(const QByteArray ba) +{ + m_satellitesUsed = ba[0x12] & 0xff; + if (m_satellitesUsed > 0) + { + m_posValid = true; + int32_t ecefX = (int32_t)getUInt32(ba, 0x0); + int32_t ecefY = (int32_t)getUInt32(ba, 0x4); + int32_t ecefZ = (int32_t)getUInt32(ba, 0x8); + // Convert cm to m + // Convert to latitude, longitude and altitude + Coordinates::ecefToGeodetic(ecefX / 100.0, ecefY / 100.0, ecefZ / 100.0, m_latitude, m_longitude, m_height); + int32_t velX = (int16_t)getUInt16(ba, 0xc); + int32_t velY = (int16_t)getUInt16(ba, 0xe); + int32_t velZ = (int16_t)getUInt16(ba, 0x10); + // Convert cm/s to m/s + // Calculate speed / heading + Coordinates::ecefVelToSpeedHeading(m_latitude, m_longitude, velX / 100.0, velY / 100.0, velZ / 100.0, m_speed, m_verticalRate, m_heading); + } +} + +// Find the water vapor saturation pressure for a given temperature. +float waterVapourSaturationPressure(float tCelsius) +{ + // Convert to Kelvin + float T = tCelsius + 273.15f; + + // Correction + T = - 0.4931358f + + (1.0f + 4.6094296e-3f) * T + - 1.3746454e-5f * T * T + + 1.2743214e-8f * T * T * T; + + // Hyland and Wexler equation + float p = expf(-5800.2206f / T + + 1.3914993f + + 6.5459673f * logf(T) + - 4.8640239e-2f * T + + 4.1764768e-5f * T * T + - 1.4452093e-8f * T * T * T); + + // Scale result to hPa + return p / 100.0f; +} + +float calcT(int f, int f1, int f2, float r1, float r2, float *poly, float *cal) +{ + /*float g = (float)(f2-f1) / (r2-r1); // gain + float Rb = (f1*r2-f2*r1) / (float)(f2-f1); // offset + float Rc = f/g - Rb; + float R = Rc * cal[0]; + float T = (poly[0] + poly[1]*R + poly[2]*R*R + cal[1])*(1.0 + cal[2]); + return T; + */ + + // Convert integer measurement to scale factor + float s = (f-f1)/(float)(f2-f1); + + // Calculate resistance (scale between two reference resistors) + float rUncal = r1 + (r2 - r1) * s; + float r = rUncal * cal[0]; + + // Convert resistance to temperature + float tUncal = poly[0] + poly[1]*r + poly[2]*r*r; + + // Correct temperature (5th order polynomial) + float tCal = 0.0f; + for (int i = 6; i > 0; i--) + { + tCal *= tUncal; + tCal += cal[i]; + } + tCal += tUncal; + + return tCal; +} + +float calcU(int cInt, int cMin, int cMax, float c1, float c2, float T, float HT, float *capCal, float *matrixCal) +{ + //qDebug() << "cInt " << cInt << " cMin " << cMin << " cMax " << cMax << " c1 " << c1 << " c2 " << c2 << " T " << T << " HT " << HT << " capCal[0] " << capCal[0] << " capCal[1] " << capCal[1]; + /* + float a0 = 7.5f; + float a1 = 350.0f / capCal[0]; + float fh = (cInt-cMin) / (float)(cMax-cMin); + float rh = 100.0f * (a1*fh - a0); + float T0 = 0.0f; + float T1 = -25.0f; + rh += T0 - T/5.5; + if (T < T1) { + rh *= 1.0 + (T1-T)/90.0; + } + if (rh < 0.0) { + rh = 0.0; + } + if (rh > 100.0) { + rh = 100.0; + } + if (T < -273.0) { + rh = -1.0; + } + + qDebug() << "RH old method: " << rh; */ + + + // Convert integer measurement to scale factor + float s = (cInt - cMin) / (float)(cMax-cMin); + + // Calculate capacitance (scale between two reference caps) + float cUncal = c1 + (c2 - c1) * s; + float cCal = (cUncal / capCal[0] - 1.0f) * capCal[1]; + float uUncal = 0.0f; + float t = (HT - 20.0f) / 180.0f; + float f1 = 1.0f; + for (int i = 0; i < 7; i++) + { + float f2 = 1.0; + for (int j = 0; j < 6; j++) + { + uUncal += f1 * f2 * matrixCal[i*6+j]; + f2 *= t; + } + f1 *= cCal; + } + + // Adjust for difference in outside air temperature and the humidty sensor temperature + float uCal = uUncal * waterVapourSaturationPressure(T) / waterVapourSaturationPressure(HT); + + // Ensure within range of 0..100% + uCal = std::min(100.0f, uCal); + uCal = std::max(0.0f, uCal); + + return uCal; +} + +float calcP(int f, int f1, int f2, float pressureTemp, float *cal) +{ + // Convert integer measurement to scale factor + float s = (f-f1) / (float)(f2-f1); + + float t = pressureTemp; + float t2 = t * t; + float t3 = t2 * t; + + float poly[6]; + poly[0] = cal[0] + cal[7] * t + cal[11] * t2 + cal[15] * t3; + poly[1] = cal[1] + cal[8] * t + cal[12] * t2 + cal[16] * t3; + poly[2] = cal[2] + cal[9] * t + cal[13] * t2 + cal[17] * t3; + poly[3] = cal[3] + cal[10] * t + cal[14] * t2; + poly[4] = cal[4]; + poly[5] = cal[5]; + + float p = cal[6] / s; + float p2 = p * p; + float p3 = p2 * p; + float p4 = p3 * p; + float p5 = p4 * p; + + float pCal = poly[0] + poly[1] * p + poly[2] * p2 + poly[3] * p3 + poly[4] * p4 + poly[5] * p5; + + return pCal; +} + +float RS41Frame::getPressureFloat(const RS41Subframe *subframe) +{ + if (!m_pressureCalibrated) { + calcPressure(subframe); + } + return m_pressure; +} + +QString RS41Frame::getPressureString(const RS41Subframe *subframe) +{ + if (!m_pressureCalibrated) { + calcPressure(subframe); + } + return m_pressureString; +} + +float RS41Frame::getTemperatureFloat(const RS41Subframe *subframe) +{ + if (!m_temperatureCalibrated) { + calcTemperature(subframe); + } + return m_temperature; +} + +QString RS41Frame::getTemperatureString(const RS41Subframe *subframe) +{ + if (!m_temperatureCalibrated) { + calcTemperature(subframe); + } + return m_temperatureString; +} + +void RS41Frame::calcPressure(const RS41Subframe *subframe) +{ + float cal[18]; + + if (m_pressureMain == 0) + { + m_pressure = 0.0f; + m_pressureString = ""; + return; + } + + m_pressureCalibrated = subframe->getPressureCal(cal); + + m_pressure = calcP(m_pressureMain, m_pressureRef1, m_pressureRef2, m_pressureTemp, cal); + + // RS41 pressure resolution of 0.01hPa + m_pressureString = QString::number(m_pressure, 'f', 2); + + if (!m_pressureCalibrated) { + m_pressureString = m_pressureString + "U"; // U for uncalibrated + } +} + +void RS41Frame::calcTemperature(const RS41Subframe *subframe) +{ + float r1, r2; + float poly[3]; + float cal[7]; + + if (m_tempMain == 0) + { + m_temperature = 0.0f; + m_temperatureString = ""; + return; + } + + m_temperatureCalibrated = subframe->getTempCal(r1, r2, poly, cal); + + m_temperature = calcT(m_tempMain, m_tempRef1, m_tempRef2, + r1, r2, + poly, cal); + + // RS41 temperature resolution of 0.01C + m_temperatureString = QString::number(m_temperature, 'f', 2); + + if (!m_temperatureCalibrated) { + m_temperatureString = m_temperatureString + "U"; // U for uncalibrated + } +} + +float RS41Frame::getHumidityTemperatureFloat(const RS41Subframe *subframe) +{ + if (!m_humidityTemperatureCalibrated) { + calcHumidityTemperature(subframe); + } + return m_humidityTemperature; +} + +void RS41Frame::calcHumidityTemperature(const RS41Subframe *subframe) +{ + float r1, r2; + float poly[3]; + float cal[7]; + + if (m_humidityTempMain == 0) + { + m_humidityTemperature = 0.0f; + return; + } + + m_humidityTemperatureCalibrated = subframe->getHumidityTempCal(r1, r2, poly, cal); + + m_humidityTemperature = calcT(m_humidityTempMain, m_humidityTempRef1, m_humidityTempRef2, + r1, r2, + poly, cal); +} + +float RS41Frame::getHumidityFloat(const RS41Subframe *subframe) +{ + if (!m_humidityCalibrated) { + calcHumidity(subframe); + } + return m_humidity; +} + +QString RS41Frame::getHumidityString(const RS41Subframe *subframe) +{ + if (!m_humidityCalibrated) { + calcHumidity(subframe); + } + return m_humidityString; +} + +void RS41Frame::calcHumidity(const RS41Subframe *subframe) +{ + float c1, c2; + float capCal[2]; + float calMatrix[7*6]; + + if (m_humidityMain == 0) + { + m_humidity = 0.0f; + m_humidityString = ""; + return; + } + + float temperature = getTemperatureFloat(subframe); + float humidityTemperature = getHumidityTemperatureFloat(subframe); + + bool humidityCalibrated = subframe->getHumidityCal(c1, c2, capCal, calMatrix); + + m_humidityCalibrated = m_temperatureCalibrated && m_humidityTemperatureCalibrated && humidityCalibrated; + + m_humidity = calcU(m_humidityMain, m_humidityRef1, m_humidityRef2, + c1, c2, + temperature, humidityTemperature, + capCal, calMatrix); + + // RS41 humidity resolution of 0.1% + m_humidityString = QString::number(m_humidity, 'f', 1); + + if (!m_humidityCalibrated) { + m_humidityString = m_humidityString + "U"; // U for uncalibrated + } +} + +RS41Frame* RS41Frame::decode(const QByteArray ba) +{ + return new RS41Frame(ba); +} + +int RS41Frame::getFrameLength(int frameType) +{ + return frameType == RS41_FRAME_STD ? RS41_LENGTH_STD : RS41_LENGTH_EXT; +} + +RS41Subframe::RS41Subframe() : + m_subframe(51*16, (char)0) +{ + for (int i = 0; i < 51; i++) { + m_subframeValid[i] = false; + } +} + +// Update subframe with subframe data from received message +void RS41Subframe::update(RS41Frame *message) +{ + m_subframeValid[message->m_subframeNumber] = true; + int offset = message->m_subframeNumber * 16; + for (int i = 0; i < 16; i++) { + m_subframe[offset+i] = message->m_subframe[i]; + } +} + +// Indicate if we have all the required temperature calibration data +bool RS41Subframe::hasTempCal() const +{ + return m_subframeValid[3] && m_subframeValid[4] && m_subframeValid[5] && m_subframeValid[6] && m_subframeValid[7]; +} + +// Get temperature calibration data +// r1, r2 - Temperature reference resistances (Ohms) +// poly - Resistance to temperature 2nd order polynomial +bool RS41Subframe::getTempCal(float &r1, float &r2, float *poly, float *cal) const +{ + if (hasTempCal()) + { + r1 = getFloat(0x3d); + r2 = getFloat(0x41); + for (int i = 0; i < 3; i++) { + poly[i] = getFloat(0x4d + i * 4); + } + for (int i = 0; i < 7; i++) { + cal[i] = getFloat(0x59 + i * 4); + } + return true; + } + else + { + // Use default values + r1 = 750.0f; + r2 = 1100.0f; + poly[0] = -243.9108f; + poly[1] = 0.187654f; + poly[2] = 8.2e-06f; + cal[0] = 1.279928f; + for (int i = 1; i < 7; i++) { + cal[i] = 0.0f; + } + return false; + } +} + +// Indicate if we have all the required humidty calibration data +bool RS41Subframe::hasHumidityCal() const +{ + return m_subframeValid[4] && m_subframeValid[7] + && m_subframeValid[8] && m_subframeValid[9] && m_subframeValid[0xa] && m_subframeValid[0xb] + && m_subframeValid[0xc] && m_subframeValid[0xd] && m_subframeValid[0xe] && m_subframeValid[0xf] + && m_subframeValid[0x10] && m_subframeValid[0x11] && m_subframeValid[0x12]; +} + +// Get humidty calibration data +bool RS41Subframe::getHumidityCal(float &c1, float &c2, float *capCal, float *calMatrix) const +{ + if (hasHumidityCal()) + { + c1 = getFloat(0x45); + c2 = getFloat(0x49); + for (int i = 0; i < 2; i++) { + capCal[i] = getFloat(0x75 + i * 4); + } + for (int i = 0; i < 7*6; i++) { + calMatrix[i] = getFloat(0x7d + i * 4); + } + return true; + } + else + { + // Use default values + c1 = 0.0f; + c2 = 47.0f; + capCal[0] = 45.9068f; + capCal[1] = 4.92924f; + static const float calMatrixDefault[7*6] = { + -0.002586f, -2.24367f, 9.92294f, -3.61913f, 54.3554f, -93.3012f, + 51.7056f, 38.8709f, 209.437f, -378.437f, 9.17326f, 19.5301f, + 150.257f, -150.907f, -280.315f, 182.293f, 3247.39f, 4083.65f, + -233.568f, 345.375f, 200.217f, -388.246f, -3617.66f, 0.0f, + 225.841f, -233.051f, 0.0f, 0.0f, 0.0f, 0.0f, + -93.0635f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + }; + std::copy(calMatrixDefault, calMatrixDefault + 7*6, calMatrix); + return false; + } +} + +// Indicate if we have all the required humidty temperature sensor calibration data +bool RS41Subframe::hasHumidityTempCal() const +{ + return m_subframeValid[3] && m_subframeValid[4] && m_subframeValid[0x12] && m_subframeValid[0x13] && m_subframeValid[0x14]; +} + +// Get humidty temperature sensor calibration data +bool RS41Subframe::getHumidityTempCal(float &r1, float &r2, float *poly, float *cal) const +{ + if (hasHumidityTempCal()) + { + r1 = getFloat(0x3d); + r2 = getFloat(0x41); + for (int i = 0; i < 3; i++) { + poly[i] = getFloat(0x125 + i * 4); + } + for (int i = 0; i < 7; i++) { + cal[i] = getFloat(0x131 + i * 4); + } + return true; + } + else + { + // Use default values + r1 = 750.0f; + r2 = 1100.0f; + poly[0] = -243.9108f; + poly[1] = 0.187654f; + poly[2] = 8.2e-06f; + cal[0] = 1.279928f; + for (int i = 1; i < 7; i++) { + cal[i] = 0.0f; + } + return false; + } +} + +// Indicate if we have all the required pressure calibration data +bool RS41Subframe::hasPressureCal() const +{ + return m_subframeValid[0x25] && m_subframeValid[0x26] && m_subframeValid[0x27] + && m_subframeValid[0x28] && m_subframeValid[0x29] && m_subframeValid[0x2a]; +} + +// Get pressure calibration data +bool RS41Subframe::getPressureCal(float *cal) const +{ + if (hasPressureCal()) + { + for (int i = 0; i < 18; i++) { + cal[i] = getFloat(0x25e + i * 4); + } + return true; + } + else + { + // Use default values - TODO: Need to obtain from inflight device + for (int i = 0; i < 18; i++) { + cal[i] = 0.0f; + } + return false; + } +} + +// Get type of RS41. E.g. "RS41-SGP" +QString RS41Subframe::getType() const +{ + if (m_subframeValid[0x21] & m_subframeValid[0x22]) + { + return QString(m_subframe.mid(0x218, 10)).trimmed(); + } + else + { + return "RS41"; + } +} + +// Get transmission frequency in MHz +QString RS41Subframe::getFrequencyMHz() const +{ + if (m_subframeValid[0]) + { + uint8_t lower = m_subframe[2] & 0xff; + uint8_t upper = m_subframe[3] & 0xff; + float freq = 400.0 + (upper + (lower / 255.0)) * 0.04; + return QString::number(freq, 'f', 3); + } + else + { + return ""; + } +} + +QString RS41Subframe::getBurstKillStatus() const +{ + if (m_subframeValid[2]) + { + uint8_t status = m_subframe[0x2b]; + return status == 0 ? "Inactive" : "Active"; + } + else + { + return ""; + } +} + +// Seconds until power-off once active +QString RS41Subframe::getBurstKillTimer() const +{ + if (m_subframeValid[0x31]) + { + uint16_t secs = getUInt16(0x316); + QTime t(0, 0, 0); + t = t.addSecs(secs); + return t.toString("hh:mm:ss"); + } + else + { + return ""; + } +} + +uint16_t RS41Subframe::getUInt16(int offset) const +{ + return (m_subframe[offset] & 0xff) | ((m_subframe[offset+1] & 0xff) << 8); +} + +float RS41Subframe::getFloat(int offset) const +{ + float f; + // Assumes host is little endian with 32-bit float + memcpy(&f, m_subframe.data() + offset, 4); + return f; +} diff --git a/sdrbase/util/radiosonde.h b/sdrbase/util/radiosonde.h new file mode 100644 index 000000000..c21cdb50b --- /dev/null +++ b/sdrbase/util/radiosonde.h @@ -0,0 +1,180 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOSONDE_H +#define INCLUDE_RADIOSONDE_H + +#include +#include +#include + +#include +#include + +#include "util/units.h" + +#include "export.h" + +#define RS41_LENGTH_STD 320 +#define RS41_LENGTH_EXT 518 + +#define RS41_OFFSET_RS 0x08 +#define RS41_OFFSET_FRAME_TYPE 0x38 +#define RS41_OFFSET_BLOCK_0 0x39 + +#define RS41_FRAME_STD 0x0f +#define RS41_FRAME_EXT 0xf0 + +#define RS41_ID_STATUS 0x79 +#define RS41_ID_MEAS 0x7a +#define RS41_ID_GPSINFO 0x7c +#define RS41_ID_GPSRAW 0x7d +#define RS41_ID_GPSPOS 0x7b +#define RS41_ID_EMPTY 0x76 + +#define RS41_RS_N 255 +#define RS41_RS_K 231 +#define RS41_RS_2T (RS41_RS_N-RS41_RS_K) +#define RS41_RS_INTERLEAVE 2 +#define RS41_RS_DATA (264/RS41_RS_INTERLEAVE) +#define RS41_RS_PAD (RS41_RS_K-RS41_RS_DATA) + +class RS41Subframe; + +// Frame of data transmitted by RS41 radiosonde +class SDRBASE_API RS41Frame { +public: + + // Status + bool m_statusValid; + uint16_t m_frameNumber; // Increments every frame + QString m_serial; // Serial number + float m_batteryVoltage; // In volts + QString m_flightPhase; // On ground, ascent, descent + QString m_batteryStatus; // OK or Low + uint8_t m_pcbTemperature; // In degrees C + uint16_t m_humiditySensorHeating; // 0..1000 + uint8_t m_transmitPower; // 0..7 + uint8_t m_maxSubframeNumber; + uint8_t m_subframeNumber; + QByteArray m_subframe; // 16 bytes of subframe + + // Meas + bool m_measValid; + uint32_t m_tempMain; + uint32_t m_tempRef1; + uint32_t m_tempRef2; + uint32_t m_humidityMain; + uint32_t m_humidityRef1; + uint32_t m_humidityRef2; + uint32_t m_humidityTempMain; + uint32_t m_humidityTempRef1; + uint32_t m_humidityTempRef2; + uint32_t m_pressureMain; + uint32_t m_pressureRef1; + uint32_t m_pressureRef2; + float m_pressureTemp; // Pressure sensor module temperature - In degrees C + + // GPSInfo + bool m_gpsInfoValid; + QDateTime m_gpsDateTime; + + // GPSPos + bool m_posValid; + double m_latitude; // In degrees + double m_longitude; // In degrees + double m_height; // In metres + double m_speed; // In m/s + double m_heading; // In degreees + double m_verticalRate; // In m/s + int m_satellitesUsed; + + RS41Frame(const QByteArray ba); + ~RS41Frame() {} + QString toHex(); + void decodeStatus(const QByteArray ba); + void decodeMeas(const QByteArray ba); + void decodeGPSInfo(const QByteArray ba); + void decodeGPSPos(const QByteArray ba); + + float getPressureFloat(const RS41Subframe *subframe); + QString getPressureString(const RS41Subframe *subframe); + float getTemperatureFloat(const RS41Subframe *subframe); + QString getTemperatureString(const RS41Subframe *subframe); + float getHumidityTemperatureFloat(const RS41Subframe *subframe); + float getHumidityFloat(const RS41Subframe *subframe); + QString getHumidityString(const RS41Subframe *subframe); + + static RS41Frame* decode(const QByteArray ba); + static int getFrameLength(int frameType); + +protected: + uint16_t getUInt16(const QByteArray ba, int offset) const; + uint32_t getUInt24(const QByteArray ba, int offset) const; + uint32_t getUInt32(const QByteArray ba, int offset) const; + + void calcPressure(const RS41Subframe *subframe); + void calcTemperature(const RS41Subframe *subframe); + void calcHumidityTemperature(const RS41Subframe *subframe); + void calcHumidity(const RS41Subframe *subframe); + + QByteArray m_bytes; + + float m_pressure; + QString m_pressureString; + bool m_pressureCalibrated; + float m_temperature; + QString m_temperatureString; + bool m_temperatureCalibrated; + float m_humidityTemperature; + bool m_humidityTemperatureCalibrated; + float m_humidity; + QString m_humidityString; + bool m_humidityCalibrated; + +}; + +// RS41 subframe holding calibration data collected from multiple RS51Frames +class SDRBASE_API RS41Subframe { +public: + + RS41Subframe(); + void update(RS41Frame *message); + bool hasTempCal() const; + bool getTempCal(float &r1, float &r2, float *poly, float *cal) const; + bool hasHumidityCal() const; + bool getHumidityCal(float &c1, float &c2, float *capCal, float *calMatrix) const; + bool hasHumidityTempCal() const; + bool getHumidityTempCal(float &r1, float &r2, float *poly, float *cal) const; + bool hasPressureCal() const; + bool getPressureCal(float *cal) const; + QString getType() const; + QString getFrequencyMHz() const; + QString getBurstKillStatus() const; + QString getBurstKillTimer() const; + +protected: + + bool m_subframeValid[51]; + QByteArray m_subframe; + + uint16_t getUInt16(int offset) const; + float getFloat(int offset) const; + +}; + +#endif // INCLUDE_RADIOSONDE_H diff --git a/sdrbase/util/reedsolomon.h b/sdrbase/util/reedsolomon.h new file mode 100644 index 000000000..7991d32bb --- /dev/null +++ b/sdrbase/util/reedsolomon.h @@ -0,0 +1,650 @@ +/* + * Reed-Solomon -- Reed-Solomon encoder / decoder library + * + * Copyright (c) 2014 Hard Consulting Corporation. + * Copyright (c) 2006 Phil Karn, KA9Q + * + * It may be used under the terms of the GNU Lesser General Public License (LGPL). + * + * Simplified version of https://github.com/pjkundert/ezpwd-reed-solomon which + * seems to be the fastest open-source decoder. + * + */ + +#ifndef REEDSOLOMON_H +#define REEDSOLOMON_H + +#include +#include +#include +#include +#include +#include + +// Preprocessor defines available: +// +// EZPWD_NO_MOD_TAB -- define to force no "modnn" Galois modulo table acceleration +// +//#define EZPWD_NO_MOD_TAB + +namespace ReedSolomon { + +// +// reed_solomon_base - Reed-Solomon codec generic base class +// +class reed_solomon_base { +public: + virtual size_t datum() const = 0; // a data element's bits + virtual size_t symbol() const = 0; // a symbol's bits + virtual int size() const = 0; // R-S block size (maximum total symbols) + virtual int nroots() const = 0; // R-S roots (parity symbols) + virtual int load() const = 0; // R-S net payload (data symbols) + + virtual ~reed_solomon_base() {} + + reed_solomon_base() {} + + // + // {en,de}code -- Compute/Correct errors/erasures in a Reed-Solomon encoded container + // + /// For decode, optionally specify some known erasure positions (up to nroots()). If + /// non-empty 'erasures' is provided, it contains the positions of each erasure. If a + /// non-zero pointer to a 'position' vector is provided, its capacity will be increased to + /// be capable of storing up to 'nroots()' ints; the actual deduced error locations will be + /// returned. + /// + /// RETURN VALUE + /// + /// Return -1 on error. The encode returns the number of parity symbols produced; + /// decode returns the number of symbols corrected. Both errors and erasures are included, + /// so long as they are actually different than the deduced value. In other words, if a + /// symbol is marked as an erasure but it actually turns out to be correct, it's index will + /// NOT be included in the returned count, nor the modified erasure vector! + /// + + virtual int encode(const uint8_t *data, int len, uint8_t *parity) const = 0; + + virtual int decode1(uint8_t *data, int len, uint8_t *parity, + const std::vector &erasure = std::vector(), std::vector *position = 0) const = 0; + + int decode(uint8_t *data, + int len, + int pad = 0, // ignore 'pad' symbols at start of array + const std::vector &erasure = std::vector(), + std::vector *position = 0) const + { + return decode1((uint8_t*)(data + pad), len, (uint8_t*)(data + len), erasure, position); + } + +}; + +// +// gfpoly - default field polynomial generator functor. +// +template +struct gfpoly { + int operator()(int sr) const + { + if (sr == 0) { + sr = 1; + } else { + sr <<= 1; + if (sr & (1 << 8)) + sr ^= PLY; + sr &= ((1 << 8) - 1); + } + return sr; + } +}; + +// +// class reed_solomon_tabs -- R-S tables common to all RS(NN,*) with same SYM, PRM and PLY +// +template +class reed_solomon_tabs : public reed_solomon_base { +public: + typedef uint8_t symbol_t; + static const size_t DATUM = 8; // bits + static const size_t SYMBOL = 8; // bits / symbol + static const int MM = 8; + static const int SIZE = (1 << 8) - 1; // maximum symbols in field + static const int NN = SIZE; + static const int A0 = SIZE; + static const int MODS // modulo table: 1/2 the symbol size squared, up to 4k +#if defined(EZPWD_NO_MOD_TAB) + = 0; +#else + = 8 > 8 ? (1 << 12) : (1 << 8 << 8 / 2); +#endif + + static int iprim; // initialized to -1, below + +protected: + static std::array alpha_to; + static std::array index_of; + static std::array mod_of; + virtual ~reed_solomon_tabs() {} + + reed_solomon_tabs() : reed_solomon_base() + { + // Do init if not already done. We check one value which is initialized to -1; this is + // safe, 'cause the value will not be set 'til the initializing thread has completely + // initialized the structure. Worst case scenario: multiple threads will initialize + // identically. No mutex necessary. + if (iprim >= 0) + return; + + // Generate Galois field lookup tables + index_of[0] = A0; // log(zero) = -inf + alpha_to[A0] = 0; // alpha**-inf = 0 + PLY poly; + int sr = poly(0); + for (int i = 0; i < NN; i++) { + index_of[sr] = i; + alpha_to[i] = sr; + sr = poly(sr); + } + // If it's not primitive, raise exception or abort + if (sr != alpha_to[0]) { + abort(); + } + + // Generate modulo table for some commonly used (non-trivial) values + for (int x = NN; x < NN + MODS; ++x) + mod_of[x - NN] = _modnn(x); + // Find prim-th root of 1, index form, used in decoding. + int iptmp = 1; + while (iptmp % PRM != 0) + iptmp += NN; + iprim = iptmp / PRM; + } + + // + // modnn -- modulo replacement for galois field arithmetics, optionally w/ table acceleration + // + // @x: the value to reduce (will never be -'ve) + // + // where + // MM = number of bits per symbol + // NN = (2^MM) - 1 + // + // Simple arithmetic modulo would return a wrong result for values >= 3 * NN + // + uint8_t _modnn(int x) const + { + while (x >= NN) { + x -= NN; + x = (x >> MM) + (x & NN); + } + return x; + } + + uint8_t modnn(int x) const + { + while (x >= NN + MODS) { + x -= NN; + x = (x >> MM) + (x & NN); + } + if (MODS && x >= NN) + x = mod_of[x - NN]; + return x; + } +}; + +// +// class reed_solomon - Reed-Solomon codec +// +// @TYP: A symbol datum; {en,de}code operates on arrays of these +// @DATUM: Bits per datum (a TYP()) +// @SYM{BOL}, MM: Bits per symbol +// @NN: Symbols per block (== (1< instances with the same template type parameters share a common +// (static) set of alpha_to, index_of and genpoly tables. The first instance to be constructed +// initializes the tables. +// +// Each specialized type of reed_solomon implements a specific encode/decode method +// appropriate to its datum 'TYP'. When accessed via a generic reed_solomon_base pointer, only +// access via "safe" (size specifying) containers or iterators is available. +// +template +class reed_solomon : public reed_solomon_tabs { +public: + typedef reed_solomon_tabs tabs_t; + using tabs_t::A0; + using tabs_t::DATUM; + using tabs_t::MM; + using tabs_t::NN; + using tabs_t::SIZE; + using tabs_t::SYMBOL; + + using tabs_t::iprim; + + using tabs_t::alpha_to; + using tabs_t::index_of; + + using tabs_t::modnn; + + static const int NROOTS = RTS; + static const int LOAD = SIZE - NROOTS; // maximum non-parity symbol payload + +protected: + static std::array genpoly; + +public: + virtual size_t datum() const { return DATUM; } + + virtual size_t symbol() const { return SYMBOL; } + + virtual int size() const { return SIZE; } + + virtual int nroots() const { return NROOTS; } + + virtual int load() const { return LOAD; } + + using reed_solomon_base::decode; + virtual int decode1(uint8_t *data, int len, uint8_t *parity, + const std::vector &erasure = std::vector(), std::vector *position = 0) const + { + return decode_mask(data, len, parity, erasure, position); + } + + // + // decode_mask -- mask INP data into valid SYMBOL data + // + /// Incoming data may be in a variety of sizes, and may contain information beyond the + /// R-S symbol capacity. For example, we might use a 6-bit R-S symbol to correct the lower + /// 6 bits of an 8-bit data character. This would allow us to correct common substitution + /// errors (such as '2' for '3', 'R' for 'T', 'n' for 'm'). + /// + int decode_mask(uint8_t *data, int len, + uint8_t *parity = 0, // either 0, or pointer to all parity symbols + const std::vector &erasure = std::vector(), std::vector *position = 0) const + { + if (!parity) { + len -= NROOTS; + parity = data + len; + } + + std::array tmp; + uint8_t msk = static_cast(~0UL << SYMBOL); + + + int corrects; + if (!erasure.size() && !position) { + // No erasures, and error position info not wanted. + corrects = decode(data, len, parity); + } else { + // Either erasure location info specified, or resultant error position info wanted; + // Prepare pos (a temporary, if no position vector provided), and copy any provided + // erasure positions. After number of corrections is known, resize the position + // vector. Thus, we use any supplied erasure info, and optionally return any + // correction position info separately. + std::vector _pos; + std::vector &pos = position ? *position : _pos; + pos.resize(std::max(size_t(NROOTS), erasure.size())); + std::copy(erasure.begin(), erasure.end(), pos.begin()); + corrects = decode(data, len, parity, &pos.front(), erasure.size()); + if (corrects > int(pos.size())) { + return -1; + } + pos.resize(std::max(0, corrects)); + } + + return corrects; + } + + virtual ~reed_solomon() + { + } + + reed_solomon() : reed_solomon_tabs() + { + // We check one element of the array; this is safe, 'cause the value will not be + // initialized 'til the initializing thread has completely initialized the array. Worst + // case scenario: multiple threads will initialize identically. No mutex necessary. + if (genpoly[0]) + return; + + std::array tmppoly; // uninitialized + // Form RS code generator polynomial from its roots. Only lower-index entries are + // consulted, when computing subsequent entries; only index 0 needs initialization. + tmppoly[0] = 1; + for (int i = 0, root = FCR * PRM; i < NROOTS; i++, root += PRM) { + tmppoly[i + 1] = 1; + // Multiply tmppoly[] by @**(root + x) + for (int j = i; j > 0; j--) { + if (tmppoly[j] != 0) + tmppoly[j] = tmppoly[j - 1] ^ alpha_to[modnn(index_of[tmppoly[j]] + root)]; + else + tmppoly[j] = tmppoly[j - 1]; + } + // tmppoly[0] can never be zero + tmppoly[0] = alpha_to[modnn(index_of[tmppoly[0]] + root)]; + } + // convert NROOTS entries of tmppoly[] to genpoly[] in index form for quicker encoding, + // in reverse order so genpoly[0] is last element initialized. + for (int i = NROOTS; i >= 0; --i) + genpoly[i] = index_of[tmppoly[i]]; + } + + virtual int encode(const uint8_t *data, int len, uint8_t *parity) // at least nroots + const + { + // Check length parameter for validity + int pad = NN - NROOTS - len; + for (int i = 0; i < NROOTS; i++) parity[i] = 0; + for (int i = 0; i < len; i++) { + uint8_t feedback = index_of[data[i] ^ parity[0]]; + if (feedback != A0) { + for (int j = 1; j < NROOTS; j++) + parity[j] ^= alpha_to[modnn(feedback + genpoly[NROOTS - j])]; + } + + std::rotate(parity, parity + 1, parity + NROOTS); + if (feedback != A0) + parity[NROOTS - 1] = alpha_to[modnn(feedback + genpoly[0])]; + else + parity[NROOTS - 1] = 0; + } + return NROOTS; + } + + int decode(uint8_t *data, int len, + uint8_t *parity, // Requires: at least NROOTS + int *eras_pos = 0, // Capacity: at least NROOTS + int no_eras = 0, // Maximum: at most NROOTS + uint8_t *corr = 0) // Capacity: at least NROOTS + const + { + typedef std::array typ_nroots; + typedef std::array typ_nroots_1; + typedef std::array int_nroots; + + typ_nroots_1 lambda{{0}}; + typ_nroots syn; + typ_nroots_1 b; + typ_nroots_1 t; + typ_nroots_1 omega; + int_nroots root; + typ_nroots_1 reg; + int_nroots loc; + int count = 0; + + // Check length parameter and erasures for validity + int pad = NN - NROOTS - len; + if (no_eras) { + if (no_eras > NROOTS) { + return -1; + } + for (int i = 0; i < no_eras; ++i) { + if (eras_pos[i] < 0 || eras_pos[i] >= len + NROOTS) { + return -1; + } + } + } + + // form the syndromes; i.e., evaluate data(x) at roots of g(x) + for (int i = 0; i < NROOTS; i++) + syn[i] = data[0]; + + for (int j = 1; j < len; j++) { + for (int i = 0; i < NROOTS; i++) { + if (syn[i] == 0) { + syn[i] = data[j]; + } else { + syn[i] = data[j] ^ alpha_to[modnn(index_of[syn[i]] + (FCR + i) * PRM)]; + } + } + } + + for (int j = 0; j < NROOTS; j++) { + for (int i = 0; i < NROOTS; i++) { + if (syn[i] == 0) { + syn[i] = parity[j]; + } else { + syn[i] = parity[j] ^ alpha_to[modnn(index_of[syn[i]] + (FCR + i) * PRM)]; + } + } + } + + // Convert syndromes to index form, checking for nonzero condition + uint8_t syn_error = 0; + for (int i = 0; i < NROOTS; i++) { + syn_error |= syn[i]; + syn[i] = index_of[syn[i]]; + } + + int deg_lambda = 0; + int deg_omega = 0; + int r = no_eras; + int el = no_eras; + if (!syn_error) { + // if syndrome is zero, data[] is a codeword and there are no errors to correct. + count = 0; + goto finish; + } + + lambda[0] = 1; + if (no_eras > 0) { + // Init lambda to be the erasure locator polynomial. Convert erasure positions + // from index into data, to index into Reed-Solomon block. + lambda[1] = alpha_to[modnn(PRM * (NN - 1 - (eras_pos[0] + pad)))]; + for (int i = 1; i < no_eras; i++) { + uint8_t u = modnn(PRM * (NN - 1 - (eras_pos[i] + pad))); + for (int j = i + 1; j > 0; j--) { + uint8_t tmp = index_of[lambda[j - 1]]; + if (tmp != A0) { + lambda[j] ^= alpha_to[modnn(u + tmp)]; + } + } + } + } + + for (int i = 0; i < NROOTS + 1; i++) + b[i] = index_of[lambda[i]]; + + // + // Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial + // + while (++r <= NROOTS) { // r is the step number + // Compute discrepancy at the r-th step in poly-form + uint8_t discr_r = 0; + for (int i = 0; i < r; i++) { + if ((lambda[i] != 0) && (syn[r - i - 1] != A0)) { + discr_r ^= alpha_to[modnn(index_of[lambda[i]] + syn[r - i - 1])]; + } + } + discr_r = index_of[discr_r]; // Index form + if (discr_r == A0) { + // 2 lines below: B(x) <-- x*B(x) + // Rotate the last element of b[NROOTS+1] to b[0] + std::rotate(b.begin(), b.begin() + NROOTS, b.end()); + b[0] = A0; + } else { + // 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) + t[0] = lambda[0]; + for (int i = 0; i < NROOTS; i++) { + if (b[i] != A0) { + t[i + 1] = lambda[i + 1] ^ alpha_to[modnn(discr_r + b[i])]; + } else + t[i + 1] = lambda[i + 1]; + } + if (2 * el <= r + no_eras - 1) { + el = r + no_eras - el; + // 2 lines below: B(x) <-- inv(discr_r) * lambda(x) + for (int i = 0; i <= NROOTS; i++) { + b[i] = ((lambda[i] == 0) ? A0 : modnn(index_of[lambda[i]] - discr_r + NN)); + } + } else { + // 2 lines below: B(x) <-- x*B(x) + std::rotate(b.begin(), b.begin() + NROOTS, b.end()); + b[0] = A0; + } + lambda = t; + } + } + + // Convert lambda to index form and compute deg(lambda(x)) + for (int i = 0; i < NROOTS + 1; i++) { + lambda[i] = index_of[lambda[i]]; + if (lambda[i] != NN) + deg_lambda = i; + } + // Find roots of error+erasure locator polynomial by Chien search + reg = lambda; + count = 0; // Number of roots of lambda(x) + for (int i = 1, k = iprim - 1; i <= NN; i++, k = modnn(k + iprim)) { + uint8_t q = 1; // lambda[0] is always 0 + for (int j = deg_lambda; j > 0; j--) { + if (reg[j] != A0) { + reg[j] = modnn(reg[j] + j); + q ^= alpha_to[reg[j]]; + } + } + if (q != 0) + continue; // Not a root + // store root (index-form) and error location number + root[count] = i; + loc[count] = k; + // If we've already found max possible roots, abort the search to save time + if (++count == deg_lambda) + break; + } + if (deg_lambda != count) { + // deg(lambda) unequal to number of roots => uncorrectable error detected + count = -1; + goto finish; + } + // + // Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo x**NROOTS). in + // index form. Also find deg(omega). + // + deg_omega = deg_lambda - 1; + for (int i = 0; i <= deg_omega; i++) { + uint8_t tmp = 0; + for (int j = i; j >= 0; j--) { + if ((syn[i - j] != A0) && (lambda[j] != A0)) + tmp ^= alpha_to[modnn(syn[i - j] + lambda[j])]; + } + omega[i] = index_of[tmp]; + } + + // + // Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = inv(X(l))**(fcr-1) + // and den = lambda_pr(inv(X(l))) all in poly-form + // + for (int j = count - 1; j >= 0; j--) { + uint8_t num1 = 0; + for (int i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= alpha_to[modnn(omega[i] + i * root[j])]; + } + uint8_t num2 = alpha_to[modnn(root[j] * (FCR - 1) + NN)]; + uint8_t den = 0; + + // lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] + for (int i = std::min(deg_lambda, NROOTS - 1) & ~1; i >= 0; i -= 2) { + if (lambda[i + 1] != A0) { + den ^= alpha_to[modnn(lambda[i + 1] + i * root[j])]; + } + } + // Apply error to data. Padding ('pad' unused symbols) begin at index 0. + if (num1 != 0) { + if (loc[j] < pad) { + // If the computed error position is in the 'pad' (the unused portion of the + // R-S data capacity), then our solution has failed -- we've computed a + // correction location outside of the data and parity we've been provided! + count = -1; + goto finish; + } + + uint8_t cor = alpha_to[modnn(index_of[num1] + index_of[num2] + NN - index_of[den])]; + // Store the error correction pattern, if a correction buffer is available + if (corr) + corr[j] = cor; + // If a data/parity buffer is given and the error is inside the message or + // parity data, correct it + if (loc[j] < (NN - NROOTS)) { + if (data) { + data[loc[j] - pad] ^= cor; + } + } else if (loc[j] < NN) { + if (parity) + parity[loc[j] - (NN - NROOTS)] ^= cor; + } + } + } + + finish: + if (eras_pos != NULL) { + for (int i = 0; i < count; i++) + eras_pos[i] = loc[i] - pad; + } + return count; + } +}; + +// +// Define the static reed_solomon...<...> members; allowed in header for template types. +// +// The reed_solomon_tags<...>::iprim < 0 is used to indicate to the first instance that the +// static tables require initialization. +// +template +int reed_solomon_tabs::iprim = -1; + +template +std::array::NN + 1> reed_solomon_tabs::alpha_to; + +template +std::array::NN + 1> reed_solomon_tabs::index_of; +template +std::array::MODS> reed_solomon_tabs::mod_of; + +template +std::array::NROOTS + 1> reed_solomon::genpoly; + +// +// RS( ... ) -- Define a reed-solomon codec +// +// @SYMBOLS: Total number of symbols; must be a power of 2 minus 1, eg 2^8-1 == 255 +// @PAYLOAD: The maximum number of non-parity symbols, eg 253 ==> 2 parity symbols +// @POLY: A primitive polynomial appropriate to the SYMBOLS size +// @FCR: The first consecutive root of the Reed-Solomon generator polynomial +// @PRIM: The primitive root of the generator polynomial +// + +// +// RS -- Standard partial specializations for Reed-Solomon codec type access +// +// Normally, Reed-Solomon codecs are described with terms like RS(255,252). Obtain various +// standard Reed-Solomon codecs using macros of a similar form, eg. RS<255, 252>. Standard PLY, +// FCR and PRM values are provided for various SYMBOL sizes, along with appropriate basic types +// capable of holding all internal Reed-Solomon tabular data. +// +// In order to provide "default initialization" of const RS<...> types, a user-provided +// default constructor must be provided. +// +template +struct RS; +template +struct RS<255, PAYLOAD> : public ReedSolomon::reed_solomon<(255) - (PAYLOAD), 0, 1, ReedSolomon::gfpoly<0x11d>> +{ + RS() + : ReedSolomon::reed_solomon<(255) - (PAYLOAD), 0, 1, ReedSolomon::gfpoly<0x11d>>() + { + } +}; + +} // namespace ReedSolomon + +#endif // REEDSOLOMON_H diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 0f5034bbe..516b455c2 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -4317,6 +4317,11 @@ bool WebAPIRequestMapper::getChannelSettings( channelSettings->setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings()); channelSettings->getRadioClockSettings()->fromJsonObject(settingsJsonObject); } + else if (channelSettingsKey == "RadiosondeDemodSettings") + { + channelSettings->setRadiosondeDemodSettings(new SWGSDRangel::SWGRadiosondeDemodSettings()); + channelSettings->getRadiosondeDemodSettings()->fromJsonObject(settingsJsonObject); + } else if (channelSettingsKey == "RemoteSinkSettings") { channelSettings->setRemoteSinkSettings(new SWGSDRangel::SWGRemoteSinkSettings()); @@ -4840,6 +4845,11 @@ bool WebAPIRequestMapper::getFeatureSettings( featureSettings->setStarTrackerSettings(new SWGSDRangel::SWGStarTrackerSettings()); featureSettings->getStarTrackerSettings()->fromJsonObject(settingsJsonObject); } + else if (featureSettingsKey == "RadiosondeSettings") + { + featureSettings->setRadiosondeSettings(new SWGSDRangel::SWGRadiosondeSettings()); + featureSettings->getRadiosondeSettings()->fromJsonObject(settingsJsonObject); + } else if (featureSettingsKey == "RigCtlServerSettings") { featureSettings->setRigCtlServerSettings(new SWGSDRangel::SWGRigCtlServerSettings()); @@ -5060,6 +5070,7 @@ void WebAPIRequestMapper::resetChannelSettings(SWGSDRangel::SWGChannelSettings& channelSettings.setPagerDemodSettings(nullptr); channelSettings.setRadioAstronomySettings(nullptr); channelSettings.setRadioClockSettings(nullptr); + channelSettings.setRadiosondeDemodSettings(nullptr); channelSettings.setRemoteSinkSettings(nullptr); channelSettings.setRemoteSourceSettings(nullptr); channelSettings.setSsbDemodSettings(nullptr); @@ -5091,6 +5102,7 @@ void WebAPIRequestMapper::resetChannelReport(SWGSDRangel::SWGChannelReport& chan channelReport.setPacketModReport(nullptr); channelReport.setRadioAstronomyReport(nullptr); channelReport.setRadioClockReport(nullptr); + channelReport.setRadiosondeDemodReport(nullptr); channelReport.setRemoteSourceReport(nullptr); channelReport.setSsbDemodReport(nullptr); channelReport.setSsbModReport(nullptr); @@ -5130,6 +5142,7 @@ void WebAPIRequestMapper::resetFeatureSettings(SWGSDRangel::SWGFeatureSettings& { featureSettings.cleanup(); featureSettings.setFeatureType(nullptr); + featureSettings.setAisSettings(nullptr); featureSettings.setAntennaToolsSettings(nullptr); featureSettings.setAprsSettings(nullptr); featureSettings.setGs232ControllerSettings(nullptr); @@ -5138,6 +5151,7 @@ void WebAPIRequestMapper::resetFeatureSettings(SWGSDRangel::SWGFeatureSettings& featureSettings.setSatelliteTrackerSettings(nullptr); featureSettings.setSimplePttSettings(nullptr); featureSettings.setStarTrackerSettings(nullptr); + featureSettings.setRadiosondeSettings(nullptr); featureSettings.setRigCtlServerSettings(nullptr); } diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index b01330bac..8a11a53d0 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -58,6 +58,7 @@ const QMap WebAPIUtils::m_channelURIToSettingsKey = { {"sdrangel.channeltx.modpacket", "PacketModSettings"}, {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, {"sdrangel.channel.radioclock", "RadioClockSettings"}, + {"sdrangel.channel.radiosondedemod", "RadiosondeDemodSettings"}, {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, {"sdrangel.channeltx.modssb", "SSBModSettings"}, @@ -159,6 +160,7 @@ const QMap WebAPIUtils::m_channelTypeToSettingsKey = { {"LocalSource", "LocalSourceSettings"}, {"RadioAstronomy", "RadioAstronomySettings"}, {"RadioClock", "RadioClockSettings"}, + {"RadiosondeDemod", "RadiosondeDemodSettings"}, {"RemoteSink", "RemoteSinkSettings"}, {"RemoteSource", "RemoteSourceSettings"}, {"SSBMod", "SSBModSettings"}, @@ -273,6 +275,7 @@ const QMap WebAPIUtils::m_featureTypeToSettingsKey = { {"GS232Controller", "GS232ControllerSettings"}, // a.k.a Rotator Controller {"Map", "MapSettings"}, {"PERTester", "PERTesterSettings"}, + {"Radiosonde", "RadiosondeSettings"}, {"RigCtlServer", "RigCtlServerSettings"}, {"SatelliteTracker", "SatelliteTrackerSettings"}, {"SimplePTT", "SimplePTTSettings"}, @@ -302,6 +305,7 @@ const QMap WebAPIUtils::m_featureURIToSettingsKey = { {"sdrangel.feature.gs232controller", "GS232ControllerSettings"}, {"sdrangel.feature.map", "MapSettings"}, {"sdrangel.feature.pertester", "PERTesterSettings"}, + {"sdrangel.feature.radiosonde", "RadiosondeSettings"}, {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"}, {"sdrangel.feature.satellitetracker", "SatelliteTrackerSettings"}, {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index 5c9a47db9..261c7ec99 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -25,6 +25,8 @@ set(sdrgui_SOURCES gui/crightclickenabler.cpp gui/customtextedit.cpp gui/cwkeyergui.cpp + gui/datetimedelegate.cpp + gui/decimaldelegate.cpp gui/devicestreamselectiondialog.cpp gui/deviceuserargsdialog.cpp gui/dmsspinbox.cpp @@ -62,6 +64,7 @@ set(sdrgui_SOURCES gui/spectrumcalibrationpointsdialog.cpp gui/spectrummarkersdialog.cpp gui/tickedslider.cpp + gui/timedelegate.cpp gui/transverterbutton.cpp gui/transverterdialog.cpp gui/tvscreen.cpp @@ -113,6 +116,8 @@ set(sdrgui_HEADERS gui/crightclickenabler.h gui/customtextedit.h gui/cwkeyergui.h + gui/datetimedelegate.h + gui/decimaldelegate.h gui/devicestreamselectiondialog.h gui/deviceuserargsdialog.h gui/dmsspinbox.h @@ -152,6 +157,7 @@ set(sdrgui_HEADERS gui/spectrumcalibrationpointsdialog.h gui/spectrummarkersdialog.h gui/tickedslider.h + gui/timedelegate.h gui/transverterbutton.h gui/transverterdialog.h gui/tvscreen.h diff --git a/sdrgui/gui/datetimedelegate.cpp b/sdrgui/gui/datetimedelegate.cpp new file mode 100644 index 000000000..4beac8105 --- /dev/null +++ b/sdrgui/gui/datetimedelegate.cpp @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "datetimedelegate.h" + +DateTimeDelegate::DateTimeDelegate(QString format) : + m_format(format) +{ +} + +QString DateTimeDelegate::displayText(const QVariant &value, const QLocale &locale) const +{ + (void) locale; + if (value.toString() == "") { + return ""; + } else { + return value.toDateTime().toString(m_format); + } +} + diff --git a/sdrgui/gui/datetimedelegate.h b/sdrgui/gui/datetimedelegate.h new file mode 100644 index 000000000..c73cadf7f --- /dev/null +++ b/sdrgui/gui/datetimedelegate.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_DATETIMEDELGATE_H +#define SDRGUI_GUI_DATETIMEDELGATE_H + +#include + +#include "export.h" + +// Delegate for table to display time +class SDRGUI_API DateTimeDelegate : public QStyledItemDelegate { + +public: + DateTimeDelegate(QString format = "yyyy/MM/dd hh:mm:ss"); + virtual QString displayText(const QVariant &value, const QLocale &locale) const override; + +private: + QString m_format; + +}; + +#endif // SDRGUI_GUI_DATETIMEDELGATE_H diff --git a/sdrgui/gui/decimaldelegate.cpp b/sdrgui/gui/decimaldelegate.cpp new file mode 100644 index 000000000..d76e0688b --- /dev/null +++ b/sdrgui/gui/decimaldelegate.cpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "decimaldelegate.h" + +DecimalDelegate::DecimalDelegate(int precision) : + m_precision(precision) +{ +} + +QString DecimalDelegate::displayText(const QVariant &value, const QLocale &locale) const +{ + (void) locale; + bool ok; + double d = value.toDouble(&ok); + if (ok) { + return QString::number(d, 'f', m_precision); + } else { + return value.toString(); + } +} diff --git a/sdrgui/gui/decimaldelegate.h b/sdrgui/gui/decimaldelegate.h new file mode 100644 index 000000000..25754c1ef --- /dev/null +++ b/sdrgui/gui/decimaldelegate.h @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_DECIMALDELGATE_H +#define SDRGUI_GUI_DECIMALDELGATE_H + +#include + +#include "export.h" + +// Deligate for table to control precision used to display floating point values - also supports strings +class SDRGUI_API DecimalDelegate : public QStyledItemDelegate { + +public: + DecimalDelegate(int precision = 2); + + virtual QString displayText(const QVariant &value, const QLocale &locale) const override; + +private: + int m_precision; + +}; + +#endif // SDRGUI_GUI_DECIMALDELGATE_H diff --git a/sdrgui/gui/timedelegate.cpp b/sdrgui/gui/timedelegate.cpp new file mode 100644 index 000000000..7883f2919 --- /dev/null +++ b/sdrgui/gui/timedelegate.cpp @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "timedelegate.h" + +TimeDelegate::TimeDelegate(QString format) : + m_format(format) +{ +} + +QString TimeDelegate::displayText(const QVariant &value, const QLocale &locale) const +{ + (void) locale; + if (value.toString() == "") { + return ""; + } else { + return value.toTime().toString(m_format); + } +} + diff --git a/sdrgui/gui/timedelegate.h b/sdrgui/gui/timedelegate.h new file mode 100644 index 000000000..6f8a5f004 --- /dev/null +++ b/sdrgui/gui/timedelegate.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_TIMEDELGATE_H +#define SDRGUI_GUI_TIMEDELGATE_H + +#include + +#include "export.h" + +// Delegate for table to display time +class SDRGUI_API TimeDelegate : public QStyledItemDelegate { + +public: + TimeDelegate(QString format = "hh:mm:ss"); + virtual QString displayText(const QVariant &value, const QLocale &locale) const override; + +private: + QString m_format; + +}; + +#endif // SDRGUI_GUI_DECIMALDELGATE_H diff --git a/swagger/sdrangel/api/swagger/include/ChannelReport.yaml b/swagger/sdrangel/api/swagger/include/ChannelReport.yaml index 7948cda1d..d3650cede 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelReport.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelReport.yaml @@ -59,6 +59,8 @@ ChannelReport: $ref: "http://swgserver:8081/api/swagger/include/RadioAstronomy.yaml#/RadioAstronomyReport" RadioClockReport: $ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockReport" + RadiosondeDemodReport: + $ref: "http://swgserver:8081/api/swagger/include/RadiosondeDemod.yaml#/RadiosondeDemodReport" RemoteSourceReport: $ref: "http://swgserver:8081/api/swagger/include/RemoteSource.yaml#/RemoteSourceReport" PacketDemodReport: diff --git a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml index d82a11a04..0ec7f3e1a 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml @@ -85,6 +85,8 @@ ChannelSettings: $ref: "http://swgserver:8081/api/swagger/include/RadioAstronomy.yaml#/RadioAstronomySettings" RadioClockSettings: $ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockSettings" + RadiosondeDemodSettings: + $ref: "http://swgserver:8081/api/swagger/include/RadiosondeDemod.yaml#/RadiosondeDemodSettings" RemoteSinkSettings: $ref: "http://swgserver:8081/api/swagger/include/RemoteSink.yaml#/RemoteSinkSettings" RemoteSourceSettings: diff --git a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml index 85c36496e..da6a8cef2 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml @@ -31,6 +31,8 @@ FeatureSettings: $ref: "http://swgserver:8081/api/swagger/include/Map.yaml#/MapSettings" PERTesterSettings: $ref: "http://swgserver:8081/api/swagger/include/PERTester.yaml#/PERTesterSettings" + RadiosondeSettings: + $ref: "http://swgserver:8081/api/swagger/include/Radiosonde.yaml#/RadiosondeSettings" RigCtlServerSettings: $ref: "http://swgserver:8081/api/swagger/include/RigCtlServer.yaml#/RigCtlServerSettings" SatelliteTrackerSettings: diff --git a/swagger/sdrangel/api/swagger/include/Radiosonde.yaml b/swagger/sdrangel/api/swagger/include/Radiosonde.yaml new file mode 100644 index 000000000..ee0b9777c --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/Radiosonde.yaml @@ -0,0 +1,20 @@ +RadiosondeSettings: + description: "Radiosonde settings" + properties: + title: + type: string + rgbColor: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIFeatureSetIndex: + type: integer + reverseAPIFeatureIndex: + type: integer + rollupState: + $ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState" diff --git a/swagger/sdrangel/api/swagger/include/RadiosondeDemod.yaml b/swagger/sdrangel/api/swagger/include/RadiosondeDemod.yaml new file mode 100644 index 000000000..f5853f2c6 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/RadiosondeDemod.yaml @@ -0,0 +1,65 @@ +RadiosondeDemodSettings: + description: RadiosondeDemod + properties: + baud: + type: integer + description: baud rate (nominal is 4800) + inputFrequencyOffset: + type: integer + format: int64 + rfBandwidth: + type: number + format: float + fmDeviation: + type: number + format: float + correlationThreshold: + type: number + format: float + udpEnabled: + description: "Whether to forward received messages to specified UDP port" + type: integer + udpAddress: + description: "UDP address to forward received messages to" + type: string + udpPort: + description: "UDP port to forward received messages to" + type: integer + logFilename: + type: string + logEnabled: + type: integer + rgbColor: + type: integer + title: + type: string + streamIndex: + description: MIMO channel. Not relevant when connected to SI (single Rx). + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + reverseAPIChannelIndex: + type: integer + scopeConfig: + $ref: "http://swgserver:8081/api/swagger/include/GLScope.yaml#/GLScope" + channelMarker: + $ref: "http://swgserver:8081/api/swagger/include/ChannelMarker.yaml#/ChannelMarker" + rollupState: + $ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState" + +RadiosondeDemodReport: + description: RadiosondeDemod + properties: + channelPowerDB: + description: power received in channel (dB) + type: number + format: float + channelSampleRate: + type: integer diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp index 1445fa542..265179eff 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp @@ -80,6 +80,8 @@ SWGChannelReport::SWGChannelReport() { m_radio_astronomy_report_isSet = false; radio_clock_report = nullptr; m_radio_clock_report_isSet = false; + radiosonde_demod_report = nullptr; + m_radiosonde_demod_report_isSet = false; remote_source_report = nullptr; m_remote_source_report_isSet = false; packet_demod_report = nullptr; @@ -164,6 +166,8 @@ SWGChannelReport::init() { m_radio_astronomy_report_isSet = false; radio_clock_report = new SWGRadioClockReport(); m_radio_clock_report_isSet = false; + radiosonde_demod_report = new SWGRadiosondeDemodReport(); + m_radiosonde_demod_report_isSet = false; remote_source_report = new SWGRemoteSourceReport(); m_remote_source_report_isSet = false; packet_demod_report = new SWGPacketDemodReport(); @@ -268,6 +272,9 @@ SWGChannelReport::cleanup() { if(radio_clock_report != nullptr) { delete radio_clock_report; } + if(radiosonde_demod_report != nullptr) { + delete radiosonde_demod_report; + } if(remote_source_report != nullptr) { delete remote_source_report; } @@ -369,6 +376,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&radio_clock_report, pJson["RadioClockReport"], "SWGRadioClockReport", "SWGRadioClockReport"); + ::SWGSDRangel::setValue(&radiosonde_demod_report, pJson["RadiosondeDemodReport"], "SWGRadiosondeDemodReport", "SWGRadiosondeDemodReport"); + ::SWGSDRangel::setValue(&remote_source_report, pJson["RemoteSourceReport"], "SWGRemoteSourceReport", "SWGRemoteSourceReport"); ::SWGSDRangel::setValue(&packet_demod_report, pJson["PacketDemodReport"], "SWGPacketDemodReport", "SWGPacketDemodReport"); @@ -487,6 +496,9 @@ SWGChannelReport::asJsonObject() { if((radio_clock_report != nullptr) && (radio_clock_report->isSet())){ toJsonValue(QString("RadioClockReport"), radio_clock_report, obj, QString("SWGRadioClockReport")); } + if((radiosonde_demod_report != nullptr) && (radiosonde_demod_report->isSet())){ + toJsonValue(QString("RadiosondeDemodReport"), radiosonde_demod_report, obj, QString("SWGRadiosondeDemodReport")); + } if((remote_source_report != nullptr) && (remote_source_report->isSet())){ toJsonValue(QString("RemoteSourceReport"), remote_source_report, obj, QString("SWGRemoteSourceReport")); } @@ -787,6 +799,16 @@ SWGChannelReport::setRadioClockReport(SWGRadioClockReport* radio_clock_report) { this->m_radio_clock_report_isSet = true; } +SWGRadiosondeDemodReport* +SWGChannelReport::getRadiosondeDemodReport() { + return radiosonde_demod_report; +} +void +SWGChannelReport::setRadiosondeDemodReport(SWGRadiosondeDemodReport* radiosonde_demod_report) { + this->radiosonde_demod_report = radiosonde_demod_report; + this->m_radiosonde_demod_report_isSet = true; +} + SWGRemoteSourceReport* SWGChannelReport::getRemoteSourceReport() { return remote_source_report; @@ -990,6 +1012,9 @@ SWGChannelReport::isSet(){ if(radio_clock_report && radio_clock_report->isSet()){ isObjectUpdated = true; break; } + if(radiosonde_demod_report && radiosonde_demod_report->isSet()){ + isObjectUpdated = true; break; + } if(remote_source_report && remote_source_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h index e2f13d5dd..9f91fc4c1 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h @@ -48,6 +48,7 @@ #include "SWGPagerDemodReport.h" #include "SWGRadioAstronomyReport.h" #include "SWGRadioClockReport.h" +#include "SWGRadiosondeDemodReport.h" #include "SWGRemoteSourceReport.h" #include "SWGSSBDemodReport.h" #include "SWGSSBModReport.h" @@ -156,6 +157,9 @@ public: SWGRadioClockReport* getRadioClockReport(); void setRadioClockReport(SWGRadioClockReport* radio_clock_report); + SWGRadiosondeDemodReport* getRadiosondeDemodReport(); + void setRadiosondeDemodReport(SWGRadiosondeDemodReport* radiosonde_demod_report); + SWGRemoteSourceReport* getRemoteSourceReport(); void setRemoteSourceReport(SWGRemoteSourceReport* remote_source_report); @@ -274,6 +278,9 @@ private: SWGRadioClockReport* radio_clock_report; bool m_radio_clock_report_isSet; + SWGRadiosondeDemodReport* radiosonde_demod_report; + bool m_radiosonde_demod_report_isSet; + SWGRemoteSourceReport* remote_source_report; bool m_remote_source_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp index ca2a88d60..56fa8a4d4 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp @@ -104,6 +104,8 @@ SWGChannelSettings::SWGChannelSettings() { m_radio_astronomy_settings_isSet = false; radio_clock_settings = nullptr; m_radio_clock_settings_isSet = false; + radiosonde_demod_settings = nullptr; + m_radiosonde_demod_settings_isSet = false; remote_sink_settings = nullptr; m_remote_sink_settings_isSet = false; remote_source_settings = nullptr; @@ -210,6 +212,8 @@ SWGChannelSettings::init() { m_radio_astronomy_settings_isSet = false; radio_clock_settings = new SWGRadioClockSettings(); m_radio_clock_settings_isSet = false; + radiosonde_demod_settings = new SWGRadiosondeDemodSettings(); + m_radiosonde_demod_settings_isSet = false; remote_sink_settings = new SWGRemoteSinkSettings(); m_remote_sink_settings_isSet = false; remote_source_settings = new SWGRemoteSourceSettings(); @@ -344,6 +348,9 @@ SWGChannelSettings::cleanup() { if(radio_clock_settings != nullptr) { delete radio_clock_settings; } + if(radiosonde_demod_settings != nullptr) { + delete radiosonde_demod_settings; + } if(remote_sink_settings != nullptr) { delete remote_sink_settings; } @@ -466,6 +473,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&radio_clock_settings, pJson["RadioClockSettings"], "SWGRadioClockSettings", "SWGRadioClockSettings"); + ::SWGSDRangel::setValue(&radiosonde_demod_settings, pJson["RadiosondeDemodSettings"], "SWGRadiosondeDemodSettings", "SWGRadiosondeDemodSettings"); + ::SWGSDRangel::setValue(&remote_sink_settings, pJson["RemoteSinkSettings"], "SWGRemoteSinkSettings", "SWGRemoteSinkSettings"); ::SWGSDRangel::setValue(&remote_source_settings, pJson["RemoteSourceSettings"], "SWGRemoteSourceSettings", "SWGRemoteSourceSettings"); @@ -618,6 +627,9 @@ SWGChannelSettings::asJsonObject() { if((radio_clock_settings != nullptr) && (radio_clock_settings->isSet())){ toJsonValue(QString("RadioClockSettings"), radio_clock_settings, obj, QString("SWGRadioClockSettings")); } + if((radiosonde_demod_settings != nullptr) && (radiosonde_demod_settings->isSet())){ + toJsonValue(QString("RadiosondeDemodSettings"), radiosonde_demod_settings, obj, QString("SWGRadiosondeDemodSettings")); + } if((remote_sink_settings != nullptr) && (remote_sink_settings->isSet())){ toJsonValue(QString("RemoteSinkSettings"), remote_sink_settings, obj, QString("SWGRemoteSinkSettings")); } @@ -1035,6 +1047,16 @@ SWGChannelSettings::setRadioClockSettings(SWGRadioClockSettings* radio_clock_set this->m_radio_clock_settings_isSet = true; } +SWGRadiosondeDemodSettings* +SWGChannelSettings::getRadiosondeDemodSettings() { + return radiosonde_demod_settings; +} +void +SWGChannelSettings::setRadiosondeDemodSettings(SWGRadiosondeDemodSettings* radiosonde_demod_settings) { + this->radiosonde_demod_settings = radiosonde_demod_settings; + this->m_radiosonde_demod_settings_isSet = true; +} + SWGRemoteSinkSettings* SWGChannelSettings::getRemoteSinkSettings() { return remote_sink_settings; @@ -1264,6 +1286,9 @@ SWGChannelSettings::isSet(){ if(radio_clock_settings && radio_clock_settings->isSet()){ isObjectUpdated = true; break; } + if(radiosonde_demod_settings && radiosonde_demod_settings->isSet()){ + isObjectUpdated = true; break; + } if(remote_sink_settings && remote_sink_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h index 074c83cb1..ea6549f45 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h @@ -56,6 +56,7 @@ #include "SWGPagerDemodSettings.h" #include "SWGRadioAstronomySettings.h" #include "SWGRadioClockSettings.h" +#include "SWGRadiosondeDemodSettings.h" #include "SWGRemoteSinkSettings.h" #include "SWGRemoteSourceSettings.h" #include "SWGSSBDemodSettings.h" @@ -201,6 +202,9 @@ public: SWGRadioClockSettings* getRadioClockSettings(); void setRadioClockSettings(SWGRadioClockSettings* radio_clock_settings); + SWGRadiosondeDemodSettings* getRadiosondeDemodSettings(); + void setRadiosondeDemodSettings(SWGRadiosondeDemodSettings* radiosonde_demod_settings); + SWGRemoteSinkSettings* getRemoteSinkSettings(); void setRemoteSinkSettings(SWGRemoteSinkSettings* remote_sink_settings); @@ -352,6 +356,9 @@ private: SWGRadioClockSettings* radio_clock_settings; bool m_radio_clock_settings_isSet; + SWGRadiosondeDemodSettings* radiosonde_demod_settings; + bool m_radiosonde_demod_settings_isSet; + SWGRemoteSinkSettings* remote_sink_settings; bool m_remote_sink_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp index 459be10e0..99e1f2835 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp @@ -52,6 +52,8 @@ SWGFeatureSettings::SWGFeatureSettings() { m_map_settings_isSet = false; per_tester_settings = nullptr; m_per_tester_settings_isSet = false; + radiosonde_settings = nullptr; + m_radiosonde_settings_isSet = false; rig_ctl_server_settings = nullptr; m_rig_ctl_server_settings_isSet = false; satellite_tracker_settings = nullptr; @@ -94,6 +96,8 @@ SWGFeatureSettings::init() { m_map_settings_isSet = false; per_tester_settings = new SWGPERTesterSettings(); m_per_tester_settings_isSet = false; + radiosonde_settings = new SWGRadiosondeSettings(); + m_radiosonde_settings_isSet = false; rig_ctl_server_settings = new SWGRigCtlServerSettings(); m_rig_ctl_server_settings_isSet = false; satellite_tracker_settings = new SWGSatelliteTrackerSettings(); @@ -140,6 +144,9 @@ SWGFeatureSettings::cleanup() { if(per_tester_settings != nullptr) { delete per_tester_settings; } + if(radiosonde_settings != nullptr) { + delete radiosonde_settings; + } if(rig_ctl_server_settings != nullptr) { delete rig_ctl_server_settings; } @@ -192,6 +199,8 @@ SWGFeatureSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&per_tester_settings, pJson["PERTesterSettings"], "SWGPERTesterSettings", "SWGPERTesterSettings"); + ::SWGSDRangel::setValue(&radiosonde_settings, pJson["RadiosondeSettings"], "SWGRadiosondeSettings", "SWGRadiosondeSettings"); + ::SWGSDRangel::setValue(&rig_ctl_server_settings, pJson["RigCtlServerSettings"], "SWGRigCtlServerSettings", "SWGRigCtlServerSettings"); ::SWGSDRangel::setValue(&satellite_tracker_settings, pJson["SatelliteTrackerSettings"], "SWGSatelliteTrackerSettings", "SWGSatelliteTrackerSettings"); @@ -254,6 +263,9 @@ SWGFeatureSettings::asJsonObject() { if((per_tester_settings != nullptr) && (per_tester_settings->isSet())){ toJsonValue(QString("PERTesterSettings"), per_tester_settings, obj, QString("SWGPERTesterSettings")); } + if((radiosonde_settings != nullptr) && (radiosonde_settings->isSet())){ + toJsonValue(QString("RadiosondeSettings"), radiosonde_settings, obj, QString("SWGRadiosondeSettings")); + } if((rig_ctl_server_settings != nullptr) && (rig_ctl_server_settings->isSet())){ toJsonValue(QString("RigCtlServerSettings"), rig_ctl_server_settings, obj, QString("SWGRigCtlServerSettings")); } @@ -393,6 +405,16 @@ SWGFeatureSettings::setPerTesterSettings(SWGPERTesterSettings* per_tester_settin this->m_per_tester_settings_isSet = true; } +SWGRadiosondeSettings* +SWGFeatureSettings::getRadiosondeSettings() { + return radiosonde_settings; +} +void +SWGFeatureSettings::setRadiosondeSettings(SWGRadiosondeSettings* radiosonde_settings) { + this->radiosonde_settings = radiosonde_settings; + this->m_radiosonde_settings_isSet = true; +} + SWGRigCtlServerSettings* SWGFeatureSettings::getRigCtlServerSettings() { return rig_ctl_server_settings; @@ -484,6 +506,9 @@ SWGFeatureSettings::isSet(){ if(per_tester_settings && per_tester_settings->isSet()){ isObjectUpdated = true; break; } + if(radiosonde_settings && radiosonde_settings->isSet()){ + isObjectUpdated = true; break; + } if(rig_ctl_server_settings && rig_ctl_server_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h index 1918aef52..7f3bbec1b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h @@ -31,6 +31,7 @@ #include "SWGJogdialControllerSettings.h" #include "SWGMapSettings.h" #include "SWGPERTesterSettings.h" +#include "SWGRadiosondeSettings.h" #include "SWGRigCtlServerSettings.h" #include "SWGSatelliteTrackerSettings.h" #include "SWGSimplePTTSettings.h" @@ -92,6 +93,9 @@ public: SWGPERTesterSettings* getPerTesterSettings(); void setPerTesterSettings(SWGPERTesterSettings* per_tester_settings); + SWGRadiosondeSettings* getRadiosondeSettings(); + void setRadiosondeSettings(SWGRadiosondeSettings* radiosonde_settings); + SWGRigCtlServerSettings* getRigCtlServerSettings(); void setRigCtlServerSettings(SWGRigCtlServerSettings* rig_ctl_server_settings); @@ -147,6 +151,9 @@ private: SWGPERTesterSettings* per_tester_settings; bool m_per_tester_settings_isSet; + SWGRadiosondeSettings* radiosonde_settings; + bool m_radiosonde_settings_isSet; + SWGRigCtlServerSettings* rig_ctl_server_settings; bool m_rig_ctl_server_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 5043473cc..bf01101d3 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -221,6 +221,9 @@ #include "SWGRadioAstronomySettings.h" #include "SWGRadioClockReport.h" #include "SWGRadioClockSettings.h" +#include "SWGRadiosondeDemodReport.h" +#include "SWGRadiosondeDemodSettings.h" +#include "SWGRadiosondeSettings.h" #include "SWGRange.h" #include "SWGRangeFloat.h" #include "SWGRemoteInputReport.h" @@ -1355,6 +1358,21 @@ namespace SWGSDRangel { obj->init(); return obj; } + if(QString("SWGRadiosondeDemodReport").compare(type) == 0) { + SWGRadiosondeDemodReport *obj = new SWGRadiosondeDemodReport(); + obj->init(); + return obj; + } + if(QString("SWGRadiosondeDemodSettings").compare(type) == 0) { + SWGRadiosondeDemodSettings *obj = new SWGRadiosondeDemodSettings(); + obj->init(); + return obj; + } + if(QString("SWGRadiosondeSettings").compare(type) == 0) { + SWGRadiosondeSettings *obj = new SWGRadiosondeSettings(); + obj->init(); + return obj; + } if(QString("SWGRange").compare(type) == 0) { SWGRange *obj = new SWGRange(); obj->init(); diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.cpp b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.cpp new file mode 100644 index 000000000..68ff0be60 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.cpp @@ -0,0 +1,131 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGRadiosondeDemodReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGRadiosondeDemodReport::SWGRadiosondeDemodReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGRadiosondeDemodReport::SWGRadiosondeDemodReport() { + channel_power_db = 0.0f; + m_channel_power_db_isSet = false; + channel_sample_rate = 0; + m_channel_sample_rate_isSet = false; +} + +SWGRadiosondeDemodReport::~SWGRadiosondeDemodReport() { + this->cleanup(); +} + +void +SWGRadiosondeDemodReport::init() { + channel_power_db = 0.0f; + m_channel_power_db_isSet = false; + channel_sample_rate = 0; + m_channel_sample_rate_isSet = false; +} + +void +SWGRadiosondeDemodReport::cleanup() { + + +} + +SWGRadiosondeDemodReport* +SWGRadiosondeDemodReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGRadiosondeDemodReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", ""); + + ::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", ""); + +} + +QString +SWGRadiosondeDemodReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGRadiosondeDemodReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_channel_power_db_isSet){ + obj->insert("channelPowerDB", QJsonValue(channel_power_db)); + } + if(m_channel_sample_rate_isSet){ + obj->insert("channelSampleRate", QJsonValue(channel_sample_rate)); + } + + return obj; +} + +float +SWGRadiosondeDemodReport::getChannelPowerDb() { + return channel_power_db; +} +void +SWGRadiosondeDemodReport::setChannelPowerDb(float channel_power_db) { + this->channel_power_db = channel_power_db; + this->m_channel_power_db_isSet = true; +} + +qint32 +SWGRadiosondeDemodReport::getChannelSampleRate() { + return channel_sample_rate; +} +void +SWGRadiosondeDemodReport::setChannelSampleRate(qint32 channel_sample_rate) { + this->channel_sample_rate = channel_sample_rate; + this->m_channel_sample_rate_isSet = true; +} + + +bool +SWGRadiosondeDemodReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_channel_power_db_isSet){ + isObjectUpdated = true; break; + } + if(m_channel_sample_rate_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.h b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.h new file mode 100644 index 000000000..511e88812 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodReport.h @@ -0,0 +1,64 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGRadiosondeDemodReport.h + * + * RadiosondeDemod + */ + +#ifndef SWGRadiosondeDemodReport_H_ +#define SWGRadiosondeDemodReport_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGRadiosondeDemodReport: public SWGObject { +public: + SWGRadiosondeDemodReport(); + SWGRadiosondeDemodReport(QString* json); + virtual ~SWGRadiosondeDemodReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGRadiosondeDemodReport* fromJson(QString &jsonString) override; + + float getChannelPowerDb(); + void setChannelPowerDb(float channel_power_db); + + qint32 getChannelSampleRate(); + void setChannelSampleRate(qint32 channel_sample_rate); + + + virtual bool isSet() override; + +private: + float channel_power_db; + bool m_channel_power_db_isSet; + + qint32 channel_sample_rate; + bool m_channel_sample_rate_isSet; + +}; + +} + +#endif /* SWGRadiosondeDemodReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.cpp new file mode 100644 index 000000000..875661286 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.cpp @@ -0,0 +1,582 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGRadiosondeDemodSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGRadiosondeDemodSettings::SWGRadiosondeDemodSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGRadiosondeDemodSettings::SWGRadiosondeDemodSettings() { + baud = 0; + m_baud_isSet = false; + input_frequency_offset = 0L; + m_input_frequency_offset_isSet = false; + rf_bandwidth = 0.0f; + m_rf_bandwidth_isSet = false; + fm_deviation = 0.0f; + m_fm_deviation_isSet = false; + correlation_threshold = 0.0f; + m_correlation_threshold_isSet = false; + udp_enabled = 0; + m_udp_enabled_isSet = false; + udp_address = nullptr; + m_udp_address_isSet = false; + udp_port = 0; + m_udp_port_isSet = false; + log_filename = nullptr; + m_log_filename_isSet = false; + log_enabled = 0; + m_log_enabled_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = nullptr; + m_title_isSet = false; + stream_index = 0; + m_stream_index_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; + scope_config = nullptr; + m_scope_config_isSet = false; + channel_marker = nullptr; + m_channel_marker_isSet = false; + rollup_state = nullptr; + m_rollup_state_isSet = false; +} + +SWGRadiosondeDemodSettings::~SWGRadiosondeDemodSettings() { + this->cleanup(); +} + +void +SWGRadiosondeDemodSettings::init() { + baud = 0; + m_baud_isSet = false; + input_frequency_offset = 0L; + m_input_frequency_offset_isSet = false; + rf_bandwidth = 0.0f; + m_rf_bandwidth_isSet = false; + fm_deviation = 0.0f; + m_fm_deviation_isSet = false; + correlation_threshold = 0.0f; + m_correlation_threshold_isSet = false; + udp_enabled = 0; + m_udp_enabled_isSet = false; + udp_address = new QString(""); + m_udp_address_isSet = false; + udp_port = 0; + m_udp_port_isSet = false; + log_filename = new QString(""); + m_log_filename_isSet = false; + log_enabled = 0; + m_log_enabled_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = new QString(""); + m_title_isSet = false; + stream_index = 0; + m_stream_index_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; + scope_config = new SWGGLScope(); + m_scope_config_isSet = false; + channel_marker = new SWGChannelMarker(); + m_channel_marker_isSet = false; + rollup_state = new SWGRollupState(); + m_rollup_state_isSet = false; +} + +void +SWGRadiosondeDemodSettings::cleanup() { + + + + + + + if(udp_address != nullptr) { + delete udp_address; + } + + if(log_filename != nullptr) { + delete log_filename; + } + + + if(title != nullptr) { + delete title; + } + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + + if(scope_config != nullptr) { + delete scope_config; + } + if(channel_marker != nullptr) { + delete channel_marker; + } + if(rollup_state != nullptr) { + delete rollup_state; + } +} + +SWGRadiosondeDemodSettings* +SWGRadiosondeDemodSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGRadiosondeDemodSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&baud, pJson["baud"], "qint32", ""); + + ::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", ""); + + ::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", ""); + + ::SWGSDRangel::setValue(&fm_deviation, pJson["fmDeviation"], "float", ""); + + ::SWGSDRangel::setValue(&correlation_threshold, pJson["correlationThreshold"], "float", ""); + + ::SWGSDRangel::setValue(&udp_enabled, pJson["udpEnabled"], "qint32", ""); + + ::SWGSDRangel::setValue(&udp_address, pJson["udpAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&udp_port, pJson["udpPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&log_filename, pJson["logFilename"], "QString", "QString"); + + ::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", ""); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&scope_config, pJson["scopeConfig"], "SWGGLScope", "SWGGLScope"); + + ::SWGSDRangel::setValue(&channel_marker, pJson["channelMarker"], "SWGChannelMarker", "SWGChannelMarker"); + + ::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState"); + +} + +QString +SWGRadiosondeDemodSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGRadiosondeDemodSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_baud_isSet){ + obj->insert("baud", QJsonValue(baud)); + } + if(m_input_frequency_offset_isSet){ + obj->insert("inputFrequencyOffset", QJsonValue(input_frequency_offset)); + } + if(m_rf_bandwidth_isSet){ + obj->insert("rfBandwidth", QJsonValue(rf_bandwidth)); + } + if(m_fm_deviation_isSet){ + obj->insert("fmDeviation", QJsonValue(fm_deviation)); + } + if(m_correlation_threshold_isSet){ + obj->insert("correlationThreshold", QJsonValue(correlation_threshold)); + } + if(m_udp_enabled_isSet){ + obj->insert("udpEnabled", QJsonValue(udp_enabled)); + } + if(udp_address != nullptr && *udp_address != QString("")){ + toJsonValue(QString("udpAddress"), udp_address, obj, QString("QString")); + } + if(m_udp_port_isSet){ + obj->insert("udpPort", QJsonValue(udp_port)); + } + if(log_filename != nullptr && *log_filename != QString("")){ + toJsonValue(QString("logFilename"), log_filename, obj, QString("QString")); + } + if(m_log_enabled_isSet){ + obj->insert("logEnabled", QJsonValue(log_enabled)); + } + if(m_rgb_color_isSet){ + obj->insert("rgbColor", QJsonValue(rgb_color)); + } + if(title != nullptr && *title != QString("")){ + toJsonValue(QString("title"), title, obj, QString("QString")); + } + if(m_stream_index_isSet){ + obj->insert("streamIndex", QJsonValue(stream_index)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_device_index_isSet){ + obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index)); + } + if(m_reverse_api_channel_index_isSet){ + obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index)); + } + if((scope_config != nullptr) && (scope_config->isSet())){ + toJsonValue(QString("scopeConfig"), scope_config, obj, QString("SWGGLScope")); + } + if((channel_marker != nullptr) && (channel_marker->isSet())){ + toJsonValue(QString("channelMarker"), channel_marker, obj, QString("SWGChannelMarker")); + } + if((rollup_state != nullptr) && (rollup_state->isSet())){ + toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState")); + } + + return obj; +} + +qint32 +SWGRadiosondeDemodSettings::getBaud() { + return baud; +} +void +SWGRadiosondeDemodSettings::setBaud(qint32 baud) { + this->baud = baud; + this->m_baud_isSet = true; +} + +qint64 +SWGRadiosondeDemodSettings::getInputFrequencyOffset() { + return input_frequency_offset; +} +void +SWGRadiosondeDemodSettings::setInputFrequencyOffset(qint64 input_frequency_offset) { + this->input_frequency_offset = input_frequency_offset; + this->m_input_frequency_offset_isSet = true; +} + +float +SWGRadiosondeDemodSettings::getRfBandwidth() { + return rf_bandwidth; +} +void +SWGRadiosondeDemodSettings::setRfBandwidth(float rf_bandwidth) { + this->rf_bandwidth = rf_bandwidth; + this->m_rf_bandwidth_isSet = true; +} + +float +SWGRadiosondeDemodSettings::getFmDeviation() { + return fm_deviation; +} +void +SWGRadiosondeDemodSettings::setFmDeviation(float fm_deviation) { + this->fm_deviation = fm_deviation; + this->m_fm_deviation_isSet = true; +} + +float +SWGRadiosondeDemodSettings::getCorrelationThreshold() { + return correlation_threshold; +} +void +SWGRadiosondeDemodSettings::setCorrelationThreshold(float correlation_threshold) { + this->correlation_threshold = correlation_threshold; + this->m_correlation_threshold_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getUdpEnabled() { + return udp_enabled; +} +void +SWGRadiosondeDemodSettings::setUdpEnabled(qint32 udp_enabled) { + this->udp_enabled = udp_enabled; + this->m_udp_enabled_isSet = true; +} + +QString* +SWGRadiosondeDemodSettings::getUdpAddress() { + return udp_address; +} +void +SWGRadiosondeDemodSettings::setUdpAddress(QString* udp_address) { + this->udp_address = udp_address; + this->m_udp_address_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getUdpPort() { + return udp_port; +} +void +SWGRadiosondeDemodSettings::setUdpPort(qint32 udp_port) { + this->udp_port = udp_port; + this->m_udp_port_isSet = true; +} + +QString* +SWGRadiosondeDemodSettings::getLogFilename() { + return log_filename; +} +void +SWGRadiosondeDemodSettings::setLogFilename(QString* log_filename) { + this->log_filename = log_filename; + this->m_log_filename_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getLogEnabled() { + return log_enabled; +} +void +SWGRadiosondeDemodSettings::setLogEnabled(qint32 log_enabled) { + this->log_enabled = log_enabled; + this->m_log_enabled_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getRgbColor() { + return rgb_color; +} +void +SWGRadiosondeDemodSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +QString* +SWGRadiosondeDemodSettings::getTitle() { + return title; +} +void +SWGRadiosondeDemodSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getStreamIndex() { + return stream_index; +} +void +SWGRadiosondeDemodSettings::setStreamIndex(qint32 stream_index) { + this->stream_index = stream_index; + this->m_stream_index_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGRadiosondeDemodSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGRadiosondeDemodSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGRadiosondeDemodSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGRadiosondeDemodSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGRadiosondeDemodSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + +qint32 +SWGRadiosondeDemodSettings::getReverseApiChannelIndex() { + return reverse_api_channel_index; +} +void +SWGRadiosondeDemodSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { + this->reverse_api_channel_index = reverse_api_channel_index; + this->m_reverse_api_channel_index_isSet = true; +} + +SWGGLScope* +SWGRadiosondeDemodSettings::getScopeConfig() { + return scope_config; +} +void +SWGRadiosondeDemodSettings::setScopeConfig(SWGGLScope* scope_config) { + this->scope_config = scope_config; + this->m_scope_config_isSet = true; +} + +SWGChannelMarker* +SWGRadiosondeDemodSettings::getChannelMarker() { + return channel_marker; +} +void +SWGRadiosondeDemodSettings::setChannelMarker(SWGChannelMarker* channel_marker) { + this->channel_marker = channel_marker; + this->m_channel_marker_isSet = true; +} + +SWGRollupState* +SWGRadiosondeDemodSettings::getRollupState() { + return rollup_state; +} +void +SWGRadiosondeDemodSettings::setRollupState(SWGRollupState* rollup_state) { + this->rollup_state = rollup_state; + this->m_rollup_state_isSet = true; +} + + +bool +SWGRadiosondeDemodSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_baud_isSet){ + isObjectUpdated = true; break; + } + if(m_input_frequency_offset_isSet){ + isObjectUpdated = true; break; + } + if(m_rf_bandwidth_isSet){ + isObjectUpdated = true; break; + } + if(m_fm_deviation_isSet){ + isObjectUpdated = true; break; + } + if(m_correlation_threshold_isSet){ + isObjectUpdated = true; break; + } + if(m_udp_enabled_isSet){ + isObjectUpdated = true; break; + } + if(udp_address && *udp_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_udp_port_isSet){ + isObjectUpdated = true; break; + } + if(log_filename && *log_filename != QString("")){ + isObjectUpdated = true; break; + } + if(m_log_enabled_isSet){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_stream_index_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_device_index_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_channel_index_isSet){ + isObjectUpdated = true; break; + } + if(scope_config && scope_config->isSet()){ + isObjectUpdated = true; break; + } + if(channel_marker && channel_marker->isSet()){ + isObjectUpdated = true; break; + } + if(rollup_state && rollup_state->isSet()){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.h b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.h new file mode 100644 index 000000000..7a4db1813 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeDemodSettings.h @@ -0,0 +1,182 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGRadiosondeDemodSettings.h + * + * RadiosondeDemod + */ + +#ifndef SWGRadiosondeDemodSettings_H_ +#define SWGRadiosondeDemodSettings_H_ + +#include + + +#include "SWGChannelMarker.h" +#include "SWGGLScope.h" +#include "SWGRollupState.h" +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGRadiosondeDemodSettings: public SWGObject { +public: + SWGRadiosondeDemodSettings(); + SWGRadiosondeDemodSettings(QString* json); + virtual ~SWGRadiosondeDemodSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGRadiosondeDemodSettings* fromJson(QString &jsonString) override; + + qint32 getBaud(); + void setBaud(qint32 baud); + + qint64 getInputFrequencyOffset(); + void setInputFrequencyOffset(qint64 input_frequency_offset); + + float getRfBandwidth(); + void setRfBandwidth(float rf_bandwidth); + + float getFmDeviation(); + void setFmDeviation(float fm_deviation); + + float getCorrelationThreshold(); + void setCorrelationThreshold(float correlation_threshold); + + qint32 getUdpEnabled(); + void setUdpEnabled(qint32 udp_enabled); + + QString* getUdpAddress(); + void setUdpAddress(QString* udp_address); + + qint32 getUdpPort(); + void setUdpPort(qint32 udp_port); + + QString* getLogFilename(); + void setLogFilename(QString* log_filename); + + qint32 getLogEnabled(); + void setLogEnabled(qint32 log_enabled); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getStreamIndex(); + void setStreamIndex(qint32 stream_index); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiDeviceIndex(); + void setReverseApiDeviceIndex(qint32 reverse_api_device_index); + + qint32 getReverseApiChannelIndex(); + void setReverseApiChannelIndex(qint32 reverse_api_channel_index); + + SWGGLScope* getScopeConfig(); + void setScopeConfig(SWGGLScope* scope_config); + + SWGChannelMarker* getChannelMarker(); + void setChannelMarker(SWGChannelMarker* channel_marker); + + SWGRollupState* getRollupState(); + void setRollupState(SWGRollupState* rollup_state); + + + virtual bool isSet() override; + +private: + qint32 baud; + bool m_baud_isSet; + + qint64 input_frequency_offset; + bool m_input_frequency_offset_isSet; + + float rf_bandwidth; + bool m_rf_bandwidth_isSet; + + float fm_deviation; + bool m_fm_deviation_isSet; + + float correlation_threshold; + bool m_correlation_threshold_isSet; + + qint32 udp_enabled; + bool m_udp_enabled_isSet; + + QString* udp_address; + bool m_udp_address_isSet; + + qint32 udp_port; + bool m_udp_port_isSet; + + QString* log_filename; + bool m_log_filename_isSet; + + qint32 log_enabled; + bool m_log_enabled_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + QString* title; + bool m_title_isSet; + + qint32 stream_index; + bool m_stream_index_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_device_index; + bool m_reverse_api_device_index_isSet; + + qint32 reverse_api_channel_index; + bool m_reverse_api_channel_index_isSet; + + SWGGLScope* scope_config; + bool m_scope_config_isSet; + + SWGChannelMarker* channel_marker; + bool m_channel_marker_isSet; + + SWGRollupState* rollup_state; + bool m_rollup_state_isSet; + +}; + +} + +#endif /* SWGRadiosondeDemodSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.cpp new file mode 100644 index 000000000..cb332c9d2 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.cpp @@ -0,0 +1,275 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGRadiosondeSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGRadiosondeSettings::SWGRadiosondeSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGRadiosondeSettings::SWGRadiosondeSettings() { + title = nullptr; + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_feature_set_index = 0; + m_reverse_api_feature_set_index_isSet = false; + reverse_api_feature_index = 0; + m_reverse_api_feature_index_isSet = false; + rollup_state = nullptr; + m_rollup_state_isSet = false; +} + +SWGRadiosondeSettings::~SWGRadiosondeSettings() { + this->cleanup(); +} + +void +SWGRadiosondeSettings::init() { + title = new QString(""); + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_feature_set_index = 0; + m_reverse_api_feature_set_index_isSet = false; + reverse_api_feature_index = 0; + m_reverse_api_feature_index_isSet = false; + rollup_state = new SWGRollupState(); + m_rollup_state_isSet = false; +} + +void +SWGRadiosondeSettings::cleanup() { + if(title != nullptr) { + delete title; + } + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + + if(rollup_state != nullptr) { + delete rollup_state; + } +} + +SWGRadiosondeSettings* +SWGRadiosondeSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGRadiosondeSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_feature_set_index, pJson["reverseAPIFeatureSetIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_feature_index, pJson["reverseAPIFeatureIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState"); + +} + +QString +SWGRadiosondeSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGRadiosondeSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(title != nullptr && *title != QString("")){ + toJsonValue(QString("title"), title, obj, QString("QString")); + } + if(m_rgb_color_isSet){ + obj->insert("rgbColor", QJsonValue(rgb_color)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_feature_set_index_isSet){ + obj->insert("reverseAPIFeatureSetIndex", QJsonValue(reverse_api_feature_set_index)); + } + if(m_reverse_api_feature_index_isSet){ + obj->insert("reverseAPIFeatureIndex", QJsonValue(reverse_api_feature_index)); + } + if((rollup_state != nullptr) && (rollup_state->isSet())){ + toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState")); + } + + return obj; +} + +QString* +SWGRadiosondeSettings::getTitle() { + return title; +} +void +SWGRadiosondeSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGRadiosondeSettings::getRgbColor() { + return rgb_color; +} +void +SWGRadiosondeSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +qint32 +SWGRadiosondeSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGRadiosondeSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGRadiosondeSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGRadiosondeSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGRadiosondeSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGRadiosondeSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGRadiosondeSettings::getReverseApiFeatureSetIndex() { + return reverse_api_feature_set_index; +} +void +SWGRadiosondeSettings::setReverseApiFeatureSetIndex(qint32 reverse_api_feature_set_index) { + this->reverse_api_feature_set_index = reverse_api_feature_set_index; + this->m_reverse_api_feature_set_index_isSet = true; +} + +qint32 +SWGRadiosondeSettings::getReverseApiFeatureIndex() { + return reverse_api_feature_index; +} +void +SWGRadiosondeSettings::setReverseApiFeatureIndex(qint32 reverse_api_feature_index) { + this->reverse_api_feature_index = reverse_api_feature_index; + this->m_reverse_api_feature_index_isSet = true; +} + +SWGRollupState* +SWGRadiosondeSettings::getRollupState() { + return rollup_state; +} +void +SWGRadiosondeSettings::setRollupState(SWGRollupState* rollup_state) { + this->rollup_state = rollup_state; + this->m_rollup_state_isSet = true; +} + + +bool +SWGRadiosondeSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_feature_set_index_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_feature_index_isSet){ + isObjectUpdated = true; break; + } + if(rollup_state && rollup_state->isSet()){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.h b/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.h new file mode 100644 index 000000000..505d45fdb --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadiosondeSettings.h @@ -0,0 +1,102 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGRadiosondeSettings.h + * + * Radiosonde settings + */ + +#ifndef SWGRadiosondeSettings_H_ +#define SWGRadiosondeSettings_H_ + +#include + + +#include "SWGRollupState.h" +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGRadiosondeSettings: public SWGObject { +public: + SWGRadiosondeSettings(); + SWGRadiosondeSettings(QString* json); + virtual ~SWGRadiosondeSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGRadiosondeSettings* fromJson(QString &jsonString) override; + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiFeatureSetIndex(); + void setReverseApiFeatureSetIndex(qint32 reverse_api_feature_set_index); + + qint32 getReverseApiFeatureIndex(); + void setReverseApiFeatureIndex(qint32 reverse_api_feature_index); + + SWGRollupState* getRollupState(); + void setRollupState(SWGRollupState* rollup_state); + + + virtual bool isSet() override; + +private: + QString* title; + bool m_title_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_feature_set_index; + bool m_reverse_api_feature_set_index_isSet; + + qint32 reverse_api_feature_index; + bool m_reverse_api_feature_index_isSet; + + SWGRollupState* rollup_state; + bool m_rollup_state_isSet; + +}; + +} + +#endif /* SWGRadiosondeSettings_H_ */
  • u1E}>=ex6+#rnEOUSK5qLZrVb1l zNE93t;`t@p+i0}7P`jNLl)FXu(K7EZbFqqmdhIL)Z_?~ewInkeNtbq61?@$b&ousk z*%yS|zbbJa6-z#c^As@77RAn^4&BVneMhH|Y1f?uPt&09jKg@-eO>zq2?aIYT}>@B&Ms=6?>73<#2DMo>yfH#8Q) z5E>^j80-2DBZ9V;A4X6kHnB-oBBM1zvK3^;2CY0gf-8RqU&5xwU5vcM*#Cmy!NJ2S zKgN9jqqVwhb2^nL9XsB1-zONd6=CFJu_4epr#U5to*ko@7URXhq;rv`tTr zpi2Ra$9OwCpCq{SRFD=B;z@0Lhl^xZUi0~}RCrojK5p>nbaa4E4zrky)(@9gI#!r- zCu{{9h}-MKuA%$|1v(QP|9SPr&%p2Kn@s5QKlk#Z=Y<37x|TG6@&eHM|F9f5p{;+F zl`7xq2?mZd)-Zg+SXEBNK`VuALcWBZGyCjBJeh#O0?GC|8Mwb_&~xSZDN8P~)3lMh z)7z2o-oB^u@wA+g>HTfvA>2y9`AEpbj!;kUkR_|EfMgu%QBwwm6&|^m!31u0A_p$e zQYU_akV;pzFc~ESk|bG4LL1LNidFt1SpiGe`_{UQWL}%U178cyJA57BxlaoKoeve_ zyhVGvbs$EfgO6P57Qqe~_7>fB%hgW()$GR59LQuO&MwkUV^FbX(;3hIDzS6tDEVAdzkeqJGFQzj-CT zj)71O+(C0jEst#dVyAN%!?x9Y;xVmL5h{7T-MaN6CYL3R$0|N7FN%N%e!v8jNbP63 z|L(HG1)1LLQ}+w;QM@gcTu!J&K0o({iJJdqB`Y0?F{P>xO2t1h1c)1)4ulS8t%hh` zZ+%=@{xQ(-%`7!5m+2xY9jibx5_8``l9>VxsqFN$pm%xvg{l~;>x|s55>QmH8>JwmBzfwQroL6m4>q#h^ak1?7{YEq%+x%y&MDHt) z54BQ|(^ndZV};B(Ef`^Ql*{a-!H5axk@>w^9Ib(?vLd0d%DeV@)XF))?W&mte`(Oa zgOt)bl=g`$UDxo$Y}+qpDk?0Zi9ztLI=tFHjo|$xsp^rc$rHBRI36E*Y!pp&lvmyP zhcX$is@)Cl)pSC=fTz6sXX@+I?ae++^S%-C(gjCixr3Q9bG1Y1xSIBFMDG%u#+LO| zy;d41dE??L-!xnyNh4PEZIu!q*Qo;H@Sv7B=wJ8W$TbQjldt^LP;vNn&~rkCe;D^4 z^T>4^m#HjzNC|R~aIB|l`DO`o$tr!u4k*xLSx!V2+AyK2xO7Z54D5p9Wy*
    7+@ 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
    79iB1Zk=9vlJ| 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ⅅNB5 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%0DBvyFBtx5s9q7^kRyBZCvI!Jz0j3>E% z0owsiaX#w(C}Td1LwIw9_YJW1@V0eL#VM z0f~b6E0=Oin&z8S>(5NZO}vTJb)C;X9TyW-T6$frQaWhdZZQdk!fW|gPbZx$E-EZ7 zEj@JT5L|RGnwvWq5fM>Vm}l1tS(}!yXoa0^8R=i`|oGZo(+%`78VLuxs-ic z*L>BbymCvQ=~P}M#idTGf-kDuLDM9Wlbt<&{CEJwf@}F|rHucIwy3miMOH~+kG;}? ziBxitug`%+ixwR|a-_Dlh9T_~f$8=7OP4MkN=z&%E-ouA6$k`Ss@=PH2L=WnI+R#f zQ>oV|Yip{qvNA$K0=*CH-M@cNd_w%W^A{wdZZ1MZ-!JB%FuTQYqqOAk;UD1K{rmU9 zJsvr7q`0_9A`;Kp@XD<t*b{jIEcp_K*grMa=4&X+;GkE+9HC;4PV0(`lkDo$ScKn@?bkhq1;V zum;c}PW*>N5Z-u*Z25t@S5HP%@TNLAr{f`N1g!HEi~2)Ck@k4A&8tgH;KwQH9b{1gCiiHV8uL2|K*dnzt}K-!lp0Z`Rp$r?Of?^2;LYyXI|>IV6#9# zB*d9xqKz?e$PZm0um`OTnz0~vSC}a-))J3g#mT!dr36HLoFyj46x+W~Uz|0r&xQPs zV%nE}^zT2vw{YrCb)Q2zB#Skpv*P<))KP{pCNAO>?}|>MGN1&!k31B~8lM1XnWAI3 zG6=A+?Z@ZMJ-puEdI^YX*0f1ZlLRd@*EG}0T1r+u;*OL(y;8YKb4Fyej z9R(2V;2e)Upb9!tVJEG@d|CZ#|38eNPrHYRM*qD257 zZLQ5TZqun1<>faH9y~a4;>5LU*Mx_MHi*mck7> zZAo!aa8SVZ?OP!+FicZp1LPy^YPLyhT)NVq@GCCmIjr?eKT+At21o;NHe$qxW5V&vek&$+4-(G;6T|hZDi^*m&i$r1{AK#H9N3LAC0?LNs zEL2v4;^X5M%t!y0FJI>4<9+hPiSip|6_pkF1%*IVQvh8-qQ0k2jZYBN*EiTL#vTU+ zB`>^oW%H&D`}ggQiH^Q@?P_yVBcwli0++1%XxtCwr4D=kJXm>MUGF^q+z40jg0{IUl6FuV%7OH`U2lcu~s_Vm6O zfE6-6v|;TWzwcI^T{&^yXJ2oevf{e0Ptp4M!84{GoV74@o1Zc~uxi!VS)UHyK7D!m zl9?fE{A`H=OXPvP6)Vo~3pYjhmTXuO^X;sV?-pfw1?pqNnzt-FvTCn5ZU8jI?FxM7 zjhW-eF8g%m*}!|ahEKqN0oY0pLq+duFdVy<+?Rz zdUR)cbveD-9Kfs|HTM@jbN_WKvz>};r`%IRMD-gIm@PC?h0GT3eTnQ5?^n*CHF`F9 z#PHX};%)~QZ|ud+rnyNI^dV?zKHYKDAxUy6(;Tu4R+`C5vRLUEMs}W-7t)Fv*3jj$ zYkHXn2h;iu2*o#Y>bmSjKj3-3Jr%(>D}#G)1d;{8)&hY;)p}q0L68R|JwhHQzM7(O zt5K`U&B@xeYu8%tpTFP1)5)i*E6cR9)?0-5Hra5?ew~$HBE$uRQED@3bt<_@ufeP) zkV-Dj%18|h4GQr0J%1*JwMl+*nI1+|2M+8XKYo0Ce0+Uvty(Dq48p9&j<)6t=g;li zw|D8%CFP~XJessLH3$R=2M_x0+T~Sv?J8Udx0y+chSs(_4Gp*O+8#?atE+JnYW^Y!Kl}!rksY~Dl#(a^5s0e zR>cr@omK;gHe<&09}Xpoy1NWIH5A)w(pOd7fK2@S{6a#4YpW}GqPleH(!zxcmn>Nf zw|Tv!NUu>Eb!xbxlSV6|z~HzYxDzcTw~(}Hpze&C4-gmY4%llT(7bfrB`S;G3a>BT zUo>&S$<-V4cI|cg7sv?O(lW)bx*r z@BVJx$ua-+@3FgqsEk1y!bg6!XSHw5%HiLBIyPkS+SCPOzx#Y)b!14x#(BXDc1ijp zOC<_4+eUx>_sQA&)MvI0h0fd2NWkX2k~l{Z*b1*@(cs3#*TsOwPU@3gpl zkWXlIhh_j@8=<}+8ilfQCdt4DwB!8=MJJEe=bG?!8yDWAUFJ_ ztqx2}YijV$Oj?}bkfpQYQ*8G!rt26hJi$s%v(juvn#Zb29fsx}((t?s`6|n8(-8G% z@uC=}D4?f2@TdAPI^WlF&Y$ioc4Io^P<7uak0TE}`bBx1{(7msr7<%jEhIP?I0MiM zph^%Qd+B^uS8IhuQ`c*6Vl~x_rn!f*uoMPVp;5`D;%-rQM?-B@@~Pv20S9;Q+L@7Z zoUzJ&ber!G)xxBtlWna{{Y15Y|Gr5RC+1{l*(@di3;xn3y|%fj$=BCs_N-aOh57u! z?#{MjM~?;t1s&MGud=+9Kj@}xltE%qHfhD>D&Y-fcZEvYs@EuJ!e-EEu9ubthlGwD zJN9(aiQ7H&E%!Zd1h?UgQDwB*t@`ulasvYbwr$&X^ypC|5S68msHRPumY$ZXRLEGe zuZz;w(v+N>v}x0(l`B_PS5~0V>UT1{dO2_R?%iQwVOg0O8l}u`F}Ag~#Kpxy0b*lg z+S^*Y+FQFjkO~X(qaq{WS6#Da4bUM^R2MH^oHuXYh7B98UAv}~N%%Ym3N2LuJHTQr zYws7g@Wt-DS74?%r%x2##RF?zq6Yd=#RzvT3!gH2)mL9G_+r?~vEL?b3l#79ZqvxA z$9IIP{5Br?c6Q8ydEqmM&wTqcpH1OvuNf;w%t+rGQaJSw@7_aH2OBp`Ui0;seX|xO zuiIL(Kg86xpYZ_22PO~u%kc5*Di3TuHEa0Nu`8=1qH30pnE%xT|L>NhY}j7z6V$$M z!HzG+CG3nM1(B`0w-kBrkA3%lzx&0kLyH#0&Kf!A{V(?{^R8b0*~ri5SB46x#K7!P zZ%>_dK;^Uaz?kt78-i^fSA5Nch-$(oKu%7{DVO|ok1D-ao87C=?a}1AlxH3CbBy#n zCB8@rFO$N2N>WP8t7&B&a#06qno!UaZRc*sCd^vY@&&+=dLe0FYiKx%A zUGQNGegCH=(ouNOcFr5GNuw2Y?#J_{^1!1<$m7Ichgi~XGwEegNo8ea(y3GX_wD=c zyYJSnSrroOS6zD9jVXIbV=rUB>7>j?U1LMt)vH%hQ&Wx~I~o%cwaaVgx^-(eY*?R? ze2m3ZKlR%Bh-%@&q*KS+S{i8F$`h5hw>MDB)x3)X{oie7V|RDApWngh)29_(yUHJY zAW=DK%xYA3w$|n6<>Z~uM7ofDy(nL+R%$eNi7NHZnn>icXhO8Wo7Q!vuE4Ztxfec1H*n6 z73BN+`i6#vrkqYz$t8NNs<^li3OsS*M94WYQ2;u`DJ(Q($BykQR;+-ZH1FcMfkd@; z?_Rk~Mw1@#y81=Kuk?%J2DHG2*k7q(ssVmf@zI9ZcswCaAL>`VV@1S-&t?rtCOFZ+rkz8G_b_jsT(xvPSwAty>s2W75_UpMU?&qSAI-&BKQ+AHO(f>vx+zop@|- z45TLo0#a}w=*|E8^Wk%1=YALY-M69NFTb!SxNiAp<3_G*4hNzNIyd&6$usvUe?3Gs zbKFN{%MWhh!R;#obj7W%xAdXa5LdlEf~V<#9vU6gNdcIQe^$N#THjBuvsmG+(DQP~x3kNGb&q~iYBxw%uNwhhdCfA`Ubr?HQgLhx% zzXid|?6zy@u42o@Kq}w&N6wpyE%d{SV(_{gmqmX6bM%0u2g>7=U%TiYmLN?Et+=VN zru6*Ttmvr7ojbNKTre*)^^`#+W^jwmtgoslJ9{Sk#EIicNl6*pKll(B5U_pQwv8J% zrX(MCP`aOQV)u+uHP?|Atwtd#FE0ZGnLTS(LH^}|m$q3K+m<+mp zm#?Q2l-9}OG;MwANC(eDc~{T!L>1e*VcPbo%gch|k&k(N;Pu5{PyJ}_*)88~95MOG zw%td*{?pVs2dxRw60fPV-~4p{hA@@ajOE`bO{K(4Na{ zH(c`xZ&>jFqS`-tT-f>`>pg(-+6fWWq;D8`A)_dv<)yT|oK{pb>Uvh!<}is|b`*#N z_0I=mDB%f+iltE#=uwA2&=3M_0aSUMGNe~lP6y6M2ZqN7Gy^#0e6j9vJW&x3s!qJ1 zR3xcqEOLjT+o5l#<&}8b1*|a{s~5QB$+rxdRL3cz`;wc`dF1??l0(&Ey&Oec_UkDR zx?LOkV{IsYVXx(Kq(j^8fl3dQM{d74IcXqrM$-ruwwI7IgkGyw9y)aBi!Z(i3kz#* zZnT>8!p=6ogT5T+r&UWs@BF@TqjbC z+kmM2{r$fG?z?_$;`KO0)#IWlhsk7DC}izdF6H`o@7=T8YwzAYpvcIG#`-!auBf~H zheHV?Mhs6#NHCjB40VqYcCa)~kR;9MjON2fj&9qw6|Q*x>>0vl?k6gsy|R+RfoDN6 za&oeKd=9|nS{v&Ie&s<_YK8RT`CNa$gR^JP4h;>>AMo$$)%?6GR|^UY%gRbMD)~U7 z^7ZkyJ#*-G=)e!$0pbM~9{%>1Z@f9?-FL_R^B-ToGdysuztVTbp3ndB z$v;Q#ANAI|e|u;4r=NZMck@SYeD<#i$Cix!^7nrp{o%(mKlotw zC*SN@>C?1v>hh1?o&4b^v)+5-<9EL+3-vEuI&s~UjUAjH6%o36%|GAVwKb-1EnY%c z`O2{?M$C?!@y+b_-ktXGr?cLDd-UgvD?@xP&i`i8TW^nh=dG{apOn5oTC;!d!higI z^ameJfA9STW0w^N$F!{YYr6ZDZ~wubHSXrpON>Y;$l>l+BjhsQ%!c?S9LD}StMZy}oC`mEaoZ?bu+%ja4?WfS1 ztlu_Kxhx8@?J8dSg9j=-P#)(F$&KqAh7PB$!fhzKO||#XN)j`roK6}!a%4nAcuh^U zSlC^9y?Filb=$XZy?Fj?LtTwRCf2EyQn4^IBb_Iz)5#|o!f?BXWJz;ORCu3fdP^;B z73&nOwCSVM62oxRmH2vK|2^4!|VW0{s93iSFSjG_=g)66$Z0i zXF##Ce0-22*HaUfL94o6QWO##JZaLTBZm(uq+*avDi%v5okB@-hqzlL(J1Al-7?rj z1vU+BwCrGP&@qD!Au=Pcz+lzo{63;Wp$aU~;j%#A+P(W~eFLT8(Uy1tDTvjD1+@8x zs3XHA0p1NhLGp+wT|}@bINT5$qYd?M^$*d-#HfP&8om95q2bD~FilK69v`C(3uyJ; z-*7Nk5gCUI;;m6(^6+SW17k8iQWg}VAK;~KkBLx(Md+fUR3ZM&2lh4ig{Y$92!X&J z8z~Pw*yQUk3X8TSKnddv;lUlg-i-%?lu>b*AkiKjDvgMS4^(1;DLh0T8AqZtf$jdm z>XE=EzzHLkvAOSTh5L-^MVF&`9E6+O2*u4J zSFJ%Aj{9v2o*n#ved6}g0)!&C01EJT!06Nq{e}5b!KGQ+N+W}4;s_7bD1HUvz-k8N zgbD_yu!c^&{enxCdsCl5ww**og=>GCb;E;}?ibkzKaPQWvYzJ-$;A*TCX=QE6PG!3 zWjE~=x5x%JA*Aev^wiT6CQOKli3Xx-YHB)r_Uzob^A7CaYtSfpPa_vg>NU!Yv{WB& z?=4%lB%eA#+TnL5Da;xj8Nto^o$6?yqVIpbd zs>N~}$qh>8zfJMWk{!qo-9mHyIe=iqQWX5QHUKR6_NDy1sA_TUrNH7Y7DwGp+QP3u z9LQDh84g1Ekz0vbOp1$~$_s9FI@OU(3NN|r%HF44*Y@hm1Ckyg%f(QtAgJd?z|E>) zcUh4Ag0H>w1gmXx6R-F7$Cw=_4}%tolRM!lw{x-!7uf7!BSYuBz#PC7|pW@zK@64j{_ z9j(=fs5EWmH%cFWj7lLDojscy6c`BTlXvMNN!YEp!AxpwjMipqwRT;0XbXO(%AD#e zl%&9oDftd}XL}2jcK7bxix)3Gd`M7TQ3iL1+e{>G*K5_C9c}4psX$KKwr&j$3Tkew z$87MH(MDq*Q6WF7q9Uh*?T4zzCn}&Nt4W`gnLcOE93SrkIoX+TIUKW76lJ#9L{f!F zES5=xnAJGwvwm>z-1G&qUBFc?1}^$g7lIe2tNG`Ki0T#8D?wCTgGX{r9aG4uZfw za-))HQ8bMfMMHffs6LN%sD5Z5%|*NHDq2;?DlR#sr)lA7T5`dmZ+2lCZg%{o)esN3 zc`+JT0Eeanug)ZjV(6;}fT(U&hme={Vb`LFmP-z8$DIv)?xz3k3L0P*@1d=24OK@E z3(`_fT|A##a4r9ONl8gjVQx-#d|aIOfdlK;ufKZbGDTn}qoJ&{bjy~_+qZAa$jG=} zQryy5S9ZNPCmVpn8*pm#=1plS$uy3JizwV09~-@V`LdMLNgXX!thLLaY^ka!3l0ic zxL|%s!Ihg1tcSMsG8jA#yTv3Hivt4#XV0EpawmF%QKzn~D36Va0fswt=ul;4MNNHG zyRg}4S6cOrhNetPl5yLTYfF0UOq@4-XH!bm6>Fr{b>#NGB8u0gt}>{`-QW5{zQ37-`2znxfj< z+j4Wy00k2|nNHEf1i1G4d$G!_-5VoJI*=aoU>W<+|>FyC$@^Jdi02uwDox zn=kh;*bDH-d<_H@jKMhHsjixm3*n)GUOTs~T(NxV67+A?s+F5IZrtVNbto~hu&_`e zlc4D&nvjXRlTIExuz&BGHEUL{TD5k~>V5n6L`8+Cq?}GpP6`V2&&|nT2t-uCRY#8; z0>;YD&gyKb!BveqQB6ZlX>3&3+SMz{i!SyOYN)+Vs{%R?cB@$`l}1KJ!KH7M7V{-! zDco!{oXtJ6Zr!?-D^@IDzI^MpEk7I)h~@2eLz}tv0wK(DsncAF(@t4BExE>OS^?3Z zkc8db+*p^Bl^GEpwtd@HDCx3ga9fL4ty;Bt^X345zvIV_)K-<7^lAsy7jz1G0SxJ`sVgamo5Q;1qS$cv^MeSc~#sfjgF2=6vV?_YgK)F z2pV;o`uh5lCysl0ZC}5B9Ta=n(xod`t=hP0Q*2yZL1Cd%E(M~}>$KOdU4vVT3=gwg z26yNbIf*iig&W(xhjLz|pxL^5?E*(sf>?b-h&U)nbXOsYh*-?CrGG6&3gS%>VakYD z-jRzE#Op%*S`G#&@AI`H;vz);zRi9i+E~HB<9KYiEF|1?$JL$l)(Yx4c(6S%+!*&f zw!3+0L>aT zeGd9~2L%Si#zdVuar}Bov0kg8xM3#{W-&C>R-Vbuh>8dUehT#W`ynym?3t{Fx|-&u z`pcKj)z?%wX|yQELF3np3Q|ue)z(yM_$~>=9zP;89D9UVvC(L*$9jP z6U}yabzHriS5$Bn?z(@R$w3pi-Bwdok&=8OCMv@3ps%mb0l>KM$jHp>oVvy)xk_WT z69$vHxuxaQ$rD#DU7&Gme@O;Q&^B>B|Ca_;&`Msrc9A2hXrH|0v-eG$uyg#VbtAy|y%O|ZJyQB{7q9d?J`(I!4?fwbl zw~ZgSWz1Nw8Ow@;?!m9Y&`TpKXaZ5wixz^Rg#dTp$7I=lAb$FX2s8#+@qET38hqvjj|}V@eCuE_ z5RlNbO$wvR#;flLH#z7qbkfp7R+{OOC--Vn9g;MAQyQ(TMf?3d1AlvPl7~DJzj~rs zT?gKB!G0}*xU~0HO~~z<5VpXF$Pc#VC$O@6ykUNea?);0gLhmYJ2G$Cs(Q&*2i8qk z7nxK&VKkpz4 z3=Zm$zr28-BxNipxWo}vd}#BYZRgjo&-nI(KmW%^fveY_*|@cEk58-jj*A<&l=_C7 z(bBwl>4DwlzJ9H{x8&{c7KTTNymwsQva2;bfk=!I?cZJD>({({%f)T`JHz9+O_2rm z2;ahu>(6f4*BO}r|22jktoQb*+r8z=-Vj?tf+1*k-uev}cld~-5{Q`4mW>l<4x5>} zabNAeU6p>3INB&Mu<5`-Nkoh~U~h$wf78xQc?TkhglL7|uDp$#3-<@>;tNj^>z=ahi+6qe(T3%L+*b*TUEgo{;*G!kaa>Uhf3t@>JP(kn8orwTZ8c^p(Q{Q zH|>lppA}`el8t8_`pzEG>~YF(MbJ?+OBqE4EzEMt(tot&-!vCHR3&bk z1geu~;=xl7ZFAYxPGg%>Q|{Il^k^^is59J(bcZaLkzJz|RSuH~g%*6|(hA;4Vw6T{ zZ&7MWHNp#aVLB^3<&Y$?k_<|e$Lg9$&kmNt2-1d;7CVy3MyO19r^;5zU!>+N~^K;Z->(%~vIupnc$Q#uP|MQAMqhLeD9k3RS5bSEgxOIY!T z;=G{s$kyV*EBE+OnRkwS^LJzOV-ktjfa@zJF8^xmzG)Lz5BoY`U9d4eu59{ylZTD> znml3S*I&;2a?IZ8({_IS-n4NW#BpI)Ccii7%dy)gPTDg3^A%IqRfWV`4ldpD*+*-p z%?_MAV%f-fc>%G~o!{*p_2qY8e7$kr9?ACU-@Z3&`;4hxqrTZVZGF|jy}5Hf{OsSu zch6XUe8PwG=K9(JW%e%(ocewGp0MVX!xw%1&4MpR>{`C7dDFDzpO5sKHhI(VZ}u)z-S5GW>IxZFma`G@Mj}TNU2W#Vu{@^rVJ(QJE)KQ%mn66}(Jn5DpgB6~z z)d=iOsYFK}ExqB;wYf1Zas)J(u?2Ctd>+ypHN2EmZSmdww)_$;VOT`*UN2 zyVT!)W|zG<4sSW{G(TT}cvXemrzlAo-gLT0mHDGN`$tQbLy}^tI!Y^F#Lyk9?<6`d zlkKUj@Z@b%)=##a+fZG*PgpAA31Pm&EbgJqk9akpR|!VaLMRos7P+NfZmcqN=HQLT z(5$y24R1a{i3Lq5i38N_L(NLu|;{~n8 zMybV)0Yag$SYj=@0j0ri$H|`OKvd9hK+g@x#>4o$0Kr8W2Ho2yG0ZpA@|=DH|oo^3l6kyojmWOZ$j31cSl4Ey_P2| z_v#7{s@gDh&9G@nd%`htAHN~POgci6Wx+raR zF#JXNL8;%M-G7eibzWPPMxnR@L5EnO*#|iCG3LNYaIO-7sqJmQ(6979t z6DSGPuBRS=>~#<>yT+kwp{4nZD9a%}>6D@^FkQ+_monF>IPZ{OVq{loSrH|>!DyPD zW+@sBaFQMf#mgh}*H^tP;WCKmwtV}QaPqQuZ)H$#MWFk-Kan3~DTpJx3IVEqYy0*9 zuQ)9dT5^@?O1h=byrl=4IZ2DoGwKGHUG0(hdB{x|97Z9lu41H@>F!jgH2JnM^QJBx zs;fhm!$_~t@=`|I;wFs`>`B7g2X@j-D1fNc_I87<+pejh#QBUk!y!&`%2HYR1*qgs zYoDL^Ad2_v!U-)gn`+&{WxNtQDJDWEP3eX0j2Gz~d}lItyOX4iIM1TX4WH zw}S?d0yqyiH1g?f4p=;@g}jL&lw&Moxm9|(9DQN>EV=Pvrg|NZCR{r+En z_`}=3`@jF=Pvi4~<4VT;{qu=?tb(wrwG+3DSyC9Bfceax@Q)E^!$QxGeslD+eb&T8 z%fV${Uyle{vpMpM-~F9C{a?TT-QRxq#*7J@E4NHuI%0PAzG%P^Ti}Y#|NifP{6GKk zr~mzbz4`XUW4oiI>%SiJ<${{9m`nE&Rny}4zWjQ%C`Mq5TC@I-|KC6MmFoZZfBx{z zvE7k(rtLTh!YbBIS@!NfNB;98-wna}li&DaoR>Dn_sYU?%O`FYC4^s|`OmLDTU;F+ zXO9oOGUdGyBR47g&Q0iAGi>C0<4*28*s^EQmiInbyUb6t`+Kjkvy!|b%-%Cczd5!b z3W#ds!H?eGxFTpEQ9TE}G@{~mc6;6vZ8TIqXkYnVP@rK3d*SLE3>yNe=ON_yPotO= zMyCVCAh<8Vqr^=*0RAE%1A)OpLIFAXs8OCK=7EBgV0Yl5_ve5Bi+$F;AOVsXO$)Rx zRQqX{JpH!m%q?RUYO55!OS(hy7mNBD8oq;u-q@<-c z2WuMoF@zd>ObrZ&wVol{Pv6vK{bd0H}zRgWfs<&&S>f%bDH}}1N;bFJ81 z)?p}a(*s%wHCCE>@D!fGf|qp~>m_ET0RtxE55k9bg+-#Zx!A$~SABZa8(EI=K#Uw9v zY*hP>nd^p4KDO&FQRNN)^H)>%+Y{qOUUN1MpUe~0*CWm{IM=K1znnO1_K|sCj{Ngq zhrRjcH~;wKAO5fZ{OGL-8UFi|#=Jje?1s)*Zk?bYUVmWap>_V2J3rtc>7@~s`+1WM z@+>Buj2$(}C`5veq>NxMfU$;f>NyFh1?}R;xji`75 zse!ZZp3AvjadA6Qxb|lmsd5uWr&+|Rs*z)g@C?h%+UJq$vl}$u#rtQ2pd(G#ky0Dv-LC)&|*wr9g$x%jJ z<+7@7-f=7bRSPYuXLZeZd$v=a*{e-=$&($jY+6y~G>Zqt@#wLIHV_10a+rjSqMYi? zWQECYMRKn;^_C&CSCa{)B0A3y!U9Iq>@jl2gM!0hrx_E=qJdsFV|QU1T2@Mn&bZW> zPGuS^KFul$Swp9rG!8s>P=rRRSO6!=iV+r&oiJE1sm@x_WvCOI%r?ToJmB>)TJg#* zW4+ic(V}TS{^0W?D)^P)mw~1P`i(D!r~qwQ+U!DWr|ynHJdCIW=FqJPW4~NAV_n() zy?KkK?4P%zD+UqO7k7zj=|G}7H}b#VdUw{@z56aN9lQAJ8L4|hYL|Tc)yK20>_1Sw zYyHugbAH$s)ZR~20zbirf1LX5j@o@&Q)YiU=AGfe>jOL1j~x5q#N_RM#WUXi@bkq* z`*vi`9X9!ciAQ&!SwD`b5{Y=9%t;^58oQ!o|GsN0=LCGep(-TK9Juw=vTa>=x3#&W zglIXiU_d~Z?~csxM=u(^sy;kcvw!aLPreFUv!`nB+Q3iWUGV(@eUx9>#x)mqdtdnW z!%5#PxV-y7?cTK!Uw^c4mX|ClR1^R?1PXUf9r2IRxd%fHagm+dXDoW}^KIX6DB829 zZ0q73AOC&o^gSkzOFye#8c{h}JMV=4JlYt@6Dpq@Z9LMq3kuXrASxCS)!=unhQteK zl|@^MBAQ_ti~EVgrJ^uVP%HRhDwGem2$a`A6Z3>Zrvs&-wTDj#c^*Rkzcv-CZK1@a zME6yq^E}m^>j6?Ay7MU6dW38{L3N~1-C4BcBC9B7we=3O2->F}%JMw=_b)|oBR!Ov zkycx;B@p?+?(6=yt3!UQ4W+Mo+w+2ms&s%Vw_S%qP2P9zuSp1Ea2=~GCEHHARp~bk z*^Drm7GHE)MDVzurOG{}pg+kHPK%5b7E#^jSxL5AnR!!}amxr$l}2|QCp%JUX+Ep1 zgEY`pKtqWGUe$r4%W!LG#jB!(k!CqiFohI{{5&Nub6REG=4HMj$G_>&Tg==fqXWaDf@55l%se@Sc13Br2=V zf>py8)y4siM0W39;xp>2C0~8DWcZX5UJ=%W_@>3#`S`Q(J4b!9^y|_7%l3+51Z2#Clxbhi|LU6+Uk~3pV{LVKf_ne5=!NTU z1jLew3BnB%7ku{Ricu5y&G`z2%766d^M=p6zJKYqFFu?9_2}*6CLH)~ zWuAAWaLY8W`MWe|HD9d8Z%xSPuNHsx)zWV!#%=Uh$0b@1%w6&oSLVA!a*xQk;Mz@# zW0&qzAz!P=x;2wme(~wtPd{5aenl1BLd4!Pi@ra+(O(&|BXRPu1;f5xK5W>k2}?^t z68dw%gI4dIu(*-C1Q8cfyJ^mrVV}(U=%bk*f3b1S*3Jhz#XpN)8c{(-0mg^6v&S*W zP{sAM2p~4#C#Z{DPXaA-g)4GnR6|7dyaa{@NC-{RQ9v;KE`Cq^WH}nF{eDSU9a}gQ|c3G8_qyoEf!kX>nD)IZdA^cWVu%pP|cK)FK z`Uyr_=eE8GFQS(ymtBq4)5$Nnl_|IMnK$*>RCgvNDRvWjuD*Gue-YxNj1mSku&Svg zJ9F`-!!B9!Ed%1Jo4PEhlTb)|V-~Hd=b-8#+s`|x9>(S{brBu8j1UcUIhAK9@kLhO z%z3E~;->Wv7DbVOO7#+RtHPo)!~5%*z+@w8L?%$P%mQ@9AAG*Eeoo}^$+CBrt3RJG z3cRNZ!|mU7zt!?2DoT)GkBh%EgC@Y^V~tVVmdV@^B0kP8Kx^DcK?0T_;F1Zjcu0@@ zsK(9QXO4?8#-Kfn`*KSZ*rFqKQE@o;U+$~~qVHP)78`AdhI0i(LcE=uw!`CNjIr?~ zx^9dyI@X@hmmVcZxEu3{NQg50UjHri;BHdP63_} z-}kK`!4egrjf%xR{oMK6y!&4Q{W4L;*#6rYT)i}+f?5bI9Lw0BWiEyn zJWS8y2|9dwZlvm&R+V~C6bM>Pr&+>knkZ=*EiGVWmz;_VF4Z}=`m9@h#;wkD$x|HS z6Rhw!BRs{3a~VZ3t7~*xB&fOlRrqeBXxcU<*?!G(HJU0!BUQJmgKt&@(N_-O`Qdm) z3N5^W;zQDdA8YXyk;5d!+Ri$pS+|XuJ?d1aJcE`Ovif!|B&KKL7cBVMT{b1HswIV& zk&l-m)2&MD)u!Flr$f!8JCj)16^FLQp=)uP#dpxk(;&NXEiJELq?g<(K(Q=`;tZoG zV3bv?w#A|EaOgWZ!G{hOq-$fftw_3d7LFUb9L8>kQ3(0F>?+_ev~+_D7V2@82a2I7 zsm>0xR3|nm3}8|`6PWEpoy1%%LTdvJ))zrkAim!YZ4JxVXvRX){RV0f#;YI`$O@V; z$ehEe2i(GaMD>&kyE5bJ^^1ILp2vsubb4t-#m&K?>f({;Nd-0A zS8gTXMKac$LUiV_x)x}t243Q|75WhzMiJ3fU@eHVW_$IN1^nC)&PDz_XwKYiD>+Px zuRE>s`%e6o2*AQpb%Yfs{bWDm5T7L4Qyr!bgj0h$`u>!HGN7?lqK7oniVD0f3u`*c zicb7w%lR40g#x=3Xlxa0JdL+s0vIBGIlLW`@4RFOXSj$fYfLy!Gt=+S~A@i>L-)V-zRDiZSFg6py<+PfWY#D$!|(CR$6K@X6E zln;Ak(D3w7W|vLrFo{@0C!=j)RCSE9oRJr?(z6apibImbDV3Gxu+ltMRnF?$Q5$w& zR3M84`lmQhrR=aM7rt*attAbVC04M=m{>hrdic;~8vrem&Gc~W!dkxSJP|IiLx{3UCOh!3>k2A=>*>J|}@G0E56A5U@^n znxXsc4~kLzz_0jkc`FAtif^sBj^9HIKUhRHq`}ooBPwp;?$g(G)Q~%%>FsmexwnpT zEJdQ(BCZ8}rmf|kkM8by!VMjxMI85~c|F7f5PJXNMi@KyIFQvq_=4hmJ~2^2J`9ca zdA#?TBD=$lGJ>tKy8)xongis)aKD9mprAZZHYg{zqs73A$Kh1p=8`590G6vckiQ2= z@v&i{8wx3(=#e3Rc1%M`uGN+y+*m)`)W z>O}`>H?F4@)vPS9SDkiCpMKkv#YoN&!on95fa)oP788(WM%`$uOC?%PIi#m=>N9`F zazVFEnP`Bm`G~dpFwu3zVd{1hI)Ex|sV~Ew{%Fbm*?#6{9G&=+E$1iO z89tMrG5Bx>zCuSJ0UUwPR!EQoe}6P*-!hH26?E9{AF1M*32YjeAigWeAK|~k zIe#hC^M}@ofz}E-sK5Mn+$Ab=sCR|eeql84Y?NS)4y@nf(;abl+q=h5g681b=o#Oh z_6i>`SQT`B=E&_!eI*B$ht8Onvp4dI#CflYh&cZ7TH*-XTRweH@KwsKveZ=^K= zjtKC$;QF0j6$c}1eU44hU3+)bhu-zRdad;Gi0aAP+J12(3Vnf#ppoONCSNlzOE`fDl4CNhcH@jS|~{IiRR;Bd_mVB-{=^9|xT?_{*7$KIf;WAS(EM;K_1i zbN}GEjthl=HY{>*eK-(2Wk4U2Mpxvj!2{?DqxxLv;AiK?((YCU_%CF_a#O}!vHL8Y z2TOsagKv2|$aN)=WrT9}=ksWxHjJ^mta4V@%&N**=_N*(>JXiB$&wwS(^O{~tFCg{ z)V~U!D%wpL9fmHVH4iKOfwjEoIzirM!F`tB|SY?UBBzkq7#?UfA9IZ^$cd(io zR#k$0`??Y6Bj+kzdaowktxR(&a~;YnwB#x&E@IRTPK%r$e|4B8PIaM6dg_)T10d-~ z6Iwjz5GS#4<08;WKqZhvddjU%1#)sJ&`tv`S(00k+@m~=4rN4O$+_x!CX$mXN z?TbFDX>wW>J@>AT1SE1fXtfC|Y&FzN%yyjgh@tR6qC#h}&|iJgbqp*y%h_6I^6uv^O6&It?0~sHvyF{hiF>%rd6LbA||La(}?}Du# zkBsq(rUU|l^F{}e=reo}zz6O#{}qY|g~O3VfhpXlWZTaAAT<4l5+J{Fzs%9^%>33{ z9lF10n^$v4jNNa+^3luMqxe%$wgWS~a|9Hp@?N(8vp@aukKg>TJ#3(d78bGV)Z~AE z`qy`7ef;*j|M|yd%OeQE!Ia_eOdUCH%gBl0o5Ju!fyQg{oMH28BJZB{TIr<`mB)9F zDKxIb1wDd_$Te~UTTnDK1*Fec+*fVLofo_<@J8`5FgXa&Q{1@A>q}H%1pt6J+CZLa zoSEngPY?I?_(TOy77_!W0c*l9^N8s@uuWiz;Ae!y?!J+Bw3RaVliuz8@q*9LHH1>3 zDsf+ZfYYIn198fOrMPb8-JJXLgd@%;UFC#YGH8IMjG~%oKMNq`lBWPvIVGo9*%emP z1T5lt%Ihh(O^2bIXuoQ?5{+N>bC(6&t_l6QF~V7V5Wjf9o)=71q&U>AJ-D75{CMSF z(uaw_tO~gzCMIV1@ZlL588nHpHZ`lMr8)r%P61vxWhq$mNmkc{Cd;0o$N0kJCXEi0 zkPsGO%^9>X)1}J3Wz7B2cK&A~@0RJjOL>OsNXJ?-C~=`f*V04ifWw?-sY6xl5TCyF z|7Y(%!=pOZeP8r`*>uv-iq#uDND#_Vjc%&N*XjgA=x~jZHK;Ck2oYC=&(B zISV0B011?H>YQ`#9yxWl1laT5x5ki!Xo5+$h1c}+x1MHnb&VP|D*WoLs<&L_KLl#V zU6q2djFK0TqlKah$kBWdr7Yr1mAt8v)t0cDVoqDa=}LKHnP903IgXw4)?L6({z#tu z0Y84;R~-*h*gl7O+~mcWqF2ZCVJ zzxw3`Ej%=d(44dNjbG2(`R0osKmN+0ONc7fymi6O*WNw4dN;W*sr9}8d~nth zN7CX|_q<#Yz2(^acQ$>vP9OJu{EN?~e81bBG9A(GAl+d^73N`pf?Z{<8W9x~WpSDh zs@zO$sR0_G3x^6OIj)2RLrt4>b{ZM@j*vuD(0l*}v4Dn%a?p~3;KboV*Yy@e(-b-? zYtkBYRh$A%HB#`d83q~o#BrWqfDZt3qH9no2GL^zTFwQjx?&ECO&bMCg+etQq#y>d zL3E<$nrs=T1mD7~uir*>Q34%i0;pT^=~#0sIg-ok&~A2CTS_WV1OukX@OP--F=?OR z*3imRMC%c(Y7^VAZM6^AkJQ(y2Aecpm#Lr*9QH%OBB$BNh2tP>p@{jgaNLM zQKoUmbdJ`ar&QzkP}tuYa?}CLg=}RZYb|d+%R5Jcq$R|7A$e2PmSq`7fL7b_0ljz1 z5G9FYSuf5w1B}B@Q}nN#?PHUTJTwvFM4p#NXExxH@#$hP7+;CYH>D3#*RNYlOVi0| zM0L;OJHJ|aYW14at5;Mkc;(ak5m60)^YjPL&p#8LLhVbeefmG1etVNOYT?eu|NP2R zvy(o2`Q88e&zBy4G5+(5p&E-V#V!wDR7U%Mnq%y^8K0U zq#K%NoEf@fh)T3!pe+@b&r(kc^>$E*QNMm`i?n_|K@|dM5YvxRE180!)wrojH6w&( z{TRtt1+p7WT^AqfdNDDAs3csLblF>;5_~JJ+Bg$y81GA|*Vy5=gn z=^zDyG(h>8vb2$to1!JOl9p15WlVCu9~s+q3EEH?7`T=Aa2c;Fy5KEgRXO-@vDg#e zsm0)Ojj;j2rw6DCH0>iB;<-~%fK%tYcZJSI17P7bn~5_A8P!?AsRsN)#;VI=m}#0$ zRE32FRKP)Mn^;ZJd0+WCS23FTGSsow0U&0vTV+YiZ!zkWvf+W=uKu1*_zR!m3QhRK z(`KWHfX8VwgB(_q&1}%A74QQHd@(%kpFRyF&S%jsyG5-S86N0?n1}kiwJN#WVYOR~ zW`h=@qi`6fQIG^8;I&%}D%r5#eaWuU5JxirAwk~0Bo4P58SM4CY)~N4nSdS*W9q~W z?H+TFQQavUY8@GD9UW}b$lL6icFNen>Q2$hs-UCg95vvxoVBQ1T*g7CQDM|76{ACa z;xj_x;SnG)JbelGz#}sx26u#zgYb0St;5|dnvpiUu8Xp_hdnK0?vr6>18;5j={j|? zcG*CCe@}aVcL&5dGT5h4tDG*k-r?`p`^_#tJeS#^k&g@v_I3AkcXf7mclQkp49gr2 zdyu`zE|Ap@i&3MLK`;=c4L(Cw^E7@vGix^|u{9&m)E_XTSLL>i0j0 zdE>P;uf4kZ_4lG*{M)=2KTLl8;TNA-YWi7RM*Xb1V~7fH3R!m;&oz5lyV%RR`CD}4 z__GO!ie`L}NJuL5)6(o!M3_5E(0Bn`z*9i;0aO(6?e$9}X5?3l7nirgOGGFm+J~mU z-v~{C7i1=)D{-d`#1Q0&ptyh?jRLPy3?f)c8Z1JwfuD$?02ZMjP0*F-m;;2yovgUs z;g&WNFwinm+7{keGwvv06i0~RT;8J)!Q!_9Rj4N*f|!-F4ijAkzVeOqiLIeCQRjQ& z&UeQJ&qPrtcX%tKh`tKmtqxJ1$e+(VT|!g^xpctFJI;h16&L&!A#(xNdzdk{LeGZ` zKLX3Mj83a9D=FC>AHRJ0@+C`_EMLAXK0dCzywqgS@yx|uU#*ZeHq?Voo~)~>t~z}1 zz`Av7zyBV7v>bk0R$6Q_Xs0h#4)Fj=c=M@-)a1SE*R5H;Z0VZSEBB|TooQ*VJyugv zRMg&j#-LRLOyGWxQX#KBR=p=-S8rGQR16@R!0a|#O?CCAjT<^zTcFedRE@DX(5>C1 zZfk2kl5t?&+7&ClU%G1L^7y!@>e6hNrYGbbI)`^(U`9if>g=hCg4~SO(PP!mn~brZr$NS2hTL0@_QW9@5s@l-D;_>s*I0|TeWh<_sf^9U%Tqy{?t>A z$1U2S5N6=*y_~I!_sZq{r}MH8#qEqjftI3t+q7}x;lqb}dwVqotHDJXtuCcfQCw6I z6TM^Q%I}vfS-fQF(v6!o?b)-Zy{(nR0{~UhO@T-2jvq@+NnW{P1!%+i^=YZ84JS|d z+>Yy6{e9DdHV57>YJA`>=tehtFKCgFPZkgF(XrM+O4~{(PQXZv7%4oNwQ2gS-^;mc zV>CN=>UKtVuX=xxIO{i^sH$iEyF^s6&p)^Q+nspY)+zB%O93)+!H`6)00h`7p8wWH|c}7*T4FD!dHuvUwkZf=^o$CPv7~&JFQoDr#@44 z2N2bi0RuWS(Yh1atzIf*x_~Ya`uJNK8T>qgItI8P5*1qC!~c{8ts%}H8#E*Y*Q+a6>fvKyiG??6$=76rk?xxWA~5X1nl9`z7cq3Q^h ziuiU)BIHfXU?OCMREdriBuRI<>9#UNIH8H;j3Nj=@hy?N@$KAYl|80+!<`yLDg;~PNxD?vAV9H*Eq(^=(YLNh-y}0 zeh!0K!-0-*Pfgfb!0F3KRXy6XDTbtQ-_YPdd3pKn-MeFBW8rT+z*JmZOia|CJ-bUw ziwFCAS#siG`+B;vv$FQ?*|Tfc&VA|W2lnqzNlD(bCn0Xv&MliaM@8+ZKT&Jat2t^S zyxFL0X>Q(^p0;V@`k0vLgx$N7k`m#E85tQnV`DdN*ic$rC>t3h0v@m1(bLnNk#XqT zZ@+0gd0hIrBogx(blSs*56zkL-ig}E^I_&(h~a6%Zolct6fc7uv^sQl&;)lgeaMSe`ww)nW6 zsVPaxiI9NZ3Gq8~vNC#mI!q>$pP)OtdvbGglams6?Tm$tf;8?$m3#Kl$;;ONaj;Y9Z5{blhz%6`p-{3G;7)G-wh*yA?5pxu#|A1lF()=(=!^ex z0J#9A>$bRy)?>{XjG{S&&1iq8ml9PrgImwhedC^5YBYn^9uMKRsok0mtLf0e1FKf8 zTCrlq;lqbVMn>dvd4GTZ!Grr(uUfHa(YFWor~4+S;o8o&>`6%Y?6c24_~3&bJ9d-bH`CLS;kUTY<#Jfho;?Hj^4@#zRacfvKbM62-5Qk)7--h4S(WAaKc1ri zsxY5>aG>wNf&Fvl%!!MO@9yqZsWoz$EGIj2>*fuMzWXLG`@k4y|NFUsz_{{qj(q*~ z*AQ~iqD9%+S#7OnEJp3%KyOV=^^zq^KL31vQBk2vA>$b|_ZQ~r!u;IDi@w{kd1Kbm z49F0zRy#O2n3%Ztop;^=wCZSY^SW#ngQl#wAZ};u(xpp_3-hfe9Z0JjJ$w4Z+0%8( z(O!?k2n|9}LEeG|3u0noii?X!M@NlDqf)7CK65s&sI+T9?u4-z%ew5A6UUDM$$t68 z7yI_@gDf)W)FXp^K&z`)uimt2V^u}j6r|1wp>~f9k}lwK#?(#7>#?D-KwmaKcmxU< ztH}zP^Uu3We()oQ6zAQ=EoGP3sHPLuCo3L$E@@4oXX~fS9=`k4zdriWW6vzS_xH2j z+GL6PX6GbP9e(<*rC-MTrxDdAw2o?*aqa9+?z`*lhoAWDu}A0LbJx3bHftt`D#5zy zX+UY`Hdb4wn7;Qe)(GO8zVpp z6cONt1h)fN4^OOizsc7p8gD$DwF|9J*B6DXrGl{-2B3_#mb3STX>W+b1RjUGMEvlM zlsI|8+ZFU^192vUsE=ctc7$7_f9Q)3x5lsy+lYpEy!jA4RL5IJ#+bm2s6bx2N0dcKW?;m&4ZI+nt}6^X<0_ zw{6`rGBf}L1JO!E1s(swZ@#IlC{xNu{T^4q>vGx6B}D~WHgAfK+Fp>CCg%sw~Tsh{|Hr<>lq<+O=!r<}FoK6>gUW4|seY*XU4xUUueZpMH`M zA7eKwdD;a;m78Z=7iV`I8I+H7V$h5I~Cn`~q#K5pl-WlJ*-AMWn#V95Z9 zdCf*$a#G@g1z+Z7XATecLWbZ0pWA5%&Re@?6+BB$c9v16Ht99_IoUB$QIK`jRTX%^ zOZr`y%VgE|ST$`vTMrx1o)fUV>?5Ci@(B=CbycO=sK>E@+v7DFO)}Z2LT}SKNs?l8 zDtW^0xXqh3r6eb}G&kY_Cy99gvzkwzN=r)v7Tmutoxq?4zL+P!tQg>Lbn2qtz`5ke z?W(yGd0sW0=FAPe`M6-L5{#vSp@7q7v#KMkGJ{ne<CmPr_vIQ(VN@WuIt(wtBKk=9G8rz>@mc~81|-8`%VmkHLoQN1H?yN~1}jXs=#hG?Dcx7TfjPNZ z^8X23MW5K@D_ieBzMJZ=4&%<5xk7*XI;x_g9GWn*)+SD0&6?T;uXbE?fD#7WaM(|u zKD}VUf@RB=$z?K@o+z$kLF6H6WO!)tqD4!VENN({2O5CuKvaA8>{+;Q;fD3=G)kEi z7!=~^u8y|DhYoJrx^-WAn%!&=Sc<^0ed+1XJ@;HjMuy2~qzRx;6qsiy9K({6l3sY> zh2*3?H%C;8(V?wdHgDXtIV-PlbadeF=gITo30rAr+nKp@KU}wV&0v2|z-y6+YU$FY zYu2m*NbJ&pSvHgi{3=eBKIKc7FpqxFmwOwv$)_mRW< zw{6`VwPU+{WDuY#EAwd7jvXsjtf)JFoM-7EgN@P7aZ-Jb96V2TpJ$clgPxqs1M}w1 zi;az`tF3W6tRaD8IDzMRh|uC8M$K4&poaQ;zWMqqh^M*vw8N&Co<(3uhuvOXUGx6? z@55buUhmI(M$OfQ&IJl1*A-gE)J-Z+VnZc?-lJIWesbslr^yUi^3HpTrDKA|orQuS zn^7Dl2M=J~`vZO1*iadvI9Xq`Z-S_VC=-+*zFP?4Kf>o~f6t5?`O2U+9Y{ocNkY+70r%|s} z@7=pcA}R_q#6<4^44V2%l1{DIzHRI3)vL0zvj+Qn z;mX-FEqjwvHf=&{kIV+mR7ilc{@(7atjrA?)&u%jjXJ-_C6|rtjE#Na`R8k@E}6xX zlyx-Yz4vDCOHb|V6^UwM)-M4rMi3R|b1USsgx!d!N{b7nivzt~3l@C&+H0=@Ji&*h zOBREc001uf?&FU?e)idCmn{CSwx+_Q9|fYy&ponc&FaL&y$vTT8NYJOa~692p#2Qt zRF)KGM@2=&CnOv@RzqPvm3&mnke6P1Y5r%QNzqFBYQdKueKha=_vb8Kx)|;b$QbbZ zjvuf6_S=O3J#WAD*5-}tN(!>&Lp_8?e~vT$!0FG^8oR!~(zga zrJuGAP`Xx9)ktZYX=4{UCEBYKd`2X%o-_9`s#C;ZCDxaR4;-OJ4|A%FkO}!uK@R1y za&&gJA)8emCWj9KU10+`_((aWZDwslLBBan`=*aHe!Wv@64xAhYtDhC(e68MO70iX z9Y$0^(RmvAQ*(bfEp7gCv#c+43yWQDyC!G-P}(@r0p=auQ$pf@hV-L2f0C#uaoQA3 z`CWGI-jptjc}7ZLV5my#+ek$P@)c<;;C0!6R*ddA>lh*ZT7t9zd_z%*{NWudpe4aR zLJd^;YU9b1(L(c%@y=c6yLa)Yw*z4L%Qq5jS-f>56tIcs)%>atF3@P>I$;m`b(mdk z(5ezeqADx|qOy{@c1GU;k24isB&xx}!u%ym7Dq>Ix0#U@YPzmQRGYVKNli&M8?;j) zZ-S_@Gmp%fGiTqvwCf@&*=WM<_{)jv?YG|s1X;Ugb@Yzypr{?&wr|_Adew^0KKmqk z$Cl>CV>Xk5r_nm9HLF)8CGKqmqVg%meXYDUGwg07-Re?_sCMtJJyuO&Zk2o(h-&%r zWpBLk#`0y$qN8?9Y15{St5&UquVSL3KaB<$LQ)A zebaQYhGrz=G?_qWSo2vBht$ei+87Izhf}oXB&};;jAuA|FYg=_T*HEE1pe}tc1~AM z%PXkSd}=h4kskq~67*SNOWwG%WZYdIwv`IT5>{JGtBOfk38}21G);`T2c5Bq+rvy? zW)RgsbS>RsL~h;B64k_f7JLw9lKt#P1tIKx?*F>|L`CreIDc>3vC1^GE-z{PqDLBDCbEe(ijbf`Z+FZcwO?*q22LumlM_J zpU+QDPAV-aZfQQM$Er%(PS@(?t+-oHONjMb}FrX=k>b+VH7 zj9wr*&U;ILp!*oiP*#!~6}1B*KVDPD1gvWLKyh)=nl-CG{q&O~8HZ7{lRAB>sj;EH zq5foB>shbMj+V@FwBO^V-`v?!7sM@?$0`xkmtTIFlaqa{rt(z7aZpn|sJ6bY8lI)6 zwJ~6ov-Z}Iy<*H+e$HJs?kXR5R*X5y!*+n1Nm${1=IeNZD)K9cPT2RD6OXDRqX=sgWqndpzR8DSBTT zmb6crsT0?!v?SZEXk~1?Yw`-6 zp5ji}rHS2TO-vIP?5F$p#+!HV^-bInlyajv@9L@alHaGN5Io`MMQPS2`v+(y}VmNscKkF;g}5?+-ypgiD~QnwmuR!OBT(D zU)|9HSP2nMTG1RhwV!B+V;Xk=PK|fOhFhcA`mI>SI->OmtvUnXB|3TfWd|OD9s0A zgp1z_j8ZYWVg0(5D_4}16e(oGa8V?x)Ezr^96YcOuxTpr_wM-TpMM@O zh#>+~`~SxT7_BjxM>FQkd2edg&+V|awY4TB?0)mjH!90YreX$poYtPM_UPyx(}`+$ zpm)jQMN5_}&dfa8)^^rzHQP-ZyFqR@%53@(i+a#y93fmPo^Vo_Cp+^9aA9gn(y96y z(ybZ~^n@Ly=LjGweOa+YRJ-bqm9eoUtX6xh#%eaAm@k#vY3Jza=*;-t z7LB~GzOEuYb?|DUc_^lzrM!EIMk)9K^Rq1KTYu2oqJNLul z{7ko5?RQz*&Nk2g?9)Yy7S-0)4h{5KjhbmvTMbIDRn2*{L04zUek|;$0;mexOG4Jd zkU1}C%ncfHBnkR#L7yYQhl$TwQ{r`*y!N7`0}X@bypX*J;t`Cwocai>JdC71!fCU{ z90fo4(ecth1j^34i=mE(jM=O*gBUu1^&bfgc-iew$JNCWz)4p0G+ml8m$DH|Y zUd-EXZhrI4sJTmr_NLQm35xaKq|Sb8^P6vMowJ}h2A#vBSn|%AH$Sb~nluqr^5()1 zUS2VKg*iQ8Xwlrb`5P<~lbG=>pTCv3G@iK0In6tas3bv;do^bY#N-JfGjKo;y(T1# zVkQpJ#Kogj_&e6aCv@=QF1*`jX@dv_Pjy+0-G)uBtZ1$`WrCbpv9^o(#6?_ z8Qlq5bg3|AFC;Z(K2<&DRYA7=#)xWM^c^1}+`L0gbmRwWwv)#<^QX68=!-wsy(`!f zO&s6ut=UD5o)oFTa$Wv{xc3kIUZG*%=>?2&|;2U@B&i)ugYhs|CuLPE?A~ z!OfdCtXZ@Az=8e1TLMFH0Xyf_he&-0*D&@`)}s%x7`!zK^X6t9UAuNoT3X7f#uK>L z$~gwGp*-H!4s<2X`t3;Ay{oRaf~TEshpw}uWz(kh^XAQMIC+A^eDELwOHNmCnxk{6 zE(A$C<5kgqgHAno_|QIxaL=CIryEa(Sc1kpK9_}d={c8{bQuFKGXP>iUJlSC@*L6I z>2+ELdOE-QYQf^gi>s@v)JhpV%SF)`Pk8u%P4F36YcHifNh+#{(PDf!A0Nyj1`iX1 z2Z@1c8azY}XAr}Oh{65Dz`iSJa349eA8B|$tIZTF`GP5r*CSeD(9YQt0>(W);1*g^kK>)!upjPw~IvO zSoP}bcR#fH{V%c>EXZE4AZOvy6YIB*Zrj?wdEMDfG4|v%Y|oCfE0)!*+M?czw&o$P z<*`%7%@*JSn@C+qNm=lgWK)j-6Y2x5s&rEhp6zx21W-_op^Qo09;2 z(j2jyd!ynlQR_}FU)>e8S2F4lNxOzOtUR%DqiS!uXXoaQjWKrg+jMV2^x&2qnwV`p z8@K3?ztAbA*|#o;dgf1m{MYA7qtmHKnd;Re_S>Jx0`o`m*zx?It=w#*myZ>_U z8yR1HmHX9Kg^Snp?Mj*aZR)@$cinyOyM@cYulVBiuOEFeaYdYd&FpWUd_MYt`TDfj)9?N5`KK4@B!o(j&UxnF-kuYMrR^SBzwYchN$Uq<_K11%lls+&ig)&N z_I}5{w>%*=y_MWVu|hzhMwrxA`s1iNlc`kzEo zZ@={9CNzH`w5ARDh+H=%&CP(rGLjeqAX;p!5v=Vd6Agh0CL?vpBr^9rBHS|)wWyGlzsy>EqjtaNMoa>I` zPwgP1i^VOruunwW=vO?Pen20hAdT?%%R`)A!#m&(F{6>F#tpZGMl_982jww&6tC*g}PKA$40aF8(?G}&31z%Hv- zug=fQ)u`llqta(n`Rodtu20t8Xi*P^#io_QeYx40>kv_;o@%Nm{4OD2q)i=yPeXW& zB}I7&Gt4Wre6hHs7&w%;h)<&(;>$Hj%jV?dq?VRuj^lJXZAW{ndUU{PQ2Cu^h{|p;Wgg9V z{q@&@sAMC3gwLv15ABYNS-WQS&YiKxsw>TUwcBCwdtDx<4RTT?8?@<_0`7#~hjWY~ z=LMD?+SExK+Zf{+#@I4llk263lc=~d&rqiq${+1_+bQ1Mz?qO} zbvY@^3EPS;_{zp?g+Wt6&{z^Q6bkxWUYiL-#Q=LLk8s+2-cZJyYS9lZ&77^Bv-fiL zLCz@?yt;`Q@X0E02~oZFz^mokC4W?)bo-8PQ(k@IqooX+N^~yzZ3h`ON$@9|BZLnTjEw`y!~eK@;G8&%Fx0WzMcKOcJDs# z=8u*<_VlW^-`?=@3mZQCelQ_rMT5}vTW@WYoDzwp|I zm!F*X%)C>Z<}Z8rt@2pFuf6?CW^aA(+fz&5|LXBKY9#--EgaVKU!^2MWn{{6j^L^bO>%_LD}OGK5rDgRw$_uBl%OJ6_v z%(nR(b=T#<{Z}I@V&DMQeE=USCe_W1bpT3s_|m-$*O0Wk9*ATLq^1PCf~Ndt)}Y@EMO`kzqa{X<3C8jZ-V#Qc?H?)(xQ5~J;i)4+{)WVa0#>rO(qFg7SGta^ z-}3i?JwNpA9_xt3tJZs~VyK}y!J+yEcK?MLzu?nT+D2bznqbToEehr1t_oUJ<&rn+ zRPw!h_dNOJlbbeeDl03kuBxm(Rx_oZ?hcFSmdR-~9mzPfX3gp)OBSc6rwtDDE9LUx zp~3z8_5o%AQ5`z4Z_2~x^%IqJ{Zv!KhK-w+EI}SVkJlcP%SP2ICEOjDo`ww-|leER7pfL{_(jRo0Ii1GNGy}doj z$;lAO>eZ{t%S*dD&Z-rIBSYOSr%&c(XS6mq23fR9VLDNrZfYO{(%O7fC4nhRii_ZJ z;&$z-o9(sE_lqt2h(jP6;IpzZgu_firDDw@4ox)wym2R>yP*Mb*q$$p}~Qc=F`Q+ zMeS{81kwAbnCx2oGODFK7jS^^YK5BM%Fe2kxx~D2%>s6`J3izV=mtXi!xo3CTtp9rH_3uYxWBZoQUi!=% z2UhOv`SiYr?t80ZQ>;2_N!()(d^LZoY{k1vo_X`Y(rv08OA}stA$|4td;fON7xSaB z#ErS{KD+Au)$;h*fz44D-KnST?pyrsy4U9)Tk_tV`(H*xmAYj0fBiLPEt=QEq8F@w z>iNA(cAR|s-~Rny@0$I{Bk$dR@4K@;u8Wy+OqK49`EL8H2VcGCzPBEHV#S;#y>UCr z-g)@DIqOt=(FCG-(bJFK{a)$v*~_1rQ?Ud6%D4WtC;sqaV`4(jyuUs6&`aB1d?|ME zF5k|DYoC5;?;8*N@d1&j-u=_R{y%?s<-rHvLAv*`|MmZUes&a=mSm2NQEp#TI`8SZ zkH1&6aZlj7<^g{-q7tX8^Ma-l!CWm^>Ue7-qH;?+XY1$eLr{8H+aQRuk8n-}npdVg z;#vwQ!4gp+9|Ti9?vxmD%5P?l=0l>N(y5J#@PQL|t3?F69)(0t;?lN9k<8HffWKsq zJN;PzcOU`CR&;$p9Dz;KCFRU?i7e$7JyA^_FEg>h@Vf4GCkjRvq`FZsRYBXzD31Dv zb3Kk8jIseuMuhw=X^aU7$OUM9pydEwzl%PxCEOZwp*KF*97Weh<4q}Ke--akhDqcV z^XCwnf}}jWOF?St8BLjB%o%eOo^urohJ03A!CJd9o6=_1XJ=*3n>TOGnl-z3$0sE0 z-ZM=V5a_hueF;} zowaJ!%J<&8xQ;5s(=1JNb+(Hq$;9rAiAqk|yMKTB!Gi}5A3As>Ba7WOA z{rj@BjsjLr64h-HnyG{$G{)ipE~=ioUM-WdsJ@Kb| zUcLwE%|~92`sjm=&%O}1cqf*={ov#O>kt3@yT|_XKOg=5zuooEf1Lg5f`X5q{Nkl= z+IAwN&dC@4>Aoux)$Wa3{{8>`um6I6_{e|!)9?S~Z(F|F+WP5zPdxptE@>Z;vL)|@ z2j+dSs`={|zj^+%`eEUt`yyc|9PiHBUXiXGyed^Y;xKqD{NwHCw-ldFqjGKG@)x zpqaFh`S;%a=Qr|JtvT`a8(%&8QsVM;#cw~n`2F>&L_}1U#ZNza*X)wz?=FAp{mLjb z#pxG`ssRzzBQHMlalt1qEqeXi>Mx%C;*D=le)90$5>dVP;G+-CDgAzV?Q+o9TORtS z*U_xsJ~};7w_)DWM_$~!eAl!k?bp_?MpPI4<)DcLdgfd~pT)>CsF6%cUQQ~i33(ME zuOwxaq~aK@X@HU^_%vbCF(&SM;Mu?xi3)mOR&qo>BfHxmPeSshhzdXfsOZMcY3Lk1 z_#wr3rsh4#n~dt_1S@=PrR>kQm9s<;R79 znI-*xkE8y?@omz7TeoiAylKm(jZ@0a$?omxb~|lSoHnzern)LQDRK4cmCKhe{r>x9 zKwy;>6-J|xW9hL;Z{2Ezto~$OWqD~+!-*-w6$lEdL8m!$=1fU(aozD+zkA{onh?*> z1a_*iAt`b1I`O1rh#x4Sy{#=SE^gkuxd#vKAL#3rrW8RQr+s*6AU8W})5i5HRxDq& zaz%7>bYWqELN2SRs@%49b7%WmXfqk{Z~_>Wc^uZ>?ykI?tj(L&uUff$>5@h8tF2qN z?Aw>#cD6;bQE?Q0=1fa|LBYwBCuJi;Q*;Po$v|g&E5POP+M0o$cG_bSTnf(6!MPMZ zyQaRbDmi)Y+BK_|ELjAC57ANEt18Qs@)5%4^f@g(9WD7eN49L0wrts)m3agn#AzD1K+7-CJwLF0 zKZcAh>&WT)V}NCAR_IKiii1n_qZ&&(b&|Ju2hLe|hWu?e^Wf47+yecg9&0VorYYUHpCbEMJrW0bHBrEqVI&j8*ae)Kn}D{fgMTvG|=Q zKYs0dU7F~0G<{pj1OIdOm%HIBeD|88Z$AC)dy7jxeB|@DmXGX)@F}AoKlJEh3tHEG zxMtRy*&ER!bo1gT|90PpXx4AuBQL$Uq-)ij)lWV4?n94n|8m>lH;>*kK~z^&V3$6R6rvV{NhLd*Xs;qUgrhz{x$-(6ON37-lXSMQ(!x8d;~@N>Y82RuzXV(32I6 zI}3S35v{IZtzBqMf_Qu+N8`XrgMB@c09*!oyQZX5E4(f{J9%0hP53QFoqTktx2wIo zqqV2AZFG3RY|xUpAE;>R?zrC#ahmiRhs6k_GIf0nI(*FMv|9{1wbi8OC%3`@iUm2! zVKvD|2K%}@AZCbPB_DA+tZAt!@4ov^M#dq9Y=p$TQh1KS{2nKyt-rSu($Le@J~Ys$ z*Qzj|+icVh_H{WOCSD*Y#*3N}fnqR^%cRuGdWU*i`Z`bbv^Vv1o`pLB^tkMnuz2!u zh^L)4i(aF$S&RX%YxjK0mld{^vW9xrHiVo@iC>NJ6q+lf+(FC+#fFZ-R*p`rOi%MC#;K!r$aX|4*Sz=Mea|0V6>Cq8KlA>> zugv=5%=V2H^Pc|VEo{+UcODXeaWVK?)v7dou1ew$uB?s{Rhi?wy#cq z_K&mYYzw4IM76@Sb7}f3_dI;xJ0GnCCassHqw-Pi!7!>W*4RumHKxRlHtVq9&2zHquz{N1)vrL!? z3CamnbUDvOP!uR4fTYWb3jPVmh!%&5%V5O>OV1^p--m7_U4--lOTpuVARb87<)r{ijP~g`a}%q|;8aH#O&(@Gg}Fx=$|cV2Ud)8ws)7LvW9-7) zbNn??-09fyj-3)zVU_EMmVLD9l;GA}?xE-Agt|1w&wG@Nv4xUDJCk+ZTLLW)ug_<+ z)wKR>5VuDB`Pz2tVLXa?;+n-g+x9H`ih^Fw^WtAgQuIEtoE; zp$G~jC!k8iGQJRuHwYW=7!Ld87Z~JDbBr*JbC*PQqk=ajdInLm*1nLt{~SK@gJAf3 z*z)%=>kqu{9H|KVWrBN{xA*Y2PQlR?_6?q=mE)8yOj*J#I`BTolMI7-agWvO(K&op zFX_fuo1b-JEYGn(Bz(ZeIY(LZnK5tk`9K42C}vgpK}${8-5mD!2LlS$Z=?ebU|fLF zh~)juLaVG;OB>#w&Z&&< zN56XQtM=V#c*5G8*-yUz&|l{~^4zk&{tFP5KP9&F+t)vN@PT(8es=8(PcE3VN}sro z+OsU~slUGcw};<!Y+!~`R&$M=AA}HtTb=@@;y&K z@Y3D)zWLaj87p>rfWu-IZhZXSSMIz2%?BS_GJEN8;yx^Par_(a=C9x5j9$3zk^A2G z>)+-)^vJ?DzwL@oqf>V^efsPN58U_aJ@Jn87P|;r5s<|s4z5kWF?|J)~Pg{1T zQ~UPH7QVTB?nZaouGWRKqvx&|+MVWD{njV1F0rJ?_bzy2*__oA-V@T}>fV2H-B-Kt zoeLJ-d-rSi-~T4k!^`Kc8cCQmwp~j=RPVk0S_m_Sa7&1=f`Yguh?&LJb=F|O91NJy z>N?y8BaKNpL!=9+I!t+>roh{mCX2_|z!-y#F@Z4c7q3f#Zv$f-KF*Vu5EUS~cmt#0 z)A05_*3`lpniyR@tvODsYG`F8B`-!6&f%lf@L^VYM9^o$z%gVk({GxdEG=T7GgV+e8Ami!0M3C<-+7 zt1Ai;BRL^oFxOQzt#;kg)be;<67k|9nzqRC&lJ0wFAWa;J40xdH7IpdoO zi59s-f`5@=#7zhtLC<&@a|=1NpGO{UifL05FD`7Q7f}!M`yC!U}VztGTp`Nhz(g71xYDhLlxjnes;B*ce?0SGI z57DLecBs4ooMOEO&+rLMQ5m#UhV11*TN$k`BSuQd;e1Y8a?W!sXsIGqWfsL*okm4s z-e0ofKs|-(%vxKC0U)X)K~phjX+`6KYZhI!9t#?9#vh_Q(A`3REO^!MUO4j^T3tmB zWkR1=pS5~|sHpT*EG2ci|0F6s4NskZCEdR_!L~OUpSqHs;@P{$os!u2A|k4Q_!ECp zqB}Vieu$+___u_Zy?ggKlTsz`R%BXAK%9(&2#M5GeDZT3X|E$O1>G)nw{r8c%y*yv z_RXd8Wa&m}C~e};FID>V6jEs^p2S3N$~3>4=_#&+1bfn?;cfa8rKfuKB-r<+Op7)h zOWI>kOqsOOp({j6qAM|ZGQp5|G?NJNQ)y|Ca`8iIAQhbzjh+jAnEYXC3XT?0LCTYT z$rB2sUiF~EO9e#r&dZMh0aNN~T6+vcDy#9)3S53noYgJEhDvc+4XHdyX__f*3zDvt z)_0(@j4b_V`M6_*bt#aw(x(l2^nzQwJ2$j~iQrgp$rh(SfvAP=GSP`<8LGQxp@>x|jBhRFid8E3S)Rxn_ z8rFD%vz+Gb?YyIxcMidbGw3%#aTEu#Go|CXl&D0z&UMvoL^C0t5Z5h9I5hzuVmxRQ zoPPB=bAHYB(s#0>uw$qCKs!ZX4Z@hSY!B}kb$C1lw`2eu%T zgeQ_lw*XIY9iCLW3;ab0C^Be7N@j>q_rnGl^BJOlAFs^}TT56&17jN$Xb%)2>G8v8 z&*OC(7w=SsFe_*7!`pMP6TA54nDO@53w`lI^A4z8Pq3h-_f zV>rWTN_bt?ITsLBF|RLR^~Y#q8;m9+elioJ(*)&d&}dxpE2+XlC6Wde@Bt*&0&zVxWTR*r0q9|kjhq^}uM8SI z?g^33=~3OB!Yl^e0Htjvpu_CK0#>=JCy$WljJrw%V;-Z)WAu%*p^Z{E zFq+DsAs?dUG@16{a_!)0hgm~lKG9P3OH>@GjIow8FYM%YT?AaTyecLz7Att_PES(Gf3R>JjSwBJQn$?B>AZ&+O|YdFCg>yf(+ za}#T6=B#IU+gaY)%9}x_;UZ^hLySidGb$*=TG2c~9{LU)cqJ`8iM7xU(c|Eee`oWSLJZvhcx790n-r zCeEdVA?9tF8n`W*A}R@GuG8ZHGKRK^$U@^`O)cc$egT#C5=M8D zu?`|TuxPY{2ZUD!0K-6M&E&V<_2naFekVC(7zi^|FuLDwOf6)@vOcF z&7RzB1&92Eu^gps#0D~gCe)-r*De?eNLev!=|WAAIO#moG}zyB=+MDs%a*SDCR zQI|yw9pbDVx6Mii?L0bg+QHfTNm(AJK61`ogybx|;4A$hfP94njd^(A0b;bAa|}UZ z!W<6G&gAL>RE3Q$8xWP!;?_F?Eixb~`-stN)erlJvUz>Zk9Y;A$-)M+c-JV2Ekor+P^i zLwzFYI(>X{uiq^w)wFGG>oznwc-dDsrPQ7M>oyL?CQhE{^50Ns*6;O4kShaIVaQSx zwim-7?Yz7Ayth;&7E$oQTXx=q{$B8vpZAoXbCr!b%fj~3khLgeDTLn&z%xdKG=jb$ zXf6c88M76KExl7JLTIK8)NenCk`ev7os^Fqc8Ra7(B# zoazXxIwJjLRYzG(0ni^X9cOLhZ2i1P4K-Puy8bo$9%$60)&V+oAOqB?i|LX2NNC+4 z0Ft;C8(kL{JRvvY2&b;>BOWdSTS#$AS0E&WmsTK6NsI^Xen~v=0jHeYHFrnC^^iE} z25=)$2n3EmC`l1NyZ{?Px}=};&=8B6 zCK|CK^9}xqvWW3PhDiB5((!jV+4zwA9_R(JSosK zor6hrv1EINoh|p z+Hzi(J!UHycN7bT64p@1TDyY*W5iEpj;tnqN88!b;=%*_)A#R7LoNpPr)M5HT#%R3 z)zRj1Sf}s2n^G8Zk|Qn=BJzpyk7^v{=3FDRvW!#bi1VIBq`ZQ6%TeEdyT%?OR0%#E zrL1991>?@5uq6-B4WLRqo27i*Q3!*3QeHyq&$3<(s>PR%h@5_#&S6zr9YaQUv&?a7 z$TFcv^IxBc}&=WC=!<^>G1X1~KoTx4p6yTP|~3VD4l2tJ6P(ONdPb&_+AqSXM>zH20?NWXLsG(}V(_yGTeG(bl<7NpTvKmf=r@1_|q zG$j+5CHgYGB0XG9Kq1mudl9#mjOWus0-eC^fIp^(j1VA{IBSOX0bS9jIV2SrE8c!Q9EV(%zH)h}JDe*uMXJEdq0v>fo2t>+rI z{(X4QSbGdxzco<34QtK_y0zmsXiN$-0l{yk_09h7bisgZ8{@7b!B|KsDj8FEn4Q>% zHNz!t`eQ&56MQ!zfDg{2VN7Q^O#!bxDj2dj<1xn66~u1;s(f^qqppq9){NVW1YIUI zav)^Nz2HL!-of86I+Z0KA1)>=-Q-mcZ&li?XBC!HqxLgHhS7lzyQ~&Q^FdQCI!ez} z&)Npj)P#7i$rs&(_wR$dphE~`N9?`D!^49bqYWd7>25534nfgnEq$EfI64FnbkjDf z%XHDh=Y&$@`q!-Ky?9{Db;-MP)&5Ig1nhu3`y@xvBqv{U4@*H zidx;W9->O~?B3S4YHe>!qI6g?h)Pd3ZClg0a%JPH)vcSNjC-dxGwwPu=cNq`qHf3% zMx`fNqBiwzi}OszkL}skwCJn+MQcYACR3Q6Y}~f8dePD|JCdfYLQ6Ajn7{M=FPpX} zUB^-?AgXs?e;%3<+So}O+9_QtscOVWYp}tRKyQw(^PsomfWJ4}-t*g80H*`cPHck&LQU%=Ts&yNF3*SZ{lq9sCiHBh>iSBi?y*R)VFpXr0nl!CV_<(@C z0=~S#XGf7-%`OE|i8(wuH#$L+x3r1rXA(LHh4FLNE^0IvhA$yA^fB3trku5OA~UU1 z&S4ggL(aegl+{D%-Gt6d8vT?Rqpji`?nEB`W;DiPf>%$=8v`fyk|(2umK{J;W9_lj ziEY@4c(S{cGxlF^7X{pjV$;%^23AuRH08liZ`@JD>k4Ug6>aV2{6;aVJ0kdUM16j8MfX|(+f0Y%xEvm|IPq-43AwG$v_YTY+7Mlych zIZA6zaJmxc4g`G;sV=q**J%~~N;6uIcE* zQC&%qMCDxh+~fcDA5Y9$X1mzCUsLIO`@VeQ@qhZCzrW{m)dW2xYgfhJ&j+F$Q^;&=C~`eKJQC2jPRN8Wq=)5CLKUH{qksRdY;#ZNr&FaP?) zpZ@&JpOK#a%fl<@uBiLs$#aEXDY)O>JiAsw-_1<0o`A>g%_Ah^a;y?cPzyHsFpY!e-@rb~L-sRucY>2}y zi58UV+3@~?*H$_rufxMe*Ui4~o`3q&oYz*E#fSB5{$Sppe*fmI*VaCJ?_S%QtRLhXH@SM9C#yy-WgHdEr@;p*jL@BEo zLo;U|2nO^aLOfEC#SvQl%>5Ab-#`z*Owbnsk%$Yu#pVpzV=kHAf<{D~p}WGuscT5$ z2GR5--4WrMgi~Nr9H=P*y& zY0?oOEp}XK4vd)m!{)%K6_W#3A*8+?Z)c`SaH`3!61*`9uh|$n8-1ZSUO2s-Jiawh z69Z5c@>{3+(Q62LGHB^oa|bz;C1|sL#L5v)>GLUhIiWty_zjY04PbqdN`F&edNqXs zF)=f(KgFm^#+{`>QxQIx%UXJoLG)+H0ddOJCpi0{K@MB;{!Ub$^T16D0OM%+5qKTv zJ;mpog`74Y8!jL$T_k422@6Kqpf3AKy9c)`tk!mwrDfFGIV86XRMD#Z^S-j6xda<5 z;+(RG+krxalXu7%O)V|Yl)N4iqq(NxhCaD|MDNtu1Kt3^G0;@r20XneaoQ2OPk+x* zUYGYHUNPoCJ1Ak~FZc|%o2b%b^Je|at1rL&*1tZL6`e-!OVn;%Uhvr``#u4ElsxbA z=J+JTx`o-_tW!-IpRjEoEq?LS>Uj_T{x9>DB4iM8%MX1pH}&l&p1S|-MnqKUzJ!%2 zPd~Ew^C)az%E;GGz4i2Gt+BgnUz?S7cp~IP0^cW(PMx4u{{HaG_dN8_ zocwPV9b3Ava&?StGChHHZ_j&bPWszV%z5Q|k*Jb8=iT$%b4#>|`^eNS+0WcNXU=Bp z_AfR)|MKqdq8urS{fp-wT)Jb@v8O~-@0D!WizP?ZFZeWj`TCYcU*;}ZQuf&gd*^@O zwQWno*B|VhGru7wl|)2!iyl6q*A8<8@C@4NiCijpp@t&2#$tyKUkQFAYZ;(ar+z-7 z0-=R_aAQbB5Vs+x3?3P0X=SuEv?7O5Aiw^CJ~wD74%DDYax6Nj=893l6-HbG z9%0XjKqwG|1ObacB6)G6S%{DP)r|`k4nQc0nWV%33r-Ogd;k^{O?N+ym0}E$7eR1c zVkxw&9=QOWa6dtai?QH|X6CG)q%h?Xyjn)zM9B*{U7=tqM$T`|q00?7&q%(!_E8pL=-l%PUOzf-WsRQ01@Q#x!gXosAmrhz*^MA!@hc zO{w&7o#0SL{N!>$HK(-Al%gbLDI9kco_7}uxC#}p4TMPb9R-*HR?IpCb zm>ABZM~(#bIcNi*vsf?|lFAalvM%5n2@ocLDx1%yuvld#>#)JnEz=GR_Buz(SWWJj zy-+Y$p|hKO7Y|095;W{#(#=|XXmvHOD-iTKoGu?zRoi4OX1&Vb45+Psjm_`!5fnw= zE~rAbF^`5Zo~A~R293Gry(PRZmr|DU&fyU0zV*40ONh$1?Zfx}{OF-ATQZ-#>%BQ! zyy<&Yo4z~z!JJ*Q-&pq4J&*kH#p?Jyip6h!_2RZcVBvEqnnh^U>gkb@UTY ztp7Gzw&I;-PrtJB(*;@cKh0jeUa@CtvT}l`@>g!CoPGbZkAB>fxTE;l|M=SjFK&MK z^{@W==UIPwZ1tRvqM!Wdf4%2(b^5InmDD*x2?2^4<4E*ZTjs!xCL6LEZ$C+$%h^XLO#^4B6-tQfbVVxW=MQd1M-F4#=6&+u^Vyq{(Z)b@Ak4*|fDlpr^MAen_~W05n*YKFxvOIbCy5Hp z`bFM4-LrYl?7L@`iYL`bf;gwo4_-!8`?Oy_boV{)52s2*wNbwQqxDZezvZLvPOM(n zx-r_CoZS8H-H$%E;tI2V`}UE^(}^nG8?$)#ix0j1*N5l+?cq#Csku!%Az?d;p1=F`H`hATVvc?A=;yC2 z>WNG9uY2Jy|MXf*%IzSkD+tOSwCA|rV=-vak)0fJo%0J46-Zn#0qp`bvO&LIaF4L2 zvy`%i94#P+k5D6rSY-yATEO zPe17}b2<~;sHTWYv`z)k?XD6bq=BN{5eOwoN)n(3qzC#H5xjgsaa)`OB~!`16#+Q` zPC@)rNrD>zw~0`Nh)@iMvPGJ*gal88ydFspC>=x%xiOV&D24D(cpaiHx}2V&nwZNr z^Y#Ho*GP<(&q;yqf{)G8Ru$7}^Z_{)N( zf^G7q*o$s%qBU z18v~XF|b5~1fCN722xSOsteA!N(6llF?0}s0}zTD%_2rhS!*w}!&u)T!I1kSUVh$F z60#JKqd9@mGQY7^rEN2zAv!mwWfey=X4Qnb1+X{lFJi*q)yEP%obJNd=2^acpC3sYPDGLvuAI3f6~wFRth%!`o}O@~l(@zcd% zj3a{q8)xmK6(yWD7fmZ`bIIWxRQCJ^sL{8jf4N9h*v@a){_T(N&U$m(+i!1ubJlx* zd3gP|JF$H!#!a7Ze)j3D3${BZ?NXQPnnacA*tuZcgU=+dN46;M#`oqv^lI@|k*F?{ zIP3R%13F;_6eW+|Wl2mLo=#K|N>6Bf=P$3kzRn#Db0s?)hIYHzof}L=_g$9+c7H!Q7mz!Tw&Fz=9n0%M#Tz!H6M5I?*u*mOjSN3N@C| zo!|_|VB8-x6@^SWf-Z~GWFwDT##5YQNbniZB;f7v$c!2hWNVRj`AMhXA(u-L6AIAr z158XOjGK@&lLb%(QC-bC1&Tl@NmD5S$bg<0fDBR#>48o~5ZxKv#vTQ30U2_+O%BpO zWvK#9OwwKE#`D^OI49ykzTl_e><$);XoHvqouz8*pmp`E76#>oL1P}L%V#vjtiGBx zHqw^PfTQ2x9k%+1fv6m~+E1A$R{H<8Pyk^)M=+Xp{OnP(Ar7Dlhzhuht=~d4C19;t ztfA|QGx+FNmL5t~3EXhbSroSBar$yXSW%b|= zFYfjep1_2>0n(2lYZgsUTCk)&gW@QNw-2-W240sh=(2-`T`laoSybd>08O zok~wPBBJ_CF8UCMi*Uuh^5vHvc&mOVe4FM=Sdse7W6S1m_oOBEe>H3NGoQ7_PMvjg ziA17$t2-r~OrH>yesLWYo*1W!iN6G%5?Aeb=&rSkldl+?q{($ui!^EJWa=KpnvcG{ z?@tRq--)G*MD^Y}^|saZE4QiQca5z5Xu%)>%U}D`TW_o}CBt2!YTtV3mFE`sZ~SQ0GcWC366;M%?w|L^f4h7B zd0^Da59Zz1I+#K1ln_m4Y^Le>&iS1Ni3ZRDJ?5HWGs`>hD-546RsIK3qS z1ds}}(cw$$6?A(+fs~9`)7$i$5JHM8?K+M?C`r@PAPG>9n{)&PIK@I<-PUE!@T6e@ z;o}uK36c%Bh7JsPNU}~v1o%lo4B~u^v?S}d0TWW`MMYQeYAMYrQdUfj972;Owz9Al zjezliBbc%lbB?%uGAkxG2S#j|!cSTNs%E+!?qaxeSMH{aWwJ_at&%nWm4S3@!J6O z>Ec{+e6)homj*2bwCo6_DCOOXFy*=JMtVum@SdQw))C<@2zg^&zJk;&*ASjT9P^gzD_3W^dqnqx?eAe}w} zxJqI64d}dm+6lquQKL^|3)nq4hLh0S!4KgU(948KJEL!8)rIF=B_UHD-gl7EpAO=- zFghLiwq@)DQBix>roZsuHy>`)CyCQ%>51C)A1?aqqw`;QW)33&Su}K%T^w7J{etiGG|HuFH z`!^nW^7Gf1=~H%fEqv|c`~N!k@kicy@bN7Rwpo%dPSQ;mBC7xOyLX;=a{iN&p4;}x zit0~+sL)2Go^B?@vzdW*b_Pn%tvv)7pY?@d{ zm9GEp)%lPA?X^Gr^B@2HzIo5TU$8oQlX z(cd2V^od7a{nI@w7RCl9QX;LRnp3hNPPOu#5AJ?AcE!4)7w?-R5!Jj|%isB4BC31; z_s>UEK`3Dqm7kyg%rnm%I(X1wvq9PX6^ZInpt&6nSi^DXfskuBO(v(#rZg1+?P!uXNyrC#)DWp{;wC+?8vxw%s z+y8Xv6}aS#?gXnY2wMt*#sW&7&lsE0DL|T9dh|%pm>aZ|A~y%NA$WJZM~(b^>W@RS z95NS#t@$Bq0cR>8bp;M(jbWt0HC#g}%E#=bKvcxQVaC)NamTBO0c2!tBaE(*Rpko0 z?2sv!)xxtk2wruV_Dz);c*{_6IF=?U%8!$7KVkFWR`*4rZHJ=Z`h?t=+pfoe8g*5? zJ|CTnY^=mowTyFk>~_20?`&SOl74;KZ zGnA0x-L8zCZE(iu#r7y0#~{_r?xwSS4Qh{v`ZrU91Sui0UrW}~8# zclK@AqP=YQ-z7>}$LRNJIDm*DaCV14SCfsZr3Pb{YFf{^(hI?W{io-#`7HHrr9+?7|b&Y}Y zbt;0KrfV{c0~yI!WF$l8qM&&GF=|A_<4w@Tc8+4mcuABdVzu8AiGwsWqn=FYt|M7P`s3ei7s} zT@fKANwyqF1_*8~t`R|NZ>JNL1SpWmh$p&r!HpnV7CrLBxvdhtL8{=Na1rw4hVlUd zPnxDAw+@I7BX0T|6Cl0>RcO#}I>YK~ctatl&u29Ggy~ekIpX!J9he%R3S`HWIBl2S zZ$vzIwxD061AQA>7Wnm6WxI)Ssl}IYAS0>~zju9J1u`x*T4YJ8lP}Dj`S9Ad-mtUR8+jXsAA{ zr5Bx0tIP}GAoUPKR4{%0HCF8_{+`LSE=n zo;I2d2Aj*^z@}tz7d-LV6H&4#)W=Jm`akq*2{Byy{KNC_ ze(>9)~)N#A*xBCIetqYr8>?i(V%VIS$NKgCfZqD8KpVFIR=9PBXYOJ1faf& zR;wu&5m%FVyv*bzn%EXkESC<6r}zQQOv1#3B3kfkD1w}(D4n0Yq9GRTnu+-vHNaCd3V+4KZoLl6?4f)zJpMcgPt za9?P=(D3w9i7ncliW*@SCF=9vKRl97r^R*NP;8C4-Es|xybH#%bcNlEC> zyA_nC0r{%cA(x&(V-Y1QW{hni#y2LQhE(+1be1=k@w!Y#ahNq67rff=Tv0%(z zz{rnMigMmD3>b%+_Zw^$!nEW-?l>bqjE=-Hmk^3dr@BjP^(f5#5u*>ufTS?{jLv|| zk5eQ;(-h0l!KsDqHzK8M=#x+9J^j(FFEhT}I3knq$P!VNR1Z1_K~#32!Q=)#U(Nw4sf& zj|u@ZjJklp&`{>;ZIC#Zht3!Vieg!GuB`|zXud$~-O+L)paE$W`4t^hMks=urW6q@ zLSi>?$rKy9BA&s5?oPWPVZb+{X=eg=1a#OiHhIKe(UgFkRJF$<52Y*iuXk z<+0|jsrz1+fGl}Z@aY*-JF6|@)JH;qL53nqUcp*=!xud;U$1}*Mb~i^L1R9r$zycY zti7M{nMsl)ND3n)kpZ0W1aPYd(>nr6iyx%11^hTPfHwnGecc_aRxE$u{`>yN|M(yO zuYdga>;3o7|NPG%&HXUz$l-_=bh|X2sJ3m}*3{V0-PJy$iAvHKiv=+YW9h|ZRkWr; zuv7%i#eyM^Rl(pXmr+-;#wOm;&ASE!_lV$C1pS&|z!bu5h_Ps&WT~ErN?hd)eKsJA zDC8j%`hICOI(!QZfx31E&3{o0@Qrxt9F30l6B%p5Y8AmxlBT!yR}&&9WQ#&8YN^S? zUO>|18r)Z+iYd;UNVW)7VSxnQXq$3d1l$8Dl%D-+ntTe;2P5Fr6(|9of`+VyZzW)Y zju3JinZ#%}NXh}xWOxS?l_cmDaQQJ#k5-w8XLl4cu2D`bR{_fEz|@w2%;+EXktUYA zcyi)zNx^`H)}AFgvaw@3_~w}L&Yj~OvB8!o;@C#AWhbZ12wU^cdrJg!0i`R$tQ~%j z5<>@@M3$>-2#Or!=k>7rOcok9;x^iFhS64rEcv`4pH>xdwhm~-#%}BR&@kEz5f0uZ zWAshHE4=n-(2yH66+siq=+A~Qt2nbZ+2(L0w7Qh)7%fMG*r2HxA1>zXLlSQ>R6u7? zYZUE1Wi_KO4cm*yUB&P=FZfDe2=OCUK4vQ{@c_DLt z$dpIRGHKlj&Z7=d?&}zI8$C5f(?n;u4GBT1zrxHJzxIELnWu!2X=<%sYUn zpaP?9L{QBL8|NIR^-Z+0h*2B~Tk^)8XyIhYg0{x6+Cmt0Q8MwAK-FF8zYMZj0$>M^NN_;sH2b}5M4C_@`(JT`7G0Q4tEa(LHJ2+f2dnun6$CJa_g?!Z+Z z(jXnB91+8vE^!9O%c#x<8q@K*So*|ffT|1qyT`iX$L0Gkc#Fpz1%e@mROI>mjoD-Nd>BQXa~83RBdoDr@EdP!JP_70{tf`qA%@Fk2AxjaXJB|!pSMfuE7GUuV&oaPI&`kz#(&)q#X205s z&(eeESdmOqxzqAAIn^vSrIwty*~}5Y>dxv{aCAa4tD( zI?L+N86Yrng4)7sj&kZFEIN1jFfGrZ<(aIym@`!K<`cZ_Ebkl;JSrG5hiN|=4vK|O znsgHd-MI^B0Gej#>VRxex#Vytni1qQUGT$*mi^k2Sc;lFhEH1X0sI6vlI9-)S;Ssp zhSu94PcjT(=oLIs!J|p0Dbcnh^=%PP0WXe$Y=?}6NJPuugs%z-ZKcdXneZEOgdL(h zoJ+x(8=*fyg;Sl2&bJSkLZStZ6K7Gq&}ictfT{pxCTRy0Irs{)Mbac#N5*^y3DVD+ z2e9^B{M25mDQbKu=|^Syg^}b7s{Q9J*@FB4*_DKimiUcl1Aa|Jxw=k4*+X>-I$*R* z7i}(qY(yjVJERn$NiMIBHMg>wLQZoOh=kQwk=io=A`u~PTB0vym*7!z)-FbSjMWwe zjp&?j-cW#!Sk<3J#;_|bmIyO`);7c%8ba1`!H`GGk1&RMU>eS?X6-|`rkYgc3Z`5h zzS0!1hAQ54g4LA+5uS6Go|n$TH^8&Bh{q9L67x?>T>s8Hh8ayQtIiKw@_BteDHA>&;^f9Zi0T*8r8cT12lnsJ$v$!i5tS&kC4>^4tt%*XBR*7!_a7jK_A|0W zoazX#%Y>F9Xf6!f(1Gpe+$BLv39T-rG$&|72O2H0XeM5=xImW{(K>^mcaMN4Nn!(y z1nsrR0XOF5Qo<>*xJS12@J~t8FU~ZDF7@CwUGQkqI{K@T5W*<|&7}fJLH14&m~;hV zfGZR_ruw#y$bW6285YvTS=-3r13>&COCf7)5O=~$odNRA0R;)5%7!WIm=Yvny_ZGv zo_>U<9C0h#j(&AP%ELUx+DGx>O0wq=+mkq^%lN^Z`J*cR{AfyeFo|l~;j7r_mmLcP zv^P56HziywKWJPeNvvp)dv{8|5@rIlv7J(ug>A)vQ^eqYMpq9s5Wd<;h&L{1Edhf_ zMJ+Lu#p`mzmORlhdY->Ohq3g8DGyo~aoMjxP=){8RgxBEtMbKa-{tRa$DQ*=V3}*PTXGNQ~$T&xPD7+J|7^ z#aUW;OABW?#aS9Sb3JFQL&t#VN;zFFuZOBwC>YCm<1yCI#G1R{S3GVLr`s;_K?FZZ zf{q_8coO@5PBdIWCkKr+bbD8%u`5b!;*m+_ia2$r2x=*$A0GUQkB0jGD^+8-7?ey? z=(s?%hY@}y5f%IsC~7Jj;R7rBjF1e3SBvmYl7Kwca`rxK;3(Qp?kHk4$YWs;n{cip zW)49kKloN3Y4Q*T(Oin$RZOlbLoPhTvKQbXPel9Qod8(Uf#_P+IzSs+S>p-bP!`hX zjTtk~+4IgDkB;~69q-+JesHgFCYm_5DR5@LZ>T08N2=E`c^5IjOoz zgiuX@Q#t1_J`CWPJMJuEwWXx$1dOO})C3+D&?F#0mC-33fD`azBtX?nvQ!}(74%9l z$cL^9+Rr<_<-Bt=ov0-52^<}`6NzfNkgGsw!GpLBDl?i8v<))GPEy@O$gA;@JQ#{0 zCv~=hkU5tgJpv;YTHnmNWE^>ATNLQ>Hd>k)q-YNmS?K4a73C4Zt|(-E5l76@G~b;o zXo;YIk`@3>33`2GN|81PMg9a?-QX(#0tg0yr{@V|Cg}2ufLX{+Lwk_th2O-wBF-rb z3>Nc-;&aYIR+&M`3whTFT3tKY>WMSI*cFX`lEj>uu)Dx35W9p+ZZUHN5CC1^7!(P= zk<1FSmpyr&pBfyB|)`Z3)R{%maMZ1j%<3F95HT+=qZdXx8fd_d8FxfK|0 zx^<`m;ge7$_AWD*L4yGk@**K_Y6}{(0X=C=6Yo+*1iLArhA||rkzn)%b2?0>8{9~Fp_~Z zaMpHOc9c~ix9_Z>jxqP$bOM4rL({a;iFK&lCMU+w6m+Fymj(MZByCYgvwo=MM6HDX zr}~xd1wS<&K@ZnH1Dp$xMZ|K*DoLR<|ql@hGIUR0!yk z1ai8RKE=$uLIz5i3<3iC%@9=(w=$MKR#y!zJ6iB(D5A9|Si89BSPTFe2(2OH=VZB> z*!vlwiLxX@)l}p+At;9s11gZWxnV{9chGNQEq%1^G_9=_jFlmCNyw5vW-ov~7<%IK zfK#@7UUrbEk0I-}@u#+j+hWdj?Gl=!sQPGsQ?jq8*l+0#__PrP<3=Tof6x#}ETuEE zAi;}(YQow2DS27YSQIknF^Z#%wuW~rZo1>2E+}Bgho`-tR95hY(y*;~%vl_=6*1~U zMt_ob$q|k~&ApCx3DUz@`)OSrqs$Cj(5iFLxU-m)#|mKN zX*esrF#3@t@e`Ydh+bHwGLd5vAgK1oX+W zK7mJjX~ldag3uYy$bEl7!ok{yIb$8b0k6&Eb%n^Oo=YzJdAX(3B1ba;8)xk&73G|^ zVBAs2>$1@HXTu5J(I52d!_y|6r%AM#G01Cx&4X)gXw8tpfr*>ld@{XbK%wm!>^F`a zW0V=_?24-s6+$|m5v~`TGm_x3%ayWfCrD;Sf*>A1lfW}0qqQpZ3 zB`=^NR6)K)hWw?3UKx~dsKrpDrC}=kh0pA?of&9d0UF{?*s-8jf(90 zbya{Lzc*h-bh@q9K@{R){uVA*u<(! znbE@`V=k~1bhl&nBJpIpfy@EqU_EzG}2k{d-`R3U1 zj@a`(abxYV%!$o-L!9@_VgGP#z}y?~sxi`f#ri0w|6&=#X|&xz1o4Y&gMdEaGx|HD zhziofkpLW&<^*pn4_icE-kK`GH5?)wH(|oLD1kxm#c$%Qy{zs8qs#`D3R?>}Z4src zIJnfV+J-;FQ|xAJlvMb>2R$dr<2bRGa%`y512* z-_W38pqd!mAGYP6^OO)nM+kZC6^Kd{6c1Y4%IRy+)f;dCA)_kt!+7 zqqXX0S3qU)nOv9`BLJ#^v?7Atc8P@#L<9I$EvG7`|Q(_;$pYU#ZttbL{t&9bh)6w zK`9YS&%}BZvCr@bsLLVH&YFOcwRBPH8glp$r#>=f%NLJHFGRe0oDs+h=`~74Ga2U=+$nKsGx&~dj4A)If=6{Hd@m_$#S8G3!22EXN{+VnB^)% zc4iz}!+@Q4C>dinsXi4@91o1v1V*YvRR`pCn7WD5x3Shi-lK)y3x?@vDhFlS)f;!T zh>C!gRBT%(h(!7Tg5nAkIonTyUj zOD_0IFL+ClUq{sua`*@-D`%DR8_%DP@|JJ()yDaoGyJ-?0B*QqeT39be+r;*@$jOXF|+-`LS#UB zIa?Pod{i*xjysDvZ55+CgAN0}wNV88933cWXr<)EtU4R53OD2u{fB7nNzNrh3#Z`L zJcZ!|Fw>~fH>CIJ>;b@ne!aItr@PJ!CGx2ao!Dv;4jJ*gy_B3gDg>wiJY|`Mj|d#?Q!6DvRG@#zqMEiDM{_ zA0IJzl@>onpfyzyVQ#OWUkmdzygLx$Dsj^fjDMv0J3u1%AVJks?LZc2)`wV1Jmel# zaB&1BR&dEcHHA|%y~@m3!Mg}@)W}eO*3pdK-X4M=1dg7$L={0xmn$MXDs}<|Wd%rF zDp(-+3}pxkoEQei{Q&{SaP|Sl(8TJG@rF`CpD*Z<;hojyQMwA;*c7n#_}#JqrVrfw z;wscX0U3y=xBez(udYvkK~PHps-V(B4oJP-<(ldUBLo+rBj;E@yhnJO5s}}?f`W%} zjuA%J!0CzvT{aXsPG7|s+JXTSGFl*03XQf?xK*sRkF)m*&R)UZE?7?s<`bN;n$?#v zx)N4fEQ!&TG5Si*Sj$@)1p67m*&cLt1>L=ZtDkqm&-*xAFKg{Z$M{?OIr|`MA7&jg zg*YUD4vB=$7zX-+N6XnqSW7o&KFt}b zS#_SE&k+wVM|)|}*-)lR)_8(3w!p1veH%V{46gj(FJqLM*kB&-QB7~b1(%kVpCa0G z@Wwq%Q%vYg^!c8+a9b?fu$4No13MAtZ_o6N*7>b{0iR}ys~~NVFsNLpj7@HFfX^@% zhhj4=&u6H@l!tT3Sz{xo$>R07g0X}%HSq3d*j6~^s$g_AjHT_sT+ymd}{RYm~CQC6IhK= z(`o67iU=PeXitMY9S?$}5rF`UiF4~;tt&U=c2#%xNN=Nl^V>6(3> z(EyqOycpH>3ra9F@lbq2ztS;$zoKCL6rQ$!Z7M?~NuR}fe$kFK^%Y!%K^4^Yh&X=> z0&D`B_b7?sVn%WFg0}=vKG2&9xPvCq(EJ)fY0u&#Ro=FJf$n|O@Ig+S2}A93uHp;6 zvL6EF&?ikOP!3nld(b|1gff;qH2nenit-3OdXN~{kM*PnI@A2^sovI9U;BQ4_hEl; zj=#SM8?GSab)@DrW9kCD6THZ{#ZhP<00^4n$*F;fmj(ZXRv0bbg26H4=bZ{tULWYq z^L3=Ns!XUdqECeKAN-|)Asg#U#|QICWj*iJNhjJ0ULD*{A}UsugAWx&Isnx`D!*og zJVBlA0Nz{Tt%|}b)&*N*&iBRt|AzO5+hVA?&A!q#?#dnB!3uyX$4=0E-!mn;0?q`?Scc;>SsvrZ|SSdI*gT!$~R($P#2jv=3e%YagMFUAU|! z(4UPDqLpxAbKZG(F%-gc?vjwT2+3X}xQBwc{o2U}p!atj3YrT3PF8}(9Yt8*0YXt1 zg6F+~hEa5pL!uK2Y26uYsKVEAFwmJ2G-O}!6#s}bJop}QAwD$G+7R84&)2^Yge z^nm}+?bY=0|F20@5x^9oh`>K7fNp4Kp^?3`JRxf*P`MNao?KiVLO@d<#BIobm9>jC zHXxsM+FV|r#~TZIQz>nzz_iEwx(1*AjL+EWH?||0I{fA?zqQwI@1LdtzhlVn7)Ejq z`&}cLTSj)|O#8!302!z` zNEsJI(XL*;iP^JuL08q?LM-S!hOZ@AM`ZS?Obs0;&SsGHv0T%Rv9_48_SkTHEPrY{ z)esdpmE>#B@(oqvrXHGfaN<5t>E%MbMw?H$09uVcUr}?-U29GAs7mHZ5F3Kg4|^pvf+(~ zOu3vkhd0*-U0osEg!~a)Gugp_i7~curs|LtP5hnrmU6lrT3t%(PYYg6L|`O%BB&;$ z3z|yKKEfEgY5iH+(85{H2)5Ix&_d}ol|iY4^qg}R0nG!`BVpxGFBs)fMqSJr>S3S~ z449E^_2(=S5IIeeHV>wE1XNbPCqRfU6>k3>Cy0vi;^J;TkTj5(=-|Ztt z9u=iJL5?C{z+oFy`x0cV8aap!W%>s5{KG~5krE_XxnEx8SJnD8CoW1`AJ8=gbf-Xm z{b|3k88@|(mQL2*$Jqy1TR&rJr}d{8!x`4pCaN8pRL;`P+4?x=Fz=QNUZvpE1OoH7NVUY#uaA0W2|pN%!I-q8vgoWZ2I$!z;0cTz3@f=s-P_h2?%z@p%t31 zk$?mK3LM5V$b3zSUOge?t+#+8PF+0ZT3Sp1g3oY8>UWWD39Tj^>rF~pB}#=w%RF@O z6KfPEZ-D}f;X|~Kb1Be_voZ^v{BMF{wjb+Bp=Af5(>m`dzThj7{QX?;m!0>Njyp@x z;UuOaUWe8%vuaQ-IwDYC5HuBrEJa~^$+)ZZoErj{UGSA(2vl6~mm^P%qJ990u}#E@ zmO2%~UC`ojU@tSETQ($vRUW2C50XRsvHpF5o_+q#^o#0Bhb!dJ0Zw%!WX?I~MxLca zPmiTzwjx@dg%9TuvMSa#aJjok!EdBgO}wG%oU@Qo9wA2ZgZ|5iO4Jxj1bt>&(c(Lq zgw;kd_1nU2u|M?hmi7RW$2Rz@Hv8&!;R6+{M;j!ZFysIfi-=_A3!SN=Zv%!FfN{-v zJaTBsuO+A>(0oB9Vgn({#ag@Z0Vqzn=Ul}hOFpuDDJp1vD>=Z zefX%!*Qs*#Yh4&74%=7^8W3nnLWC{o)3VlHN^=q)$|Z+0SY-wH0rb_tBTgrKJ zIR`RLh@DUcXR74Q)x7zbU^xzhs<6E(WP?#!b;wo|w$;GjknLE=UK_O43AU4h?F6zJ zpug}LR4<9Q*7Fu5@m!sgto{Teic%jZ6m^uYg|!a{DfdiG-b4^h?3`0 zqnXsm5qdO(k!7%o3|4i7*Jh&fY|5E1eN9-lkdG+zchbrgwxK1x&?`?DTtO?5#gOnp z&}A|5BaAAa)zxs;4&F5?c(uR;VmZ7dGX;+tA1>o{@LZ*gIu9Q$7yMW8@dzb>3GiMc zuJ6S9%ZR2V@?;Eia&x#f=3Mu#vG!P@C7Np3fj1`jPamXZO@d1Yy>DbBGhIxGu+y58 zth!*_RT8x1Q}Uy%wKa&2XSp%YlW3Zcatl5KfGn+PU^ErT5^2Z*aoSQwUk^>0wCRDN z2rot`EdCCaYeZ``8TGhL!CD7_IcR+gtv$i$j&p`%ys1X8RE8|YL1QjjQL4_Sm3fRJ zmr=r7KE|3(vF0|x+5mLLX`y5u;q0C0jbCZc%@~X;m_RUKLH2mbFz+*vs#>gXKNKWs zVh&9mn(`QRF+N&Fs2WIZ3#Dl!RVN5}Ei`VN>4adZh1N1`tq5C7!j{6Yb)u{SPC@B~ zkpQpF0>YzYS=8uJT9zT`v(LML{Bp_B97>7A-{yGB}uJ}1a@#!;A{XsR1B_= zb!c=bVxQ$;a`E`Q zPD7L9FJj7MTgsB&iBNf z>q1^Y>AFq+vb99ZAzIeRTSr2eeGGZ3oQY*VQcwjLf6%99w3VDT`<$mFXf7ns=EnhX zX6o7{U$jVZqALw_AcQ&S(+chp&eqB5PEeycoC>-767;#ODxcAz)3_0DamYo2-HWSj z{vNHTRqoL1H34%!ZERt5Cunswttg~M57V;4tTF?V1PvOL1Sk@Mv6R(S(wbUQQ6s+P zPR=pPdo)3JSJ(~>V-_hp!aI7Q!HHNw1^+}Wgc*Un#VcSZ_K$ltsu2$&qYg=m_3_kQzA*Ehn_A&`ts*o%a-oH&)Qr9xYTKF?vld zG_QK=&Of1HL`@A^8ijlxT(LE~q9CLsXqrR=)qkVS<}*RJnW!T8X-W~nem;qXTeMV( zyGEx988p^_`5@^c{1q|l;$A$dMSyXn;L~!pZWzE(N~pI5#Aq%tl1&b0k;9q9&{1L} z5A{+b@Xtf!@BySD(Edps5ZkE?dh`&ZJj&?`ps5Ori(o*|@QqJ$)j2fcFGRa$90<9P zQ$%P%+^7+ere@B2;4}K?dGQ2~^PUNbeyEGb9i<^lDXl6d6_uo_9$LNd?cOAO+jMbW z4C(UzLjsrE*EL@3o~5@RA$au@(2N_%J9)#UY8AHZi%RV#LLGV1;EqfP$r|T z6MQNmV1!XVbf00$17#8|t-F{%(u|LEf}S{c105~t4iU~Ebho$-C?^;&2LmQaA<0qzJXEK(yB^IQA~~Il0!%F{zG`*flJhX5Ff}OhO()V zB1Tik+d2i096I%o=nCr!I0YCA^@t+?0Rb2Afg`NyD3o)~cpR_~`CGaquqbgL4w)>~ zO$xIJ9zCP$B>O9{`UI?UJyX9m)Ea%E7jaeSOf*#=6R3;FTQca8lR>{_hL-tD1&QQ6 zTGrgg8_EO&8ZvRZ5>kGQcPqsVyk^OV*UjQk9$4!jr9Dl`;C+=cYGAUmunjP`C~VG! zp%<$vqLs&amrPvbPWo|j$l&Wxd0G|jPL+F5Yj+rXS@TKYY2cD`E+FX=Xo!GafM96Z zA!;;}QB|^rCf?Q|cw`~mBFYAEhMGi=TCkr53S>1$Y57rrxghR{uu-Aq6J9N?J4MM$ zI9;h=DuomR;=q%#njB7(Ic_gRdo0j43-ORgA7FYRnzQyG59|`qL*sS<+B#_B90g%> z4h$xl(L>bGVQM6kRun_+;H(`%uRIvgBeH~|5-HC59rr8u%BT>K|=jZo&Mh-&h;Xw$FYH^WemG_+xw z#sFHSTNh9s4=8Jq)b*J56sE4j)YX`}YPxWBHK{p<4#3i%V05*tp^mpSqV>GCs| zOk*SO9OB&y!Ka7LRa`N83AmtD7idj`6S`Yu+iwr?$l8Uc)|OHcg@*`S#uv_?4%86Y3(UWRZl366Y| zE{%VHXhobtbrWi(zy?^qkuvw=eU;eh{X|1N@~v<-X1sIf`JOnTc?VUug*X{Yv>c#i z^_*oW6flp?;7LG)n6!_zbOF2u&BZ}eKC8}U^mVLt00=lD@I}Gt+e@Gg4B4uKmgBtX1fw}lsp=?o1EX(+9Fs~QT1Yo7mjs`V(zS4g z>X4}b&0U(ySZyV1IxBc}mloHbS5TNahBCX*!GA_4=DoFr>LOA3t`nyqjA)TU>kXhO zgYgL(B_f=Y9H}GeMZpK@iuBKmB5@N-SOowPBx?{e1^s%#s}lPdQO;o)xFa{y z)?Uui#hTh-EJf>1Q`$yKQ%|W+kji6(qMDFb5wc2BRzZxG5hKO;PysfWhxKO%x(@ly zCS%=c)X2e*G3UIyNLrzJ9xe9F#|MvK!-crKR`SAf$p}(lplOBzr% z_vHAxGkx6|qK^2xv;4hzf&OA_xC;OOv-h9Tl^kc9AUyxSBmLa7+p{xgcV}AK)_mX0 z&a{!HXS!R4l1PdYt?0?}@IY0Oq6|GL(^9Kj5?!$@Pz77QSl$~Hs^HDV_1?Smnb!eT zqr)JjfF_GBPqU-222E5pO_%=qr~a zb(5#?-T@FJ5rQh1!RUrk2qM2z9`Dcs7vX;m1siS^wRA4&(7b2mvF)mDOCdlDus+Q6 z&}uf%W_99Sd32*Z-mSWh}Yrz52wr5d} z=VBA8;{$nQLov_>hQ#z<@5m!>(UuGQ2Hp0aI`*zK_?|ep1$~-0)RsQ~&%)*3DP!+w z6Ypvhv@t>&dMn%a`|PE6#i6ar1%IpV>{9JVb8&lB$lDH7>6}iQDrEj-5X@G&Y2%+PDnV7tlPcE$0-)~# z{UXzGv_zGi69C-7LF}J0N_hpNaYBxE0NgO6vQQ`vOPEgsP_ZCZLDj*lNZFv57Y@^m z3~kh>wZq7ZYg9WtZWz3~zeb%VJqH^fkO3+h7LcqWaYcd(V|P-U#~92>nP4FkD5QP) zv{XBIl>=%{fmS zMtfJ{?Ni~lJmi+A&G2^TLx=Oxv-x;mK6crN^yQ+LXlZl2w-7r+Yu^2PbDnO)wS(;% z+oIby5gerJGMugO&v`m?-kr3pK6EG_Ii8Q6$;U8w?bAR3!$Y}*os7^x>VGOZ7AiDN z)s;1rv)0mmESO?xW@mCr^2bG2RCGiH`}HF#I%9$(o*qv|`!l{XqW7rkXQzxgHU=Ck{q>)sA~aIttcmGb9-zopBT->Fg!SK1dbcN1BPd(?%I*}Y-1}6 zw-o%_O5wH~$^H$R>wpm+g6OS&5lX5u*#|mRE-7R_o9UpP1Ue{%5Y{|>%Ftfv+$QcSgS7hW%(c?Cb^BX3G)-c<&7>&^>>l#fZ=PnRGmWc+&IqT$(b@iBrcg0*fuly?nBhO6`OawmUi4{Npigm~(7Y#&(3xELEC7e@KTV6}y=TES$yi$2 z!={z5t2BAm>7mQAt)~#^1f?U=>D{hOv>Ty5s^OH+)~9Y0KxH&l4kgI=r#q5O2@=ZX zCKjr5r2rdm%)fep1MNjpVr=UbpWyp+RsKH(aNP}C8A7Du1{l?+pG7SMG&v%YIojE- zk$FJAv+QFgn5jbripQU8?Jp5gEn1 z$RKA<`S?;}B})p4gk5nS6KQ>Vr!vthkG!MXHxvWg@O5STK*rP$|nxWF+Dsejdm6ST@dri*t^o$cE#UoBg8qn*X9Sx)Th>aBTrAor-qkyxZiFcZI>tnL!Y;W2A@1z)a2NG>nhYxsgsH zZ)o;VX26|HWu=0_r8p&kE6Ehc9%b~Msqpq<2;6-)#%yy^do9pDgUeg;?zWFIJz$3z z+Od(LUv->R#yiz9>V?p0Xtqt_@OF@!Je?s3c9_VgeV}x3fb>}6TwJgdcupIh?t*_S zQi5(!nRrL@AEg?;cte!y0m`D3Q)4Ni*Pif1vWAXf-py1<)}hJO3xel@3m`Nl%d<!v;#Q+T%(H&!asYizN;5jm{;O^1wTMNEz=tm&N`0he(?~$*&!cVpVp6oyt zgUk>St-;zvHt{Am>h?_r8$jp1TR^ni%UqSOk(U5fKCD2wGAZv-01F0E=xx{b(~9=M=+4$*lv{#|)r zN5O}bv=;m*$DX`@kKsF@dk<;86MC?ZN{ufzw?;?{Wf+lisQ!y|Fs+v?p%?s}d4GG( z(`q|%qQaSXparDLM3vU30)34~qUXc&JCY^jszT9JY z`-&O=?Uvuy2K5HIz~&r#(hCl1e2*aneNrzL>xPM&*iRWf}a8?YtAh zxwxHlLXN}I$X0dy-7B&7Qn*tZY14z3ENQOB+^#H_m=uS*^WIL{x#`$04z(jr&2!Xn z@5+1HQG4_5Erz32a~}kq;(At4TT<22ta0`ZXthg9GM{o%9dopmf~=zpwHm(Nvg?Eq zr^Ax(WR-xpQ4}SVAmg8|a8{H)X7s)gAg8z@z+f{ix|Y()hFWOL3sDHJEdg)F3phXzM3LS5L1z^LZHKN?@%XOrO_=k$9@X1+}g;}kyAD~ldIl!j&CXiXny8(fz8WI=_14!Q&KBX1eb_d%nlV;xtMWDE2PZLLBPZ!?^<&r2G9Paf+~-N$keJR%L~kwOA3qDmpc zf*8ytCREQ!VPuCqwwZq&Wb;(Gy%=oI`*-NhHf4OPFw~mqZxaSv#i4DG-|*4w;O^k@ zonV$A2g)ehHaM|c_M8!;6LQL#knm^yc*b zUu5^bm_POEm5XnFH2BNu-Zyf`Uy}AbpV{?Oxp$lHK37QjN@|8l@!QipNn^)0U6vQ6 zN#*=Uj;YC_94!cbJ=90*oF=y$Zj4gez^HQ0jk@hUW0IB@Y2)vr(BdgCg2*a(a z=R_`HBT{t-Cxszv^M)FT3zwY9a8k_a$Xjce>p{6(=%i%1WJm?RWQPqPF?vKBK}#uo zE>G_I6vJ#Rg`A@4ndvZ z-bgNTL38g_#<$5s@5)2($RqEm1&K?%8hyPUNC}`Se&mGfBJjlam;Fa^zF? zLfT%)I0_kCF*9CB^yeezjKDG4iagn_*|unt@8><6$*NX#JJW&DVg+UsvVt(ig&kAT z?qYaX-oIOO?NOWu71zmJ!p@eA+~g>2UZ6r3bF>~%FYBes3(2c%_Vpko`9P=qSqP>< ze`X|@9SaK+5z!tOT}jECki5a{xHmIcO{6%$rDBpZCHvBfKb0JbxsN66yE2n)x)+&1 zwlE;NKs^m7Xv8Mnb0`-Z$R{Q%WA~Y?Ko?(>LaK9*H1PX>m3Bhff#7QXJ~P1efRs{l zg0vC7i>mXe>ey>|cIW*&OQBuGKzok1)^AWJHh|Ts_D;>YQ?s|L;~TY!4VvveT3Zun zEe1RC{%*SEKBD{j^uT2;(64&VD~=P2{U9QwgHwF8^R(b^V-ccKZ9#Z^noe4`-dt=D zgbbCCcG{=xgv3}ba+z#2Otc&Jt$Do2zpWJ5Q4Dk$o}H3?x8OXI^_~-AV`A3J4?<>* zi^>H9aTG3N$yBUpdNfDRczIEX=ECFJi})__3y#R zWD49ULG%a}11-pKybn4BR!aNeXipp|^8mO(d;#6LO>=c<_BPGdrh5+N!hK{zRf>VJ z;k}T`$*kmwW<60Mm=IH0IV%z}Ss|TDW}_Z4Ff6;zAPt&xkKx%>2%=JTmV(>!-YraP zxEa((9_=y0L)9Mz@c_=sjK*ciZk&-V&R!Hj7Vw=X^ZvbP_<8ph-M*1_8v0wwaD#K3 zYVXkfCy9|u%&NkjVl5V+tdW3RY*cmbLk1SSTZ@6VQV3(nPSv>=Y!8Jsvrq6gV=7Oi zDkI9?nBaNRkSRopFh>oAbyLZWmZ%Aw5e@7tmNh226nh z%wkm6AX1QFydbGiZ_}{v(+c+OAXVAQG(-|T4k|Qq))I1YK}7gQvYHeg8K3IAAWrNT z20Mkp4q>=U8t+jicPXx;s;}3Gj_0$1Ywz8IjK@%~Ack`(7oC~v?Ug5w$P;@NTaWJU zK?hw5cTY#VFoq_>r_uJQ3gEtyV27MUcNG0wAv4s8&B{bOoeGzlEM(lYpn+6Yx76YC zddPZze%3mvzN;(r4Iw7FK&M=(%Z}tlXR6PYzU;{i__D*GRx!~T7d`&Ws3$$(ox`Yt z!dP1JiK1Uh*~H*E(Y{NWBy;Ce(d{3m$+%7_)S2^ksrDXmbeA4t1NZqR9ZIw{-3#_9 z55MzAp{EdN&s^RD!E6a;1yf3aoPkUigkV1H1erGcr!@N>b-Yy_BRlDN&z4f4jW&}9 zyLES$GTALn9*`Wz6xV6Raa5i_f_ro)*$pDY93hgpAXw@|tLE6JIS**A{o3SCb$kbz z0vdY{w-DiUWCtS5`MNYmmtxLdqd!eWDaZxo8-68?+>jlPX+M z=;r6++fkQvZ=ZN(vvBwy<-@P%PQ5;T;f*U7-<-PehIaU;(!QSv`(KmKZ`D10`M8tK z_+0n22xCj6a3XVGY;%beFVdb8Zsp5M#*i{D3_tS8iF|xG7rmSdU!W;D{|Sg~#kNBk z->gn-)SX-NKALmCn(F+cxD&i8?`zL_Q5M~bqf2shiq1~S)v35U6%WuQy1E2sm*9Y7 zujDx*+dok3hm6o5SU9C8uOmx!O%)^sve_QWgpy)bl#u5vg)yWppR^m{KHYmnwRfu% zTh;ORK-!AFtz?oQ+LaG>>0S_vcGty$psi_vKGpew?&>V~=`?W=SsDPiKQJOg zB_+u;m)56l6AWF;N($(&Es%+)B}rBQP^+8{seDV~1ARD#^eDCbb*u?q!Xkn(D%zwB z0aRJDJ0nx9jLPz`39hFBSowXzikUkPPO9?we6m_ZHTZVZDFAPw7hN~0qOG%ZLPfGD zMri0P1aU2jK(HuB$+#4q23Tz_az5a@%0h( zq5o~6|E)3x-c~0zkRB`2#!Z!yrQ;X`Nr!4{m&d#1NwP#rqu876c6ljaB#o{g)b@Jx zQr8X;7A9S(OOwe9w#4}|sY+b}uX3mReVJi@W&{p*`tn>gRY(}if=i5+?0 z4sgn=N!n*r@NH8@H_8*;$SczPF^l%}$#W|V2`aA^>@|G5bDnL;w1U4|8rx$;#;hS{ z1F;p=R4(aI{k@{?fNbm0>^t(_j;V0xbc84io6dVr9(qr)b?Ls7x#$3$9VrBZ7);Q)ysD~XvZ6DX9Cw9AY;Nb|aA@*O%C=V;Z&SwJBO_J8 z?Zt3MG195~x@2chc5-jlbwUmgNhue~1%-r@t3Ci-n`QH^QrT17{^|g4!)Y+_ojGphvvJ8hA{K^HGyhR1Vsp8aFS2C za=Vj+81c*kHnl{o-hBqS}d2g#W zv2iNA<0GL*cWe`fw`-o$YH%PE7>c+qc_z;J#*X_(4gtQAqt21j_R({Wu?s=>NG9gh zGR(v)Y7VU{fb7&jRl`Yf+@JPDvayt;C<^FQL5${NlbZXS>Nu?0cN?DWVyJ66-aQ@b zC?CT&_O>*(S(xY$Tn7aINg;S%iVZ6nZ%&~T6#w9LG)eLW8>N3 zE_^8+7D=lJ@Ug8qZ>Q!#qaG^CF$}{PQ@QQE;>QA2v7{zZy|o}ZtKG`zJIIQu$PR6C ztK!&S$au+I--%o z4AdfGW-%(uW7S}!tbFb)db*F1%AZG|;+84SB7HlW0ir_LAWn9?37v3)EB$090EoXX z!XcNm-)B)0Oh&EfG_hgTb5?PlknKmL$%7_j`$5ffC>J5=Be&UH;iTs8RozE4_r4s6ov$lFUl+jD+#GJ(L;rq#WT)ATC6bB18zpKct8|lC^t+lXjbb@yXxMhd5_3}GeYQ+93R)xo;(HyO2SYQIgAA6Z3TI)kPc{* zXQYc=*`t3@j{VX&@k;URYg6Z6FP(cWcl;$~|Bt0(zZQG9suM?Zp|O$_XPGdoEsy}F ztcar$BIomoiCpAjE_^;0I-3if&IOJe-UEhfr|xXm?OQe5`=Flc_`B-FyBc2+W#@R` zaBL(amVq7lU{^l4s}S0&ySl{TO?m(JE2$oFqAhy4C+ZxE27KXAFc|O!e6Fz97W0e( zQSW%r>j-$=exD~83WwvVXex_bO#+m?BHXdGFrBt*QiLGhEv=_a4wG)UJiQ7dBV5 z7@g0J0;9oP#s^ZR*!O_%VpM=(1{#YNIG;~@=C4k-2U7(dQCgV6te`r@W+{|<3vw`@PE`YsxA8@gshZuasVQ-+KYFp0Xf zr$FnbF>03>8Kteoe4e7ZLYqKE2bU_4PLURJ>ZI06TF&4zSEe&wbs2POJbu=eI1fez zA~lOe&0x@%=nDjn$A?;_k@u&g?R2V!v@`GBA`QK(*!O`X71@W7@Lsr$fF98lt@8tU z=rJ+EB3!74*WqJ+$aw3kjFs~ zj~l^D`J{ufUS{2gX-z~~@yCUJSF+chxGZAT&8b@DBcR!!r`>JsI z{akpAvbQ=bFifI7aUt+~&3938ol@<)Y0hqPGh-)P3w|GO>?)GqFu>}9@oI(5u0zN0mhiU|Q+e7?peRZ( zA@n(ur^n+b#^U3FOezbhdgr*^5*8Iq0BKeMG>cJ{7OwhWR60FOyKf+)HEJp9D(ES4j{`%BoWTr|QHHa#_A2ZuCHv!|J0jQv z*)ex|z>^;EWh^YJj9{`q66uY&55{brGHqnrMl*eM9MBfsy-V|*G-4x#Z17`N?NDDY z=aNpveOz~U=RKSAWEycZpFU&qp4uQ~COgJI7oXHa{YLmgE_ynL{Pgb3`MN--4A&Kb$X;aSKRv^=wyYhiO`M`c=Km=(!k_#R)0>|~h2|aL1X9oitk$x>QoDGZw9Yc|^ zBbmWXy0f(y?h;)e#2vlia43=zlNpJuY0oiJ#1~7cijvAo;UscQ2*!nAEbR-$d_Hf$ zIU0AK6PzDtp4~ZbXT?Y_u{va(?rK%tow8@2=sleE9MAgCW+DUGq%8|B#a8`Wpr~;} zOXsC%0finJ*6Cp5Q@a0%>ff*X_U3%M4PTFew|F}Ycbo3mgbbl|^llKi?fJmoT?lk z)43USQUFxIx-D{`0kBn~M8~+{01yJp3zl$0AhqEfh6^#zS6dTvRg<7xw><0jiJ>S( zjnI%dwkO^DmNNc+!QV>8!86@|6zB+gg3w*ICK}%XriF1o1eh|4LH6%WC}T9ZoQ~`$ z(X!~af^UmDzCq}JJ9F`!Oy4GPxJ$Gj5&{>56AY+1Ui*+pGXb13IlIXMR(vsK1@LXZ>10PoFUF} z9b;d15ME02pU+-?ui$IFnrPQ-?+g8JvAaxfl&3xUphN{Bpa(C@wgW={7I}PAF3`qS zYjsV>x{9H8-LY97!GoLRiM?9j5=}Bzv<_3O2M0=JXr&zF9J$G#1u)ZdL%`!)I~8P# zC`TwI$z?MKX(^r(;Q(8m0lFK$CBQToLTv@_7Pb=T9ckztVc@=43Fu3g9Ly1|VDN z*rDvv-zPg?5cj@Nyzs_{1Hb&&k$;>z_nLP2XW3mpPVaqPJiS4>)Gm$g76-Qrmp4d* z@2KPN()zzJ+f|UDgXh5bQ7GC3YU2j6|2<(~i#XCPP3)&b3%uv`U_YoQ?T}4-L0)M+ z88bakDjAm5*-U24?sbiv5Qp9d9VrAmbAc0doH=8q<Ju!W`R;T<43U{oynU=q zn|K#FgLIano%z6aaztjd33qDmNF|jFpE(sT2j?h7{v2|1)qTe;D7`&#SiEd(@`y{D{l$N zK*m#NF-9>u?3^n8$Y>`zY~NIQ;X zy=Rr^NG|I~8X&G_r7BOR@G*wwE7fRqATyW8Mhjt(s*Dm8)rhEu1vQwGy)n@l5+)+a zp=9`C#(hYbXxChH_z&5S2<;%NhOPs8sK0=Bk%sA-g~hZ%g^Uj!y6)bSqXS#E7QAhm zYp>!wjJvc_E#-l<)&jj`c+>kq&bK%3?_posmJhb&d~JqnyW#3FJRcar)0C^x;e66b zE2YYdjc5;%rl}YWXG9r2b(k$_a!0b@K=F(WGNh`iuG6#~8#2vF@s}&^}ty@H~>kB zs}|_feCHtMHO~pvc~Ao1J@>oJ@t;el-ZU=!qImgNSB8FlW#Cs+{lCf&{5CiIcHXun z@7$jEfHv*Oxmpbu9RSRXl;XNocXsOTeROu*tcljW18ov<~?lq4&{9N@;)+bhW0`c+PBE=9?833@*NWV z$J4MX}oUG0tOU4`ZUr3FR*chcWwxvX*6PF%BtJh z#pN{=nGxyFd3P54TdySA3xO_SxbsG>#xEk!Jd+uT78(Z9mz)Vut1(~N9}@&gG4v%; z^_cI9pJ+VNOW|FG@55Egf|8_&|{YJOY5j^6_96OOAtI}wsRo! zF}6cKqig0Ca-I4cq7DHWA(e5jWo~x;y zSJSvM^2C7QI2{O0rwez2PF+pl+R5#g;#ye}zAfk81W6zby`AlUCp)xRoaoj($8ynu zqTr#ej#89wb1Nw+CIZ>gBF3(`B+%KIfp3L{JjiM3Jm@T%fD+4skfcUa;a&v-+up5B zY~aca+B)uPmqxqwz@=%DE+1b^pj-tpq6horkv79ghXUo?TUA?|<~gYa2TF3Jkg^-W z3##j&Jkga%#k2rwC9A5eX$m)Xz_nIWY~rajpDDtEp&~FI zpA4oD;g~;>6p{)lqRMMCx#}93S)`K*Bn$>A0bs?sSDNT_yRpr1RIW#Mf z=g3kB#Yul+%tjv!K`snSxY=;#ws*Qu$HO=_}l$yfG#PQ?5t4aTSx?aBG~q9+x{c8X(rB-=sNb55tj?C50Ka>5v|<$Enrv55qzNjmc+>7?VUvjH_} z&p3_MPnCn95>EjqovNI2uSKlG&7|f-sRzf*puKW^d6^AR8G^<(pV( zA8Q%3l~v2>nxd#6b9iM&6oHhGiDgouWZWGNOgJY;Y$HQsgF|Bj!{hzqW0zbLy>aI$ z(REmLf#Xw-xz@FoxrO!}e}&^!NF} z-{vm;I)C{$)01y~kFTStY_UA%KtVqH^_j#7y1IZcH-O5rX#pMc!VC(xvk`-MOo#wUhzQ+8}))X^Sr z?ew_zdb}Ta14rEcgD&4eZ}3zg+#8Nw4kZTssR3VVD3BSGwRsp7IxFyIKL3kXWRy@+ z_N8QhiVh*T7O6t=FscL*XET7er>{c;N7J+KSI0N8(*nr&iypefn(gg*<8`25fQqXr zLGs43mz~M;lZk#;6151VYH7LpX98eH==8+d=V;AhROlROG+9|Wh<*?qEBZ$~$w(DR zdgi}W-ZucAho*or4JB~-ja)^4hn`3y7F!X+C$bveHTGE zh+a(YmnQZ}V|&T6=;R*FwOh6KNTZ$Na3@(V9qtB0l5M**=kA<;Pa(9s6d?*S9i{zZ zQ&F(1jw^|F+LlGD;K|y%H2khS{Jt`_O>^u5b<4*t7gFPejEihCrQG?9k8F2|;er$? zNYPx%f!@{#o~3EEXulCU4-TZ;w-vlw$YgxHowlaCcdDLaNOOsnNL#;aUZ5xoS)Vl4 ztxar(7%Td>DWmVoW3BQ;kLtiT?o-F#&$+gM6oRx(N5Ky|^Zst#)uTA}N{%Cn_dMf* zAzEHDy8*KGQd%@6j``C=o)m_>C&!|F&R8Ik4kqLNcsQAjN^(4tiNurPU_9)JMjfHV zcpy6L3yt_SB$R@KwS`-smF_IF&%+S#b5={{bqMQ+>v>#O4iqeEvkxAqIvO?*-X$ zOdQ)M*?LrGJIG4Gzdh$|%lo&NBJKHbmmb=w2fK|xS0UJw3+z(7yF}N{tfMD0(U}_B z9_!s0Kl_$?@wdfGzq)$)7t_6O6wkb(9{h>0`vu|XKZ|``in~{idjvtq2y!Y5wkIdE z(qu3*;7$#?QzPCK(J6m=)R&$JWZ(~81;D`>l`Bj}vGJ@XCKcaB-E&|nzOxi=*Iipw z+xzn9yV?ZV+oWmkVA~WbYP72q=`2P%3*nA@s69^;nxIpRQQ>a9yBO}u1v<1qyX@O8 zx?3}oTjQgf!=u{+6T4#JzLem}%47=F0-{QcNP(u9T?#sFrhlbXO$0eC34SGX3Q0nJ zzLM+|$2W%uwz!?UCw+&T}7rkdR zdsivcUi7!Awyj3!9EK%iiGEJtJBBGbFI>w?vMZb!bSE!NCQ#W>mq4m4A(!we#K$wL ziqvOD!>af@gaJI!Z1}BDkk^0az_O05+F^?f%nlAjN>SNr16no3j@j3sj(M$2+57N^Lds2nfKF`A^KdAev(3Ks=mQSg&Pj1b7&Xq4Rw7BbFUHEw7W(jva&!&C=N5z>rd7aeIA@0p5p7lK{7t6dsv6^FKG2RlSi zH~SIAeOmQhp#6i+gVM+r!?lBqOS#%}ZpgU~#PCt3yBOR?7Kxm@$*K*RC*W2MEgv;6 zSTzv6nyV-8+451gJMY<=?){xO_>N}VR0!;tj&@xEk&3lX#X54{R%K!nXq@Igo}88Q?VON$XfW>Y_MG%H0iVk9j_ zQ$j2$MB~{=G!yqH;$SfSZkmG|@x?(D20f_@_T;cPg*b;jsR4HacgKT4Z^Da5WCb;o zgdb`q0g@HN1FF69P1IE$13T40)ip)a6jfDZMFf#k6tXXn*My=<=j9dU1oA-+kER?a zvSZ!C@V4woYj$XBw*UReIlGyi)=$TF4p%cT-5Gd)0Hx0mXZZgs9 zNP40|GAk&SRP#wXTPFbFh_Icyv3Mz3!l0 z7t-*1;>cEEbh|L#ks4`>4Q&MygPSs!-{G@AkWVO)w6sdQe?77ZHx@~#`SmG>%&7*t{tM)-IsNGs66N0Vcn zo{`;?{-YDoQ{%DI1^NqO#1irjgKzcFR5_9qK;O?#CeBPGLWxh3=Pltnf$I7(vwoHbEcjfD z_QeM}GOmR(3|gg&z6>1=+qcj4@a5&_l@0}?G>rS%_I_sD9z#9!Q%o8Dr>zl$^;o_^8I@s#?ZC7GDrX$-CiQ(zeT>JG zQZ8l#ccfwTHD?vkBSWIw0_hWDu}jW`J(x;llcG}IM{*4aN;D(K;@Oxh8XgaZ0DCy< zjU{ZM_^>Z(3&!l>*hDZo766?JdE&vi5RjBafywFW1Q5HraqZMKKqP=7oad``Atpub zGKjDDtl~Q-d(Ozt6XA)o6T^M>(TlF}OMb_&*Eum^v)i4npx+lj$^((XaYt`&-|&&0 zo&#@Z4!xlrd!=ytm8lD_PhWh~IPt1<=+)$rUj|NYvRybnIX3F{M?K+`Cz7>?$UJFU zlyw~=NqRf)1E;7nr5ylsw@en5gyKG>IcQNJ_%Vt#@86LN_GtcHvS*Lz-j{WKkZ~Q& zxKCs}rz4I-zR5j7`+DgIisp9)_bkyPr z*%Qc)I+A2HcQV=QU{-T|89L%AOxtPgQ99_!&2?A!9CUYJX=Z{K7gKqKmU1RWHG7xg zBx5dgNR)HG5g90CgEUt8M7vp3bw!cUz{dUQ3-*L7oXv=GZfTYJryEq&ue~ze^1w}l z#+_BL-2D>)dIxkpmK6-w0P7!V#~B=atO;I)UIxWxiFpZC;ASc-`_GNahI7!Y@Sx&2 zCJc3CF1??=@H?^p59%1(Bp;ze>G{s^83;Q+%5;B7dkH%~OtV|k&VQBY`cb9}f=9P+ zO!xjynmmwWhAx?E>Ut}7QH~k$NyT+avF*%z+oogN5kGC@4iT{fol-{M7W;oMjqM@R z0HJ|G#)q#cbCl~)3Fi$>RupeEJK%!&N(_49(ad#KIgYFnAzKC&WZ5+>MUoPR%7M5T zNQ%L<6ox+-n4w=UkGxHQ?3v2(5;si@$mvYh5lGqssWD$_(3QCCh+lFfJdsRZS4%k+ zS9dsb!4^9?61sHpV)*FWsl6|!JJ)JQem33r=7*PmdFA4pWLsh1OR4?868rZWDPLYm zbIwGxiP@X5Bx51a?2^Ava~&u}x_AdVY8N4l+8HC-J>0m+#CJFv{))&jBvb1FeJ(T5<&nrwuRh`|}1Ujkmeq&tO;woZP z7+HR@5AIS&ykc~v=HZqFs+d3U< z|1jMJ<^-C>m{!lf%DV{CE-)={tP)N3ZOB~wojBU9`Yw=pcOg_#7C7~pnMh#9n#*<& zbpI*Ce<k&lu5hB$#4W7c|a^_ElhZ0uvbt z?aLPq;$8G*OOT~B9VuS2R79m4gvs(vu#TOkChIi5zs2W~$GV9>g1?q7xZ% z+Zh$pAnM^k&2z|bwvtg<_tu=J)9~)od?(>w$OKAi=9A@BI;+VT%D5w0e_UX8s{T|Y z=4TJII7-PGS>EV)Lzu;=3Y9UL^~nW*p&NQDK8C{;&lHMyndjBFv>&>l}&$3?dsNm+OG?RY*3F3%Z_8h za1R}Wb9sX_@_x?KHWlsqFbz7j^CMx`M*^-u4*;gc4nN+iO>Ur*Mn<+t6MGal`rmQ%PzRP z>ZU5;hTX59i=sQ`tdu@+mOm!qXibjY#!7T$Zzr=wz~ z1mr|McENCML?TfeGvnKQ!|jv7WBk=+u9F%FWhO*68HaM`OFyqMKEz#cyE)UrbPA2E zMq`o_#L-4p0vHnK@!?>NzVtBO5*Iz$+dS*X!PW_+(0GNxR&}zi7^EGSMIyc%$qb7B zav|+w7VNlnl~1h8g_Oj=V1n&_;QMeb0haLT0h%Ef^t=JiVpQH}7M(I!kL8(#kT*0z zLJzN?uSX?FWhKObv7i?{dQt>`!l)65ro=!z>j=|fRc9vRz4nA7oJ9xs`Q}x{99c#{ zzh>!rt{)f?lBS9cMllSWSrbMfJP{8B!8mR3;t z_8RUU-Pxhrx9bivrHFC-RHTg%ZYu$yj$(+6Oy>OijleN>_Q+|?e^&EdAcK>U5!K(P zdQNNZ!@6gG-oJ~s_XpbY9%e&wa-%k}NuAhixDY4V0V)MsHAk0ZKa$UQ$wZbl!DXO7 zRaG^fmM|un3=&)zzoLmHGO<)Po))8NF`N=7Lzw}0a>N^PhQYWNlTo3Ypa~|OOrL*7 z)uqTojQ*)FN=xXMGU=3<2q=M3&2~~gvq3uex_0cf!kIU&_Wfe|{2PUnuc$}g6p#Ls zbbgyQalDubUe}aRUM*w;dg!ud@5;HhTupTr{jH2qo#r-sd1hwmD9KPnu(REB7irOV zWf^!i9LYXUdcc{wWKUh3O!j)yL!eWF5~k%!2Dp^W_X**>MB|v{0^C9|Rf;U8sB~7? ztQ2yvg^9UvuRQn`YT(sWmoTy+)W6voJPx9RS0g=efUCQbm%~|GTJl3$fKMZG^DE{8 zLS??{LE8@UIZ@SlZDL-zh+_DvAnH<&6rSh=8`gM5;cuKr_r4bZRmh zAg;3*)u=B8J`~G{DA8+k9Sr+W#^6%Hga8r-UWIr(jScnmL6Ria{MoS!qWv7?~OHi>?7U=uDh1hl+j3AYXmTfwn%Nrx7=thi6h z_QTS|0daJXG}fiqcI3QdeY6yzgJ0NIK{~~cEq>afJGZO$9g3|L!4zAU>e#2c4#~Ei z@>r`f`o3=4Q1EP-3T>xTO+uZ9yIq-Rmqt3oQAFErxIwCRe3E#?;Xx!ijf`IE26`+qF#dr>^`2i$kJ9K<9d4Va+h~a@(O(xE}Qv>1bBv{}z=KBD=5wfI|<2%92Z>$E=i2#xk z&5C|e4uO7wpd*EBGLa750%-#&yfYe5B&L*;$l$Q&tmfQfxG-L7FNN9+=SB>8q_G{U z=U6T_T*!EfO1ykD_#M|*mGU}`qcV~$K-(iknMA53%o08gV2W53ZIIjVoW-cXg=zT9 zrf)%lEKgR0=oB-}3<@>oPh<4#jb<@4PG%*Em3{TpA)gQ=Yi3y)@%K6syDx`(?FkI8 zQEALzpEK~WBRURC?{gDiBhJM9BhDq#9 zcv^EGP$#<-qDouj(T&R3d)mYXgAVj~O|*Q1Kiw;sYf*=7kQN8E_{L4TUE|M5ov)a&!&6dymIl)>E1VTCti^cy(%2~N2#~n@DCQVVQUN( z&}?$BU-vLN720u?&adn$__k*HexLQ8tj^4oo@pbKy-7fkh=GPg)L0D)>se zkdsI?Riy_4JpyOqM2f&S`jJf*`U!tL!b46KH1zni)~Y;zmlS>HQs>{!d)q$DbZL_t z;-j0Lp`&avu9s`7aCM|Ex-t(>X=N ztB_zMDbEaW%z2Qo*xQ>(b4KcFF_Mpu>b~PD8tKHwynAzzj?V1L`#Lp8mtx!F3jpkFm7mjR}*%4A_+=%o08&Ky~6H7F=gBDzKhdT6D7MxoDbes;mzK zC3bLFI4Oc2@%6BtC{6RF1vJ`^;bEvEzPNDK78~`YK)R@`S~`w`iGNVb2VI``@BJ%(>zKCrJ4+*=HTPIVTUk?T^h zjZ6pzx^mtg&ACf)ejvL}=;5J!+DBH}naBZYQ@rQsytcqz!`Gv`cPKUxwfD7@TTObU zWI#y<)RbRKdG(arNPD#Sgy27)avV;K?-V9?YL1-{0IID`cXi}KNAhV~CK>ibvculw zC1*5{oTu_wd~Otofpk=)9kJL_|D2$tq;tU$W#~Zm_}kKvU+PC+E}nf2jH-0*wcPQS zDYn(s0h(mcG0ptU~0h!H(fkkoM5*SHN7r;f}fF~RpnYE+&IM6AC zL>X}__Hgj^m*qs38CAwS9X#W^km}o<^U zlw-MsjgC`v>_(d{1UgHh?Rn1@ee!*6a;xU()&nPv=s+&zpo13V#MGUgC@@KtEtv7e z=!}|cOV}lR;+Vy#z@NaPCIad1i@_0JY9UP{3N%fpBYL1$ z^PH3?_XxvVMLLM>EotyQd8Ac!?AL=A^5})dP}wqP)gj7L5DaQsPfSXllahUxVrvDd z%K1B@!`*?wJzL{nKYm6fftGmBOINQ*#Ak3Wx#`M?x4p^yz3;W7DAXS(|ZaqkP-;h%z3 zebi3|){Wz@WcU0md-%7~g&n!j7-Poej;kO>w7_M}eZX*RVSKuk&KS16UkdNgy% z?x^o{Ff;B;kGaW?K;LBI!a{4OOyF)*Ak*ae9If>RA1dW&2?4i^z(9wt0^l_G34c~J z7$Vas*>qIXU-*Dju}5fic_wr@HPVywcas^?z&73ABg8Lfvu;rhgFmGte?s!b$x>7x ztAzPmW`k5>^j?~(Bl~1GPPJ)R&tWFGnyOa9sCY|EaDtWMjrl4ITZ;l};JQG(Drwhz zXBFE{G+}*mW6{5LI@*r5mUFi$w(Y`bm+U-lghw#Mvczy(!6hc2{&PpNBi?i}dnYDF zmvGaV#i+PfATFF7k6m&lZGlW6A)qXi8CuQ>M?5WoFNgSP_DnBzQ+qq9ouCEYcq9Dm z0sUb0y3`v2p5g;Rbb{!`mUL8~5)dWQG7zQtv^STq>)}Dgdsc9rOxlkIM~``jPX;D> zBkqx8$d!rtg+xe91mvV&&x8Oa8IWQgA!5(E&u2z=i(}i>$t{IY$8@4cm~2bi+G7(t zllEO%*Dk@?DLJ>xjvcC_Rd;MOoSSm4ErmdLF>;{b?<)A((Bl__JCup7p0N{W#zWpH zP4vjKk3`_L$l`NzKqcgon@K)vo_r2K%c_*5;UAPQ^+>1QmJYq4AA7ZM`jsmeNm*qa z{h4z3RpIcjluMnutGAH$gI*W1K_fDxIzON@`#hWT?#(&pCW9B2dyD4XBl#{wB7Lsp zWk>RoozbazclK2Se9NBdP0HRfNuv2On%x7zLMK3d0t4?8a0N-aKBkL!NG+u4G)pKZ zCep4Gnr}}rxV;c)%>{R}lVjGc%tcO`&g@-PPRE)7I|dsRjSS^4uHL8$h#7AY zlyERR9ug)Jl1EU(NLyi%50-^IQi^ISmvrf&e${4rxo)sDn(HvDY4Iy{9rJ0)<#AU zhCFn*6*yKI&g7^sofYNJy@u)5LFR+m(o2hcx*o8hVfo-{08v>YU&1E}jdT?>$W}@@ zNs`2HB0J(qUYH199`_85O^%O`*vALmJF2p?s8{wVDNJ`#3LC%Q`E9eLjtZDNDa_qIH-NAsO0vxK&7 zCCEbW7HQ}$=iq^pBVJF0RxYE?SZdKC0)pJ21;}(3@|@iGya4>bkhRIvnWKM5cK)LpC=aNU+w$IRQ=v9>^j)d{t&+dB z1o!y6s`sEFh9a3UPL;r=xb^UBE2u!HJlR1}E3eriI+X(rBI5|w;;5`|yP=_JF{gkM zDS|&69g)2UG{=^lZ(A<7QxBZWCtXvyPmvC?m{;(DAeVk&#FHIBwuHn9{6ub)a@_c> z^^scw+A;=9dKSYZ)qP4F-XRUVV>mX^j!3e5LaW#1(M_4lZMpcQsdBz!(AZ|xi9ovF zl}rm{IKvWP37-bc!>ICX>n2DQH!>DX2my8l!bvfjA|$dOvt()s9Qhn++A%2P+H#C3 zna=4NpkRDy0y;ii@i=(ZLW5DrHaf8OjyLZ=Wnk!BBBMU>Le`&4I_2*6?pJ;LB{$r=1ZS7x+>vu_Gn|{jsB)gI zd0%V6w>9tHsyntCuC|=FJ?HDn`FE0;2LC}q;Diypn2X!;X|Luxr#bhO!nF2T8hG0^ z_`&IMzdIV?It+{4U0i5vz4Pr;OK_l8GtzeRG6RpJQScQ=mRlc>yjDnhbyu%EuuDAs zj(q4<A>AO0po>f_*Z_%}=gmb&jNp00f7I~q&bix)fwn90_PnQ6v9)QQqegUuR;=H_ zZGZ)~d^whuJW*P>3;_*6&67 zFoVL>=?kHvj-oS?i+Ngnil1Ow=sN%B5IH&Wfpo9aNQNDtT9hNuZP7gSe z7j1D;Svgae9H~BM`V#0uP#jOlZdr@X(gIR$pzjsX{4J#F<``84WS&j)oD>J%qYZA6 zZpF4!^IxO|f7Xzn81QK^(do+!b2??hn;i@Z;~6!e=_z!Qw~OB+=e2Y$K8d1~$J;@w z&}OHi?FIi1WujHK?L`kzQj$!ocjx+ENa2hqkNeYOzEnmK^SUxMC(IH)L0pSb0chA@ zQQ%b|$fX-Gr@jOZ%0O@(if-d%;ju3T`Z7TlThcNDy>IoD>x@jmF3KKY(z zdrzBqPX)%_RmR@oP=RsyzpvT1LGJ3_gGT6VE0H8|OFHr?7Y52? z%0Y}2rI@)@5HimQ4QtMWQ_-CTUt9Lld%@9Tlfh&-O$sWBtis;py1i?I>K-%UfogX9 z=sREQqq9?ZQPttdk#TUVDuVS(WGkEvS7>Dqktb5$qK{Gv%%%WFFSlgmJ+IO^+-aZg zyQ~cC5)b`KIrxfxCDio^eMCER*7*?BeDF&)`n^lvkqo3zQznq#N# zKa)?pOKJ+~fz(gQK7VG+of?b^j)drmllFfym>Tw_2R)eqccvc{At;O|Wv{B!YV>M$ z2;gVlka$;MDUn-XRP=$W_pCUyxfJf0j&&;ITQu*9sZWiK4AcZSn3G41;KvCAK9j0!aU%im8alKI$Dk9vtXO47Uqot*UKP&bhJRrE~1BBs!<#T~pDn zLa@W|wd?M7&DE|sJ5+n8GTEuvI^~HDX`)>k-yss<=)@RTb{y4${rQxK9ptAne0=AK z?pqHIX!iY6(VcnU_SD4<@rjeMw2&54?0j6>hqdUW3bB#!UQ8Q|_|oc+B_$KM8Y(s_ zzq!61U!HK zr{nbV}CZmN|VB_zH~|ggDp3=+2{SyZmGpG_cQ$QFsXZ6C~=*)Y!mx4r~wej~=$8IAwS`fpesk&47HpTYKr?S$xKkW?Dfy%k16*!+7 z+-XKdiu#*t|DP``lnIau=31+Tgd!Jj=uFKp=v%?AAZ9GFE#cOIzOtlcl+Z}5zgw_% zT}p3{BBA zL1ES%iC&Q7CJ&UH3)C^hX>fZ~iy=0MJdu5E&LAm5xC`tg2hzk;?TzKH*7dCUUJM)1 zMi}d&W`Y15aN}{%3r@)RgQU&9^+tizs_8<~s|@c?9e7i_@SCae-+$(tMO^boa$`hLoeipCGhnkuYu6Z6FpPWo~y}@oM&?`bfl#4wLxhubQsvDK`h?-2FcuXj*~+Sn#;k@i^`x+9TPTQC(}946tltP;R2_SDduz@` zE7tSgc4@3j3-sac9oAIonwk>moDy4r4$QR#Si&cT+smlXD$omK=zu{3x)rn#j3gMy zLLGI`*C$0jH{cn9tl*gd2cN%V`9Q<;-1XV7!U&a#6T0%Ds<8+M|8YG5pQA*ols~o7 znHRK{BH_@yCza7HhLbc>gPj+%&#&Ia^KAG|NW+Ovl!lq=s zIVqM`Qz%f#JOJ{Z_4TwJ9Yw#8HsWJZVN`oLql)*wFF4Pj(??wbfj~_For36v#6|Vs zY~y-r)I#9G8=MC5TT*fp;PoH1i<&-n z6Y+!BvWNd!9Xpy&cuK0($_c)jSRgz3i*HilCBpcSz|4q$j5z?-X-EjqzLXbA90iT< zy%imm5gAn-A52AdT}{wButMZ;G0RNRT0(w8K%StVM6sqMUsSXQgi+so$|~?GAR^k5 zk|!nk>6AcbJ}sv&?iuqmpIFHF^uQ&}bwGEvli>;9Hf>@v{frEert13C%!>kZ`VWi> zyh@Oio3doIghj^fWmFIw=t|g`QxGTA*Rzo&ZD(V>$@Q2~`CI`#BO6B3Y#keAR?d)T zqyG|Z>Pe%=H08uKz{ExzvXd{OVjagVwJ4qd^zRtw@!|fTTItM-f)JAJM>R*!bhIPy z*`kiWr%d)J?qgE0SB#Gc8K)q)g{(&qyn^5pM86;fB{`xfaa~Pe7|HcUB<7jk5!D_U zOFi$L7hNaHvwn{KU{nSF_H^F{*>##z6BHk+6RHG%X$A3{wumOMI)?fHvc4$v8i}M~ z75W5PGftX0Mv^Ga^Cq%PjM(C>$}~4v*ZkiCe-5*ISp;dyX8nw$Lm1z$PLfIVyl1m9 z@s4o#WohpVQ|Dj*@bWJJ{pd^S?jH#!-cd)76f^T2(O999)V}z+F-WJbrAm~@kI!2K zm@3c#4AtMxCjJ=Ryvd@`_)wt~-aQ@NQ3|yd!XM=0qebbC8nL`KSiX@Ek<@5Rat4Jl z3!O6IO!YaE7k%lWNY>@nvB>qbGO*i*D1S1d4X zpXGHo0WR&(Yg7D;?JbI0;LoQ?kdiauR?=f6$(~%uHPrE$PrTNbp@kur9mIc2k z&$Gi0Wkh6`vzf}w6ntphT;6?l^R*p}$_S5Wu0vC_GQBl>>0QZnDyM@^5vf9v@rr~R z1!(1iM{dSQ71E6KgHEA^E=Kb#YiE%*2uL`P52$afi&!v)@W&Vfl#8342w-y82a8<{*i5E7A$Nxn=`g-B?YghYzUOe-ve&j{@ z$SgDS0Ous90*`B&+PhJdU z#uB23tEtcokzL~hKbMCF0ZHwkTX2fhoC1nYJTfs~nDWQZo z;ZNf#N?@O#b4mJX18d~9mT z1g;6-BnC2L&fOU>A(y~Noks18ZHt9!1~b;cUWB5FqoP>C{7Iptrd8hsd2*-W-bRKG z0$X*@ZpC#bp9w(LqKjt|?pgxg1W9^Er_6?T(;$@zvz|~2_Y^!^#r}6h=LuPs=j}9lBv!pB)eIsH-AfMKh^bW3*cp8VmXLPhvP8EYadG}^%@NLO`LRRKyRCp=ge(g3`4PFoN2wE<_t}@iIMth?` zUZFQ2m8wp*(`Yb|Q$T(2B2Xnu8ca}Pm_)RE0^F7_64~hjG^5IvqThPcKnx`LsDWw3=L#P_Giy+kPf|;Kl%EVi$9+_|9bx9tI`Lr zh{u1gjvUNKZ07p(TSSFX(JoFC=naZ&!GI<3bweW)wc$&}@ZPC#+jJC+YM<^uj~YHF z+)w-p0zrC?jmvsHC=i<5_? z_;|T3ivcm^$W9zdANs9wq2GX1m88U?Yyo2pla5bd z_JPa5Ann#Fl~xpjx!3@R6k}97K&>?I8Pu*hAwOL}6+*?%D#3_2=}8YbQe-_fn4L&T z!R&mq@BoSoguX(m7L9EbvLV%dPIv9ed$-c5j;>bCdsL5(q5dp}mh=Wt%ImST1V-hK zW}|7*(9saAVV1DCzz7)(2XYw|47CeY3z)^IKDs)+c$oU|%GA{>#VgZ=(v(pw>4Yi0 zPy#d)@Wfq&`S42V!>dzsBKgb%nSf85n$F`(E#E#bSS}e;Q+edc)KsoI$BEc!79$qwG2I3Y1u<&^kNDm^PixR;=0&vAoJcSZO%$7KBE0AEkmnDW$0tb97 zVQwovoXTCvOH*>FB-pRWwyW~^RAzKa^h_I>t0f&38|mQ{n~IeRXl@Botv1W+8l`g+ zKy|uWP^PuS6~#R*OcYZSB{_Vhn7cY%w1fmu^vFX>5^HFbrB#)XS2lREvPM!-k*F@Q z1hX{XNYPum8%|A_c9v`+C^Y$!DY8v%#1H1oVO=L^1z}|+B7TBhA!a5l7smt<2OB)i{goQwDIGG#3B$BmT7#u^bBrU<*Ctnp!i53yq|2U#fedosrRI7PRLIi zxHdhRQ34=UA;A{PP9{Vz*`%0LVK_MLMy+EtaM9+)P*sXTNcW$SM>ZC`tyAG0>f{dD zdAJ}1r;J-#E_tJvVw$Q{R(6E5&Tuv@poytV=G1R1&<4#lpm4Co(8BFwR0P&3LqO(v zZ$7s}hY#-FVUc+!0XfQZfD1PB+ZO`o5Rh%iI>@N%9D^H7i-Fh%`&ni}Bo0XymZ?>B z0^mckf2v#rlnfT91yu<^p>X-i>C_!#x}1U&onq;vBq3o)%$=(qthy4NQo>WBb4nPy zqD+8Pl`{4zC3tXR)9A!NeRM5VAeASr2Y`6v zl;}pm_GFZos53Px?dO7go&ENk0@xVREXQ*RyXHQmj%_Y@wv_^HIZvDF+9^4YNzqY! z3sdG*-fM^@T_`Cjb>evDgMU;Gy#`WsrSDCUD)oaOiw9p9kH4)u&d>pHpQh7YOcdo< zJ~_b{RVy8&6W*h`PSD{wb3%T)KocOO9+1^oTK1>qpit4XUZYa+?NEl6F0i@mTO*?; zXxNZL#Te-*_~|rd&Av&tb?BkX`J}Uu4Iqb08e7IXPxLk}LjE_b_f$wbU#|b@|f8FMjchufFoK*-OF=ANZR-H;Ui>({H}`#V`Du zfAeo}efi~|WyNH(#MQ^A_Cjfxqdq5cpdV(u~a#zybt7BLB_y?Ix<{lnzl< zv_2(081nqpU;SkunSoB3fRx=01foT|YE{@b#-i{<2|jf8 zY;{F4@gaysNuO3D#njjpdE!IeHZ6`#365zkKAo4Rr%1iWir^Hg?uBIJ3tgQrjSR9P zAR_hh=rGcMDV-p8!g6n+47??PQI(7C8<}ZZm3x2qN=+=KTf+Gm=On}J{+8gfKGuDT|@F+ z8$2GOXlyzaof;_Gt*fShigs#P9O*RJ%9w(8i{ad+I(93*vvSHQi9xo~nU*v1X@#NdW&gb$cU!LxL^GffV#_?A&JAWcx*s6JZ3qsiPx=#a&O0tl46v78e z!PcvZ4lpXkaU>VFTY`PcK=w94%~6*)g+g%@m<^6<<>kDzVelC-*uPStFBzJ96mSAsPH(T$|5>$MHberYgxYhSwT#3 z1~4_1e`Rdsk#lFc)Zy}PWncMSpjKZya@dr7xNBilCisKZcM%DE;BSUm2qvSl_%8&6 z|LentK9+b{K#XeYV;B|BlZYlEJz!Ljb`~8K0`#V$cbzyU=_@pJ+rw!oi1w&L-vSEhG z0AkIiLCMY;Uu|{`Ud1(4?2$#&8j?xxcwQbfN+cnRAEpRrM zwB5<${}e@WN3zZ^xBR)7>+zSs!AFds=5wo=l~H}|YhML8g~FH>J*@e2%jS)yvSDX; z7kqdZ%=K9K`|UsdhWD);2!mUQ1e^>{;cB;y_jGr3cePKkX%TesJptdp-L;Dolvl?_ z*Ieo|`3inMa_$`D-&{cm=?M4fM9jPekqmJ02_M`we6_ zvEl9(kE^0G=`wX@90)KkqcY!OK2jYa<4OAyRC_s-9i;mK8uxE_pz@zf6)pF_Q(Xgetzzp`&v ze{^7494)2CyBx!1&jTowL{yW_BG?!5f9>!gs%A`~7@J+|=2oHVL;~jLm@sqlhmSnW zX$>;UlDCx>_tF=?KziSoe^e9qp82!??SFy$fBRqm*VfM6U;oCp9(?GbzxkW59zTAZ zmmnU2WA*A)ES@j?`q#fiKKJ&X{qmQ;#LE{~1UU4;f$Cyi=+#IYIs_!ITJ^{qzS-S? z<><^1om{bD3y0a`EF|g{LYYF56?j^A#p%@I?uVbEGe*)zbVMBP(Cw{P;++NWR&8>V zGPzUsoRLyaZgmWdifgCln=oRElWb6PozEQnwXpm7!r9lZT>AM({lC->y_oF&sXVYN z7qj6la~}L8F{O(|F^~@&$a^+V$95D$yFL?)3Ml3kP+OD;st2dJv?-WvYGF&Pxc&Ww zNEPi2H8*E10vIFLL;do^uAHxHD%$yBy8EMS&qu<}sc4Vk>Ct@0^~mrY(^M66nx@k9 z-$i>O7++)?r%M1Zph6b}PXFaOEbc(T(KPC@iP(%0IDp$^x{w1q92-ZfE?mt4G8b6UIJUxBsL|7GZ7pwv#V}sN7XS;R=l?*u9T_=vQ zS-*%$J8+8!W1jo)ARb2~oLHF2fSZ%5NF)eG6$*PzMOQVWg17~_k)+JmzWUYf?v7X_ zG;g`1RzR%ITPxt^n70Dpsh3{-87)^Ll}Vw??|$g)X|6coiOCw$R}UZR^t*Xpy)rt2 zWScpR4>3!pxv`Gqfh z;dgJpmr?R3&z%3#m%bbcS3Pp2*mv>#pZ(dNfll?ZsX$&>W+4K+Sm9Xc)x0RVCsGSH zuKaPcugT{ydShp+83Oo6ftlnml}tAQ&Zq!$rmwhYLPDc$@KVGG^=qDkhI2bbcCom>t|vfMs@tyQS|BP zE71$11LcegKTV)}{p-K}E8fZS-j@46^6U`kDhE66`C4)LJn7T6e{F~s9M82lmU5P$W%;8X26_eEx4e%HdE z;D#)OoHk*J5a4g&5rQ&89!E8q1a>+OG0Z#_1mkQHM5@#0e)!xOwhVlVrw1WToeeP_ zCG%H@4$d&DJYPpejH<)ud=QL;DZ22;Lub!)`8`bWQ~nknArfOIj~8Dg9N_De0mi7l zbfNbQ|4Bep4?WP;)qbTshdA>fuDqU97h?5Y{&V39F!j&B{f#1J`MRzbM+T98{+ayM z=2!5%GBbZ}*_oczWoP+bR25VPkSeelUOjM&SE1^sK$sprdwN=nm(rut!ssKXKj^Yw z>a>r*lg9&??=l}>sMgU^CpOQE+(TLODpdVCGdAv~$6t9F&By!+pea@R@Wy4fxDTfb z5wHErfBqjX9&hhEvHh-Z{C7DvapBaF|M=&BK4|lXGsdA4=l=XlUkZjo{1HCuhx9!B z@PjB;P^)V&s%yWRKLX12+kg5^bseCNrfj#9HuuqX;)*T@9EkCu`7KR+EI6Z5wG^<3 zlQo3AT2hj^*tk5}sZDI8nXkY$b?iOGzDM!(N@*A4Qbea9gAFai4vo2%!GbAWDy01C z*wNIkSCj)k{iy$!ANK!Zy7vuf?~l^^-q2jx^6~=+IwT%7bVN)j>n|Q4}{@PVX)0` z?YJ86$hkHtM9muRDeZAfwAnRzFx%h(u+Sc z!vGLPUpsOb(uhk+E;4cDb1|kIf&)Sk42Jt7Wc4jbGB_SOd)6t5{K{n;BClpY0AhwG ze;0tKxBxa|L*(m+2Kl=Hu3+GSdHA_Hs_F;bR8G;P?{hx3Vvf4uOr~*(=kK zm&J$Aodr4IZ{dl=6>cQPOdbja)F&1RA^bGkvla^bAYU(DJjZ{6)(B$qt6%*ah+bLB zu3xuyZn<;OJ8!KpUv!NMKsu^vTCEQ@`Ow+Zc98z8;AsV}kL) zv9tg2&%fmH1*;w*4dufRKh)FRiGqM9>Hs`Jw%|rEvsf2;HNVR}QJOz|)iF zzPtc}4HT+Cx}37)D3WQqET6W!2`t2@m_kBjxET>eb6!$Z5B6!!eK}8i!Ml}~qPyBb zr_|s@E$vpNh{{eQ*0pqw9~uKXb?tZM)RLOXMJA;FozjWlDF=R1JpJm2mw%Bz`HFJn zHR<%b>csI99aM5BWa{-`7NZL6(R}AV%@#f_V1iB7*|aihSD92*EP3Ku$}4mARe+?# zjD;B$p5oQmFmBM|7b+xGs#redGGb$TXh8RTpigefd$tt(U{{^G=ZFy-Er^jjK&rr* zK&n8V>|{$_NMxj(u4$SYO^Km|7*3KQP|G7rxK3cKh>C%lmd}aY*d974PTc2VRJ=HJ z3)i`~xR8TC$k58Zi*UmS{t#N#T!*9D6OVHNY{rJWCTZh|!IcM|*9Wk?g$qkFLipfn zc?)P(M3caZE+iuzJ{M;dpbngSfl+n&JzqV1NMx&?BdYY*hYsNilEJ5(_>5s#mB2i} zqD(c?HD1jFkWZ!f*urpPHjzjGjOtR~1xQ@Ht~6!zUZiz4@bB*Kn77<{J(;&wm@itW z0`zouap?~J)SHU24-uK60or%Q=^%)dIV;MTR`C%ci&h;K$3ov5(MT6)!pxj%N`x-? zYRTw!jX!ka;8b?>Lv7-UG+s)LO>6NUpPOx)n27t!H{1b(ow zsi2|`h?Wvd5NYUfENtm|fKi~rOpgK(bxcx{L0Sk)M9U=T4H~+ng)d4`3`4xBle^Wi z_e()C>ON%^!asA7z29~f1^w>2Nwt$I#>`Yn7~z;|8o4G^efj8x5<6o#8| zdeT=R3@251gmdxgipl{7rl|3(5)za!BULE(8zw+ghD;~b1bU^RZF$f3smS)6Ym;W* zuDT8z(Gfa#;f`!mkQ61H5}o0!E1VT2MN`STdLS;0`O@H6r92t3vOKbc8v^U}h<|H( z8k~N9Muq+n@()+IIio_4|K0C=2R{KYE#61NA0t%ULdOcXx%R>YLULLLH?EweRRl>-NG<+2U_)$)}Gvx@?M5Ds`k9P(FlPlSih zcTb)~3;@I=_e4kzxaTq|JZmnCG2;QuS6ki!`3mv`8UaRiJ{bn!7|SL=9bOq5K}fKQ zS4M}wbMgeplTt8Nuw>vV_~R4QLXOi8?lbq*rURbU$>2c2Rj3c`nTPO>McHDhzFsEF zOJGr7{Nfj0dF3Uz7bu1jF6;>w41SJN** z(xMS@(w7(OK|M5hXAEi- z*xX+*A%IauQesvl%bzi3ULl+m;a)ng<`%(5lKjLGvcWq)qhg&kO$5Nr85MlchjLBB z@nc8fMxT4|zs91Xt+YGny=tKaPW`-j}73I4r20nEDCpZ+TfVWr~vaV)jJ9o zdJAV%AyxR&{=Ixr`AZ{%EMzAb6@>(K(3H8!7|y2g6A_wby5@bg`7Lnc%JYOLiG1cL zli)^aqKx?8zyEjtj?dHaTXV~OcxV7WQJ{xDI578ab8{%`=n zxaBQ?@Aa!_q{vM9=1uQ&%Wa@jf|vr`?CI|0S%>UJ8$@_qEsW~Y`I8a%&{w|vAHVp8 z|Ig;PU%Tt;UrYH0GU>#T6DR-tOT?&7o;m-mZ_V0}%QTU>7hn1@V*bJxzVOqRUijv> zzJBJyaev797hn0mk%qp$^NdwnUu`lf07Myg`5!0EG~&mw8?tA<84U<6GO0lOvtsie zhI5^OID{;e%N7}EL5x8M=3Mu1ABi-if)F&KgPLote$%~VT3;yg#TK3ai^G(gukx_LqqWR7#w(h*Q9i$4}-EehiosxFAJK<-K@wzv6~v z-jpttq=Y(rAhY*%_3+DuQ!ih=^k(twYuQ~t5>CCNy3c(Y)__BzE6$_JMC+AAS1Gbn z8t>5~! zM}8(B`(^g*`?~KkS$(|C()8LWscF@HMxE@slISUhI>n(@J@jdrk-Sk%F)b94Dz;1* zbpw?RKHyb(L&_PVuFZd9J!e-YwGxzQQu2G#L$<{E$>arZW+)|j1tln|VNr`nT2$6z ziWb+jq|Q`asDU{{DCFc4_|tsMn=EvQVcma0bMDD|+e^Xi)3F_SPpdkyP4gTvB146Y zpKO)g&YGZUs*9QZ1yS&Ci@l5vwq-*6ydC|0D<{8;*4(y`^(TxXe6Rs$iY*eQEdC2mMJ z$*9t_5-%ogSLMl%blVkqyqFo&5)(o?l9Y0?UdR`a7}B5Ny+%<2i&Be3o0LM@q*Eqv z7ygBkdP6yE=~?ClU(2FuDT_$EX}A{~Y<8;MDAc!y!%`eC{&=iV$1y{otm>(TL| zl9;B2=Zj3IfRZj2G6CWA`N?JzuUD6%< zrei$?Z<}y=gXZtGg!yctL`bJDsLW#*jWeohpNt#~WXJ5u z-igFH@G58Ok}G`~@MH#j*`YvYG?W>SXY5JAost3>IgH0Ehuh50il%Zh>X;E7l16tJ z&TSuMx2K+8>F*Q#TVhm8e@lN$e@lN$e@lN$e@lP2`ZvR< znwnNLHLc`mTo9|uXkOJsSk2LRU04G&RKS0lK9!#}v(R!4)LPKMP~Tiz*IZlMR9n+j zyQZ;bbz{w{hMJWPH7n|Cme+aN*NG<=8&6yVHFHrn z7mv??!aP}9_f&1&Gj(;#>g$)+*RN=(U)5N@rm3N(slK+kzOK0esAs5chGzqAt!}Je z*+78-JoRi{{nNE|h^H!M!eh6NH8+e$?-YJm<+vHFo(GTIW;}e`V0qCJK0UD1G2qeF zb&s#9d#1L2MLpVhW5e2}3L2Z%H8rnqYFXdZysoJUKTY5#^JyfIn>h&d2%(V!&#omj zuYHbS{w&A2j$$*PZCKk--%>_h1?YBw8iqB^^{boe060u=e~S;mAFKmf0E)ArrJ->x zfxn0%FQdK&s6061W{x#YGcR4u+^ZVtXW6ri$|JLZm;of99&cpt<$xQWHO=M65e7a@ zEN$f!;wi+y?yhdETiIB*qM>$qL+!G96LrrLAgXGgHZe!y0Pr;Zxf^ng17Z$9Y=|6h zp_DY&)iu}Q?Tu^eo64wbe|brz$VLx8GbG9D{9AF5(S)+{Td zOoKRTo2tM|rP{~ztcF>Z4OHHB_046VW}rr{ZmeC^Ks9E0eeJWHDqRN$vJjUWg_Ycx zn8k0d1@IdN;vx%kpj(2KuUsD@tj1bCVOfsp{D3Xvdki(s1z z3n`hws@Yh`|Ksq`5~^UyoX-lb^AoCrQOHVdd1O^B@WWL#kFKhHe0A+JwcrGebuFMx zpgS$=zgjU^e|omvSk4=h6)qnRHl)hA~x1ip;L(8g7we0JokJHu5g<) z3lDO3#TganJyqfp zGTj~_}_>Y5pcyC({P}Rw@sDPQ6tL|0;pg&@ciVuPzJxJk-Mi42`sk*1@NR5Xt zeFETR#Ip#*s7k5<7QuG=@F2&^C42_(Pz4tMk3(%0X8g_AOrYYSDq_q)4U>-t*3>;+ z3yD~6iEEnBF3Rl)WC#ofS86G!{7v<1ASuhjvP?U0i|ACD=rq>15LkGov8FD!0bMSD zN9d`h`ZDoi4>qkOO%*uPb3ZDRCkssV6?ogcjIFAH!(GMlj3{?WS zPwiT2_#h~ZJY5SjRH+J8kz2u&%Hpr~obfOBS`5_`s_fvAGt7QzMO6j|M^oLZ1wbKL z7|zD3!>??t1n@b1yvfjN&qLzsc#LVE|u(qNG zTQ^I}S5VhvAp@K$RPivNe)dnG(ZbKTPZdmB1~gY-`B{yYwS=|6x(fKu3UC)}3;-?T zjBN%jGnlQTnx72Kpxy-kNb=-VX%0`SWEmXD({k4H;Q|^nF(IzuBvK4M1nx}qnNj9v zY8k+tX-=wgi#Su2kgH-s6}nUHGfVe#i?9-%g<)!RIM-PSoS=LxEVRZ1zl+yBUPG!8 z@Eh|d+#otkchbN>suZqnS;jzfb`2P>P@h``#&sIY6sM*_YwFiFm9egI9+W$UD$MRL zIN;A)tQlrjFm%(EK6G}MIzP&f%m*4eQI94%`qk%xmiTW9=sB*7v z012azxFT|(9CJlw#U1eBDlT$Yewr|KU=~!z!#fH%Se(>~=|v!g9F_3glRr`pj7TcI zQ{7s0V!ZPygDH4sFym>m7I-qIW!_>P*NjgU<}w~mN6Lxk`2)a{vDH~V6rKi_Wm-eU zQSs#Qn4eGS=P_4UELXpok(fWrJ`D7er4XokwKW(IX*%Y;3lOz3-OUi?yp-umjtcnC zg+SlJN3eX9%ZAhCfp=5G^2YjQjrGqq)IVKc|5Sb5lMHY?(?I?!SpMLPxTIiYjz|S( zb>+ETs@{~;nr32S7Iwvn4Wm;;;7l}gtSzHuHpr8aEzZMcu`#eK2GifvH_c*H^(~~( ztJdk2sS-`ER!_JxtZU$4lflR}%5JJC5YLP!fe(QIRVjz&;XU(#2b+O~-&_Nn)>OOa zK^3!^7yNO0HBq>COfGH1aq0JG!Rp{HW0=dl2aUp73j{Gf`@2LQzKB@3^qXh zW8=D}3dJdddJ~NE=7Y&~OjLLVxp{*p&q~)*zYcCzBN^9W0eDwJpq~~FQ~?iM30aPr zhp!G}x~~oX7CtbVjjEV=$}5?`@}a4LrVoH-pkZxuO>@)AhK6TRaNw6~>YrFs|HD;v z4_Aiuvq?;~GQbLp470)__Nu_Si-~L8x&!#Z9mDd^GA!T1V9CkP3d%KYdCddFx@s{_ z_#snbaXh-3rULnFAlxQ?NV9}Ba6HEF_!`pIKUGur4AXd_O#!vdP3VrOM`CDN+uVrO zNAAY@=EmBlhMGo*{04Gx4Hl$0+AN42q(h~_a-zUmZX=p)(|VeS1o*0~7Ul-ft|?mL zPqfktFJgh4Tb^raS>M9La5Sys;GF=i^y1Gl%^coEk?@X!$G{#TH}#gR7cD1@DZ@zc zGtOkP3R79dVey}FGctr{5fviGTUtmVM@gmEu_b7HY84I+N<$@2=%tLZK!C1d(`_6y z<3|4F-p>k?Em{04;JIyr$W57i@Br1ltJ&GI{=7_~%6B;vs`jal7N{mq02MBSxf-vT z6qB?Fj{;N?eGUp)nQ`Vk$wYO6Ii01+gxTP;5Dcc+B5?f~pJ3(sv+`#)*VVRg%nDGA zS?ZzLJgnk5zxrtwqvGq-W|$KrOwDEHRQYBmwo(7^0TBP-2c$P5=2QkTCkD8mswGnO z3s>8DfSjtmgJa;fmg&z4p*A`OaKlu5{k1r+KMNC zZ>338fu#h&C|b^?Di2nkDiffp0IZkcp4?|P>Zm4^129x>RXtdtN)^XKm>Zyy9=wG| z3-V;5o}mt0b8XX_mc|v04Mg8-Y9Ctz5mNi`%G!rGF(Ls|2i#wVRRY}{Na$Lm@+XS# z&!A=r*TkL4C9^m_8Ca?Z$Ngp0{9t(vu5ef1t$K>zt$A>H&BH5d9$#I%qM@<2rKNst zO9MkAxD*XwTABdjH*^K9;iDR$!gAP8Mu`|VB67p#4GBzt22Z-nP!X<-YB09J9hEpi zO)4mR!eN5_Y<{j~?T^;2dtu$WAFW&aqqQy1uf-K$kCdY|2~G1l;%603#y!oHmlMEx zU;_FgQWlhTLQHsbslfy}TdTmiBLagxw5)x8Ez+ ziWt~7AbJtKixE>kmZl73dC0-Di$nnDtkq#=!&KJ+Ok}XmnM6-jm`Z?IAsP7HvU@hj zlSO5D)&d@k$**#Tez0fzg zU^StEfV7tRpjn>)yntmKecMdz)u?Fd%F4QrMR_a4Z19Y`HmHoNQ7O^u#Deiuuuy<< z?O|>v{%2r5QU-FVQVBTN<7~LoL_-sr>Sm*pN`&PSVPJu0bB?mRDgoCGDsEQdv;Ak{ zsgR`E;CIW(D2FVA`IPHox$>EJNgvi&zn;aw+?(;GpSicU8!Gy_jIRB{7AkI!^coO4G zWst&YEvdN5^rh?|PR8|K2az7SOQ^i1np%}nm5g!%h{u2-RY2^ji4DtXVgY>=qj%4*#d{GRK6GtvtZA$# zHd$ds@FBv)9;t6B=MOj;C>m#MG&RAxeac%llH^nmsLCh;bAyqTe{vt>JS!B|Nme8X z#5%-;DZ9DnLcmk()n%qjY2XpgLHR|qeafthgk8m_0{lczZl=~$*_3EP@uQaKezX=q z--k{LBhmV`&1;&QRy8#(YiN9`w&Bs$bq_OL6d!y8WhugCgNcf0SqO8)%njpv)p)kb zF%Q-N_pEODrtXQlhAM7R=29F?SH!wF*2_^x$Au!u1iJU;hWe&@ zprN_Gv8ADDZDTV~H4Db4{LuEZYy*8?pr>qv!zpUelh%1me->kT+VssQxG#M+kU z%Ot59Wt#OIn>wsKNKsYT)pIYbe~$E9%pZ3V3|~r&s?1$D@a+@>(=Cz6FRP1)Hi1ro z2BA0OnzM#=&G4kjlk!XpgfY5e^mRm=;FzIJW#&Zw=pOMPxC?&5lh_sd{K}*X>+Q|% zy-Yg*B&?~5PVqFeb!H3*!}t)TYCSp7$v^t!&z_^*9sd z{B;a0ZQKV0^fC6v?=H?8zk{eAf9i2Yn`WpRV9G@Bo=2a2Z1KMFJ9po64>FBN6_rRu zMzf!IBlnrbs5qbaSS-ksZV*-hk6bVrzyjb8mVfdbtn#0Aw*ux_E>vrPO75Fre1&KY zbC@s}GtT%U?>Lz)!^~V(@9A!3M!dWYl`SE}D_EL&`{8foPw~hJ<;0lehJLdA;h$3` zB@_dDyb5c}ScBv-5CLj#SlPt(uQk#VE?VHvP_@Rt?r}C*_9&Y#BjMO}g zshD~iLY4leJc)o2?L#YQP)i%O*VH~$TfeLx91Bgixqe+s!#a>5jo1Uy~_~Gh0yy6F({V;)nAvGIb&u|(O z3$mGO+`2K8MU+MUeFAu97Veo1%iSA-C8{NS2Jq~fyPqLY38H>JL%5Hy`UlUhd1MtD ze$$HPmSv62Pt`R%PJ3u*1r^#XfX4eEo9RO<(@6t{~Xr< zajw86v^iv|pyEdVhK>#lpsBtNT&lUD0cfE;+9nv&!Yu@-Ll`nB#eNcqdr_FCmPU?7 z{H(zAuQr&2TVH5~Eh@*1tfc ziYu--(}F(&5MSg3g@f@$rXFKCz<3Y$#9cvz7KvQWnn?}^O4DgS;@4n~n{{A2S=4*fZ z|NQ0OED8`6BE0*ayFuny4wShRkwubvjo-aZZ@l|%^IZh?b(~<``@MVazW?u^uDSQ; z|Gaj4_dgGe9De(q*G5N9O^lsBezfh(nfC78|NOHzmesv*|4)DQ?AjL}{?*%!FZ}$e z`k#D%&HB5WUijWiZ#;hYLx1tDhraUQivRvp)3<(D`}a@OeftML{N_FP-c5PVQDG5O z7OdcIiBZjm3OQvczx5j6EP+SM9%1=nCX_QRlZecZa#mKr$qKIXd9sf$Q=b_U1Aqf@ zu%8r+vl;H@br<=?!&Gyr@>A6hR>6`IxY0rgm8OC?SFug|rm+yd+Kd*N(Z)1dA+&;- zCwP|GKmwj-3)DCndW?08kF2hJXccY$0UlUcbN>pasv*V98dAV8H)lU(mCOz5Y!>pr zG4P>t<>wrZVnNlwnqav*7qi08;vCn;9U%~RKW$>Q>9&Nq6_|1UDFHcohha&;wQ$b@ zsE+WvPp|qeuFt^1v8Ec92pMLcWmt93)2r@%dewc;5FT6(&P1!rL6y)sJdMtTZI!}M zYI$SbipDw!<9a5xxr9a+M7<&{Mr;Pwv^1?~YJ9rB9x*(yeD!_LuDbUbU^UtZwJFwS zA6mKQhpTEZUcz{6c_RjFO||S$`btE(3FRDf@B4ieoY8uJG4M4yjsVWO&bI%82I-+y2hX>({AeuzV#F0ZW`ACOief_wSr1Q|D(d<9+mWp%5-oreO38g z9K^#+nnju_Q)-mO5XQ`Gu+4eZjGQW?tjC%yceqalk3IP~xQKP76 z8bSW;k3aRq?Rz64H^0;bzVY#A?%R3b_xlgM_ri~#-L~~ty=Qk%j-5Y#WOskxvBCZ$ zhYz=I*!+6Kj~@B{(_dS@_TER=eEqT7Z!CZQzGv6n{p{LruX*mCrXT-c?Msh5y5{d6 zSoyclK7a3{P2ard>A(8cL;vZnd%s3+WI2hfCLqt5CI$7!%BZeEk1Sy6E|a18V166@ zM3dl-Sus!~Wq$_q5fj#1vywCujDt748I-@a3gpj&v04c5T3B|o9H|2LnW?Ni7*Kvi zC3!qOja8^lAxra2`$6wh+d`e%>LyU7`e#6l*3|rP)tZM_u6bz18gz>QhKa!a%LqTH zU^biK>KPN&w{93Sq2+P|!EMY9L1pf5HlKzi{F2V3=>r&i%=;_j!)Jn7!22%t*$KfC&& zl#-!*Dq_Jaoy9kHRzWfS+V+oXII|$)QbC_UisZ8R^R>PD&U@{R(+4rxbHu^ z@}U*0pQ&$Hv$myneM`f0Ya5?mi^PDmp?gHv2T@82k`|zWT?q{!AH->h;xL<7wW}Lz zapkCKtf^_>s3njOyVX#;x}la%zo@4(Fjh6xa$8D#yv@J{-ZR}hhz?^>#LpN>Vt^Y@ z;aLtA!^~3ve8^A}R>RPgpbMA5)1Dr6$Z`RMk9ygB9~^kU!CgD$FYWIX}x`s$s^)>eI|m zj)elxy~R=89yp_~fPAWRxf=BSa}qWSET`b0&*2H+ZU)Ajc!S|hg$LjtI~V07VW_dD zxx6v$vDGzTQ4cI%bN})+KOkii>60vkrmWYQ57lI4QD9{@b1{d|Tmu&Ra`PyU>`hpu z{>NfQ$dLfMjrh*ZV&O;55)==|oJp&vKU{`gIude&y${LLK?q9YVbn4!xSKjl~3IZHY7pf$*NshSG%&F z+-sPbhMJ~EfZKGaUt69~gM%$mqJb+@|8NGw6g*X1Ur!^SFe#%6)Z10M*G$J=Bg2v~-iNTB+bD~maVx_znhd6PC zc$EcHm4k^MhH`lJNOO7JSXn;=(8?-isDfzsx~A`Z=erhOvWWQ3cfU(-VJ`yM>}oSS zEy1d>yr%x_=$P{V{=f6Wl}dwJfp1x!GJ(%QZtx7JJZJL#+u!-__~@~rp#!hIS^J0g zUvK_d-2=-Wd1&S1|L}vm>VMYsU%vTY|I^pM^0z=w5)5g=%`pZEd<^^D{2^CR29tJoeLgq8TeU&H5f-ZUwEaQi*m3^_RaVJmZ)&o zd@qG8bE!&m;#Hr4F()3l;=_Jce|0(9N`wUVlP80hA_FO7X*#c^adk6oKznv(16s|4 zE7tsA`Re=7B`sU?y)v$g8(GQCwK0d^TpLyrb3IsKBIDLEivV#{5e^IH$TPr{f?Tl8 zhUM-xV0my3zJ0SO$1vwzmS9WxRN=1c!?&N9g}XimEAM)e@a-p7eEW&z-+5vgaL-fA z?q9az(beEpb*q|blQlXMbSda+&;_Bh#T8tnrjd>=t*4{e>Ka?Py_>SJ8^Zd=7GhdW zYo7x|SKeBrR8cWhWGp)U>L( zX<1|AlXdlvtgbzV*KH%8gQ&9){u5>SzZ0A z#zugaG1S*DucH$N@pE-k)3Um{CswU_Vm0B(Dm(?Osd;8i&9d6s6?Jv18$hI*>YAGx zTAEFeH3u*%@Tz9oJy*R2&jcquT$8kt9rL=Xp=LFylt_ui9ZZ@~o*)N!7_P*^-4*p~ zmesBX@HoPdI9N|B#z_sESD7Ugb$-uj8~b`sw~tMLBC=mAA;LTT~^_-kqV4z1beYN0ZSRFO?A21c+Lv*EbwuDdLx>GWoznyYw#OHPPLRRCWC{stA*Zp_xJDTTq>T=Dl-`tAaZ0*StwI8q3nWZ-=%#=j%<4Ql@&dE-u~sk{A6YG(~mrR-`x-V?LXY} zU+?+h*B)5*cfZ;6+;^Y;FRNd?=X)#v>O0T=)!k431q0#Zqz4KIBEbDZE9H)i-tkH0IPPa0nC0Kz1?)1 zKD?ImFPa+w;BT*rhth0%R_Z!{mOy$YK4-VGk!)x!W6PV+Up&c%agUNc$=U~3)ZV|W z=KC|6Bt8XJb8p#Ep-OD&D90kOoa@IelcDP;J=ee-G6Yz8h6#&=yTh;uPJ&fBehe%T zax4(x%3DBnJa+(=w|`>z)~5uI&ql@no7Vvra>chEU;eGfmw{k?_sJFaKE3k$&#tPJ9O2&;d%V)f%IS3kMB=9!w><#p&G>(?})OJvJ>%9BvFtJxv(tD96X*4*{vYL2o7?unJ(d1A%g_!gQv zT=9daS3IUuTfkHWMn@QkEYc!Z$_*|=m>j8v4{nuve$FpxfKB={@G5g6ay4UJ9B{)E zae~~CHt2cM29+OYB#ga<=UWZ3ae4ik<#oVnJd2?_hy_><7*BZzsVIvaNsAn4*v<> zQyr`th22V zA2)%>@lkjS-ql=D&cU;7$8U}u+wzNF)V{aj#jV?a_0Fc(fBoC%e))^qAN}};KYR7@ zXV?7C<;{P;{^$4KxAOn{jVHeHP{TJKYrg9r9{h{1e)s?Q+TH)h-+bra-T&<0Jlgop z`&R#t@2&jXuYLc|?|$kppJ=-4$+h2J@ss-yIrsq4;%cxWo5iS55}bCJMO#IQW(vmY zNi$ze%g4Yc@6EuL@cfaAd*(%)>u~UT!z&60r|tYoVX7Xq#B&Ys`ZrSx8Td~YfapJ; zm0Q&`b5IGb{$4}pXFa^C_Wl($-)Gy2?=vaUY<#Su$jWSP4m0{8E77@r+%zS+76+=L zK^E$8i&7>4BUXIk_{QTa7XWT8 z4(LUXmGP~|RuUdv0o?W2@^3%3{5y{?zx#=0_dUJ*fn_TmUA6kDx|(H;bt{|eSFZ)? zR<+bJ)T~}xTeGgNc3nNLYg+17HP^0es#ystK&V^Ej34sd!OzsyJh6He07?XW`|;%j zQm3uB>+v$^C$5hpz{r`b2QvMMi%5(K{Jc&^#lMd0 z!{~G7<8Yi#^&CC|wsi3P1(QwzCZhsCw#?Uo)q!AvTJc*Z5V<+MNK=i>yahbBZU3j= z{JLd*%R`$s{Oq^CZLVv$uV(e#zj}T3uijYxv!6Wp!cTs%qTzo&xZ=Owzxpr#=KlZi z^~e9~-#zl5{_D5@_pjaie}3n&|KFMyzSsD(`x{<-;Hj2x1K)Y_zdqLV&HGk-b6LG-8$UNy^= zk2{#EjD@VQB92OIaF{UTCpwP=;7TA>6M+%0^3S@p<%Quyo4BEEva((C08PmeVVcE_ z=CC3QtaQhMr&n`W2+ghICMeOhn9y8QxRD79%b6E*c#oCA+$gN#d|u2E-V0%lBwj?A z!qwt`ZJ1BpG;T1q$5wn}VUz{7<&m2Pi_P+iKUsWzj?Xt9TRsbqE(kn34<0RpKmJXI zZ#}l`uE&;r`|)MpePa3do?dbPvQ-bST!S&;Q+4&v)HmSz1er>yd2}_fhFxoZxVq*M zwln6z6>A;mCLdUiqN#CxoI^Cbr|Jh?24(EIJM&1I}j9F zx!+JzCShc7n9t3DT5-UQ2f4Zn4!pPVIZ7nk6-X0&NMt#MND`A-M19CjKjB$P41EIm zR{`=4f{dwKh+y$g;K7*0r2L_ue4`?dwgQr#?7MhYz(HTfG;??z?(+Pc%WvkQ`_N%d zp612185Q2nK_r;%0I<9ftLF;B%l{ z9SF~tUtUwY`o15pfBda~UjK)GS@+I6FMwVB^ts1>^Yb+?{`jF+UwO1)-QAC_`MYH= zeE;ts`_B*5f8&2V@}Iu>#DDqz%CA1v{PnsY-}`L+-#xnWtIJxx^+f$Y{9yTC-}~%; z``)s@TK4=s_b>nNh#VDl24!6-@v8Y46<8jj%!fGjD-%GDO0Y`E3g|9*Qo&ca8-o1&71kjKwCv-SynB_U@|0toBgO*`#@DD)U`CB(XMKw3473{r)p@Y%p+`N z<@dpvo>@&BgF%U&ox_2yja$KK!8O`r#0p!TnGN)`e1qLW5H<|r(7mW zt428tF|$hX@!A6Xa2alWi?m`ZzKM`OT!t&S6adFJ9tD8|@mlfVikheDnpQNeUBir5 z)j#)K<8#k7J-5E;xpfWeT0o)JG&a;QtZt}ZSzo`rw(gml+GlI)Rx~!PZfU7myS8>6 z9$Z_$zNH>?gb|m<=Ng-y$G{jA2jZD)n3z7PVGZe%m{w_J!o zYiq1oLmYz9h_&@#SDcm+M?uU)xrp45)F<*$&xj60BV<24LQIQsEcn2mJpxL^BB9kw zeAW;04nud+9sv!cyCSZJkem!rfN~fJDb9qfT!#o5<7D`0zLceTh9s56Vnuhrm%+iG z#3D)CiecpEX{8i?GO$g) z^l)#!TL1csYhHd~+1~EoZ+`!k-~Lm}i!VO=`s=HH_s>mlzW&s&f3xCeZ#?mA^LOuG z^UZHP{nf8M_!nP&@XLSoga7N{`u}|~4 z3kgi$T~%H8ePm|k9jD)?-S>U_8Al#fUDfAI_jLDk&pj9naV`b`xc~tS$Q7ZG0G1CF zKnU3<%csH>@|shNA0e&VNUYPDptH-6Ny z$6Gb+?XG*RYhRmvrl9hCKFZkR9dzC$_?p&?swz(#9<#8S<)kyPaI6aCHz(x*sn2rN zuhp>}e#q*iG-$Xg%z{sgI+tNE>{>j;!4+ycN~hy^GV+VuPBT4D0trq9iZ zqD0s-C88DZP97Y);zXh=%Mj;$AF5E1ne1iBi@&rnikg2B%VkS2Me zVk`;(k737R%cY7Giuuh-eex;PiW?OyXK^h{VgP_R2yw8Ebh)QaA2xdCZrbV2>}veB~`byV!_i#c#^Ma-OJD z;H*jF0G0FD9vKFcW5{Cpj6+3V)c`R<`g=e9+3) ze<3}5iP&Z43G5Y1t6&l@OeJZW9=+0XS#pujiZKscM4sp$A^tUb8UB^h5|;|C_8ayc zdX%?e&*jWz;8RmC}nit(J4zs80MmDx}t zu;D{xo~au>LldfW9v7n04-u74>xxwR#a}lntu0e2`Lqmwy|{Hn%u7-^yiBF!CYACF zDi>0va@(Io=^J1C^0`QHm%7imJ2dVN^ew^I5zU6`^zA?n576m<7Z~XAJ4l3tPvxvH}@L2hba3dHJPxGl! zt6iMRs2_lG{V)H=zh8aCUNm6!k^F|{QNdf->hLh~5gFB|$M#RYQ~dNh#ZSJM|MBlX z{>T61_x-%4C3o)kUTEuY4&4vB=KK4@xBAA-o_X`y-V3|JyM6ag@^Co%WH|p!m_wu< z_riSplOGz+cqe|??YY;L_+H0gXC#**7l%92vwpZz65{oFR9upl(!*@&jGSUNK1p*( zv*^W;d>6`-2~ntt>k%EkWRXKKT`MuBx0KLxAN23grWdy*q8IjTzh%&}a?qyz#Zq`x z%egF9P$Eu6fX=7nMkjuAS*i|HX2XFt*-#>|VM1k|+KSdqs46#4q-r)5PW#7j5~e(-q6?<&0X1QYHrU8hE6E?^rW-og@WS`ZFgWff(=#jwIGB=8Bqvl^73@C zD(Q3-6d7`muZJk(+X);3eK7ok{*Xq$u!{OX7bw8947y-TPvIqj8~YADOc%gcxImCF zEuACg=EUr(nCD|!i>rV<(JqQPEk^o~2u2ZwxQY;oXp&HT>ma9+V@O^cvyx1?QV15R zTG zkLg9k!fa?WE~I=$9LS#>1b_PXXtw)m7iZI`>@dL@_gfwQ5ea-;ogI}ghrb92cgSXL zJv`9A_t5$6&%%SW^S#gPKl$sAKL4>h@IKT=_dCIjwtFL*cZ0b8r+@hAKmVtH^x5}< z$Det}kDY8H=>E?1k$CWJ!O6F@=x+R=lYctQKNE)0?LlxeIG|_!SoD#gNEI9YqeuTL z&-#%JG1e`I{E6GrXf|Oiic$W2LeM0{#Zg?dxHj=X7az{!*0tC>fpU$B=_HveSNi#a7BPN+0dXe8%hK!-g80LLr0vd{eY_Utk`g!i?g9bV8evU zEUoC-h|z}hT#Bj^Rai5jv$&EQZ72(j>VStT(>w-{!wyNa9R4Ta|s}8l2|DPlu z6UNih|8?g^nSpVA9po@f4&9Uff}1M_){;_Y|K!)Q{J|KUTcGsIyxZ4_o_?>dZx4-K z(QGJo*YJi;fIoD-qKK!{;_zVh@Ob+0X!_uAdVDxJnvV}>qr+J-pC*%0kf%-(8G)}j zjv2syU;r7dy*Vk^Q`P8!U@{zzr!G~BT%V+R>R)!M%aL(fJMX{40fRoqGP>pZxBlKmEf`{^39T*(cxjzW;-K zGFS4+Fdnr;<9alyg$MQH-_*O#hi&_VzJIN2f9OtjQ8|o?8UI46=nnw$?DbKp|kQZ*6n^CF;iReasJ8YXig`MC`Ty!*V zhq2AzX--*&I2G5q6c>pbRb^RDElPFJCHc2>iMDIHa5$^QjdQxvScB-D_Dv*P&OW^OubV zMNUgb;s5#b2~=rvG@BjI4<8*KJwAHy$??Na8J`?64j()|JbrX=^l*OoV0Lgk9Zm8m z4gEL>lQ2r7(X=>zaPaW)@q@=l$BzzYM^pM6ds>X= zr`c#ubB1WD6N}}*3CJFbh;(EWL3C(p6bpp#kP>;%7~Oe9_QRBj6HOL-AvZV#Bs20P zRJE|EJO~PM6qHFP3G`@mkWUUrlcN#RBvM5bL)sux) z8!I&d+58X^b7d-#Dpbw|jvS6ZXjyVN6owo9lYj9qxm4lsD;O0L|I7dJ?@^3@MCD|V zELO)76wgEEkAHsfn?K5b{)^dX-?4*yZ?FG~m+z$0=1%+7hWOs&@4Mr<@cF0S_a1uR zee7jP=fQ#gli!|y_dCghN7lo~mLJtr?{*(9Wxm&SKkRuQ*44L~>RWEHg~}m06e(om zn=>p z$;DYX$3`c_+3cmtIagp+^I25NKQk8H{7DynC06zPI#6lb=~M;fvUH6S8+)G#sJ5$L zTZd;>sT|ldHo4I=IUh4B_v+&X+7cBouQKjS=B`3s)i8WLimjAh*q0s5Mo06>gM-QO zJe!Rc&%hZx>7Kb{^wm>)kp07nnz2S>BRquJ4eg9i@}A3Qt)#}5yW9uUWmAW}z% z4-aO?v&rFvds0r*#@D2 z5w7KgmESxMP`R7Z;{rTd##x;as`S79`~MTbkoXk%zxPl7S!GJrSw@AD04{~}|NbBU zW7(+8$khTz^=+U9Ha;SA{;3g-+u!+7lppr`#z&8T>;y&aH-D5JJ=Q+^e(*2wmY8BR`` zn@OfesS+fD8~5z6W%zY6Cy&fYad)`KEVb!OE@?$8*7T^%>29>)K$|=x^*NuC7*#Fj zQf%1ILUBqt7vWio5m*VJR%&@gQ%Y!0qEenyDf3L}=xbE=o=&-K3zpYj7Qr&B0wtEWZu#9= zMAy9D(XV&3n?3E$K))~OJCadT%&uvRu4lxM70AtabU2wD&t}jmNY$gmBPbLSBv{1! zXf~n0$w#9pJBH&hc$^;=*+G`f(|DFd(-;c1B1E0Dgkn*%B%b2H5H4lL4iTZ#CG6PoGA}3sw4s=1 zlfz;Jy_-U(NTed&~c#zcTK3UcKLabzgjE z@<4j%aM%-_5`CS^VJ0n$L`1{QT2{ z2YNW!7u_2}?}nD$*Yo>UzKxIkjC8If;5cc(-(0k2RPkgIjK*Fuva{TXGg^kgrB~7M zS7X*RXHTWYa~DhKGHqh4UShT8IxG7*i&e=J)_rJ`Qs}76nR-+anoIHY-g7}t;zOIP z3()CKQ_jCE<$6kNIMAtV$WVn1#W|JpLPVrNt1>GtF?zLTOJ&yGXw{=!oinb#78A|Ezf4^*?7i+DDg0y#SR%o&#N?dO4Ry|EOaSUE^BUyhd9mB*dK;4n_mTn7PU?z#1XTgXjNR19A^9QrThx6k{2Q&!yV0LgcnIDd^Jv^Eo z9?v*OEV6~|{AfCvkLk^Hhm+|MgGe+9u7BSTMsQKbz^waJcWFuP$jq#4Cw&o0aJmOgz-3pNFfmsL5P!P zo|n1+iI8blHjQ&SFwLe3KEl0VNG`Mq&XoIM&dP8VgP%=est~4#s+dbbt&k3~1;~Lv zt+DVhN>lla>Wm5)Rg{1+K`o>}7xcyF@V22<*WbDG<*&c_{}>;s)2Z_4p_|0rpZ@m2AN<}YfBtuW`lIiUe*WX5-}&+J zpZwwHzyFKJ-~V3r-~P9M^YhO~-~ayMcfOPU;5S3b`q+rKj(%u=`jhap-$@?*mWRr@ zKS89x>ZDG#Zd5$B#HrZN5@-`cUW0U};znRyhRU32Lf{LD6>*+PxM)RHhRUpo(OInG zOy_wIx0!OzIh5?@d^TjL!ny-pjZ-zKDmsixnX{-Iwcwd}Qb~G1NfF9a`XNrG45w1& zJg8Hwbd$dVDk|_~K3pU!_57M}(#|LHVO!e(na`U`o{rt{Q>k3elFAJ^5BkNP#K{(X z)B)N@ZS`75Wl}|6b)zHS?yEbZ-qb9?^^KT$6`Om`mt`uZ*<@bK4@dK((d@989^~U0 zG7}c{Noj0ro{tU+8o;74tnuh@RFK(_>#%Xa1^Gdi!4F_OQ*KBh)XGX6V5hE~xkwnX zZ6>x?_|Y_usTh^ygrm^QeTbA5+eT;_foVmylemzN>GA0JlllC?WQ_Ap6UawcEbL^3 zmw7JNsho5Qc7g-bX*@c}W)H>(4=1PuX*d>karbf)=Y*1qEp%-{ha=4^_n=}_##@O9 zN`?jb9QQ;PJ3zbrv6|NO1}Vi5I&lYFOs-y(_<|0DXbDlx>C& z&z%bPRu1Q&a-UrSnw^Z9N{&wEQSrs7R>OR-qRqF;Aai9)oXSz)U;px#s|KKQEwHuF z)+783@M9paLgw)grOD^Rmi~b~YQ_iBS6}^qzV*RZhr-=I_=C^?;otwgfBw(@?8m<~ z`<v zF}esFR>awGpi|i}p-nbK=V@5QjZVv~3J^HedrFiFlv%`+Hd!24^`Qz^*Q4{`@qmkj z1Xd->{nlkz^oy0g^Mtng!5OS|!<@>opi8b3xEaj@I+QeDY9nMor&&65j5vcZLWh&j?2CNgMe)s*;IO&y7I_8tEx5RqM z=R>7!WloAM8hJ^|H9Q@ahW+KDaxJG&xo>N%{UknY%OyyyR>j_5lwpp=V`(jts*hUo z^_KK;N50dO>xw0Lu%AhBczF2u;lpn~e(>qT<4=x{9vvJ!n9h#Iv!fA!QH>8W8Zw(D zC$K0KJPGFHWDW!fMr9^8wj899Nl_@$sQ{`3d5Wje=rA826;K>}gc~6rrUh}~3FO0j zP=;b%^AsP+d)QtG%?d6$*uq+t=3)D(3n__5VTwxT8O&*V%yjUmK!r>PV>WJ>Ai=$m zsUc*Jgm2+<%=w(mMf2#SILj!+RUn5hibRkwV#|muJv24nP<=xWOg_yE@`ol>fk?p! zBMY9iM!>YmCvEal?p0odtIIrSmJRC)4Aa-kepBWgqgv%~xdG=GRWV6MONwy}%4hs@ z_U4(N{mEaud3P&gi(svGaZq!`sF1T-6ci2k*T4K_d0kLc9_E3c`d;F>oR|&Fjdlmd zNAa}v`49b{{_gC*`mcZSqaTld`?n_Fe(3-6fApt+@Uw@%|2xOO`}6rHpX%TKuK$A{ zjvgEufA9bGlRx~k&yT+EjXqJWcvlFw#JmBM+Wm7e9UYT-(;DkT|uBCGCg1J<{(KC;rM zK4;`JX+8zjvs{U${NB^C)}#`ZV!wv0HF)ujY}}tq@6c_5fp}aQABFwL$I)guW)OD z7;&SbaXLuVgr+?)`-zc`*r`v3=U{1UL=WbKV#Fj)#}V2I?SuavJQyE8nm+hs{_xX- zN8dg;dIU8rus0cnkQGucHhYOrmSVxDfQ`Gcs-_FsV)L2!lqQ<_1c&oj+zX9F3wh8B z9)^!6Qpn5?SHz(Z*HZfyw=1#C2qI@L;Gg`9e+m8K2bRx{ z%JXrYjpC$;;ymOa^Wbyk!S{?G{qFeB|IttWtAF~7-~Hp`Klp2p|Lkx6;2-|O-~Bs( z^T+??pa0@-{Mirw{y+HX@Bi_GfAmj&@Bj1P{MoTHClT zB-{G9IenlXKXiWQcOU)M&kuk6yN5yCK;Dx-dDs&wIyQq^*R)u%x0xNryRBJMxb)+g<12Sb6662y8t5#WRL*!78?{{x zR-5#ESZnRGYVaof$MZo`1n(2l`z;Rry54IkOH>X?Ra5<-seDMtA2sD`O){z*4dLU) z@P1cntETD&b{zXz665c9_Fg%*m=noLMi0=%`7|EQlgUvwdr%YyaX9jv)N(T0$sMXJWw@9;SHW)dUlfj>Oh>Ji1A7NBZ z%CvF`1dHP&_6o=r$4Ovawwn-TzbW&qj4GLg@tCeO$UKUZWfU=NSrfO zs|;T*0f+q4fBCPFuDmHZ%>0N5kOIq<*ifP;Qtkh)#=tWgrQ{W-& zL%7};-e?TA`f^vZv>Ih#dx06(gPF<3e#}_ zl5r4?ya48unpSKWk*-I&5gTS|*_rJYjz9K-i60U{G$rC`kj$cN9_I&1ahQw_Q*7}u znTFXc#>eS#Ud)qt>_eeAJ|}a6+=V|0{fs)BI!cpU+V)k%+_;`Bocrtx38Xx63TE(hDF^8sh zvGKduvSKI^VbH*zu6UY;%2_~8k4!Bz)zDA^UGX)=SJ_rm140Xzw<|V*l>m!@n@Nyk z!KE@Z4>oCoir=i@Ms+HyG8Zwbpzv^)a1WtY>6E77SI!6@`ZvG)cmMtWOzOrfgeoBc zP%X@f&$Z$?|N57|EWZa3g^|fWa!@(VIa|RdmLXI2?^xMxIBm$@Z6n?unAZo+t%h>V zh-$~5da}O#)1My?>x_y>Rd_;>!`=oi0#`1n&(@$dDMd(wEXWn9<1 z?H~MB@vr}XfARbO#pm-!+NX~VRL)ndVAKAXRMF%=TJvnpsLoQKs?$6ZHhgHsh6Zi2 z;XtSItS1|RXBamERSi0e3%C)e8qcLTPmfkq4XMIqRO!Tc)~OWZtd*%+QH6CYdLpN5 z(^Co1)wpz=Y1K8ZcbS#m^rBRH@rzQ?g1Y$j8DJNqQohWp%vrEvl?Ggple2ItHD86w z1wKP6Ct9a+AsbXKe4WadUgm?k$a%jmao%gl;N6A--f5_t@LeeLJ`Qh)AJ&Br>w}MK z{d+yBrJAxASaBQ_IeWtly`-<0!liO-9W3!@4&*;i#>lLHND zW>ie7%3hV2iyN3bE4Jp8HbAgzyHVo2&sZy{nLN> zul|?+~H_AAN={>`K=&pwubLn=G{?LKROm` z`ujJBul3wp>3r~uKYH||-#>~D#ohLs<8c?2`?LxMU;KiWhoA>AGgxxfs5ZRkiEQ{# znGF-#WJ7~a<^N)C1gge!aW>otY`77q`q0I>YMkl9RCAD5FkM@C)f{MC$+h^LAhdh63hn1liGHS z4p=io-Hr@5vAh)6US{JgbgsgMj@X%HrerD<_(9v2zTy=w+0_`3U{PY^`G6fr62qK~ z=@hp#)_87p*qgg-8rjL@r{xqV%E7h7g z^YSK<{Ly)dr5$ei4d>Yz6-D^?s2>}6t&aL}AXWeCzyCksQrZ0Q-~965{p(-;l1tUf zs8Ha4`w#!&&;Qw9?6*2_FPwDqHG%+@L#NyrqD+H~e1;q{y-~v(H{5YOe>{vIbnNL~ z*S)T!I|KVpz5ii47UxISPkw$pJyL)32g%QWI{AY?`{dIfcz^Mae*SykiT=hPKIrHl zzTf!9$L(+RjE{Tz&AxZPZQr(w`us>h?75Mpf~lG8-mTVZ(vW;yJhx zSQDeCb0bjIAaDT(T2WP;r{Ouf5qP>`xD!d@RF$a0h5((r{GEqSE_5nM&_|8r%{X!n0&wc=I%nUoBY^Dov{J?AylS zjkz+F+AhK3hF320JStx+{@7D$&)cPORdLPxg zA2)lDs)1!0Vc@1wm?w~`Y@Ftklo=ICRWXk8QJ57$R`@9x`3aPWOacnxdWGZUmRH#R z2z~%FfD>>tfTp<7*h{BDF^@+~sz{-jNKtf(rPHy`phN_fNo^-K;Y@yJL%-lF*(}WG zQ9288I@E?bVQg?U7zvaPTPP7u&6;6b%%~U!sZ~m9Wn~s*i(#Y83Vg&~lteL@5F{pM zBb9(gEorVj%!adyevx(I>TpulfMpwqRnD4DF=^xFsQ@3*gAOi6HtA+UE@75Y4qKf@ z6oF&Itf%@7fUiJhPGwaFmcw&Sl^Z~Q6XRB|CUVg;iD#V=3dQGC@hR%?r=!ol!;OkR z28c}VQgAOGsoDgU)5DLncm$o-WwX5rSiv~7>}#qhRw*bw7egYc#h-Wfeo(y2I} zX<^j+TYu*#f9vo5_8J{{9dD;_v_D&wq08^Uu6S|BXH4y>0pJ zd%f3N#*MqeJ8$iNT~4+o?K(RnA7pe{c#I-sd`XKnqgwdH$&1Z5#NvYVjEeDGoagRF zr?L?@s+!GNY#2|Ka|>^{5vUr^rC8|E6%Fb6>JiuwqZJ!s#Mw}y3LENkS)T8-?h6jg zRrQForbHF0dbCks#agjSKU$^I^)gm{_C{ZR8P)}&B1Y#jJex{MR(a*T=TK_T1u31Y z(voLFx&HI0wCaS)1zv{Am;Mge2LgC^lNt~K6*~cy2ygEX-`*d*QyaWnAG}xZf6(ZC z*y!Er4eP2d`o5hf(X<#HO(*nPy3v@Hq)H0(_hTOvlVCIr@(Db^iwehwnm}S=-HHt- zG2PT+aVZDh1CfG7O^(y?VS+?4kLcq;0^m}~$cu6}hBFl|TxvXz=MVD3hsEqcJ~>KJ z5{E}*W)7gB7um@PF3y`-lFHQ3`o!0b1lPqLbij{#X!K*57q*?KA ze);dtvNsMYU%3=LZNS#z+S%Lf+aC{tJHz;{Hrb6H^&b3|{rOK*J*)*q|M(N{5B~V` zgel6Md7Wbi!3FBy?xVUtlq?VdGi2IZ4y_~ zg)_|H3Ee!p^GZ&IQ+oYnJ1=)p=WwO#U9sjyoa#*|Q@SA+XXCbTN;juMNrpDr(48yr zD={Qcm8A1I&6(EJXGK+dPUEuW*I0Ip?k5S1yp;F0;O0g^Q z#@-jrxfi=h<*J`R<$Edf_GxgzTJiS2SOEvVxyKH#3GdW}ck9A?_2GN9MY1}-X9HyM{L6S|wm`(gb0Y9@jNYh7>Gdd9;zGTzwH4Uc-H6zmDYF1+Mam*DE zGC(1*WmJshDYI`83vsdaCisvaTf2)pmc?eK(>!$SipD`Qi?eych?8j) zvvs_{etrMLYd0!h@=QRr`?Y;GJ>PK>+lpxNz8M<3wY`g+5o-0lpZ@H3mMgYr^TYD0 z3a7F-BP}{l&mTalC^i<`d$m11tvN?+byjN!H}~ZC%w+e+zc_NDzUel9^t0pd|7iN@ zcjM1~kjCS|;Uo9(*!kqMKWI1lvwK2h9_}O z@uaFBoXVA?VZ#PiY;^f$PU-SDI`y;I=(#UIQ>paF7w4qszGUZp65%+X^}f8^#g^{U zijopl*tk(;syE~+JYPcsXWZxNjlDS4TV00T?aO&jDRQtzrC5bZ;nP@CsEs}qR65|Z zsr2hlV#6CMRLWQO{^}UKel>PCs1(>6pz;!x^FA$4)Ur30lr!JjTe3(C8$h8r66fuj z%wZozR%ZC-ZvXAw{=0j<_xF0&8-u$YVQ;8(byM|yKTE?RrT6w{VUz_i$o-@U(ov9& z131?BAf6tjvj-Vxa+JWRl8G0M-EgH-1<8|}TTVs}L>iQt_~?(EXzD?*l6e?U{ScZ} zz&uQt4S-9*sNB?qX2G#2^i_~H#W1sp4|~gDc+(JVC}z=U7L8}|iV^&85~781?gr?* zBf}2$1(Cr976~Nm*Z>q@qZJKIGt^1iLJf{ZV|iTrayuOH31Jb<2|I{0mVh0Ok7?3< zI*%f>pHI>nd(f$58m6-d+n7zU;*;EwPjlO8V*5g{Ob8Y<3u(5@gb|y1Y#J2zvU+m= z*6lkLHF+kW+V-HWdeBoHIz^MZC_H8lp63}wRiOJ&S~3G_HIN5gap!OUlb=n$Z}q)9 zTC|hR`$yk)KmEaI{)v|zXaj4jt=-!0zrQbi6wZWft^`HjN!s~L&Zkl~7VGT~Oux3* zfA9Lvi`#>@^<;1UiRnk3EOUnPkiP|pdzDX%M4UE{DxZ&oQKmdP@l#|{1vTFrzP&ei2mR7s@55UE zMx%ebHP{yv!E&4=3G+NI@??~yqckm&q@Z=GCI{K!!_ncR(fmOUqnaEha49f8jLE2` z5C|Hx^Yd~DibTpz4Fc($q{=O54i;GY7VTy6CrUV}$pcrY2U5ieavNTiO#FNrK&_Io z7mwViaHHG_b0^4XZo8LQG{Ze}K)^ndJi)6X!-{k$6ishuvznZgM2e)R&1J) z&ZdwPG&Y9s!$aw+}_=hY)N)x$(FIzJQWwq zM7o+qhM0?6Vg>1|fTW zA$t`gKC;Q_6{DIQ6kvKZo*hr7$CJ_Fcyu%=4kyuM|2JtCxVXcNdT_DJ5uSUV`3fK<_lMqc97@EC^FC%DkB5z|Uv}gm5&E#s?8xYJ3!P zqe_`kQH*K?2ZD$gG;$XzkR-@cH1)y>aDhK^kORB2Qp1QfEmVw1wGy3zSW7(8DITVR zOF1!9s1SAq-%8*{3+z~jEz$FUJm$0*K%_Vs5^M~S%!#as&u8c3cQozEg2S1y&KB9C zAwMIgQ9u4s3so&xP#zFmY8HtI3v^M$iwjneIZ+P7^A==YkT^c1Dt2)9ScEU+3#iii z6zK0WZ!xuqUP>4y$Y(G7Nv5%=iF@_^oxR=dr~hwf8}-z?je#*7nu1`7gef3BG#D(i zJ!tRl@4~tkM?J-VJG(o3wf%wIXOrJ8Sd;;M40M842wTt>dwaFLoxNvs#@+qB?y#%- z^qwCx;1l8L9n~DZg2Q@@Y8K`A1s^8U2if#NJ~_^34@Z;Zg1xsWN$Gvyd2u+(4o1;5 zcZx)dL(%v8j?>i5ZBf0`lW%qD1y48H@^wOCuPE29L7})9wJB=FLr^@L^+9L(a)Y)8 zP8Q@{yzXG-J#6%6v5YSe87HgymP#@<)aT+ndr1P-UU|j2opG5`$Gl?MLzg+PH?2}B z3@QaSSjop1#YTVs99WEcoY=snDD^s}&gKGC?cvm$OgWYBh_fubqI}dDu#2rW;|iQy z@8S|xth(x_pyCiEO2Sdmkqh(cuRWCpUxM=eAu4z8g!0{fc~5+KSA2yKz^laYHG=js zi-HwxLc3TE3lD=)k(uoauPs0h+R%G#r}O%5=gqzLJNxbHt=`@Ka8Hyvx+Z(JorYc( zdZ|yNC$Zzh3}}rgixXrPTTXNa6 zfgWUQL|ZpE?aVL}O^*~ckY!I)dPRC;2~^paB~KPzNpwWQl_Xb^Jz4b?7?=^#iVyHSz$0X^uJZB_6v`ScR)}Cz z)EBl#YbemOhan#*Ts|;J__S_TkW8a=7IPM}uSSdEMLxL3-?S4IY<&dw(!kYX^pG2P zjP7fyr^v1>+S1Sxpjmxm0I9-9#Z!z>cT)H$87GDA*o1my0wj<_yE6Wc9jZ!k71^PP z7eHF`aP3fA80TW5JqPuWTE(kK6&aNtXeh7pqXOOHZ|q6v@kyM8)+b{x>Oq2^l+^=I zVyn#ak|#5?XnGbsRLGtyv_Oc9wb;8938ay;W>iNHCiBB$ewZH|f$Z=&KYloRz&JY2 z=ZD$sAe|kihYv=_k0-~Erw0$mv*Ypfcsx2R(peTw60eBtEHD$_NI?L!B#=UH;MqOL z?$}mCH}+M1N7n8M>a8BEOZunZiR0@|UcX$`4QpuT| z(S}7mtUo?el0fN@E3<0z1|`3zp{Rj@ZCb_cKQ^k3fYfme2VIQ)&h{@b;|dyT;d&B5KF($p={ z50t>y0#6TIBd|^1vVFt$blcM$Pjx)S_7n^FiW6#nVuYC$<#t>+2@SwGFf9)z1kuT@ zprF_i2Wl0JoN!FBD+iFAzofG3pnvCVAGpC773$Z*vTAoY@u8UJ*WuvQGHn^D-xE7_^3dP z0tFI=GHjTVKlew|()ojaMq)s=Bwrr7;?NNWw$QhSgf;A0gRa@{7`?XM>*&3%-s>5? zfjJQEq3nu^Cuu%Y#z?bagcMF=F32XCt>E+Got)Hg;e50@D4UhfcF{!mv4?AnrnJ@r z(jHryi;l`@5R*TFxCWmo&xSZT?8!t6HEV$emx5z)kY?9T(Kx=g`yy@^YI;b4I(ov9 zYM_N7AYKGpSHejx6hm!b5z=FiH&P9e0n>s)=>d(a@`oQGUJJouBae_I_RJ%V!=6YL zJd!O=MqY)}E#!=j;&#ZKOjR63wq?nZfNVq2G&6vok#a5PQPG5|HKQsH)A3P8tI!@K zNX#FO=8K0;v+-ey?ZKn*gHNYNk0%G%^`Mxtd?XGZjakWpl}w6*IDrM@&x?cj@bTo~ zX9vfh&L+nNz1wIKkB-KZ2lHe$Rs(-uQf{>e*PDZDE#afK^dXBj@i!j4L&$)eP(_l! z8IlB6K2-U*pz20ts%})~i}IvPL>*40Dm~}3VGkGKVtwtRldc@gS@hpeWO1U4P&xar zCCiTLR7!5a+2{gKsFXaNjZ?2za-lwW)x1jnX)J5o@Pj9DMm?9MTJ0tkx%o><<)Tif zdUHmcbmXQ(lh(;a7OuuL3poy(eMOL&SuS>w!+9~ZW8#HlS}4nhaKKJr20l7nS%Ew` zB5hp>ACYN>D)v%f2`&YRVGkQ>KANP!u{eqkWXY2RM;wqv4Y*DX907tQ`jY6&*b1H~ z;G-*|q|A`;(G~=2I5Y=vEF|zzazxY*&&%fF_&CiEB6Q7cUjG7I^}4Qr;jWSnS{y5*xE&9+!3YP)mJ4~mKxVR=Gb+VO%76Q503Ns5ivbXN3$4ZXpxVxM-NRfmrrLw29by4(t@xgfHdBj;Ho?` z@zl^&BVUQawq@TPNFOx&?>7e@w#E0F;=2v;-KIorn9%uL%!(>JX%bAC4M_qePkM%` zRF$4{*f5o6Mb&ILo9@E8+sglEPw&y6AE&qB92U)c7F25fRZ!_BPj;1>w^pXo^_~R; zrE=goutO>x|I_gDR=3P6V57_>*s4~@Ii=dIGS%{50Mw*%8!F9vYEHi2E#fuk>^A?A zkUw#qf@!_HfXNn*Lh*lSRFaESm(h8B8?;}CLTxwS+-|BLVbUNZ6Gu^Yk|GK)`yvSSTckp_t|AqpXST!KEbI2I`d z#3I9%&0%MdH&CW&!x(5jmafwPANAJI1yTwoSTxMX!#{8cS|~w*LP2F9G@><>$!TPW z6q*6IW7D?Kougl8Q`Z;GTR0X?oTt!>ZqWQNmDI`=1-KN9s*FR9)w2dY$df%3Dek3c zK73I#2pwA%UqP?0C^Si2u_FT=F<(QKgRVKGzzkm(bO93%HaQHU12yC$jIa~Z9hwkE z4Z}4u<{J!ND-6C44x(Rr^4e()5g0J<(R>RlXWU|G}a~9&oVWXu~@&u}c zYH%22X2>BkgTq0v7UQG}hbgIo9OP@b1pcPTh;)qyt5y#LP`qjdjr7r!H77Fd&@gci zeNFe^Op4|*JXI%uBCyNAPnXZ!3Sd+Q4~DH96(-KflkB?)Xu68IuL=_zLLoWmI=RAEC+E<)KPs@-Y{ zUSI(~k*`RXLGbwi@=de-#inZFlP`KG_P-!`bc5NKK+*|2cpE1loI2A>Bwye&= z*k}e=xyX`A4bO^iaqeH3jT)Xgi+i%7a%a|geX9#zV?eFgjUv89^oi{OczI{|^6n7Z zZ|&eCAJM~EI7(NytUJQ3nH~ue`{<1TCH`r)87-swx&w1ZKYv2PNQ)WPm*++ zjt`52hm(ijJ~(}q03A6+l|)ArU{P#z4<;mg5|n5a ze1d76Kw7p~{)(9j{E1d}pd6Z?z5o({eAQPZHlb>03j=Eih5%k=4f`gfs^2sEJ)P+5 z1JM#`zLBpfjv`r-UwEDApe1g>-Xp}^i>VbKE@aPC zMh5(e-Yl8e0ko3Ob(Yk!#Ve-6Jc5z57(m=Z`ZM_!qSZ@Yt@G=|s#WW3H2%uGe!op@feuO4b{D@H*b)<|g-d;l zEJ}EJ7l_~5C8K(YcA*SvXuq=6dTp!u##Zy4o#wTA=T@t`)$6xaMe)!b#?dH_iZDVy zJ@SibG?^#!qZAw*rH9Aa(S!W>VR8JZIDC-LkI->MqZuvlnT_F3BvMG^_{$u^bP&ys zl7k1?VF`Q$GguUkJ&ebP{CPn3NZ^um;`y0r!km~w839oAfa#Pko6GS&8sp0hKtZWQ zHxrHPlora0FUg)LdV=5zqAN(AC?hA375Gy`!(lYRJXDY)`I1NjaJ(cAVZ(5~3?XAP z&}A-LWspf81{+%z;6T5~v>;UrGg!=af(;;l5w9YtqCo)3KsLWU+OB|C8U2plYpI>4 z+U>xuO!$`2GX`z7*O1zvC3V_zx33LkTQ&oOExX_ZFscGwc9>7meW#;ol24*^6z1b- zJWHkr_<{<~?64Tm(|i)s-bp;3<0}{)KAb%GbpH7Bqeq_|9z33mkMe8=fu^NI*|c|< z1I=fLKd`|yTK<$R1K~u4OVj7aUNZLCSQZZ`+UyBOiq#?Eru51n8u-Go5G)$<0+HKW2sx@bhGd#M$TJ@_Nqfkudq)KR+wbBNQ& zBcF$?rr;nQ)882(RE(I=ss*-U&CkJj+SSfirFFlcaUm%rJZ?yJeoZOQWN;hW#eeWIc3bD#x zgsEP<-+yUq@Z$FH#qGfh__)=78UOJ225;^U-fav&Y6%~Ag>6yo*^ZIK;iL$P#LvSZ zqu53|;_sI6$5VeY^QSX^GWEt2cQkh92jPQ9*|$HNeE!|px4$#{K;8<~hO0(CyO%09(+Jr*Dy1H7oZ}bIgDA}UwK{s)um{pvZ1TDA)V_>0| z6Nm6)o}gVM6S+r!C+sQo5#u3H0a-T=PXgQ40;+55GB`wGk=~P1Fvp%+~ zb-(zcU(gTo5PF7@i;m$XCNh0`iM7R6Pc>LmDU;{$Od2zVNQK%7Y=tm#FJ5M`+?NiE z!X?9~bf4f}g?uVcPfb$gxD`+%8B6_Oe>qFld2KF#?yPmTx ztJgZi_gaH@o5Qyo!kcyCjk@>-ORONNV(LS0iDLXpLP~49&aEjS9CY+$hq$K=lJP zjEyvRjvp3}zdeB!n|4*bL8Xm%7#4*b!9KRyg5N8$81o zqgepEaze%9<9*~VPM*e#|$YMUHJ@UY2IJU(D5R@h#GK9%GNMit~{Ja(cHJ+BAT z@-oBEt+22|VD`=A% zad|pXC3qEAD;fDKcvxQNd89SzpXl%s^FLNr8L0k`Ddy z6)T{)&cbyF(jCYUlqkwwvLc$6WI{FYF&R;)5(&5(mmykSi_ItFOVvkXm$q!pdeW?E z0O-L2HWO}9hP@s;V3W^qEUkA>kn#8#hZbl>1Nb4Fg`X`YjDuz)XW4RUJg3B|K+x)HFY~(IP&h#jy$NH8Nsz5Q1 z_|!I-mK$5DElZ{(SvaL;#*; zH))yOh4C!JXhW4&1=oN!pN}C$ix~oDClW8;WyTHjL*YT-}PQ5_29^ z5jmk;=1HNWRge2jSo9xjRLfk7joQwna$psT6A()&Ig4twS76b_Qonnd9(u(_h0laV ztJWJv+I06^P8ts`)X0+)v2(5D>~t!p`{Jpz=Q5P;OqCbzbzh`w=eMiWH?ldZ8YKdK8;UYQw0USoN7sLEZAXk4ng^3JW>e%pV;_**t(qL8=^D zSV6ZE^jzu+J(3k)l%OEa01PX*Lk{c&Teu5s23syni`dmtt+;O?6MIQ|;5u+1Rv4ME zC?!(VSk*wH0i+j$iHig2*fqFgEhA(rq(DX{Jc$~^Pl4t!g(7@G4ka~K^h8}@q`04& znd!jFbUQbkoC0+;jm(#{K*nvsEegkumzx$^h)iF^R;N)^Hh79}nMDNMlpc_Tu+sAZ z6OUfJh#y1BADmoF#%CZwFW#Z0D<(dQEnowGe8N7q5!8y72V1CBr5MUAq-yyRp%q-e z7G^dJ@;NQBN#Pz;GWOU@812;pW6Yu!PX;UkR55wdQmXi~0(x1kpi^X2z6#4kCJYQF zM;gbXYeBmHtltdU1fv=Uqgh0QdWY$VO;Mj5B=h6^kgb@2oTTv5Q81n+lUWL;^K5ol zjAm&%iIZuP%rYmByQXocH~6s8eXrhsw>D(MbMjj?<;{KNjeYrzeTiONurItpaP_Ge z(uxx|Ds!a?-5bud;X`L}o*`|B&IQ?Uos07YDACh!iYHYa;)`c#EoZpPTEBZ)7Jbj6 zi#nlF>{rgJk1REKt*?D{R4ae)|Mp(_<5`dmEPSH%!r5T&$~h`ET%47BEKka-t)2^< zmH(_*o%*Ta7xDzYd9O>{?YzLeia`Dy9Nv8CZWHpf;BEuFcE9=NPW%1+?)7H>PG`_m zRMm6CJRZ-B`C)N*R2(1W$H)2cgZ$Cs@uN>B4xI(>>7&6ff4|%o5bc5J3}j#I7@dLBm!K4}f;LD2#h;c&MPVTpAL{oQi$D?A zua(xUU~WW86fTUa1S(g!immAs6D&?CpQlekWyEstGWx~NQi`sz@kc%_j6nm7_{f(( zm9$U>kSc>#^HSNgeFFZZhl&pRcFpVNMy+54<1x=7jM>J7A zWNX{|ZtOat<3z3-BTaZ|=ohh*MM~iHEvv3-cL&l(&A~hSy|?xU(4*JMqNLaNW!lmk zpia@I4Gk)>yWsT=o@Vsz%Br*>Iv3~HN{P-36jiu>&XbQ{7E80%n#Q0YnWB z2RR!-t;cj+G`rZckX3(3!)F6El%aHH zqR||7kCXx~0%SOr-4{^U6Vy;rLaA$Zdsa^lL?hL#!Z3578<`Gs5`1Ck4Y6ebDwv`I z0fKDt*b*BhNH>0(?CYV#{Trh4hwdvM5@vVwp)TU+m&JT+vX5X0Jo0 zX${!L;#9c0?P?o@G2+L z-DrK(kJdz>Wv}>J6gnCmj$nm;JP8tr)HqBgQ96yIaptWmusHNN}JB|p_5g50XLqFGF6_lD*akTiK-^FqN*>?n`#iK zDk7UKgC(cJ`+h1@IqFmvp_fh8>bxKe?Kqze4`7M4%+uJY=P6kj$z?fd(i7a}BAi@4 zqwG?g(q3Np$t)_bNXeZoLtjm$w*}*leJU=dM2xhC`Usr zk*rK{a@8Lh$;>GZywRagl@#zK!^_dp%CN3rY(^71nmGQ*q##OxExK@6g(SIyq1}Tm z$=(nj%~-Kg6(C_m=+tE-;8=F7Ite603r7?-v*0nFp!=fY3{`h%1QOIOoqEL~6cC*z znORU+a5ZS0o9U>Ek1Z+?DZAe@y92v7bOxd~gl}nVJWflLzBi~Ft$n=-8dkeuwwq?B z=k^Ewu#a}SLn#nZUUY{8tJgQX0BIgug4iuHdpJeM=(hC^d~VR9v~Q_ZwoXDYXa2Ky_s^Z;TgsJb8Ooq4C=HB_-ki+>W5~oVlu>AXRFMsI@(NkY zX(bCXNUmjc;97i(jR``zC}c%~Wx}^SdCjQkg6Ya>^(`&XC08AoQr{4;6&*!(RoTOp z;QHy=P6y%z>6`fO$iqKBr||u0Y!_kI((VoVAGJE~)Y@;=x^LI}Z`B60oGz`a+lMwW zwOYoOb_K8uHLYZbn^TWo3q^F7oMA{8kR;BA6>V~!ByD)iGle~iesQWQ^9(sG9ZzM!FBFLdjf>3O$=xlLNn)y4lE@9frpbv%?3;M3g<~@qF}s@D z&@4MezXqd%g|x91-M;7zlt3_3)yZ{gK%&5?Abij}4_$t&qLE&rg}F(P`I%l$a<()u z$c<#g=qp7inrQb2W_M`yM0Ws}qEWLzR02_tWHV8%4E?Dhc|!;g3dp{IU7|ni*}b;a z;k1l)$Lz4F<%7Q615hZG#1BDq%oUpYd^l6?_VCgWeU`)e^*diaA#n!o?r7jpGSP&`L6?qlp^#mQ2usSW$DON2% z3kQ2?9Wq+8lw6H3oPjMqLe6;fix!SANgL29KF6fZm-uRDTE(c$)HV{^OdUP41V`=Y z!;Ur(9U0e8ulSjGUSXpms3LB0IuEmhD4l~OoW^Dz419Y}S8w!(?=;$P?6=;8QPq2I z)%tJjb1|Z*5+AdBZD;uUj<5u2z@tiKPokqXjOWUnsY+F|c^b~JqN=i7fvVyxs1{qX zQL>^n&y_PmL}wexI^~iVXL0z_C!Wx`vb`&@Sl5w@aB}S8MCU^%t@dqawB&S7s(QBY zHk{VH3$m)AB2Q&jWiH5~@};IgZc3D;=fd7|7H3w=S?xWmz{M$7bs@ffyLB4KCwLjw z{>C?MHNJU^Jn4no%@^^F+y-za(xw;gGzg?`L7{4|e!TMvvGwZBtvB!PT&p$qB%x<( zTIv{?ZRNI)?rQ2-xh4n0p4n<^^`^346LgsK$~Doh6ka6$Ha=8sPV|mXHGr^_J~o8%>tQ)F`YVx2mZm_JD9oinLC@g z)0sP&ITLITywS`JGYtxedTc^ALQxBbL@4NyXvC74z<%I2q8EoE zIE1U2U7P}2?rj22>Oc_tq)=+Jw)CeC1k38e##-PcdP6?Y$+SjM0tqH3I+O|Bf!5d= zSrM!Srb6?sDDtQBX98HDh%&8=mgwZ`tkTFGM2eXZmn!nA%sFk*}JvH`U47^~3Sa$8!&v}lE}MI{R;^0yE*4iA{IWi^!5 zbTq!Y7&5VI&8S4S=!HPfQqr4%oWw{c{^T$@d|1qnvt;C1fok}Qmzc@eD-Pn~Afe^F zW{E$E%`EKN#_eA3{aW+ATKnz&&YQcPH}=@eo=BC3uk8x2?Fg?fK^k7gSbKZa`B9=% zc($svT(_`7)mMInd?9*NRU&W_AKIiUH=C?%X^pC;Y!rARivvr}vFMdI`pzXMp%+$u zr7W8)D!d@7vY%`5*n%NV4ui*^k3ad&48xcXzneQ1%B-2lVZ>(n})M|+s3PXR`wYx2-n9=H)oxauKQq?y*WKnhx^~iP~NDwLL zl+h84E;0dktgg;tSNQIXcHi#8(t38cW3*9c*Xls9dN_*a+EZXm4PYTd*&8AOud)-( zqd*QENYS88tN;>lCTNEi$$Fw%x$cZiZ(_R>OG{NT5C-0Wh9B6Gcx| zJ=KhiFf$z=)kr2AV_TRR)PybcwR)P8#y4@eh#DwphZag!rgOV;3lcv5mg{h2dr&3z zykS__89i!1&juzlzc`A<#|aWpE9f2UiWw3`v#@3I#QcdV6j#QTcoC%t7Q79+`0B4* zu;63>B1Kcymf&*MjLM3%bnML^P5k5d}I z3nDd$wY0FO2hq{P{PAbgqsOqZ$VWHn3vQ}}BO{(z&@zZoI&(l+=w7NuBQqYGNQ8wk zeGq|s=Ay8hC|;)dg&vFyf23O}I%#xxkP<;p(K896*GG<(L620oP~k>M8;PhVq81A( zCl!I52vRbXQbA0H!>B(9d;Op*MtwOM%JEQ&(69F(PhGRsHX2Q>URU<^r5%7o&u$If zE-*4VIr6-Tp~a#c4g{~)vs&;iB^v6f1kf-kfPD0&V1P0xZ)S>_K`bPE#9p*nOC%$s zS@U8r1PZEx8wEo-LTh0UqT~;UPET-pq+d*@oLmoZ-{x*SbKG1vWAyR34}#(ku|;_q zhlebP(<`Dx@i8HaQ<^)&t4SbgoubqVl0k6dqVTNFEv^dPBIN0Yi%Af!ptx zowm`2uJxVXfYge6748P96_8^|&opafn1!yyvJeO&^2sJ8EmNI|?ay6zVp9R!joh$u z!x>rb*ftUsN<>rsU6?4%NOMx%r{_S~dSitJud-v+f)#~|?n{a%s2&fwQAr9cv8NZU zSoIP;%Izq(e0Uf==*P;#x@`XR;!yP^gI3kYfd=+!sK=K8UoZl@XpM=?7`Q{x6$UuU z#cu=OucD>vF{-q1vynHNhND@SPyB)}Q+pWUU(smh=kUJ5_7l^khY3wPw#>+OvcN5p zo@Lx_ci-D>ytQ3_Yo|rgson1DFe-{U(YrR;YoSgkN0QDns*CeHRcXVAI8}pToU`jH zRFw!+O{hZEV6IHnUC!dfewI`UoCOtLsnRK|H$dlAd)=IrhY3 zR+MWylZ6MYch#5Uq~m`!@Cq-(>B6y2#g@*Ya^S^be(+?ifk3Qes8U0P<<;@R<(kju zqy~PL)vmAItg_nmOj&3XqoPxF&RTgUQWTeBUiGz)_rH2$p9iSEdSe&Bs6K2fEid=k z<8L6Kc`#~_DRH5uBcSACrI;w=nLeAFX(k2XAj{S9*enV&%Z)TMqFD0+IZllcdI5Ar z=$0bI2_-ue%|Ot-feK5oy9z^d`(`k7BFRtH4AOSsr4tKj(;osaRq~m0_&A+EiXm7B zkCWM>IGmVfEXiKKXEbZl?!LHFlXn}+ep9P;&1TGybv-ZSPc*?oLW;Ov1hdhZcp^#69hRH8iSexNFFp| zxXAQrfKPC7Efl;`K1ZW&H(V{Uu z2Xl0sHzeBqYT9DLEEElg1f z$-|tH36RiYg$;KOITW=D1Sp#53$#oIJr!u$nXX5&><(c|Jc{PCwJ`Yfe{8u|p}`iU zhpnU)PhDEUVdBJd-y2!f$Ov9e6^2tcnz}xX8`1-t6eRP80|z&`*TrpwVulnI^F}tx z#1l6jyD%!z=tngyt~(UW2^r9cI)+>&g;9q*Y^gm?+dT) z4!^ZMc!?rX8ya+FmI0@V`kX__gep`e=CWMCau^#2p2M=vs^wgks>Gbbny;M0%5N@2 zRbQS7Wj$g(RF#QU&N@t$Ry9=jUX*qJSa!M#sJ}1meIh4qF2NLsQ!Rfwt5aXT0ifLe zQ>i%9CTku17Xh{E^ef%StQ@jccJQ~p z4}X$vbV&YCL&;FIV^I&#yL2V14P?8cxji@&Tnfe(ri?@l5+#Tg4}EhW*dP=g5J?{L zbB*RpC9-69TGC!^xD6W8ZcW_T?%loDxpSv|o9Nu$6}FpN9hw695WT({3QnO#Q#(8K z(*q9)uh8vOF(c6k1S^u9RPl2yEcBqz{S0SOXf_p;B^1zpG+Tokc|D+oL!CzSXsgFG zl?uv*OeN@J3m{ccF)NX*R5r0)V#cEC4;0i8usK!GsYrwvX)I<#V|j_JgcMsEy1k*- z=L!X#8U}-o-D&8JnpUgp^`_D2IbG;iA6uF})q|2y*YI2I39#q?|@#nmE3rtv;ek7-3yGt=$DfX2ZBX_?cQM)6cK zDgipxHrjQqxv$iBBMUIgvR438~+>k}G74|6jrXkkz%vFrr*)YW5eV4FLF_+hQ}=2rcU?dF@i-8a}X zeXs5Gs~S}1*^R+Hb3@u>5gaOU-rllBZ79ywsM^mtR0ZfPs_JtNYc}&VoH)=qoJ5Jr zRJEqe+2%olQYpO2y3L$JrE;RA9cz6#|5##GtXlF4P$kvgbkV1l@-N2eEi6-!C(d$j zrM4$SHc)Et6{u8Lp==wMJ=dy|#o?5>kf*PLkJni3x)LWR{bJb#U%$Egjhj0!-r9NP z&hDG{_dl#P?{s=KQS9leWb3M<>#l0~njaZqtOt?m`jY7k47;b>T@(Mmhswl~%X}pm zk*`2sB%`C*eK&+TX<@4SG0jpBVl_(jC^N7{8ia|4Ez~MZwR~*TO!Ju&qR)oCC9ForqLcVnGN7C=c<1nJJNo zN>m73NLnL9XgoNgfcs;Hk^y`0hPW+mtl-Yrfn){f{zU^?;|vtLr#OAp9Z2vntJ}9a z9kbmsTcBgL`)&`Srp2<6D&E)(r#5>Ukt|0GMcEtBvyh}{Y}j$JIv35Lr?44*34wq{ zifAFsGK84Y(~dH}sX(+-69#8DiVK99d&mJc8N6G9#3?@fWI(38Ga1wfG6gR|zw3VL0ghkO* zddR3Z9J1h<G5{+Xk_WHVVzummCxA)P` z?#nx!SBUP*J3aQ6^4`na{g<}~FK-RLwKaI@KD~YOr|)&%G* zs)}<#s=8CAsyJ7pYCq>t^_weGb)d7jj1^r0t~g5@phQ_a&Itd2OT>PjElYQ~AWLhh zQ0em5DDUN*Y890-Po$z#picAOzik z-R+TVHJVDTZ+8T*-?LD2M+^pF;CA6vQaBJp2v)aaHJe7gYqua+QaqFs=oH)wF4b2e z!K76!6eE!h$R!Jm!KH9>g2IT#mY?fxO6xnoHBER7t~bQ(5(%F01-=WK1tk@r4qCIR z)muihZMC~jr|&^paP4S$2kqBz+f!8zh7cV%VpFYmO`7lyqXK=W+jF{nI}8RI ztsJHrsft5@m8mS`W@8I;!WKBW4qaOo(BM)~H#Oo94^nK8pPEmiA2>Z49%Un*G^Nbx z(O$ESHo)y@z!aj4+8}>ysFXd_327$F#7CqdoeIp!ACeKea5busMj_e2E6v<@d-y^{ z7;`w3qapiVC~%0csmGxCVQkbDN5Q?A-l1k%z|5ib9W<*lk18Mg*~rT$?49A$aDJ2? zJ}AKKFwMq(lsQS^W#eExj}IS?jvkG%ogHO22jY8;?&~{^SGO9kZns}!YjDGXUb+uw z8oazMfS0z0FW#p&nZLNzdugl7=zwp5rS$Okbe7)Mc^+Sw6_u%4(fL&E=Nzi`Q)ZHdT;|c2p_Pm$} zzWQx=y*KaGuGiYTLvdgldfOu1~{o z^w=PB7%@FwXC&y$fe5S=eJ8ep84vZaPegsB?NkI#Dq%|n5>bx^L%Y?{YfW{(trQ8G620Hv_NmRlv-Wf-5>6Ny0izo8dx24?W{30p$c0* zAq;iG*yt3nJvbIMuM4SSUd4v|5>d-!qfqrskt2a@3=%_68saV~cBVSHhApk6#l%Ys zMVN%_Q-rC{hW{XTExIRNk%g2bnm#{-O!WP3*X?wib{n@2`sj8RP!z4*W22Mg8B5KQ z*c5xfLuGsfa53eJ`3LA4TkHkqTiqA7x-V{ZPPpF%><#D4y>JL| z5nEcboXb-6p7W`y&-tvG&}mf4pUR?eRe;W-DnRG(#flNw(4bA0VstS#x;Xy{2~C-& zlbEYe5h>1c@4AI-P${s2_EL|&a;Y^(sT95}%X-R{p93qrZ15>8YFkk`{EMg3o{RF8 zo3*cCy8t3prty^<+^YyODw3-DS8wcp^~T=UZtQ;T#?CixY`uJY_r1O5mLLy3-^@~f zQh1}($wI$~!f_N$qG%e1V?P+VUT(RmZbh^XfgXZCE{-A_izGCXo`MX9Ds(W{;5YCXXbO)HL7}=f{1QSrkRwq|Bo+D#b?kDuyy)C zgcU^+wnK_qEz}Su3Q5)J;Q)H$D7U1I|zxU$31uxy}GA?IJRquHsRcm=7D+fB0s@XhSsxnmO*IbOAwHuw! z=@FxZ4%`S7okF?HMPNr& zPIngUkQ-N}bkZ-LFMnJsQ{J_>btF&3*Ek;&t4vmA?<*hge(A;zwqL)!|E;a&oBQ2& z8~qPj{ViGRd7c!9MjqRv#2LkQ9$1;{<}U0ip8Cnu4M(PzDGR9zdS=vf(xH338AKaH617!XQ*a^kx5prz^L3@iKb?DV8=5v9BUp#DiwUVR3T%Fv=t4kcmTWd zM+)!?*-8Z%n;P~MqOU{)H6{}pxSgKUCaH2-eWyhcDd?9EcUhECv5lZ3LtrF=k%-vp zvA`>V@z}Y*gDCL;0RQw!L_t*SPjq*rTDgppd^8YJ)ioh-^?}nu4j(RTX*JL_8nhOJ z)sp-^v`h(yNcYSpM2aWcdcCRcH2l&VZJ%f)sYybp9ThRxp59!Aq1_lp>+$cAI9iZq(~WqXT#Jdh}MG z7+%#ET-3m3kI{H29mqieS`{J|1%Ck7X&J4$T5qWJw%(+e4FQ$x^0`x*FVgD~9U5+9 z4-bka%p+B_NR<77;6P~5Hd>^f!@UaPV&%A4m8QCff<%F$Aq1{%ws6LwKTr}$P9y<# z=;7O>F-MwiMd3htb2DE76{oXe6=u(jO4dEm3}jmGo~^I|$D;X9vFfC>(!I7=XNv|L zB_BRVD`QD)HoZB&dF8a^^bdT5b7u?YQIE*OC=jb=G*_nI%?Z}X_qi}%}`yabp7k!;=TeCzJYoKBIa zss>f4O3y{8YEXr$$2>h%`#GO4(2Br@25qt~MqtBWo*$>X(G#h9%mulKqpYG7%bbR=v0|ynMG}!RaboqixcfFS>^nSSa10zr#1dR zIVzV~;>=sY0$pTgH}}C;Ki>W7$J<}Ox%C3Q&}R4T-P-k5XG;*ewyCEdO*At?PXt(z2p93# zNT1)Ks91tdddQLE0S}dlK^I7{F|Jwh5D7>XGz*nzP%E4ZXUw2(k^$d>d9Xm2;Iun> zt#379Z**)jq>($XBP>S};bZ_6;v-ivK9UF_gG)j3nBnzkT$0X9g>@Diqoe3RQZm2M{v;0Atr`H?(?-NfnLsS)Gpl|v zDME^_v1wIw3O-4nX2A#eUPMTqLaTPs>I_V<=#fcbDQb{53W>pxBFWA)e{8XzqN=i| z4(X9bzSh_)fno;R6JDeksAaQPL__;$tscGVkQ#A@|iuzHb`{s7@)%(p?wp!oX;@Z@CVF7s$ zbEDR`z}?o%CBAjH{SsqMk~nJ)bShO7s!-LMr>CkuPvi>}Bd}pY71phYvtcmLk99X9 z&M2^uN@5?2Sv+O<>C0A5Ls!XNi zIjnWbtM2@CR?78Ml&`J=D^NM<6R6biyeVJEC8@UjnNj%?%RsF@UNnFP3P0ZaI!$}u zeew3*8{3T=?S9=bq$G4^nKw_2!q!qv&lFlUs*tQgFtWap^~|hq9T*)eJ@ zZNI7RHMKo_gk!1E0Cl2f8?`aDl6{JbsWH>32qMz$I<1Djzb9|+N?TpK376`-=z|+@ zsUZuJp-C(hL=(2?yex-H7&6JO*o-ckHNVh18WoioY-EtiV7qL2XXv%D{i!q zcg$8(tJ71BYQ3ws1h$le!)!E z^PrMv*7K}bwe|~#Uto#KrIixlVlTM*SN%8{fpgyX!k&y>|bF zkGJ01sofKVo@Z%AU{3>cZ0otEWs;r=W+9rz5DKLwT`lPtY0rjQrF|{xs9{HsdS*PJ z`R0kBg?%F)dW8~OrAc(EvHR-!-FwlZtjC zTJg|~1v3!=#gf~J zftKTs*s|$aG)ZfSt7G9V9v;(a4btAgY0->$b-!n|M1P@N&?B1N(DI>2?Pub(kU4_1jC73_hDcdFZ=rW|6t_&8CeLQ&vnS)wR9rG?*}(30 z^ae?l))1_Y9taQ)XosI_4tsEcmNfGv%NI4PFXS<1&V|YW;7l7{4`VOkygLSdz z6Bj^SNWz>x1WOO`V~}lngEc+b$KzX2B0a*_D%)gQvXUce&eNk%@^;tzIng%jeBL<-?-QMCa9JP@)wZ2J@V_x)_0~_gtAXCKa8C&iO!1N*^ngfb!leav29YUti9r zeC(yE+Q~YsO!ah&y=xs|wR1g(l|Pl!o2=J=HP{);w(&eDUD}hOL-xOPjd6VstW~vO z_iQR9f2C9|?ZT9li&Od5_P=r++Zs)8Cz@Zm-u&`4;w#r0U%k$r9K60q)7wA3|MH!! z_v`g7X)p*4t#H&#S5jHeC37U%W62(&7w_pw$Ikn1F|d-J8FlTr?<7NL6L4a|O~kNJ zh;HZ!xCRUA6Ahr#67gHEB0mr6koI%R*4Sp4;quEdjm~c6(l{?KI#_ zbz^T=+1`@w-xu%R8Qi|vyLqd3^LGE%mUM4l-)-5AzTX)HT>$H1Q85ZH!B^;cLp}&- zHDGc`Ly|#5P1j8Mg?$Gu{H;^13$X=-Uk;W!)>rrZ8i!?3DAFF<% z1*s0gOb>IzgPF1QFLYXCc4$SC9m^Jd6eKqNUvheiH&EF~BF^h(S}-zw$WW>vN2Isw zuys&r%K73w*)*Y^4KMO1C5=SJR)eK6boxlaEt$o}BwBWhEvy>g4*F-@COa-a(v3>90c&lOmls7$5) zlC@lzs~vU1%7mUwr4KueQ!1~PVSQw!qkR%wm?+IU)RjVAgjKJ6IZ9{$()HbENV(>V z@TF@U7!^xwRCpB@6|O98qrerZHvZ~VzK*kDg0=gV>w65SRsAd18!)P`TyK5(dK-L& zXtB)NSFi7V^~TQEZrpp}*4;OEwr}=ZT~F0Vj$RmguIia&W+I%%&WBDR_#-hGiQ!0! zMshq>GnmuFfF3bVB31Gd(TRpG94i*=Z~)**D1a@}rr*=uuHkj9ppU}E%$gj!vm-B` zm?4ZR7Ts_du<~vynK8OpvM5NETgZCU7u}W?^{reqGr>sFeGc_x0KpnUQ2e$M_mE@c zf|@{sx>DHTh+#(vIzzub@LGMh(a?6cg}e6$x9|3D-R<4J+rNE(aCb+%zbkFm)ZM1B z4@Vg=r(r=O9yeGR^;$#SYwCL)vo`cvJT$e8NYNHvWn>~`5eazJz=eU4zyUTDy~`i>W3eb6X@mK7 z`hFWa)peU4r_phnU9a7CnsuXA)A#CTt>d-^VQ(1GLx{tmKcJ;b7xU#sZ0Y&OE=7jy zE~Li{p}bmHm|mj6w5&k31Bzgoo@ltRE&&M^(2|`%_98V*jdVmWZYgGdJhH7&mhHY^ zqPD)`(YjD7d(AVSHAU;42K4qD)faSHmJB}?TBV%M70M>WE})1PK`+~()v8RGS)$mq zZacRtNu{Mz*|MK7t<|_;EWxPwY%Tr}0Ig-po@T!)%&%V?>An& z+xX_4`Zw=1U`sFF>wp(vQFp+40BOa#46QiTtDY|#GE`>6hstai%=6>wV#KK`%QIv{ zeV&G@*?^M7Jdvs;JP%G(;{q)HM&GRDQk*Ex)4&_^WY#XB(s!OjQ>yTOdLc$AxvXJj zOP6K+yica&3b2sf-?+9@2028z%nH71lS;8Cvd}5cdR1$n0GL2$zcHIs%B(2Y$*QfK z^tn^L&sT?j54&Hvv9o}FHv3<`Ui7_FlrKpvF zgcB6}kt9HnbFVLZFy)}FXkleZh{ZriBQges554OO%Ox|Rv>Hl{mG024wQ(k4e; zC>_MEZ`XTPt#3DmJb1QzR*`M{IxZ)pkv=sU@Rcc4h8T3%@FfM?C|(tInPZ`CFhUY9 z=#+~4kc!x{iCF`Bd1A1bn?y)i!BsNb%)R(J5~aE(H^}LCm37wvcFh{;`FR;$7r|oX3J=GtWJ-X10Bk~sKL@a z$qCdT(!<1zGdmx9qiIlpiJy+#B)37F8eyz~DA9R>miQ+RqlID3P@<(lJ+?F`&4{N- z@ibGO7O84u+jn5wl(}Y9uiR_Aa<}=dJFORQH($KfeCc-Ur915xZ?|8#-6A$@2~=(7 z8L}ZmWj17}!iK>-KmJm<(R0(I3sQ;+RbAv9sv>e0Rn@o}=ZXkpQS!N*9ju-GEGkX9 z9IPYU=wi>~d=n}Q(-Wy2dp66nFD<0vQk>P^3-TLR;G?|-mHZQ`ty-tr2FBi(K4Ng4 zdgiR|-qTX~QqE${!U2z0E!C2xddD8lr_neQ4B%W*uqG@7jsr7jj5*s#L#F+>EA484;-% zwq`tlCppMWhN|C14PAAwqweBx#cR{vcqloozP{hp_S>{;zi&2Zp4LcJgZ{v30vdF4 z+MsLHo62rmul3AE$E?GF_!?I{jl_VQsjI-f!tTIpL#H5EG~EiugM2ncedu>+O)R6< z(Dv)A?2u}#9cEN zoH5Pu=MOUi_@9cBabJsJR}?}MgSH%YjC_ca?nK5`OZ!qpekR8~)NkgZnM-;qkUxcx zNYN@36Xc4K%VsVcnWQB{CG3%9VjDv2Xj&DY%RltHJ(orUdtMuM)w1dhTq7;YP~TH` z7gD9}wai9CuQ$|M+i0*y_Bt%g)0YE!O3}*I?AV{cu8xCb?zn|!#o9&@RuZ3o-pLbztsIz0W+eE8rwi-sWX*OH*@}E{$?+9j3aRl9$%uumo z&Cji%uzh;Dvgxo_#rUZaWQL#UL9E4@krh@xvWu|;vXLF-hMS@dlH^l>s_*tXPN!wJ z8fLR;HR-WOT3SL_Gb$Jon@-+lw#1+9r$p6tF3W}wt=KT3O*RbXIq|e&1gb*wtXLBx zP!*l4QI(#jVQn<6%t^GVOx2t?Ra4=tImgwgN=ccjbDY6Oolj)#ET>XA#T8lW-k!js zv#j*N=fKLZI?Ki3Pog4HWhx~v#Ii9Zi8;w!vE0iGJT)Idr&dPwjOqj@bzZjG)zz(0 zxd|7ga)+N0i{Ht$5+}bL{Py;KgYl&sjO#mJzPA09Yxlo?{odQ#wY%MZS69u*HGRYK z6w47ztEU@nRcoq7OS3zQ-4U%8N3z?p+Yzj0Tit~T4XuXacVR*_9V(?b6RklNbk&GO zWqexavv0$A8c0J0-~>|8ksvO92XX-aPy$-avj=CAcRJes&}zY@@Ud?;*}9!Lgso^5 zqGVt6Xr?wB8f){#4!DAt^w^*T8R|JLXcOqWZ9YGpmSdp#>BKPXbzSuL+&T7Xmb%># zf{vOFm1Mv|L2W<-bGZOp0(v%7lRonv!5&NgO!cRVU5G|DP-B=D*%Gd3=rnPqxG458 zV+$XVhFa-K-^hm8Y6;p&HU?)pTkt9tG@{q(&^qsoF1}oP&(A;(LxT1njP;BB>rYYmts_1x7)CqyW0M?vb&?~?W_B1MpZSTbGVQgtt-np ztV>CC?`3&fF#>Bs^GtYlCbUV_Z=Qy#5|ycn(UqyX)HzfIYsH4RR8`{&Y$yma%cnSp zwR)b0N&}vXRe#2)bgS#Ech%H|FLtdCKZA-hox|FJtNNca3nTgHvT&nfES%<4wikR< zhSg9lxn3u+QQ#S{`Ucmi+>?t^{=UxOH%j0m{ocw(#aR?y8WpWLx=+V`wEfi^JKwyy z^Udq`UbuGqez$KWkr_IgqZ+nk+oEj`EvsjmUES}({9Q>O-@pS zzJxwlhhXhCmA!_tyC-aI_wViw@9&G-d%}I5s4Kf|qYkgaN%wf>vJ;wdv-EC=WPu*>zF-{Yz0Xj|-w9y8qF@Q)#-M-sGQ+q5@g?0|y2JA|q z6;KCeHnc~QH&LAtga(G!flG;AbLiA0uW2NGvdIYdQ1A)`AT4`spoU$i5SfGtI8cO3 zIrSlG#<3pmMpFtqY7Fh8aXnlD1Q7`I)*VtS!G|!3Y>mxsP2RuTxqGL5=U(@2P1+Ov zzFla+%yK8XmI_P?`$E|6d5x}H>w5Km&=8`woOYG0r=*OeD@Dw`>{`dH;r_E{61$>D zD^v8X2EIpHyq@NY^%cLbf}jtD609~*+@9tSRIiT&K)xOftyls^D3EM<`0jeN5Eq-m z)rU^e(pgP_G%W$|^tvX_#l{3fNlP_*Y&%m&%k*I=4t$~S4SFtxpy+isfv|XaVgQ$- zCk-`kNOSG!JwLjgYeuFj5svD$?AE?s+g10@HmWB$(}u@fii^6-s@TO3IfcytPo=;W zSgRAPDGudSi&YAoNmX&KOx1_VR2AoGs5;O^sOr%ZIf?ynHbi8Ts$N{4N`+UTQsL9G zFr;M{bun1)$a>aF?|U{M?flhsD&0RStk}}|EPCjRQC5Ks)|zo4Hm>D-t|mH_O3s2R zzcL#qeF`dfm8g6R7vwjt?fup3oP|_<={lcAw)5o$Bvt&U$i!>!H*W0x)f@YN<=XCF z`Dh1)zxwgc*RJ3H+DEtF-rB$4AM{PbP69XaoY1s=)pA7B9vD{Nw0pKQa6G{aB`*+l zyC-Q)$!JPuOGZcQbQHHMyWN4=XeoO=qfT$3@j8Or9=a_C5*(zPfaWJT6uatMG$Co| zG$dNKs-pzmA#_LG?dqtf)>3zC(*3%;-PXyv(B)&>RCke6lOR<)ZKKw=Y2kHRP>RiD z!gk1BpWL;ZHDwo4br(`KxO=C6`*#1lMtvc0eG!K-?HyU%8PL#kR>UK2*u zwrUc^s6?|6Eie+{QZOn#8Q6vBO;~^`=^IH;kGoogHn+8?Yh^(+_va6 z6~ApJLvJMeW7(e&-dF-IRXBi_!O5UjYTPx_fy$yyN=(aWK@bOSr=jid2wS`2c1_;f zm-cstJGYv5-ru_R=B@W$yYbFPyB{}{rWA-)Zg>-V z!!ArC(}v!#ZFV|#w{3M>R;OimLDT9q>AlfiC6;U|tV69Nw?8!7f{7nn-;UXf)0 zmRCfB>s_JtQs`m3ls(N&Bo{Od|%!6@~zp|ngt6k5GD;d(oS#*|_-t=4+ zegF14C;fUwmCm7B^RI%_uH^~PWp31S9;e^23&M|mGOPRl1S)NNDi)?yVJT7z{wi1) z)k3O%V`)@hy0-mgf~V;R$&KnuAJ@KovyQ_5*@s)mq18cepuoMaUc39kjk_P#8cj`; z1J6tXGjdc%QOu!X4Q)s8JuwR8I8x$7b-kfxb}Vn;$CByxM7<&C4bf~0Mx(FQM5_g> zaI(cieDq`-1)ur`n|Q8AJ=tpuR%2k+diq}9tdT+~J3GDG4SAanAZigE1;?UY`d&-h zg^JNIV$@f{9y|;=@T$g=rnc8HY6GXmCvo>|nmc7rR50+`O?|%uZ*!p(?XKI}67OAW zUV~ljD%)MJt>)q|?ADFFeQjq?gKX_I%)PcvUez-9J9e$_HikYbY|BwcP5Lx(Y9zrw z;8JGV_eP>OlCTXXN;Fm7LNcPh9`>{VbOAmhGn}Z{8_%?8#u9T4*g38gDmJk4Au0rr zHifOQKm(n$rYNZuJxFLa8*1%-@7~SEO>nPsZ>zU`t8oW{wcX!tsBlwy$uXOwO%DkU z{oVjt>3774&tdODu%K2l94kdmS4p~B*4Jo4*kXNrJsaS^Jf*A?)FaafoMl_^V_;bb06e||>aHt2!6x>WrW_Ehu24gt7tcL=u z3(6&XeIpXxT=PdzE(0=TXPS}7S|kmfUPGyYuGJZ^7eeE5x>g&i1pR_k*{OKTz4vOO0MeBCRHUmi>g4J!x@TG&c8V28qVWci^z(qZB(eb z#aUEM;&e97USaLj7opmWi?GqEr=~if#;N)Zr|KvtthvR-U~*Hf=Q2D`Ju0*8*v?_C zcdYcgXK>Qff4HR7@uNV+nJTQE@fot-$g8nZlMPnaxOSx%huT`tbJG zuHSj(&erv2yKS0!8rfOsq@EKRjwd^g;5vgSlJnf~d_h*5ir#`wxuFoG3UFi54h1V5 zTIf(y$xgI(cckBtdRepiK%(W0R2(LY+@lb-%->3el$yRK|u+fa9!+U~x5e@D1m*LHeN zV+D;cE`}iM4P(E_miL59DXF0460~C&b_PMa=eLmH3WAS)zt!`bJ+E0#c?r3QbhNLHb*{5Ma$#3a#&l}6}Tu%;+Xs)@1K=G}ptA!n)hHcqz zie5vHX?)OTYev|GY~`|%ib^=>SU9#(f*P{7tL05+e zW@0!}AX083_l01UglzTyu|TEa>}qHnYS zcEPbsoGVcvRpHoNH>#=_oki7(&gUeUw7F|(LQBQrT|1>$_H!<)8W#0%PU1Hema0+J zg3@_UgYP|)N>yi4Rfo&+B)xbdRRef38*R7(C(W)7TGjZ)POMav)PZclSMn%jjx z1%>KnvXzKh(3czvMD>lDU^i(L%xS}!+R6^33Urn2fxfT%9XAz>pvR=D**EF~voW-q zL#qV@yDhmL#qX($SIu+l(GTzTeV!p-@e22QJl6$*XGeeHc{@f~9SP zhPKnSYXh&@cezy2{2@pfMYdRQi;pMLYMhIu8E9z(HSQa^Xpi6=ijfO4L?mdV62fl^ zaG(SV)u$IAW_>yBN-<=mEkrFbYJ*__p{aGO-KM_P)VEv4PS4&KgO);%2hs#A!EX%Q zdf%xJ+=dvml?bv(j|Z};>q8`@uuG9DS`DiwkUlQn20f%HN;E5f=(g2(U>A}zmfQ)p zwD7$Yw!8LT%h+xjTOE5B%@D%oAb?IS37bOHmXfYk44tXs&-L)o2oDTB6PT0HDqOfB zxHD~Sud7q|Q1LnxX$yP!roxe$&Wz%~9vwN^%*01{vlEL3q}lHq3?!gXW-x?Kc~I?K z!`2D~axB=7KQw&olDt$6a~%XA)BH?B0-2gO5Y4u1b-8;%vyj8yjkA~$KQLQ>9y7GN zS}24Qt2hpe2VrvH`W2&kT4AdC&8aZsS(gs~>t$@5@l@8T{Y%frO}jEDrd6SG z#;2w7b(~4%%RP_E&+nqp@0m`tNE7T|3iNCH%h$oym#^Lb%C&nhe0=YrL6@YfyE8;&eoakzRuv4XpDdJU+Lp7!mL=#kcF)=1RSz8rQ1T4Hq3!nT2W z8psi8@vTnRYSfk8UE%(&c%Qby{e6ippB1Z%ehcjxLL41f(O$;{yFG_APEEQ-KCniD zQ4IC0ujd0mF38q^z~xvYDVXc-M70Xp87bl1iVkc&5eIgAV7KVbd+=I{T3NKT{Qx)_ zt&3sOcSo)a8^(8MCo~SI!GOK4>cNt`g3%o64Uwj_cQub>i+NIyZ#B2Cdjl&J-Bj^1 z6$px{mYLhY`){hNoDbENPvdurJ7U1yZHf zMHy*^QWNk|Z%Qky!^;l%kOa1Ija&m&+Im4cbgK5=-do@_X5Nz!Y?%!|U zx>>t+efIDf+GY?F>FZ@Ax2Fh zYz+N+->bo^TE@am8T(2+a3`8K)j@P8PB zFt7?Cn5oH;=}%RBRH6=yN{QNLJ}|Pr=r?-SUf<&-`O7AMLxE>;=P)@4Ivvi{F#6jcQPFsG?JW=Y}3+NbldGr3?^DM)1#># zPBcCV-5=3Q8{?UQt((jAKF3rv6O^Z!=~~!h4>Qu#brg1U36;=ZHd{{iU^x_M#YiMGm5D^sBLVrM)1}24%r