diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -10,8 +10,8 @@ LINK_LIBRARIES QuickChartsStatic Qt5::Test ) -add_executable(qmltest qmltest.cpp) -target_link_libraries(qmltest Qt5::QuickTest) +add_executable(qmltest qmltest.cpp ItemCapture.cpp) +target_link_libraries(qmltest Qt5::Quick Qt5::QuickTest) macro(add_qml_tests) if (WIN32) diff --git a/autotests/ChartTestCase.qml b/autotests/ChartTestCase.qml new file mode 100644 --- /dev/null +++ b/autotests/ChartTestCase.qml @@ -0,0 +1,55 @@ +/* + * This file is part of KQuickCharts + * SPDX-FileCopyrightText: 2020 Arjen Hiemstra + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ + +import QtQuick 2.11 +import QtTest 1.11 + +import org.kde.quickcharts 1.0 as Charts +import org.kde.quickcharts.tests 1.0 + +TestCase { + id: testCase + + width: 400 + height: 400 + visible: true + when: windowShown + + property var createTestData: [] + property var renderTestData: [] + + property alias errorMargin: capture.errorMargin + + ItemCapture { + id: capture + path: Qt.resolvedUrl("screenshots"); + name: testCase.name + } + + function test_create_data() { + return createTestData + } + + function test_create(data) { + var item = createTemporaryObject(data.component, testCase) + verify(item) + verify(waitForRendering(item)) + } + + function test_render_data() { + return renderTestData + } + + function test_render(data) { + var item = createTemporaryObject(data.component, testCase) + waitForRendering(item) + + capture.target = item + capture.name = testCase.name + "_" + data.tag + capture.verify() + } +} diff --git a/autotests/ItemCapture.h b/autotests/ItemCapture.h new file mode 100644 --- /dev/null +++ b/autotests/ItemCapture.h @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2020 Arjen Hiemstra + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ + +#ifndef ITEMCAPTURE_H +#define ITEMCAPTURE_H + +#include +#include +#include + +class QQuickItem; + +/** + * An object that can be used to capture items and compare them to a previous version. + * + * This object, when instantiated from QML, can capture an image of an item. If + * a previous image of the item exists, it will then compare the two images, + * producing a test failure if the item is significantly different from the + * previous image. + * + * Captures are stored in the directory pointed to by `path`, using name as file + * name. If a test failure occurs due to differences between the two images, the + * new image will be located in `path`, using the same name but with `_new` + * suffixed before the file extension. If the difference is expected, you can + * replace the old file and re-run the test. + */ +class ItemCapture : public QObject +{ + Q_OBJECT + /** + * The name used to identify this capture. + * + * If not set, will try to find the TestCase instance in its parents and use + * that as name. If that fails, name will be empty and calling verify() will + * fail. + */ + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + /** + * The directory path used to store captures. + * + * It will be created if it does not exist. If empty (the default), verify() + * will fail. + */ + Q_PROPERTY(QUrl path READ path WRITE setPath NOTIFY pathChanged) + /** + * The target item to capture. + * + * If null (the default), verify() will fail. + */ + Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged) + /** + * The amount of error allowed when comparing captures, in percent. + * + * This is intended to deal with items that do not render exactly the same + * every time. Small differences between two captures will be ignored. The + * default is 1%. + */ + Q_PROPERTY(qreal errorMargin READ errorMargin WRITE setErrorMargin NOTIFY errorMarginChanged) + +public: + explicit ItemCapture(QObject *parent = nullptr); + ~ItemCapture() override; + + /** + * Capture target and verify that it is the same as the stored capture. + * + * Note: This needs to be called from a test function. It will produce test + * failures when capturing fails, loading the previous capture fails or when + * there are significant differences between the two captures. + * + * \note If a previous capture cannot be found, the new capture will be + * stored and nothing else will happen. + */ + Q_INVOKABLE void verify(); + + QString name() const; + void setName(const QString &newName); + Q_SIGNAL void nameChanged(); + + QUrl path() const; + void setPath(const QUrl &newPath); + Q_SIGNAL void pathChanged(); + + QQuickItem *target() const; + void setTarget(QQuickItem *newTarget); + Q_SIGNAL void targetChanged(); + + qreal errorMargin() const; + void setErrorMargin(qreal newErrorMargin); + Q_SIGNAL void errorMarginChanged(); + +private: + class Private; + const std::unique_ptr d; +}; + +#endif // ITEMCAPTURE_H diff --git a/autotests/ItemCapture.cpp b/autotests/ItemCapture.cpp new file mode 100644 --- /dev/null +++ b/autotests/ItemCapture.cpp @@ -0,0 +1,171 @@ +/* + * SPDX-FileCopyrightText: 2020 Arjen Hiemstra + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ + +#include "ItemCapture.h" + +#include +#include +#include +#include + +#include + +class ItemCapture::Private +{ +public: + QString findName(QObject *object = nullptr); + int pixelDifference(const QImage &first, const QImage &second); + + QString name; + QUrl path; + QQuickItem *target = nullptr; + qreal errorMargin = 1.0; +}; + +ItemCapture::ItemCapture(QObject* parent) + : QObject(parent), d(new Private) +{ +} + +ItemCapture::~ItemCapture() +{ +} + +void ItemCapture::verify() +{ + QVERIFY2(d->target != nullptr, "ItemCapture needs a target set."); + QVERIFY2(!d->path.isEmpty(), "ItemCapture needs a path set."); + + if (d->name.isEmpty()) { + d->name = d->findName(parent()); + } + QVERIFY2(!d->name.isEmpty(), "ItemCapture needs a valid name."); + + auto result = d->target->grabToImage(); + QVERIFY2(!result.isNull(), "Item capture failed, ItemGrabResult is null."); + + QVERIFY2(QTest::qWaitFor([result]() { return !result->image().isNull(); }), + "Item capture failed, result never appeared."); + + QDir dir(d->path.toLocalFile()); + dir.mkpath(QStringLiteral(".")); + + auto filePath = dir.filePath(d->name % QStringLiteral(".png")); + if (!dir.exists(filePath)) { + qWarning() << "No previous image found for capture" << d->name; + QVERIFY2(result->saveToFile(dir.absoluteFilePath(filePath)), "Unable to store first version of capture."); + return; + } + + QImage previous; + QVERIFY2(previous.load(dir.absoluteFilePath(filePath)), "Failed to load previous item capture."); + previous = previous.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + auto newFilePath = dir.filePath(d->name % QStringLiteral("_new.png")); + QVERIFY2(result->saveToFile(dir.absoluteFilePath(newFilePath)), "Unable to store new version of capture."); + + auto image = result->image(); + QVERIFY2(image.rect() == previous.rect(), "Image dimensions are different."); + + auto totalPixelCount = qreal(image.width() * image.height()); + auto pixelDifference = d->pixelDifference(image, previous); + + auto percentage = (pixelDifference / totalPixelCount) * 100.0; + auto message = QStringLiteral("Images are too different: %1%% difference").arg(percentage); + + QVERIFY2(percentage < d->errorMargin, qPrintable(message)); + + QVERIFY2(dir.remove(filePath), "Could not remove old capture."); + QVERIFY2(dir.rename(newFilePath, filePath), "Could not rename new capture."); +} + +QString ItemCapture::name() const +{ + return d->name; +} + +void ItemCapture::setName(const QString &newName) +{ + if (newName == d->name) { + return; + } + + d->name = newName; + Q_EMIT nameChanged(); +} + +QUrl ItemCapture::path() const +{ + return d->path; +} + +void ItemCapture::setPath(const QUrl & newPath) +{ + if (newPath == d->path) { + return; + } + + d->path = newPath; + Q_EMIT pathChanged(); +} + +QQuickItem *ItemCapture::target() const +{ + return d->target; +} + +void ItemCapture::setTarget(QQuickItem *newTarget) +{ + if (newTarget == d->target) { + return; + } + + d->target = newTarget; + Q_EMIT targetChanged(); +} + +qreal ItemCapture::errorMargin() const +{ + return d->errorMargin; +} + +void ItemCapture::setErrorMargin(qreal newErrorMargin) +{ + if (newErrorMargin == d->errorMargin) { + return; + } + + d->errorMargin = newErrorMargin; + Q_EMIT errorMarginChanged(); +} + +QString ItemCapture::Private::findName(QObject* object) +{ + if (!object) { + return QString{}; + } + + if (object->property("name").isValid()) { + return object->property("name").toString(); + } + return findName(object->parent()); +} + +int ItemCapture::Private::pixelDifference(const QImage& first, const QImage& second) +{ + int differentPixelCount = 0; + for(int row = 0; row < first.height(); ++row) { + for (int column = 0; column < first.width(); ++column) { + auto pixel1 = first.pixel(column, row); + auto pixel2 = second.pixel(column, row); + + if (pixel1 != pixel2) { + differentPixelCount++; + } + } + } + return differentPixelCount; +} diff --git a/autotests/qmltest.cpp b/autotests/qmltest.cpp --- a/autotests/qmltest.cpp +++ b/autotests/qmltest.cpp @@ -6,4 +6,19 @@ */ #include -QUICK_TEST_MAIN(Charts) +#include +#include "ItemCapture.h" + +class Setup : public QObject +{ + Q_OBJECT +public: + Q_SLOT void applicationAvailable() + { + qmlRegisterType("org.kde.quickcharts.tests", 1, 0, "ItemCapture"); + } +}; + +QUICK_TEST_MAIN_WITH_SETUP(Charts, Setup) + +#include "qmltest.moc" diff --git a/autotests/screenshots/BarChart_simple.png b/autotests/screenshots/BarChart_simple.png new file mode 100644 index 0000000000000000000000000000000000000000..7f6fb79713d791d310e5d5c797c2385c4576fdc9 GIT binary patch literal 638 zc%17D@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yaTa()7BevL9RXp+soH$f3=B*L zo-U3d6?5L+-N?&q$iw3J^7s45bq~x9dAN@Gu=j9qk{k~3G0{fo1FjMuMyy2YE+;lasB<0+luLv_?a9P1XyTD jB;HnRFQ<99weUak=5Eq^Fs~n&pcp(|{an^LB{Ts5a$SHs literal 0 Hc$@L^mpoZo7bG^g-VuB-gSAPrghBL$l*%$s_KPJ9 zJ`dL4RD6OWOa zu2!*Et*n00{2*k_lb2q3VV|CR*{yr>)Xbn@XIRnJNzb(_w@*5Md->JPQ)A@+nps>a z%eT4R_UN;j%K7l3(l56k1ZY?8sdcNpW49Wp_sh5UK3wAI(kB`nBySeWlnc)vDTfAaB@mtg{6bim<$gVX(nM=O9jIiDK*V&nP3 zs{un2FQfy2XinAr8>dx@-@^sK2x^7Jbda6t=C#ahzt}`z2x^Mn+Wa@E#tZTfxPWbe zAc$LA_kFC*nP9vO<^nXiNUYoKpOk0jn=wNIyT@ z_L~ofoQl~)4}|p~1T((*|D#1_%dlI=_P>4ejWsxolzF+td;<=B{09|hN8zxqxM;m} zEDkyEE!m%6V~bs2Ov;9RN>i=RVc%KJyl*Lxdq=vUeX5P+FJ1<`VEOa-8AiHXq0hT_ OfViHnelF{r5}E+RW_T9> literal 0 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 literal 0 Hc$@MspaUIvOn{JaynoODxP12@mIu<*bcCt(+ZIWhbCm)hHO=8)OH`S6=S(GJNmL+O6 zMJ*IJtR%6L#D4Mg!~Z?J=f3A$5C8%40(}27XD;yGbMIO1^FPn}KCdHU!C=@5U^TD~ zSP!%S&32nbafZ9ua0!tBwIV9N4z($}Q*y^`-pbcn6q*w>k1FL|V8NPM`)*gY8c3|guPN4{l z10#qq1Heh32k12DKwBqp0+DFUfz9<=FLy+O%mSVeYmwk@1FrVlmHz)WM3&XeOoExP z5*pfPxo?d>)@oow@LmxSrymjK7;qRkWN^s;-wT|MggHMVK`OwomB1!Mf}Oy7fb0DK zn~`RiFBujSHOPc(0JZ~nAkqv0-H0r20S67<^#7l5(nt{jB0*9xtR9(2JAoVg_8z1q zT39$jnBS&Te;f2V*t`M>bP;fVE2RFO4{9j+Lhl8pkcK%190XoB_#q-pr;`SXAQB|e z6z#w+;3nWk|MxcZ6rTH6%E2B*f;NVp&QpjGP!jeUB>aA>X$CijobH4`(}*kyk?{N1 zBEO~%nOgP0N@ho*TI4%z1m2JQm}9^jz$*qX`@cJ!uH~}De4j{58s4YafV9Icz^%Y; zWIi>{;j5-7MVHPXA{Y|BM8Bbq?nLy+lL1Y}Gq;*!I zC|RR_oy&u87@1wK0xtslk(N1iIr=P@l?L(JVms0lcc7=|^(f*rn}@{&vgHSnU>Xwq z#DQP!|6fcv^t;vi<2C1;V?x?a|G%R={5;b+HX<#$8~7;FBrgEZ8@#mlKDr-zk~0f- zHC2wwf*^*iMGp4uz@12IT!o(SGhrG%QTve475!({p^)zRK0imSY=r4GlIM9ptXKN2 zDK$2VNZpS}Q-d^13nD}z=X)F_GwgQYo}M+lIbO@)82nM)Lv-`d@+Zo&Hn9v_hn&(o zfxCd4kzmi{Y!^{pp$}<^T11FuBvcD=&q62N`zA-H;lJ0zp93S~l$`Smb<)FQpG9OD zMAy3-k)??l?#*|%bMi+&$C{B9oHWND1J5$b5BVL27T~<963bG9cw*cD+ymT;OsY02 z3z#9(=>!sZjZ`w(p4nCVW>4}40 zk23P-Lz2^3ivkfzP@o$)jvfLV(L>?f{Ti!<@9f}gu|UBJY{U3>!2Q(mT|Up#jPcrX zB+9ZPh+%6GG42KKL(cc689p+GNHO65Uk_Zt>`f>0-!Y7A{!t{%1!U&bBZ1q1gt?Z= zB%Oe|BXD{ZN z*_nxk?olr=GFHpl|9dU#e);2U>Z%m@Hac-U4?IDEeN6Kv4=w!=@scKp57%x3?gl>M zU#}$J=``RJBE}Rlp*C@T6KWC>VgM1U1`(kN3Ecu};R_~69;Ogs22dzE@j06Oc0RLg z>_97nzxq)c4mDADyM-~z0|04E1BY=u4Sbs#p60hW#u5$>FIf}Iu=T)gC=~f2l-ygD zv+Fc68&04fsudCAJcWbjs$?hp_cj4LDjZ|(r(eovB(H!ouv$dQDN1>hd*%uzPOoAGa16&Wj7`W_Nk5DV$UNMNv70Gw<{=)# zc%Hos&g0xKIhLFTF{}pVEuy`L7Jt-Z*zT+6p?u| zjGX^|O6BQ;lzf&EzxmSkzu65ZitwwiQc5l+MTv<|v7S=-d^2*U8?jiVQ%7pTFp1*0YZ)Hwt^f#VUTd4|25n)QWWVk`-Q7*;@9<72>&A=7GY&aP*W zfQ}*o*+S)~YEs=gf*jX2By{IPQs~!#e)xC%>tSTFoCHog+(n(VWb!2%&~>*XU+ik& z8vokP?6u(_(A(L-QnePt-7mqpgCL0BOb!978~} zCrXx#j<+$sjq!EhS@tqK-|M>=sA_^3whfWuK@_1{pR-%yY}O!RRMG-TGHep%B{nnj z({v1Jqc?z8Q1Ms!FUQqvT3h1V=isF?E>;Eu@xxBl5} ztou(NqW1JE+A<$4)`AM5^&7nmV5?yJ}`xqw*fc* zCSzh`@99~i*#1k*eWJYG#vuBsu3 z_cwkV_!RI#vX1j;LzS zY%dnL3u*M-WapkF7)0878a=eaMiQXhk7~S(D{-0MZwx)89>(}awfH4fK@h`sq8f`& zp#sAYJt)Vp4v`}a-A;t|7ycmfwM~Eo5;2S+D% zu6(Bue8(HWmoXmZ^Spw)bhTWUj37Sw_kQ3rNPFxEc9}p)xJmNoiccYvYX}i1uX?wL zob7$U`SF8QbBtNuu>b-((2m2#SVXlhHPg!%Xv! zO!M~?_yK#FQ{}-z;ga-q@?qQ$0zZqQRojAH&LF|AK|esK6^2pLZVF|I^K9N;;M>3# zfWHTxb+~0Wq35FG2~N|>TWsbn>|AAZ6WQ!}BSr%SP9ZIybeBv}=RY?V7;GadyV z1NJ*yRfP_h4StO^tl?%H58!wJ<0i5d3`L~r2a#_W`W^C1^w8TuHW1JQd=2;l#1Ya5_P>8mLZ2m)Y4e$jslme%GiAtVad=>Z`cJa)`OekJ76U+M?iCOiNWN$(@a<(_4 z5N#S0$mAMBCRJGGFokj$|A0)YCme2oh>L?KIL#+{ixH0DI0LN3(Mq{|twpACGR3)( zv|r*_@15~3^x#g1f!83JSVE{?f%Q6^0JXx00H&myxbBu6KD!fYiwhx`o6 za<4#9u26*!qLA%ZfyW)LD&pst9e#yz;5j}|7mgzs52CPeIwahP<2@LMa2&+AnzZj? zv?Ee=VodueSb~kfCzxi6X{IoqzZlW2i=sgu;-Q;>&mo6ARKFd_q25N8I0J|r4XD5_ zB=iyBAA!FHz7<2aRe*gAaXas@@|**|fpU`6qR{Udpc}_3$}1h#0<}20kXhYW_MWi? zhhrbTJb7+1+@fL83F4E0p9MZmHd>XGAZ#NWFF%P0umL&iAznh!sV|`LZR}27EqI0r zS~)@s9n>(261MNVBw&^+(2m?*e}VJnV1>_p&#Zh*TR6U_3<+dpL^YG!pu-l6pOw znb?J#_H?LNJ%wGaPtt^=6=R(HIL5xk>&LZd1o4H3KZQ)I-ND-@koMS0zO&wiOtH`$ z8%DW}zXrbMaNP@h+7SzleGIaP!xR`q{^J(P{m4c{fJ)AJ!M|5axt3|g(S+kHdpOL# z#i;^b6oUAY^&dqMt2=|YlXWRJlZ}Zd68>C z=0&o4P?YMgfhV2T(1=({c#;WrbCfllLZ;IeLL!t%5}I3$7?U`<{b$k{_stYo0i5KQ zII_^$_5~-1k68UIDqT+u8DpALbn+w%YIZLuLA+D`8C0Dc3i_M=c-K-M z%@{z@sy6aNz+XZR`ST7}byG4U=7@bvb3dI-(}$ym0_~Ld5on-PIv<);>(S(@eq@Ct za#RnrQeedUBMWAJFBn05_mKyYQ+|E$_Pc0W>vfb*drgvn8_1emoroM?0A7fbnU)du zVcbtQHJoCa6*#t1u1Ok^#nD5#NtHC7IDzD;G~-knrUAzQdw7R^3$rNcf)K=)k=zIT zbJTq#U1!sSF6e5?qY#P7l@uiseC8`ib3}41N9@D6mma3+r@%@aS5R(}mrN=VA@OBv zan$4J!et!#jefr#HgcE)7w(T#>NYr6T#rgf?xx%+KaHHOcFLa+(`c^83bOf;Q^41O zza^4md1Eir6!-x}{tn|CkV*PogRufx8KwCk#yVe?(uHw4wSO&eH;$iRSH_B&7cN+X z_5&EkhGUc<6TsEcpc@08b+bq#37G9$8twvZWS0tva*A8p2T^R%AM;@ zlVB|{g5xCeN0NtqoiBVGWDjp&Xny2^2;xJ!A4XBDa4z{_G#l_*$~9FtdQyZY*EmW7 z{uK)4#%R^$f_+T$KDw!A6nAbKZpoxlt|N&~g=SdNY&=b#7GMPhy7(pDxscHBg_>B` zqejxV1>+}CmF*77NjOX?OCC<4eHN9gKY6*f-MOssM~vfm630KF?k4Fewv9+;x}dC8 zX#vd}8bmUe#%&lM=Z6<&YRy}N`1LtHiA<|>NOuC+j2kJhv6@2DWRv!nX}p9S@~_1V z`DKhJnP3k+-uZ5)ywYMVid=;z)hd#Xm_|z~Ke7^qkNdcfgY08o$>n(w#Lw@z2Su%J zqdc#1$e;XG!T7s~B%#T51Xble9BZp0*vANaI7xvzWPzkh<=5djg}P>zOe*!*8o)73 z`DD5#91h1Zp5)#6oX&hrtZiszr`stf!6}s6*dC0ZL{nvVP)^E0;9I~~9q!0H&n05H zVJ}CR;%i7Y(koNdFwG9%SF2=F84kyG;EZ?L6F4NJ5AfR=t7TT0GeP`6u*>>UWDkaYt6o6`h|k1uZbSxOq{vyG zMN1^S8oav|$4cC}Rx|uCn(W+xA8@8x#h ztcba4kQzyx7Yzj7N~nlVdAe6A0L-$L!t;r9zGbYDT)@|Wgvq7j!dT6hWg zCXSbbcakRM9l`ikj8PnYsj&ja?HKp+A7-@{rT@_EaRVwyO#2c^AER(p*t3*OuJkc_ zQOCo5vB^Tjtnn+1Q_DV#$Dpi}iI%x=^x-(08n44>MT?7;vgnR>jQgnLeX~9EtO(+@ z$30}rNlu{FlA)G3jv`j+75q#4v zz}>UeBD2*X??vWSdMa$Pp5G?2xs4IBCf8d?d+eX(F(V?%ah8{m482u0u2T6CEXbKS zHX#{Jm#wtnxQBY)JDWqEmmr3%MU5A33f@YX8O|T?L|M-COt2BO1i`-8NIGKP_kYnTD{v<@xyy`~eK;4s zV)rKG^@mRQ6#2cYHc&o8upiZ1y*SfJL`2LPt9TK~R)1==7RLs^@>LoeF{UWjI5og6 z6uB9zyiU$c8e{`-2l)*ZnkgsE5Xy3f+T&H=sn~TrV!`p7oWytvGId&Qz&KXc`ll8Z zEtV6rE;W{rCe$8p08dBl5wU2H7I_-U zS_$$+MzFG3gmu8`9AD&mj9V%>>yxxlhKHEo^X$iQfbz=nR-`Q^NE%=}>aoHKx^K}Q zUAJ{{^v)4Z?V4cAi?`9m_tIZoMi3vpx`Axpsy?!sq8~X!>3JYy$h>-sh=_}ew~*}J zO(|fs%KzPu71|hSf&Qz{(sjpH4&T>L_pPIhw5(#Xz7-e)R}Z#|)Lf-dgKRWEF;Beq)7>1|^AaN)Zl>eTGo0DDp6L}0z+ue!Fs@sPxP-sVvlpuA}usNCe$*v2Q~lHrSA>}Ry)S>E{M8HTRdL2=c3tgs#{ zv{C-xE+Cmc8+=1E;y^=s#{_L?0!g|EaRP;S(`|c3y9Z0^ChNN z91KRAk<6w||20Uq)6v#i#DR0wB58tbBO9_ELZRJsa_}r7Q961xg~Gcr_YrZaaSX{~ zx>wdJB(rIa;gD>n=dpu0aL&yrz&ZcpYO)1~gXH@k;auK+#V zk#&d*bxZ-Z0YQ|p@~uHJPD{cF`8Eq)q-P4Cevs@vYUR0*Zcp|=2#8l zLNk;IvXN|f_bg;;3sWPOcc$W%NI0f!uJbe1O{5wXZ{qez2<4tPCTKY4A=SR1}|RYH)hWW%;+$S$;b zI%n(zTG2KlqMC4+?82UnWc`o^^7A2E0Sbn#@c)FGVLWGSl&n_iBI^)EL|kfgl9kH_ zB*ST}A-$}Euo~D3wxZzwX{X#lH@}5GNRe`<9aOgx=bcAX8%~m47NMT<#@8SjPvkv8 z4dTS=WHw;ve@u{F0e2FaWa*?~(Vs-9wjv@fHBKYhOcTN(8J-OGt)V=l4&ubR0*VE< z25*j1UcH-)g&JiP=y163fDsXw7;X{~Bs8g3=8V^jIG8Kq>1v%Tu=rw^f#t*_8TC}(1?g? z!4TO3#Z{DN*g>)$j;#Wk5+^;3SWV}Q70FJ~?I)|QA|k2;@&V}oREw}^;p!5Gb%3RC&KwcTUp$I`-H7cT7QA9FYNq*CC zIb#h4%BRyNAIu|2XmS~F+TlXg6cJG+aMLJZ7z%zNXDp8(YYJqeReAo$G}$(#MWX)^ zQT-TU_C7~AR+mQ*BTI%#W04>c)sC=P1LSLvys^3h zAsi}|57`+JQ7x!JGCG?Q_dJ4}E>L+!;A~2S*ORT~iioHd)RA4CU^a4{V7P!Ll;rsw zc@>ahNVu77BZr8HYQbu@C4~2+Ztsx`Q7Kju|~4%8b(A^3pSH&N|M(h zG_NV*0MM5>>0x*Fda@=~Jz2k`9@y%aP>6`ABAi>+BP7E_&RAYk#FKa@eF*3Y-dssG zinW4lZGDYDiLf(DM8u^=1Cq^fS&wP51&l?qb%i~^PyyLron+g@JM!Dahi29lWV^#h zL|kgLBH2u1lx&E1f|9%^C?Zab6kMrIeCUAJku5{1C%YEN7W{f{5fN2{b|jl=oFU&q z4Trf^?Gg zLmJ4|X*E(|;dR4e>3c+#!0Lgk$q(^{QLQs%Nz;R0-!LIaFIs#(jWuMWR&~fe3)i2% zmgt8>R1Y=+*HE4vpF*-5<~t_HPTM$!U-u><$N*Y4H|?m`BF81|lsjavg=W@O!1lRZ zK}5tNVjI#RX`Du~n|8)W{r_nq6%iNu!4t%l7GBR=jVByyAe&g+3S4K{Y$n1-L@XlA z0Xy;QoTo5A)|46~f7P@@_&i{`g7FYpKV&`G_VLYReUoNj7nPS%h={mYXaue&TZ46m zY~kV%*>d=9;1D>2a)KNK-VJtMhtyCyIk*}nThf)iwTK{L+&LoRVq+VU#kAQpj!dVt zuVF~GLr4BFDStdokRISI%Kea}BSbnMk~C`w&8%yI_ssGlA|e(GJCQ7=(VLlbz5oCf z;Ymb6R8O{f!&$POd5VYw=Pao-LCydNQSo9LYsuzFnsUar0J{wfW6BW`7YVi&*iE*8 zc7UvT)lW8h)rUB6&V@Kf5GR}KO|s$M7P5|d6H;60aBn?uBQcs4ap|xf$za;?oTORx??jqXjWB9nGrqCwX1v>xhV06kLa7FP$kLM=~0QeEZ2a zuUHhXiO8`lc;h6J(R8G06v=XE z%S++`n*$jlIFXZ73_54g=Q%A3!nbh=|3+jY!tg^O44oOok8W zUL?b5%jP7K^^AE16$s*^S^LR4>zmM|lQbFXkWCkAkzK&uhHc0@MnuGg!&-s6$>u(~ zk#nAoXpJG+4b7`Jfc;_gD#1)k7aRm$pgeN5${#pSi}X{TSzqT*{-zm@5fO1AxDmLE z@`~IkR9X_2oAi<;%_x%bgOv_26G2V^-zQt)yBU!oUDUV^k*7P@_kF;;i1V!ubrg7(tOL`AoSXErY|SWn7;2H-z=sTr zt$`vI2-XhVPc{hDjbt#LC7(vJ8j_|1$@bBijx-}dytDp1Vp^JI8&D)5OdM|ZCzEbC zx85B0f8)pb+`s&e#l?0aE)Z6OqE>q-*9enHdxXBn2_&oOV3DC*-}9B6^8~Y5U+_)f z8Oozn4n+fcDc2$`D6QXh?o1q015Io;$ItG1g!^W3yoiXIa1HQb-LBk#~%u-v?u$K+%3dRQvdolU{>AUUVzx^L}Y}WyMXT^m50%mbV zs)%{QR)hUK*a0w0Z6jbWf(-=YU0^SR6@&3d!0w#Q5yMq=D&YX|6mqsV`LP1B>$(v` zYXFKhtbh3?+6&Y4e&wgA`M*EP*4N(0n(fsdkU;b&%lQz9bH;T9xAVYT>i6v7Ri z@Lptcr7fjiB+EaX%>idc5QiHw?7P4{z{gW>ZA3O+7rqX^cN0fnxE1&4$C&)i{aig* zI^`Nve)2kIM{q7Ta~Tnl4{HY=KzWaJq2VB!%MtcN=<@r8iNP0v?}Dqecz#sQM#$+)5c8;G?1p6}B9dkMIY<-Xf zuLDn* z5s`vzLuUPblrK|o7Wos~DVO6RzwHdZ=rHgElHplnP6Tndvw!rHMDjv`qL zi(!wWP;a{Z)Hv`oun%0g=FI}bY{l>VhW+j}Z`2568=s}gwIA$reroQ;ICtBQ+3#c49|-+P%wELoY%qQT zvllQM4#o#C`%}zf#cxCay9w-1b8;KQU@w532*%HN$NXe4-VgTsVDp*+KATK>9*zNz zqB4}Q1f>C)RO#_nWP%-`yqIx4@G;;)YqVT9D82ASIbe za0Cf`INpi;jBxxAlF=W`RIxh~=Bq)#xk2D@;Qvv+9KuQzz3QR70bMP+fB~|l@;3pW z0v^CD?3WsG*}&GIWZ__}-=)b;$WbzqsMJ@mrszJcHK4j-TMtOg%#H1P`+tA@kG_mC! z%FE>&fFA{Z2Dk&W3qQYzDu)$-+tF|SF|rM%4g%yo}k~!FckSKgR5KEH;;@ln`0467FGb>4}2E=#$msLPBeY?D#}YnrYV_R zR|TIr3Va=S3|zQOc@@FzX3YL9C(AyQNtI;UyDDgsKgR6N=(sNjSS{F{-mJ>g99FVK$m$Qthu`QuTO}^i=Rk{sOc6i6P)63|k3yKiFSX z@Hu)a_!f!DwLiz?8U_0j*hgUDAD|0oVkK~{h}kp9%xXg2C(b`+jlL3xGdCZs|; zQvWAt13roRudc@IN!(&rWkxJ4Yz@kDdsg&W&L9ZA6ep)Z{BcGiva498HN#6CsIncObH)TgrVGSN{PU{mZ9BfN_V(Y)QiBwC|f?Vz$XnX7C}Jy5wmZg1kW1E=L~N| zS+IyJ5X)ar%;AGoNC>PavJSqHOEOx zS|yxYeh`u48;hCmSUiFNICmVguOPwxEak;yn-Kw$D$6uUHX)K6L)s=C5nF}2>NNqa zn0*y^&1dx^ss>hrdRIN@w>$^>D2i5XBU>tR68-*dvXiEg zDAfx-k`=z!@AD*YlWqQBs4>K!qDfbwZ5nZ@@Q}4}qkR(1=Lj1rq$5%<`Uq6`-U;ul zAJ2KO1MClAIn5z5b0{nRCl#Vp2}$zaJMF{6KSZJ8@cjWaGx1+zw(U}1>Sd2Vu-o}d z`%8Yt4p5s*j4`ku`fzO+kxECh@`63(TUr;b=`sEyOjz{fem2iU+$4x$dY zB@Cm&!xiW^4MX-_$RW>j)=vOm1O66xVZQS_svF9Y+~ac^y*b*Tm&&ClMakjv6#6U{yUAZPn6>+R{)KbD%^B zo3YxGI;pN4;V*iBWItG61+(hUJvlCp#dFCalH7%Sl03&f?RSI)j)s~)yy~~G5kxvO z|7Fa69B(GdbhrBxGS(xoaS|pjQA5M1ZK@pC1hy>viYXbc! zr%`llOU`$IW}Cf=G|E%J%eZQpbylSiF>XZb0p9EXUZ1n)H2RHtk+$DXNh=h2mm@sH zS{~*sqYRQ?a|NaHk*|Pzb3w0V9;gn20GM3?{5bH_zy~Q`t`{WyNBrMAP1${{{nNlJK#y-{6d}#thRAR?nlHYaY%NrRK~!6plm>-`h%m(n-(`~D zp~$1T-!p~^50mnds>qO64?zIb7waR4BuP0*8dFG93{u(em_jC3A9|8qL6&R@hR{T= z=g@+VF9Sz$ZnDDu%Nv?XunlSP4$5( z4wvmS0DK3TRF7BBT=Hro2;jrAccGbPA0ykb0_1ljYtrqYvfpvczqTMUt*CI+Q8ZI+ zKUz2YMc^%*8<_89EEz~!G$CjE7T^y5dNrC}kcUZh|NGIszXBDchDiL8asT~mIK^>( zk0O804&UPAC~ErgB~-G$C{?-hMfDK`@FCgVz$g5+o9vS*^gG(gzn($#V@{xgxXt88 zT|g#657H|8{q{Q2D$A<_y=vFC12-T-+yd-Enz>TLgDI5hK1HcPU?uI+fwJFgp=?=< zA_sVvU*}pLWrQNXi!$V|F2;P03q^GjB!OzH9zfNg_aG-dMB;bUpeI?S)r0!bk2{HM z%+BQl|8GDD%97%R}dtJEfT2;HM1 zmHd$+r};L${2Bk7ukwGY#ox$7brS@@tO3m<_yi)$)y(X7tV2I|r6u0_(T_cjoX$38 z77maJ)`fB^2mJOH(qJcXZgfu9bg^JokF;w-itCYg{XdlK$29v9{D6c2HZw=>LsWj>v1H|t;p}FWKJaw z?am_mxsA%&CygmYvJRA^c^mmJhmj^b37o#@j=tFn6xnMc<_ zzBj8Wb;Ha<5j{LkBA?|7D*rY=KphXi#V_y{e^LFxkflM81d4LqjjDHl1SOgBuAv_Z zYY|PpN+w|CVT@8^o?i5jHs zRwIFJMjB!>BEVK8pverpb7(arV>#M3CBq!$aUxkZ(;7!0*XkB4I^Uo zBQvER5pfs=7tZ?qCXjEGkfwla{gsFetC4nSM1tGwuelkKpb`|cP=YZ;jDB>jZ74F8Cp*)~7ke5N zhdvD)TXGS<6qYtY639V)4=SSj5Hh=FnlLql{DToBESr$&a=!av{xkhZ=*H30Ju!hA zkg0R2?yDgZpFw8a2qMHPe{M}EATgWk97M!O?ok_+a~>d{?|Gy(_5p9=+{6s~F9|FU zf+W!DR5zfay8BS|>82SzF^+^F$(XN4W<#Y6a^{HW37hy7qevhN$XrpQJH4(#Pv8r^ z=Z3VxxIf+qB|l~w5w@O^&r&ysV~!$IG%<&o(EXT6%l4wmgC|h|=O)fbiaB~?b=hocM&m$D(t^xu{;Tqz-%2#jNRq8Taf8B zlY?HQ6md$(l7v)eW1h_F%qWo{c}>Pi9U~!4^14vRK1(U|JcYDe(kk|R_of52Vt57> zc>ZuX5+lL#CP)IAUOSO*awj6nRh-|HnntEmA0-F39+_h6X7TxI!6-7DhWy_(i0m!M z3_IUqGovUex*w6^c~s1~yz0|(aCs0Ufy%kJBa`b6H0Aet6#AXby_i5kHi&G0L%xRk z1xx7WW9BR*CeXPJBT`SGYgsB-yb|99u*q%HCg36h4YU)zzt zas!Hl?L=g0VeX|I6^}%@lb#m-1TM8Lq>~OJTpuFEK{V&(b>K}zit4ORz66K_sRU`3 zO{gk%Co;#bL(Y9t`MXqlZ51gcM-QV?{ey@Qhk@S9T~ky-B*<(apJgo~#x_(wel;S` zHb35sOr1+jnj)oae-F|UhfziCA^(35aOQIKDdvhukoiL9SQFAR?Uc&Rlm1;vRcsOt zUd6(Zr${N2K7{f%Cn@!tO3Lj!DV5ugMMBISksu2R)r2K;HP%zAl1(aslQ8RA6kV$G zThjGDanz@gQ$LBE{4q+=vSAcvPLi4Z$e&2^93z))SC&P<{|8;{L4jHBl*a%7002ov JPDHLkV1imXD+vGq literal 0 Hc$@6{tnvBcK{7B07*p_9-i)4qg6p|1ZNu;=m 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 ALI3~& literal 0 Hc$@