From 45ef7c5be0a427365013bc98dcace151af16d42e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 16 Oct 2022 04:48:07 +0200 Subject: [PATCH] Spectrum frequency ticks MSB truncation: base algorithm --- sdrbase/dsp/spectrumsettings.cpp | 3 + sdrbase/dsp/spectrumsettings.h | 1 + sdrgui/gui/glspectrum.h | 1 + sdrgui/gui/glspectrumgui.cpp | 9 +++ sdrgui/gui/glspectrumgui.h | 1 + sdrgui/gui/glspectrumgui.ui | 23 +++++++ sdrgui/gui/glspectrumview.cpp | 6 ++ sdrgui/gui/glspectrumview.h | 1 + sdrgui/gui/scaleengine.cpp | 103 ++++++++++++++++++++++++++----- sdrgui/gui/scaleengine.h | 17 ++++- sdrgui/resources/res.qrc | 1 + sdrgui/resources/truncate.png | Bin 0 -> 9295 bytes sdrgui/resources/truncate.xcf | Bin 0 -> 48488 bytes 13 files changed, 149 insertions(+), 17 deletions(-) create mode 100644 sdrgui/resources/truncate.png create mode 100644 sdrgui/resources/truncate.xcf diff --git a/sdrbase/dsp/spectrumsettings.cpp b/sdrbase/dsp/spectrumsettings.cpp index 3b9b34b8f..d35913079 100644 --- a/sdrbase/dsp/spectrumsettings.cpp +++ b/sdrbase/dsp/spectrumsettings.cpp @@ -53,6 +53,7 @@ void SpectrumSettings::resetToDefaults() m_displayMaxHold = false; m_displayHistogram = false; m_displayGrid = false; + m_truncateFreqScale = false; m_averagingMode = AvgModeNone; m_averagingIndex = 0; m_averagingValue = 1; @@ -130,6 +131,7 @@ QByteArray SpectrumSettings::serialize() const s.writeS32(45, m_measurementPrecision); s.writeS32(46, m_measurementCenterFrequencyOffset); s.writeBool(47, m_findHistogramPeaks); + s.writeBool(58, m_truncateFreqScale); s.writeS32(100, m_histogramMarkers.size()); for (int i = 0; i < m_histogramMarkers.size(); i++) { @@ -242,6 +244,7 @@ bool SpectrumSettings::deserialize(const QByteArray& data) d.readS32(45, &m_measurementPrecision, 1); d.readS32(46, &m_measurementCenterFrequencyOffset, 0); d.readBool(47, &m_findHistogramPeaks, false); + d.readBool(48, &m_truncateFreqScale, false); int histogramMarkersSize; d.readS32(100, &histogramMarkersSize, 0); diff --git a/sdrbase/dsp/spectrumsettings.h b/sdrbase/dsp/spectrumsettings.h index 8d2829fec..04d1fe328 100644 --- a/sdrbase/dsp/spectrumsettings.h +++ b/sdrbase/dsp/spectrumsettings.h @@ -107,6 +107,7 @@ public: bool m_displayCurrent; bool m_displayHistogram; bool m_displayGrid; + bool m_truncateFreqScale; AveragingMode m_averagingMode; int m_averagingIndex; unsigned int m_averagingValue; diff --git a/sdrgui/gui/glspectrum.h b/sdrgui/gui/glspectrum.h index 9b50b5102..0ac19224a 100644 --- a/sdrgui/gui/glspectrum.h +++ b/sdrgui/gui/glspectrum.h @@ -63,6 +63,7 @@ public: void setDisplayGrid(bool display) { m_spectrum->setDisplayGrid(display); } void setDisplayGridIntensity(int intensity) { m_spectrum->setDisplayGridIntensity(intensity); } void setDisplayTraceIntensity(int intensity) { m_spectrum->setDisplayTraceIntensity(intensity); } + void setFreqScaleTruncationMode(bool mode) { m_spectrum->setFreqScaleTruncationMode(mode); } void setLinear(bool linear) { m_spectrum->setLinear(linear); } void setUseCalibration(bool useCalibration) { m_spectrum->setUseCalibration(useCalibration); } void setMeasurementParams(SpectrumSettings::Measurement measurement, diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index 2ea4ba314..d14ee6923 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -193,6 +193,7 @@ void GLSpectrumGUI::displaySettings() ui->invertWaterfall->setChecked(m_settings.m_invertedWaterfall); ui->grid->setChecked(m_settings.m_displayGrid); ui->gridIntensity->setSliderPosition(m_settings.m_displayGridIntensity); + ui->truncateScale->setChecked(m_settings.m_truncateFreqScale); ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); @@ -336,6 +337,7 @@ void GLSpectrumGUI::applySpectrumSettings() m_glSpectrum->setReferenceLevel(refLevel); m_glSpectrum->setPowerRange(powerRange); m_glSpectrum->setFPSPeriodMs(m_settings.m_fpsPeriodMs); + m_glSpectrum->setFreqScaleTruncationMode(m_settings.m_truncateFreqScale); m_glSpectrum->setLinear(m_settings.m_linear); m_glSpectrum->setUseCalibration(m_settings.m_useCalibration); @@ -689,6 +691,13 @@ void GLSpectrumGUI::on_gridIntensity_valueChanged(int index) applySettings(); } +void GLSpectrumGUI::on_truncateScale_toggled(bool checked) +{ + m_settings.m_truncateFreqScale = checked; + qDebug("GLSpectrumGUI::on_truncateScale_toggled: m_truncateFreqScale: %s", (m_settings.m_truncateFreqScale ? "on" : "off")); + applySettings(); +} + void GLSpectrumGUI::on_traceIntensity_valueChanged(int index) { m_settings.m_displayTraceIntensity = index; diff --git a/sdrgui/gui/glspectrumgui.h b/sdrgui/gui/glspectrumgui.h index 6612100cf..3d3f47c8e 100644 --- a/sdrgui/gui/glspectrumgui.h +++ b/sdrgui/gui/glspectrumgui.h @@ -103,6 +103,7 @@ private slots: void on_spectrogramStyle_currentIndexChanged(int index); void on_colorMap_currentIndexChanged(int index); void on_gridIntensity_valueChanged(int index); + void on_truncateScale_toggled(bool checked); void on_traceIntensity_valueChanged(int index); void on_averagingMode_currentIndexChanged(int index); void on_averaging_currentIndexChanged(int index); diff --git a/sdrgui/gui/glspectrumgui.ui b/sdrgui/gui/glspectrumgui.ui index edc077739..cc9ef8907 100644 --- a/sdrgui/gui/glspectrumgui.ui +++ b/sdrgui/gui/glspectrumgui.ui @@ -88,6 +88,29 @@ + + + + Truncate non significant upper digits from frequency scale + + + Grid + + + + :/truncate.png:/truncate.png + + + + 16 + 16 + + + + true + + + diff --git a/sdrgui/gui/glspectrumview.cpp b/sdrgui/gui/glspectrumview.cpp index a6bdf7183..f830ec9fd 100644 --- a/sdrgui/gui/glspectrumview.cpp +++ b/sdrgui/gui/glspectrumview.cpp @@ -492,6 +492,12 @@ void GLSpectrumView::setDisplayTraceIntensity(int intensity) update(); } +void GLSpectrumView::setFreqScaleTruncationMode(bool mode) +{ + m_frequencyScale.setTruncateMode(mode); + update(); +} + void GLSpectrumView::setLinear(bool linear) { m_mutex.lock(); diff --git a/sdrgui/gui/glspectrumview.h b/sdrgui/gui/glspectrumview.h index 234b220bc..b14c4fa93 100644 --- a/sdrgui/gui/glspectrumview.h +++ b/sdrgui/gui/glspectrumview.h @@ -179,6 +179,7 @@ public: void setDisplayGrid(bool display); void setDisplayGridIntensity(int intensity); void setDisplayTraceIntensity(int intensity); + void setFreqScaleTruncationMode(bool mode); void setLinear(bool linear); void setUseCalibration(bool useCalibration); void setMeasurements(SpectrumMeasurements *measurements) { m_measurements = measurements; } diff --git a/sdrgui/gui/scaleengine.cpp b/sdrgui/gui/scaleengine.cpp index c096a16f7..2bd490b45 100644 --- a/sdrgui/gui/scaleengine.cpp +++ b/sdrgui/gui/scaleengine.cpp @@ -30,12 +30,18 @@ static double trunc(double d) QString ScaleEngine::formatTick(double value, int decimalPlaces) { + if (m_truncated && (m_physicalUnit != Unit::Scientific)) + { + value = ((value * m_scale) - m_truncationValue) / m_scale; + qDebug("ScaleEngine::formatTick: value: %f decimalPlaces: %d m_scale: %f", value, decimalPlaces, m_scale); + } + if (m_physicalUnit != Unit::TimeHMS) { if (m_physicalUnit == Unit::Scientific) { return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'e', m_fixedDecimalPlaces); } else { - return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); + return QString("%1%2").arg(m_truncated ? "'" : "").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); } } else @@ -49,28 +55,41 @@ QString ScaleEngine::formatTick(double value, int decimalPlaces) double orig = fabs(actual); double tmp; - if(orig >= 86400.0) { + if (m_truncated) { + str = "'"; + } + + if (orig >= 86400.0) + { tmp = floor(actual / 86400.0); - str = QString("%1.").arg(tmp, 0, 'f', 0); + str += QString("%1.").arg(tmp, 0, 'f', 0); actual -= tmp * 86400.0; - if(actual < 0.0) + + if (actual < 0.0) { actual *= -1.0; + } } - if(orig >= 3600.0) { + if (orig >= 3600.0) + { tmp = floor(actual / 3600.0); str += QString("%1:").arg(tmp, 2, 'f', 0, QChar('0')); actual -= tmp * 3600.0; - if(actual < 0.0) + + if (actual < 0.0) { actual *= -1.0; + } } - if(orig >= 60.0) { + if (orig >= 60.0) + { tmp = floor(actual / 60.0); str += QString("%1:").arg(tmp, 2, 'f', 0, QChar('0')); actual -= tmp * 60.0; - if(actual < 0.0) + + if (actual < 0.0) { actual *= -1.0; + } } tmp = m_makeOpposite ? -actual : actual; @@ -104,8 +123,11 @@ void ScaleEngine::calcScaleFactor() { double median, range, freqBase; - median = ((m_rangeMax - m_rangeMin) / 2.0) + m_rangeMin; - range = (m_rangeMax - m_rangeMin); + double rangeMin = m_rangeMin; + double rangeMax = m_rangeMax; + + median = ((rangeMax - rangeMin) / 2.0) + rangeMin; + range = (rangeMax - rangeMin); freqBase = (median == 0 ? range : median); m_scale = 1.0; @@ -361,8 +383,10 @@ void ScaleEngine::reCalc() float lastEndPos; bool done; - if(!m_recalc) + if (!m_recalc) { return; + } + m_recalc = false; m_tickList.clear(); @@ -391,6 +415,8 @@ void ScaleEngine::reCalc() numMajorTicks = (int)((rangeMaxScaled - rangeMinScaled) / m_majorTickValueDistance); + updateTruncation(numMajorTicks); + if(numMajorTicks == 0) { forceTwoTicks(); return; @@ -518,13 +544,16 @@ ScaleEngine::ScaleEngine() : m_rangeMin(-1.0), m_rangeMax(1.0), m_recalc(true), - m_scale(1.0f), + m_scale(1.0), m_majorTickValueDistance(1.0), m_firstMajorTickValue(1.0), m_numMinorTicks(1), m_decimalPlaces(1), m_fixedDecimalPlaces(2), - m_makeOpposite(false) + m_makeOpposite(false), + m_truncateMode(false), + m_truncated(false), + m_truncationValue(0.0) { } @@ -570,7 +599,8 @@ void ScaleEngine::setRange(Unit::Physical physicalUnit, float rangeMin, float ra tmpRangeMin = rangeMin; tmpRangeMax = rangeMax; - if((tmpRangeMin != m_rangeMin) || (tmpRangeMax != m_rangeMax) || (m_physicalUnit != physicalUnit)) { + if ((tmpRangeMin != m_rangeMin) || (tmpRangeMax != m_rangeMax) || (m_physicalUnit != physicalUnit)) + { m_physicalUnit = physicalUnit; m_rangeMin = tmpRangeMin; m_rangeMax = tmpRangeMax; @@ -623,3 +653,48 @@ float ScaleEngine::getScaleWidth() } return max; } + +void ScaleEngine::setTruncateMode(bool mode) +{ + qDebug("ScaleEngine::setTruncateMode: %s", (mode ? "on" : "off")); + m_truncateMode = mode; + m_recalc = true; + reCalc(); +} + +void ScaleEngine::updateTruncation(int numMajorTicks) +{ + m_truncated = false; + m_truncationValue = 0.0; + + if (!m_truncateMode) { + return; + } + + if (order(m_rangeMax) != order(m_rangeMin)) { + return; + } + + double width = m_rangeMax - m_rangeMin; + int widthOrder = order(width); + int maxOrder = order(m_rangeMax); + + if ((widthOrder < 0) || (maxOrder < 0) || (widthOrder == maxOrder)) { + return; + } + + for (int i = widthOrder+1; i <= maxOrder; i++) + { + int irangeMin = floor(m_rangeMin / pow(10, i)); + int irangeMax = floor(m_rangeMin / pow(10, i)); + + if (irangeMin == irangeMax) + { + m_truncated = true; + m_truncationValue = irangeMin * pow(10, i); + break; + } + } + + qDebug("ScaleEngine::updateTruncation: m_truncationValue: %f", m_truncationValue); +} diff --git a/sdrgui/gui/scaleengine.h b/sdrgui/gui/scaleengine.h index 904b561fe..b562004e8 100644 --- a/sdrgui/gui/scaleengine.h +++ b/sdrgui/gui/scaleengine.h @@ -19,6 +19,8 @@ #ifndef INCLUDE_SCALEENGINE_H #define INCLUDE_SCALEENGINE_H +#include + #include #include #include @@ -48,6 +50,7 @@ public: float getRangeMax() const { return m_rangeMax; } void setMakeOpposite(bool makeOpposite) { m_makeOpposite = makeOpposite; } void setFixedDecimalPlaces(int decimalPlaces) { m_fixedDecimalPlaces =decimalPlaces; } + void setTruncateMode(bool mode); float getPosFromValue(double value); float getValueFromPos(double pos); @@ -65,10 +68,10 @@ private: float m_charSize; // graph configuration - float m_size; + double m_size; Unit::Physical m_physicalUnit; - float m_rangeMin; - float m_rangeMax; + double m_rangeMin; + double m_rangeMax; // calculated values bool m_recalc; @@ -81,6 +84,9 @@ private: int m_decimalPlaces; int m_fixedDecimalPlaces; bool m_makeOpposite; // will show -value instead of value + bool m_truncateMode; //!< truncate upper digits mode + bool m_truncated; //!< true if upper digits are truncated + double m_truncationValue; //!< value to subreact from tick display values QString formatTick(double value, int decimalPlaces); void calcCharSize(); @@ -89,6 +95,11 @@ private: int calcTickTextSize(double distance); void forceTwoTicks(); void reCalc(); + void updateTruncation(int numMajorTicks); + + inline int order(double value) { + return floor(log10(value)); + } double majorTickValue(int tick); double minorTickValue(int tick); diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index 9817bd60e..1c7d14c12 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -1,5 +1,6 @@ + truncate.png caliper.png flip_windows.png waterfall_3d.png diff --git a/sdrgui/resources/truncate.png b/sdrgui/resources/truncate.png new file mode 100644 index 0000000000000000000000000000000000000000..87251a2a0f9e9a52c41234c5ce0475cd990c483c GIT binary patch literal 9295 zcmeHtXH=6**EXO6(wp?&1BTw4NRuwoi+~{s5C}c=qJT8%y$eY1O+Y}TcNC>4MSAa@ zfE3@L=bYy}>wEv4wZ8Y?$y#@knYregy|2AzR`#rfX=y&f$DzhSLqo$?QC84KeNx^$ z*tbyc--Kf(7} zZVz=j^SvIGTwg&NpaIls=r}xwRTaYC$YuwdAj$Jqe_l6_JwFSd@>-D}sO~B{KkBA1 z@r*q=FTI$wZp|7_zYsj~GLx36%5bKg@l0QGz4D!v!W0V`DBTy*+Wm&La}u~%d2lo> zdrF%zq-+*#o9&FhynWvG^wwDIeL6MGVKwU`+R8l!!F}`o_?>UiZ{2%)z8zjHjto{i zh#uJM%x3oa144qRl=WcLoQuCzTDh@M#Qc5iVSc16A>_lkkxVeOBC*{ z-uOWFNLw`ZuJT*)`~-ya!p@xvx$$-Vlz6F5TF}j}p40m;?zR)K!&+R3=OEk-tK9wD zYIao_`WaY5`wEU<*nD)Jb{oxNEpnWzPdO?!a{?`Gg0mp zAU{L3WD=SsA0@t$p;pmNj%6K8qQ=#jpv{dei+FnOwh~~RZdY+mt{V=l`>tA=xxeut zgx-6zG1)AH&i(}hOO((dXRfB;-TV!!6sLkzt5jEFo5A8014F0$L<6Ifg}TA=Ec)m3 z!Y-a4?H~6CZ7c|XDnJl|Zfgdd;e{Bj;L|@|#K4$(HH;9MH95#QQ>ReVzdgtrcm}6D zprk(@ov0exk%UG+>UR0r=fHJN(K^|Bl0owADrZgRVu!mDA0Y4Ry$#8s)RU}<9=56w zF#xz_MQt_{ULP01X&N<_NV7!{TL5)Z6FQ68uffp;>J=)$pwDtlM^%-`>g4vR_V?>O z)Z|63nU6P1CVaYIrq?>z8i5}<+me|1|Ex}`zWr3<^vj`*o~Z>lZm#-gD=vF=*1&u0 z&v+X1B$Ev+t5WTX1k0rrG%q}5%`7)_?$cT1_%+{=7&Fo>$*D|0vyyy;A3+ja`fAO*p}+ zY!y!okB-ga5^U4-$LAYVzH?v}B$1$kAgO!BVha3JFSlNv_SLo>knY{1KoYD#q32_hZ8 zM%n$h;QJHb`3>s5r6x=^R5FNqhk7!eJj90e`;0uQ*U0;CjbnS?jd2x@lKOW|LxAB2`u&$9|Dk+-pNM zTqjUJ9=CYJXek)rFil-5`Pg+z|5@YCGZS)1=c0w2h5R#Tle-Li9y%~%momf~JHkFu zWB|59k8MP=my>TsdusU$ZZ>@7FyjuJHDlIFgX-cw@AqUgD{NZLxQa<%I!6!Al`9p{9&yRWgAWd(9hmO9!<_cb8~%b=AiP--q6&Sv(^>CJx9JA?E-}|lp}UmV#A`h zisowDhB37mxO z{Kkk4dG|>$Yor&8u_QU|Gmp>&rzQ_S1y3IfX$&8UWrFx%hOMdK9V`Ut_a>1jUv{Gf zwM1St965^OW~Cv%1`*?fNv>P!DH%I`dBaL=*lA_x2(1RFjL6qW4NQ1Wu!}kGm(03! zx4wO{ti(hHH89>64FE2=Y5of`qRukDN^LYS3s&T0J{mwcUrq<7>tnfb-GW|;7b_bZ zYcS@Mun@cWc`+fCw)a;Nk%DOqk&c^znPc4qugA`-ua-Q;AIb7fVAN}w5{2=yw@gw&+#kw zL2Jd?bE8VUWB$ztRJzj9Kd!PXgCSK`I=dq!ax#8r?MV;Pv|A<*u{fUZfltcgksW5) z3mBN_^EA|bse`XnQ@Y$00{HzH3#wROC=F%5OtAQpDJ2w3y6DxyDY)ZK0e+ z+OJ~v2F=VFBkDy~>!J=?ScQen;)b6^u`aT^MDKVX46Y>Zz$jn*2w3oSS3i%VG+^=r zbb2f4E)K>jZF?-Hrmgx6o<>>0@mY$mU#)$8a`Y(j;m8@fuHueGsOdI|hA z;87&J;Q*EdtsFaOf_ys%-v>%Gzi&*E!fRo(^O=B9>UHg`_?lU-yqYatv`dd%HArOK zdn_828K)7X8z{dXF32h1FwGQ)y`OvF{pn)p%@}uN)5^k5i`tKDAI_Bx#k01|^e`{_ zdJ|nG`cLxiinP}>9eWZa+@(sy12p$JSI62(@ve#SOy3cI9b;2r>Kfm~aO&(PDb!i- z8@pxk{mBS{CIc9NZAzF_pO@;vupi9@GvlsOUAD2(B?w-BK`_7Ggsun~TVrV;{=~h= z-!_7+d<;Fj{gw7R0T5$2Fao|RALl?zBkx$&GH=+(?8sYBd+2&l{;@vcb2%R)5yxVK zy00z)#%y=;2zo35RX*a5ly%%FfybTVOM^6)&G#u}I4|y5?9t%h>RKFe?Z72J z%&!s_a1n9&Y-kfU_dAbu#uDh{&?>_ZxQAnJN^Py>FY4jTx^K zPaK?J^BOC#8yrwAiVn7gylMFQ~s&1aA1gV|WaPH7;W#JQpz?^51-L0lg{h~o_ z{h>r1=mhFdto`iEf!g?XERlkJ;q&F$HWjrhOZ@9B&6I`MJkj|IclhNpaTi*T`l)*x zCu88GG*5^R9D}sW$vGRI)FUo^LbOhNI^N|mtfbr?GBm-CsG!h`>>585teR;1o=c<` z-6xAtJW6hHABM+oVCxt3eU4%L=Salq}l@4H)1Zf$X!G;9Qw6T09sxYnNBYl!;! z&}m;Cr|p3cuy~0@Ot+5Hw2-s6hF6(BP0wAnBZ!Oo3EmG^%DW`qlbrd_KBWRis(8n* zOt;ZttU`l}(2_6m>UIon`~GAXW|=I5yI=Lm`MH`HxAVwS6Z13i6|+y9R$D@~Trk>| z=lnc*6JjoBsz7va1K?^<7JU77*HDNs30eYcX0-GoQwF;DEz<_v>xc9Sm_r&e5j-aA z)zaS1b$!={PPr7qq-CmnyOqF6|3j1+W39E|N% z72SR*B96it=>r;v2*h~Y@$Cx9%!13%np~2+IiIvcMjZGXx5PpOGqwND8l=9_MBX1z zxbU8d^y492-f_+Wuz!3k!c9+yPRp9^!|gp{f1S-W`vX!c^iL4%HYu8G^ha6Yo{P5t ztEwfQwzExzHWlu|S(>zf3kuDwo~L1t4i}K4p6(%Ssz9xg#jB^6D#VVV%M>|JXqm z<^oRRBb{KpF-N6peDa)s?7}h_@3<0f*;gs#H$khMJ||jo6c}V`2Nks^XE%i^9uCQO zmaJF`!m0J^U%r+$f@b7J3x`-5SmH@QmrHjRt|3!re32i z-GRGs5bXYvLU78|;{N`8Qkr~N5_VskBLMLE^8LXkqLNGge}kTknqeX%E2aE&!4{cvpN$&2~&;J3hqmz613JeccW=tgX#BQvvfs*A%3W>6f2X z&AWCZ_0OIwgyg)$E}#T3cl#kCAa0d3qRk*O+8?i{9B2nRV;{1e&-i@P(j_q{N#J|<_%j1BJtI}JM%G~*&zgE{uL=t*1MR(wSK`hlC z$KR8qdEqqCQl7PY3jXeU?mQK3hg@-&nIA6{`2-``T5bT z3;U$;YkwHiYt2hO)&Ah)5nznOsM{LIEEQJYWo<}cjh3vcmT@nhOCLif9j+zi{z!kl zWRO0f>Q_}ix~BRXpZ5eZx0Q5g;Cm8HRq8ze%aD|KG#R?TG{UAEL?v!M;AzCk!AX)H z1nhVoatE8Ku|;3l7a^Cx;a4=WK@NQBHQ62#JR=-fvalc9cKZpzr?)c{bcMFDgOd^o ze2-Vq?jD*cf#pWf4w<0@vE@3hQ09tT)~p>JfHs1_<4ae3dbJIK8My zLvw0$jZABwWB))UZ^v?ajR7}U1C#j>N>_v9@~~wr!!4L*%To;fpfW7sN8Se_K@-xM zD<9%QmLy#y;ing8K@xU>HWW5iVdJ4vuW{;=F);F8)bg@~N;RxU`Nc9d6~H zp#2$*rDOi{*}^cE&fL!*3&WT?t=E9=J;H+7$kT?vV!^uSvzB@xlr5K-fyOT-e-a*v zm4tzYo;^WBLw^aAm)BB}m;du#26Y>g;TtQh+$l@jZEm6nNF)GqF2>|Y7!lob9pfU) zkt@1q?8?`8jGHFJ3gC$fux)RT?k))oudN`c2w*%zUtC|#TW4mw<^{YBJ(z#Tu(vC{ zJBxm;6jW^ajWXLNDOQvHCEQ+b-BXbWr0_W!7MA)WgR@{>{KM|T(w1q4m1ow4%Q3(+ z9$m)YBWWX8@%=-oI@m@AGAy@@70|WTm5XT_a~8W*Gw6^JPH^FAIo6lA7M9y3R~@)Q zV96%W_L?;cP@;5xT{eib2K;1`-(!qi=EYm7ON3U8(#ny98wOyb3)pbxV&FO%3u~+A z!5%CuFd#0O8zIh#?S0iRxOA1H7%mC@+-=F(duH;qFxLI5ccMYrRutA>?Jh1R>eD%7 z=c(R}OkLaDN;zk3nf+?p3G1~T>|W2 z#{+^mSU`C^>>N?|XlQ6s4?G+}U|T4H(E@4(vzKPxYi?y`gh8a44TLrLG#urj)-Yu+ zXQ+;srY_ja7Ay{7ejtM*J0ydfq;3TaHt)M)CFZ9 z|9{~TFw6gl^LcFKtcjweqlkdu;_29n>a{3)KZaV7U1FgMgFTt z3l2h9Iyl=&GpobwT|NFYpbN8u>L5TjqVbD}2#bjb2ndUdh>Hn{2>%D94|R4yCEN`s zKOc|aZ(aykLJ7qPLM0B&4rB%8b+otoHRUEO5-4X-!h&w{6vh0jALWaLyfYMpaB$Xj zaDYoQ-&n?YL-{Mc8Kr&)MH%LTLU`U}{2w{519ke{`n?6tDJ4kplk+{BL&sE7w0#;2(ki&947%a^d`^;DOqs zeg(Os%9)@xVPiBj45XI2t|F==`uX$c$;rvbj~|(tneFZEudlC5OG~k^uuwymmX=pn zSJ~Oww{PDzG&KD2<40&{C^|a2s;a89v$M3c^#1<7wY9Z?fWY?lwvCMq003BBUA?@# zeD>@aCnx91%8IF}DF+9~^768Yi3t-E)7;$L`T6;iCr=m{7-nW>9zT9ePf!2-`}ec6 zGj(-!Iy$=P>1hQ81xiZF@$vEF<6}8FISLAj(b3VPqa#^aS#omnk&zKmQPF$%?tT9J zSw=>Nh={1azrU}q@AUMPkdUyarw55dDk&-9_Bjg4>Jx>Zn65Ed4elarI5pWoQnn3tFL z<;$0ijg8#gTq-K6H*enX^Yg2ysDMBqPft$_42+nVn5?XHdCZgh=kdPoICKewb9~T!F8yg!E5;8kG8yp<`;K2g}0|N&Khs?~(i;D{$9v(9@ zGdDN4$jHdCv9YMAsOacu7Z(>NC#RH@6fQ2V`}gm^di82zVnR<(kAQ$cQc@CClI`y9 z!r}0>wKYvm&4q;pR#w)B4grvQ_9S;xh-Me?h#Ka{fCFSMig@uLd>+9+1>91eEPD@KmO-&6C4-X0o3JeVN z_xJbn^YiiXL7*yJM@Kt5I|u|~VPOG-!OYFgpFVx6t*x!4rKPB-h^lu*L`3xU^@W6l zHa9nymX=spSSBYYsi~dAeC@3f;C3SFcU}R)e zTwI)yks&WHudAyoAtBM)+RDqztE{Zt+uI8S0@>Nw)zs9$U@#jSo0pfDudi=FKmaP? z!-yNFQ2C9H(ALyJlU&GzV{kH*Hvo;`cESFc_%F)?S(oaxb{N4(;IN z?z^vU-MU|W^;K?eZg_b3i4!Mo-n`kVQ>U=7u;a&%w{G1!Ffj1&;ltOjUvJs6Wk5i{ z!Gi~{UAxwzMGJp_{{sgOWMpL2sZ(eF{{1;QIbL2~pMLu3C!c&$RaNEb>G{z|AKkcd zqix%^?(Xh8cI>$4o_pNf+{(+#O(xUUty}Z+^9u?Jwrtt5dGqE`qei*9x)v1`ZQ8Wy z$tRy&yLPSBYJK(;5Nx_bczJ1oLSx1i^y?pudE3do~5fL$S z=FH5@%o#IgOrJizq@?797hX7d^5pZ+Ki|B0^M@XKXxOk}ufP6!b#--8Qc~~Uy+@B8 z{qoB%A3Ahs%9JTnr%oL?a^&NWKVDW=78e(nkdW}wOD}!##TQ+>cJ=V^Xxg;t6Hh#G z>C&aag9m^2-FKZkcmC#^Z=#~2?z-!)ufP8KhaY}8cI;SaXsE?vsjRFF2?_cB`|pn& zIkIoxK0iOdUAuPq`1rj4{`+RLdBcVc-rnACzy0<*@4T~Q$&&Nu&%gHCYj3>q#_ZX% zUw!q}Ns}f$_uO;i$B%#JnP;AU`suM_#}*bA4j(>z$dDmii(PFzx}p;{rX>i`DJi$@ZP<9ckkZ);fEjY z+`03E4?cMBz4w+cU!IbZl9ra1ot=I4>ecSuyTA3;TXW{jY1OJ#mo8nJG-_`{R#4PE1T}(4axbjvf2;>lYmzJ!Z_9r=EK1*=L_chezM`rh5Q4f#Qp&+6uP> zJ@N3v(+N+y0sQ4Qy{-;!m}_9K0^C}O1Bdh}$WJU7F)$B@=w?!u$Bry49-JRBa@gR3 zc@0gm{R{dH8$4`8L@ZO{h=RU-B2xHYqlWl%-#h%dQ3U^^KNpQ0-lyNdp#>3*Qm|M2 zvpu!P<~f5gav!-h7CX_S-_6Oli(->^Jf zc(a(UUD_sQ#x&0{W!Jnh#}pBfUD&4}VrZWs`OPBR6bH+IS&T2MG3GAAoD<=4FYp@Dh7?$x;?2Idbf>{E#E6`9lM zADsIBeEjC4=(Sz(i$vz6{)5+d``a5LbJ9{$lK;^MbpQ2lxOc#?!eL3RsOLR^9)z~M zo^*H7Em)7Xn~wwH4#bm=Q(ttI+aM*f)^=#EZBwo7h+5ljwYJT*w%u!Odtw`( zXTaYL^mXV?r_ZMIN6T%H5=Glk3%b_&wYF<3L@*u4(|{)w!XW{yD@0*_QDNfXKE?SX zaEQK_gIDa3J|i9*H9R6RTi?jZ?wga1yLo8D$bn<>oAr#$NXtmg?1>(fmYqz;bF!21 zie&lfNZjT9hYc-^h1&(OR+Bl2pFB+~mM8fD5C@UDKx4qSK74^133lFrn(&&d45yn!R~`%zzx7+g342Y)GIx`vTN4H`8P zU8p!>aDM+ndiSuR#394-@+0z!aeEK!Cl9em{d5%r2I4ZHYJ3gUF0~%&*1zri)ODy` z@ldbo9Q~T)C6eFOneeCgVB2(`e%$ne*V)UW zvv*I)yLI-Zeu0M{etYIHo$Gw8bHHH9g*pfB(>ZvY*e>4o}nLC6ss4W9=Da- zPRV^{zF(29+%`7KEB*9_lSomj>)bcxvsYLZERGd2WY5B@I6G!*GJJH))x#1ksrmuC*#v|9F z#I33$YhE7MvW}B-%cn`-m)0D&rHShAHcq@h*y_+io_V`s`({agWK+da*iOyvsAee6 z!gl?g?xu9bRoJf0Z)<3zn1%i16LpgHZ{YcqVt39SovGY%y=z=~l@RGlwM*;gcHT0| zGlnWB+#59SHn8Z0S&P>0IB@LL*^0~8Z)x`Gn?GKwJp0w*-5bhHPYSkFVXrO=O2w9o(3Ukw$A(d8pEhZX4M$=Bwx>gea(k5! zH^!N=6x%AXre0G;o7~ZAIH&hJmtCUb>L*KI9FUtG8{nxLT)cuJGrA0){N8s_=+vu< zJA~I!Y{B=;I1wsrU%%NaJY2EIjQJ`+XhZAcCv|AELh}<16)ojmUlFfpO%8kGX0tm_ zsP+^|ie@?EA(9m>@FREJjGFUXX3eO z>x7#3d1sNKh<=2c@f)MaRK#P1ntH`aWZ`9uEeSP4g`;Sqh<6x=Go~?`97R(_oHG#a zU|hubD&rIbcYU<+t+{cD3R+!Toe{723T<^lLj^yKeO^!u`nvsx5l+!cpwJFkq7?jw zw&$HAl@OsFh^?oD3hjE22qj!-rB2~WU7>C9qI*F5qF$&{PiSWvhA5Fj`#v>TsV}t3 zgdhc-<-4drC0b~w0s@oZ`;FF^N#KrTZxH zLfdEXRuY8hOQ@YQdnt)Rj3v}Anmv^yAx05u=bSv0WFfjTZu3x5gott{9LspvU1=ml zyqRzmV>zLA%j~A43ek#jEaQ8O6>dtJ5Oqw1Ef@zePGWqE@e{_=jMq#`x)4TJLVw13 zj4_M}jExu*8KW6P8T}YtTK3fNZ4%X$t45?bCMkBmA-kPK^`&KllN>C{?YlOMmvS6&CuLfl zxAW)K7xoVxbfV5|KU?TV-PnHdDG%zq_KLwq?ytw%c~j?H8pPf5(u33$wfXMc+m6Oi z-_ovjqAsJ^@?8~+5KpQ~V{}s&B}0fpXC+gJhmAn(W|otZCA9Maj!F}uZE`RuP0@D= zZ8zW(XA66|qBIj)SAyfl93ckbdCF?oF2rX!!fq(Ilnv9Tg@4ji7$7OHG!agU7@sAK ziWr*-`zYpT05x?_W8tD`N!1piDq;$u=6Nk$xGG{gV^q2@DdIpH;q#2G7z5K_aYbb+ z;cmuljB6N|Gj3%3i1A1&&Y(HoBoa}4ihI)pn@vZEyJLhRy5sq2grbRrx_~Kl6}vd+ z5Uw}~k;(WX<6c6|4&5;b(TQ<9;~K_q!r+Gpw@|`(#!id_8OJhCWt`8rjBz#Ndd3Zm zD;XCvzQOnk<2c5A#tw{0jGm!%Jzw)RtY&J@PskB_rbDZxdVsKe2>WBu4X5Qj2q7}{m zvj7pLXi+BuMSVqUToEK96|K{c!SI^2d|QY>XLu$|gu{Bi9u5aeb9=9@2*ulWMTihw z!&mj-OlcY4M~Waty9fSXprRGnqR5jP-$2yC+un>3e)zNvvBFo;0`@c%K8n`hWSsC; zw5*Hq!b{O|s}h8#q7Aeq3J*m*mn_Wq9`jPrr8W1Bji|o{?oDN*32i>eO23KmO~%oT z9T_7`bZ=jGAQI(lM4n-6?M9ZS+KouO&&KC*#(HKlQ2W_Hjd6$h(rm#*;$604xgKQL zPQ$Rl$_?{mlV>6lPkWIuyzEUR3cblpo^l})-F?V(?sV`Wb9y_$7bM2}k%`@J^n+Y! zH&(B5>YPkzKgLzDt9YN=y1ybEoK zV*{m*&=xtyz~|8BJI0a+GRM$R@e$f94sme1#iRsyC*tWu#Y1S?uq4GDZPO} z_KB|x{4Q<1n@VJKaH>>wD7e^7%d9WVDYzj5`HJ zd}mijKXiWkjrnN-=5e zTgCqAU_W*Us+Tn(kJkS2gO23C+Q07W$Uf`gTrawhKWt1lwcS3&#IC?sEy=;urnASW zeH5b7_qfo~g}#-oFS`LFjr6sjbAtI7lN`zVKhD-)>&DjqR&z4^-}%GnZ?HOy6IyP0 zGqU&1_mI7}J3MkOi;XLc&NFN_VL~-=f(+}^0IgnKMQnz|wzN7wq6i0UJps#GolHh| zr*3o~WkY+xlg-$RgxU|@Z0nvT)GoSV*h`kofZOfc+;kz^GZcLf_Qqin+Z*S_Ze(dZ%h}R|9AHZmf0`{# z^UG{$y53|<^SI_sCdT1qHZd+s*~EBmV-pj4kWEa&w`^isTwxRQ5C-BfF(b5K*cQ!U zYN$X%xV+6a#_N5yF=2<;#w4C$8*|qcwlUprv5hIzXt1ssN}`27-nXm)NVJamosb&Z zRncNjrP00Cq%xiEvU{ueE*oTT4ChXBcp+2ZJ~A%IB9G5~a}(+hLHn8tyAu0#w$QRG z0q@-a%yEMMh-el(%j!M`@-wfsbENz0TqC}}j@0G*>jQ7Tzurb368G0s2bD~mHo`>r z*Uhece_d*3Cd>78LwD-sdxJdaF57^i87$NrPF`e`o@HxP-Orco(Dn9ght8+fp|Ri> z_58^M?et+2^o|-xqs9_L5SbmVkj>7`huG{~Zq8=sn>aQ*`-ACb)Hb- z2(4W4!a(bT0lp2f=__ov*Y)&9IOYn*{kEOOQP>KCTlQNae;>E)ib&2;s>PYt?los9 zc0;Qbj-tAH_w;VzjTC$Olyex9oq20mmM21(!M*37#gOgXmgxg>>Vzt{9YQ)h`Oe8u zar)Y^_m@m5?9nPSIVRlS-RR)r?h{xy`K|~07r*k}(HmC7UjDUlTllV`;f^-&1`l*{ zuJ8~iG0iW?DNN4^bW`)Ess;B0n(hR*GY$3BIFv zo$&$2C_>Fpl_gl;V>zLA%PkPMooK^2ig6+1AwsR%B|uSyNMLNo*q8As#xlm0j2jrYGk(f= zfbmPlBaHhQ^}l|=+wgaB{x=w3VjRu*AftuRH-Ikj5?|If#;J^tGByaLZ+4Eq(-OwK zAo|Mo03xxITVZ4{+6BHmk$9II>D~~MmT#Ph#4s8tYLytFV!Sw(M~CO!cy!nw0Y|al z5r*1sfq9+^qwHo?-eM#Bd)k`+`LnF17P{FtZWlG%zmFLH<4>`g+Vi#jb^`YEGut8t ztiI-tv8~N`*GmT|ENlyT^v#o=aI9@155IcU4ddx*{|8>$c9n+THyvVnPW$jj_NyHm zcCjLV%6f=~v{~OibelZ4n@(|Eo|^mqX*=mtm2-64f)^KUIdoCOfbPZ#ALX!9NLq(S zhd(`e_R{qq9ytE>*$bDh-Lwh&?HfP-P&sP3e1Y7yt{%qwJyRwzH7qON9wgp@H6+YxeYZrU7d0$e8o#=zD z*@>Q_|Aj}V;xhKTjle{=eG)X zu)1#iTe`(%oMQcFo{l!fiYFeQEL*M+khr+_x{z{b2QeUFnu1wJqrzp$4{L{rq5$D_2V6> zf$`{=CAp1cnJ%ZjpWch@hEySlN1RSdT#~*K*IDv|l6y<;FZr;}@#w_#Kroaa36JZX z*g@x{y^@beKB;rcD4iS0^nIF4U#Au6$J55?Y@tqsN8=YIPm^4xb7q9jS&MaUDsQgr z75aWNd3`xe^!?`LI=7JLxhqfKZzd2n2?5U20CuwufEj^itYqa^~ZN8m?;ib*B*E(FGQL)EPz0{b7mhHq~5W2IUDh^0eJYl1jq$DU-v?4!o z8ibde(gvXnAiV3#J5dGzTWM}lwDO!YqRY1p@%?6hZZjd6Tc5i_oK$r`@o zlpo@D)logBe|9?%19=e}_J0}ldU}>v5mTe8y`-2C?W>iC`Zt~ zoc~z5F&;arsQ!N4)9t*GE{Vl}>EU97A z9r4$Z-?Ihos6R?MQa3vg_6uIDQK;RaKSC1-_%(Q+1Ah5cMvC-#zRi(7%PE!0AiCdh z<;>D}j`X>_!;wDoR*v*}f5MTzItMt?=e3U`eQqCdPRV7957a;`@kQ8ASp6um^bjgC zkXTBq;;5hJSN_N^iFX1Z6=G;0WtWm~ap=#uF9=B{VGX7LVDfFwF&XxRKuE-ZP{@bo zbCF1thEYr~$xbBJh9mnVn$#uSRu?HK(I$fM{RrftMB{pd@6_XDl$}VFMp8=3`~#6F zs86`JKGIXd5=B@RML8 zEne78O|Uq4C^pCDQ!g|S_HFGP{1m(K!M#ZP>~D@QasMfJ?6*cchAMV-s)iuj=~T2* zd&GvcT>)sr*sqb$`OpI`9DV}HoCBU{_j*X@d>6v$99xTq$m)pkag@|K=u9MX;wiPW zj8Z$Ay&-3KmQWRnNKb@y5Fe3^5RWEN&gVxnkyxBe*d>|rKR4Wn#CozQVmM=53Nk{X zf{M$;O2(0l%^FdP$ZjSQhf`S?Z@`g2)Jbt^6txYU4?1IOSTAfdOMQUqcMmkiuWqeOvr!o+#O>4cir zTu&O9IH5R&s|c#&IPJKV3s1UI35j-E<*4LHP9}WsPRRuEG^Z4<`Z`m6!8jyh&LhL{ zy$KnZbi~8NU>xa>BPSiPu>uFWB2pGuiGg-GjKp9ZXn+GwM{r;=4m^k~#YGn!G0>3* zail+Z6(Z55OSphrUO4g!j^u$ez*~_ILf}cW*TI2FIPfUA33vtGVn7UAyN=khcpFFB zgY&>Mzzx8M@zx5iNm$7^hOr%^uSKv6;WS4Pfj+n!@SKh3aU^&}9dF(5lAh5Y)1Li# zuIew#{YyXo_q5siXWhwi!&tn`CSzwqDvxlgA`+?W0QP5`!ML5VG7iNPA~>F~9pf;@ z>5S_bzl^8K3d1cTQ8$4whp{{3NX99QZ!zvHpIL1+ogBTxW?8?}I zu?b@gV;w@xQR8oRh4CxKj~SOUmL#yLhKX8|N`~r5#$3keRH|;Mb|MnTXf!3(G0tQh z#n_cGgE1_P>L4^Dk+{I4$Nh|(85c87XMCD*C}S_idl;KBrZ7e^1~9rYI;2zV{HBHQ z3gdakuNjXq9%kInxQp>)#t#{HFn+-JKI8UUs2|r~qrd(m{_AIq`xp-~e#v-}@f_nN z#wte5LM@>3HTy9}FeWf&GPYyv#yB9Itp!RM&T=WkM#h&J^B9{m25}YKbuN84#JG-e z7Gn|PBaCer6BvC7H3vPrR8dm~hZM~RysekY&ExG7#&L{=i~|{aG2X}6mNAF1F=HZQ z6k}b+5JrDSZ$>kt8>1_u%IM7KRBPLXxAoVUcw2w37jM^L3})0nOaI&iK9bIu&Dfgp z9>#|m`!kMUe46oP#y1#OpvDSe0Znv-fQV-aHhLo!a@oO)isqsi?_)&m6OJrn{DM%k zsh*TbNo2g2v5>KhaWms7Lao~1K?#@u##F|87zZ#u%lInea>jDT&l$gEtnxsxL%6sT z`Y?tv#xSNbHe+nZ*qQM@#;%Or7<)24!q}Jb(OSp5^S1u_`*~YGPkY|ZVN7F;WejKZ zWmMhiJKp50J%CMsxx_OzgIicosiNidL7#||k%vBr=dW$iaP;LR33AP}MeqLRZ^4fYr1vg|ya%Q+z80@ht?q$_O>z z%1{b}4J6bkCWh!v3L<1M1mg%b<9;d#;z%08YQq94#I_=U3c0;bQtBI#ggP~`I6W{& zzX`OYh&`;A7~f!gm+@o9lZ-dg$+`7rCpM0;En`081jdDoA2EKPM!vEad&wD$eHmY7 z+{k!=X7PzIjs@Mz_#)#@LhYst2aoPze4cSPp{9j!xM>jMRzl4l!a=Dg2(_;a9IZn7 z4l%3ki4@FgMw0}^jsyyCb&aQ3*J+P93Vh9`P?P9Fv#PYKu@rF9P6eXfn)_o`l|NcD z>nh@BMN+6V4;X|_OA9Zo?+ByU%0b# zTA#5Q<3o(Y87DI?WBiQq0@wPQ*%5BU_#oq0#-)r0xdzzj7S{l$aG0ha<1EHKTovqY z!~Cc(5aDTq2+u6=3*b)R-3SH!=!(FSFX|q|Y8-h4f9VHag}-Ql_=_3k#o~SWmjdt> z{N=U}{t~U>FYn?=3EtBk2Yi0OpDw8gX^qE`sW{^Q12$rDU^aL=4rJP~@esmbE{J4l zUppD~66K-bo`{E4x?$rM!e7rgQ%UX*h@W9+oC}rdUi2Umg=$UA4WIrX&)zEMIRMoO zJO=<_I+RI%g}Q%=;I-gl{~287f5MH6C2ys3X+Oe#2m!vsHT@J1M0xV%7;mcMr&uBR z#c<~=?4$*IkQZxnBoe3Du`OqOjqwS_2N+X4$v3vU5sBmMF0WvGhOrA{j2E2j9}F0) ziml{yKS$7+AOMnj5@Y?>@$5+>f2*TjV*lGYhX3rDYf6u-sGh0W{;getUweM5sTI4^ ze;l`=riK0}M&D}c!7YS*&Qf2RFr;qvq3J{Bk7-h^=Cz+DJ8J$1d1|fCr#!XRT+UN# zRV0iWVO0Gb6<29JkW4}mdE>8nPOaB67pgNaK-vjOsF)9EE`!}+0CG~4qFM^Y#+0F* zR=4f?Xve9A(7JrlOdwy<6?M|caCh8BGvw?IOD;;^SJNT zuM^=}R7dqL-De|9f7`7|{?tup!jNe_`R>HtsUgZYYIMs-#?Dyu-p5~@{r*Z-HBzlt zD$X4FaP9n(;vPBmj8@k+`j;1?famB;pgB5XI?c_|-azUArO}HVxitD!q!o~3cqxb` zquk3uAFFDpOPFmo^y@jq{pK0 z24s@TEwN;*)-{Ray!=w+<&mfV`bp&Jk+{FMxC0XRl*(V;)in(xUE9G)tz8-;+yCLq zU4l@3>}+-2_P0d-KT~~mr`H;~VFp1rlulso)ZZ$yp2K!cMOI5}%c2opuS6DJ@N!x+ z@i%Cs;+BggaIn(HBfQeqAF4@?gn@lE+G(AbGOnnUd#7UMP9FljJUvdrHoeJXms}kB-t$4PjaZ_D9H(u(i6|cS_zZ`H5JN^*kabjjJ0TTAXFxr^kUlJg`F zmRu-#tmFxjCrh3wd5+|Tl9x+fD|w6LosxG;J|y{s`HrgIM`$!5uZl0zj& zNluWQE;(CrYssA?cahvva-QVDk_#n|l{`W6WXUrn&yl=PXG9t)+W4P%!g=CiivPrC z(`Wwm`G2)P^?|?o-+!hJ{<{DEy8r$N_g_sv{Jq&>nqtKh;fD%5Ka=*D=6;-&+hf4I zekiyZo^syKPh)RfvEqC0(1P}b`9mJb$jY#!WF!qAT7aXxA}R47Y0em3PXwO-YB)lM z8t63i=y_RZ!k?N%zNVLq+HB3#U$a%ZQ(Nzq`_hg2*?X~*w^{#t-VVvTBp;M~T=KV) zzn6SXa<$I+GIWyfCii_Mhv;1JjLw5F?S>wM9+2EaazDwBNggTrNy+0SPm(-C@@tY8 zNM0uSUCEnu9+E9tw#%@W_5ERTO4cwrC2QD8dHkH@OOmT3YdR07eul?z56S+L!zDM+ zc?9)$JVtDj{ISj>ujo7~LvnM;?Ih<)mXWzpkH~%Q?20mKnB0FtvQ_d6Iv2_7DrzhD zJL_C5Uq5EIzCY%WheQIYn-qoN6{s_LFfF<=;yrzbbj20i8=Il8eW5+0S12K;JJ7kX%=CjO1j=8IoncE0z7O zRQ9{lhveU7zblpf?$t~B@!7I{X3O@OE!$^~+@B-+%^cZpUYGsmb=ePIm;L5-*>7Ht z($D*Pg5-3`**d?uL$Ykoxw1Xy%J!VQT>txgX;$XT_L+Z79zQL)Lh=uiZ|l53>gWR5 zo(p{RhY#rSkfg%IjMyuWy;W zFP6!EzD)M>WgGSLy(8Osg}mQaOx2ICD3$!CK3oY>!RF z`teOtCpJl)*i<5q%in90yze*3_S+=eZ{cX#Bx&MXauO*+C zd`0q2oww?wU>*iPwt7hplpG;BR4}AjRIQ*N((L$za-`YmgRnpmF609& zPy~7n3lxFIBN?ZPH?UBiDzI2cv?@Nt0(q+Fh6VCe@hTR`Q-wFC0jZ)r<4VRPLam1p z)m5qpV4THx593hAR~Tn9&R}fIIGr(zP#aT%rE^sg%y^RVTgLYpCo@iEoWl4rV;Ey| z%t%s2ORP(#3R-(t6+bZc3xum{RVWMUfVJHyDN5@|Qj(PNrL;r^tqe(-R7$GSn#Hty zF{N86^GZor%EwY_ma?>zu%+BBEs9JPKvWDAz|RI)-XR+KM_MquKGuAQL}v1rPdff< zpLCvI^Q6zL{d7`Ar)H|nKX#&56ZLi_?%Ew=(5Lp7Ak$l3fc~_=h!T)qozhkD3RcxR z-6~B*y|y7QRmD0$?-n*vv9!)JU!|a=R(o@GvWiuICQV2}y|K2;F;PX?#M0vlD#|7L zz7?-x>e1pkaVjdsw!Pj^#k!LtuEnZYh4RZQF)FIQo;}h)MWxrXO{1~MmF9OiO2w*` z%fG9yqL?e~?MM}6Tn=y7Q&IZkkRG98wM&Qex+)feaYzqWQL*K4F-%2;kV8tSiYl#^ zDIqE@~n+4evr-UE<=_s4X-Iw-yILlurMmN4@{X^uDM=6PXCo+s*fJW$f(jz!SS zSiH{-pC(If-b=yOo8L?7-uRH=B3Q^md< zRWk-QQ|*c|Fk8j4OUA&assXg9iHcrn+?S=|b!d|u+@sBKk7lE7n&KX%_Q|49g(}0f zzl|9GrBSEW5n`DIDVM1K4b4d(nmi`eN@Gpj8;Z0*@PocG8QxLW%OqB zXZ(s#Gn+7BQWYZ@A7>oKh&4)ad@!RAV{rFs~uilvfSDy^j&T$&6;Ynaj6WmG~#tE*8lBGuJU=^)hyQn3v!N1ch=CkwYv z6E0yyN2GNPjk_~d$h6TZ10{W+#wuoy8mC%R%-ZRa4#gH-(jeHPI2C#=UTp-q7R4!0 zYf+pGu@=Qi&}vbf2&opu2~cWL91o!u#c|MSQQQzREsA5I(xNy9A}xv=K%+%*G$dLS zM?s-QaeWB1D2{|ai{g5aXHgshbr!{SA<%dw#bzk6D0YJoi((UWSQNWLhDEUo6&A%V5Mfd53=I~=Mo6$Ic7g(nVn+zDC^nG( z;+4?fVio#ZY;_n1t52$%0jp2SYk}4OFI8Ws7gcIvO+gDg;LBsJc%Ua#ms%KR2rX=N zdJ)p=1L^gK^m;*hJt4gwkY0C+&i^)&ORn%PxWc;>xWX8@HN~z0p0L=3m2ZJq`4(t| z8!UFA4i$(3R3Hjafv7wMqU02al2af`O@Syi1){_hh!RsEN=$)RC>n@`qJbzr1ETm0 z$o}rGe?>~QT}G_RiR(9FRZb#Qpb=qJPNGQYDF~}`5@B^tBCO6ygw;8Tuo5&8mJT4o zO3*}D37RM#!U{@&vVyQAG!d4BCc=`?L|77<2unf}VM%DBGzcsRD}54SrB5QP^huNf zkp*S`4({+DNmCv1GdEETz@~}=5UZN1yP7Ftm(@ckw8XFhK8pi<7WgZk&3}?$tGW%< z(GZPN(vMP=w4~HPx>D*$8dK^-dQ)m7?J0F89V&GpO~NaoPo=J;Ri!4T&X8%Ua1%9U#T}~VW|)4VyQ1_WT_wNWoaGK&QgEU(b53Y)Y3rG*U}); z+R|Xs-O>=!;L=bPcND$^IbY<2kuye4898U-~mP8&IIr< z?l?c%9iN3);&ajNxCXR4t_SUoYeTz3<JhVI15A6;mM7wJWnq8Dy4UehLXb2ZH zh>C`BMFW}8P;O{2GaAkv4d{V}^hAStp<%tzz?k}g#udCx$LMeL8hS0ghu%x)pmWhV z>D=@gB&j5=B(Ws5B)LN13jX~<`;)*LNnni>YXDNLVV99(4ZDmSYuIJvSi>$13Nbd^ zW#m}HE+fYpb{RR=unQ}8Bi69X$gzf9MvgV?GIFe8s*z(2Q;i&Jm}=x$!&D>38m1aK z){u+;B?PgCTqDOCa*Z5o$Tgzkmky%hmk1TVL|6=&2$jD?sQe{DYJ;pZ?3Msxw`u1>gwyHt8cEZzPY;k=IZL3tE+FWuD-dt`sV8Do2#pD zuCBhhy87no>YJ;pZ?3Msxw`u1>gt=Tt8cEZzPW!w^+mVA;?mT6u(&i47ME6c86m^F zjF4fY)nnUlEW;1~8DtpFcxf0p=B44}q?gtuhrKj{ocGdtLl*ZEFptK8qb9GV9)kQg1 z7v)@Clyh}a&ecUZR~O}6U6gZmQO?yxIae3uTwRoN|9GOD`#X!W(_f;TtBZ23F3Pzq z%IK8%-+_K7QU0xc}l1Fv_Zy)wuDW zC{95!U`O%+*i-)R6=gkO@ydTTVDXnI|CXZs?-FO@N>oVPAJJ5;cG;qwUxM0*PQ#Ef z45@>(oNTAI`2py86x4h&}k@KR3~$>Lc#( z#VQP*mLl@--ExjR0c!`+B$GxNn1Kj{8<(DQm=i=az8X_d*EAecekq?t7tx zg<4sz)B`=#hun9C;8voKpLYQ)>5fN^K^m)E00`4GX#< zrG_QvkW%}IQ)(Y_N^LU2yvCIn&QKOLi>n-{!htFqsH%Y~8mO9qDjBGXfmSx5$_1)g z`2AB~2v%n`#+ZxBf|KN2tzp{jOswMFu)_iSdR$9J|c_&i7*%>!nlwK zLqsBs7Kt!$B*GYy2*XJtj4X*T$RxselL$jkB8)AV2=t> zK$Im0ajG|K7Nu*khbSr$0;)uatrB5`{T6SaS1#^fvo&IR&DO#rHCuj%Yqpl>)NDDl zt=Wn`_|w*bnyrvXY*}XE%psruv^C?Wt^GAyrlOiHW8fXOcK>v2Dz*xr!6hSyh!bPu zCh{p3#0oy;q~a%>RP^Meq9-R6-{7R;PEIPmLPO(}aySyalVQdX6+tCVG>Y%675Df>!USjxsyR+h4}l%=I?EoE&fdrMhdD!`$F z8!DusY%*mgC@V~bJ5<0!-T$|E-nl@7q8L{9?TVO{ga12yRx?DxEVB@BpyovEfe2v; zB19yJ5S$=lm&h^;E|EtIM4fXuUqN{b%3o08m=eh3MEobR7O(tY%v${A1pFRO!2i}6 zpphBXOO6?faM>U?u9qC5*GrD9T`xIkDCaN=wsH=m#{kY@^vLHNMvq51htZ=a=P+El za}MJH`i~r`q>^(Oo%DLiP8~Ui(V-*fFgjf397Zerhfk2ZRzGkKqxoH&!)V@ua~PZZ za1LYhdz{0_ew=d{S&cb|k=2-U7?xDdVPrMt9EJsE14hIGBLb6RNo7yMlFFV$qg3`J z8okS&M5A}vlUR|=o`5fWvnLT3&z?jaR@#EGi;HDXA}*FaiI_>8L5{)y zDGVbSGl?_EF;SdBo)E*1V1jtJ)razr?1 zkRyWsd>LfTtBglxUK2To;q@ZrFuYzsxNOV^h!u~!a}ERLjaXQp${Rlz!{v?J$8dS$ zv@u-X`2H9!ZyY;@%Nxgz;qu1vL0sNgK8VX3%Lj3JWBDL1Z!90g<&EWoxV*7^5SKTW zo4LHP+|1>Tx;EdVKgGDzB+9qr9fV>Y{MO{tr=r z=rT^gxwOn;=h8BZolDCsb}lWm*txXKV&~E_i=9i$EOss}x^rpKolA@ETv~MJ(xN+; z7TvkD=+31@cP=fub7|3?ON;JYT6E{qqC1xs-MO^r&ZR|nE-kuqNxA^%l2iiDrA2ox zExL1Q(Va_+?p#`Q=hC7(mloZ*wCK(yd1hLf8E&R!mX~5HQ!Dgs59M|l(lT-nN%S%U zm14?$B+|*9!)UF-%mv34W-d6cFmu6ig_#SEE6iMQ zTw&&dV>&Skjw{Sua9m;Lg5wG^7aUiZx!}0M%mv34W-d6cF#nM}Px3x}@qZKxFclOS zz@8{1a0I)7jUE$t2gI(a_xqyu*E>OXaTwu@;`6?<{`1cjC!8a=7RAL#Y z63aN1SjMTuGEOCyaVoKlQ;B7qN-X14Vi~6r%Q%%-#;L?IP9>IcDzS`HiDjHhEaOyS z8K)AVZ<5Xf9rxMFJl~~59#4=7LmT@Yvj8lnalu9f^ zDzWSjmP)Mgh5jD@v(aqwjjq5qy0Qko(Umpi8=b`r9;6b_2C#2*Hh}9pMhCEOG&+EN zBmY(G8~NkEFTq?A|5fZ8om<7e(Yb}}8=YIozR}_H>>FJ=&-ERb&a-bce>wX`^YNdz zU@po0W?=sjo^37o1$Tx$1qnr%(jdC*BH_Az4-{??F_Kn)MWZ$T5OZJW0 zwqf6>Z5#HDuC`&{=xQ7GjjrlZmM7Y>GI}uy1rQnth`m6WBL8;K9Dp z0T1?#4tTI{bO6hgB1mw+gMFg|9_$+(@L=EQfCu|Vl^*OHReG>*RO!LKQKbj_MwKP( z8&#IDZ&X>rzENcf`$m-|>>JH3`4jp^VZrPhg$1*36c$XrQP5)eMnQ|=8?CvsZ-ly1 zDtY>;+z!4{g_(V&3N!mk6=wF8D$MLFRhZdVsxY&!RAFXcslv>@QiYj)r3y3qN)=}I zl`72aD^-};SE?|xuT-J?N)@`VRH6Gy6}qofq5Db|y028B`$`qMuT-J?N)@`VRH6Gy zX>xg^k>;KBdcc`J`cW4bnv?PvE(9}FJ{aSw{$VD57@PmfN<^!=T@_|b z52-NI^pFZOPYu3p!`q2^=^`j*$>QhQs)TflNs81QEtZX9- zTxllW#4#qCo@ZQOrpbCGRqix(&%xV6wVJp6O0}W7=h`*TIO{l^73JB3xjfsG%dKRl;$^96ok=i$B{5`VRRvNsaVgGJ?xv2 zG*!~Lt3FMf3@M7DX_V0iqG?iPTH6LR#q!xpF*N?!b|sdkUoN}RkS1e3lN3i&GY#4C zsMo{H&IAaI|ASE~AR<*Gj*sk*CP_2>GJtNxt+#i~D7z3OkbUiIgy zmtwo>rP!`|DYmO#itVbGV!P_4*sgjhwyR!>-B~Zi?yQ$$ch*a>JL{#`o%K@e&Uz_! zpk9jISue%zte0YU)(cEJ>!sM8^-}E4x~g~96QZ4URqw2;`W{`?_vos=M_2Vdx~j`k z?4PUp9uvFjKUeiCUDc~}Rj<-jy-HX0sz0Nuch(C`I_p(`ow@3-GgbX{{xwy9H7>ge zGh>|Lv`!oYQIFowqQ3BL7WLRL7WLLyEb0{x7~!YdjhlxcKn6f~vhbJeVd2mCk%d3lpM`%`91H(F&2{1L!NNZg!jI|xCAqBp z8Q!e?!J}FE8^^Ko-`k3n->o16&a~aw%`20<=@M7g{AVwc=1&TO=Kqid&40jZw5tD; z#{a!}LpA#Tk1D+XQFZtKr0sX8>NZ+`y{^~j{@>Gg()GR2^}QzO`d$-x>p;@=y(ae7 z_nO#S-)mxTeJ}n8T1>IoYhrJGuZg|&DieF_drj=E?=`Wvz8C-LEz(naP3*1jHL!G^09;$omp}M#39>U(bdkA~$`*m;KJ%qh=_Yn5h-DROm2z%@9A?&TYhj0kSy@W$B z?j;<8aWCNzjC%=t>+U7&t=A1M?n&e2-<|wh(PPRvJu$_YZlvw9mv&SNRV-q4MXxZ zHVlt!)(wN_AT|sc2iPz?6U2joRxk_;ysYZeYE6^WOccFSlhjP<`Q>z;Ury!u)NM^1cl9{WAWajE2nYnsMX09HR znWBee=9aL?&(%XRl_f0ll_f0ll_f0ll_f0ll_f0ll_f0ll_eaKIaNwCGFas2XRyf6U(O4-DYh~xg>)0&Z)08Zu4gr6`w-o&2iu3%{Yf$HX$uCif#@C=L$Q>_ zGe|3Oio7_Aq9ms$Abeu?@N`L}_=zTGvd;ubGbj zOLeW8Fj*5Sscmd(T~-$zV?jG8lS$l%>Uxz%;o>O#Q#$2N#Y~m$43OikG~#HetcLk`|&rz*^j?bk0t&_ zJ@(^|A7ej0E{gs5xG47HSH!a)Z+Vyf_^ed+}xG;s*_7i61nQCEn`;mUyqHS>nB3 zV~O{AfmePS%qu@l=9Qm5$5`UC-eieyb&@51;}0zHJsx3+AGC!f-V6VuCDwx~ zTa5w zPX0YfF3Bya8ab~t_ndNxlv|{E<_=i&BS%3VBRP==NNL?%JdkIwo7}!)i`U{Xjg0Ka zW_WQ+rFHAgEoB^47(i)-yPjuj7q45pRSR4~skx#jHs|ItZgGsDD3Wz0o4GgVvYA`F z4`oqkv<%OA+-T7|EDdRm71I{Sc*+ypca{y@U6~~9+S>Mw$i6)@1G8&f6#Ft)6mOvc zk4<&q23)h?flM-OYZi2Xo(FV;+b>#KU7M>l%gN9{skY6k-C#68s@-V6v{hshXc9l! zshY|AWT$Exki31eQJAFf+WdcS25QVf4a;y3D(|m7%kF0V#rV-s1N;o%renJEazc}7 zIU#K>$54-_;b!%^jGNUJC6Mpnxim+y=Y9GP)*DsrhsUp?a(-KntFNJw)W#dn?z2nF?~YA_45?RoSi%l_M=rWmI=0`2 zCdU>gU`a;RRP`Nfk7Kg5-@>Hnkcs z;z!J&dR4Da4$ZSDw-?^~hWm9dM@UBX;zvF_P~R1I?d<^TxP6&<9_V(rJl^RwG4Ns| zKloHP1Df@mxajIzsKM}2s-o)|dbxePr|q0hk+{7a7G8^*_4T)pJ?*)m&e5Ep^_YRR zxm7bbJv3o~Tt*TX5*AuVi0&G?Q)tzN`p~RX-68@o(6_a@Z)#yMdbKTJc;&`0bZ1-a z#FT;v-2S$f_f3t9f~#h0T-LUC4EnAucu3vCcywD^#zVXMC!@nwKimDYBd9QRRI1ku zm^yk;W3_tL_j~($Sq)FB)D`KIX+TQ%EpfL;~v literal 0 HcmV?d00001