From fa0a02bea9101b8b2e86c6368b99c125447ec084 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Thu, 26 Nov 2015 20:36:12 +0300 Subject: [PATCH] improvements --- Tablet/TableDirector.swift | 76 +++++++++++------- Tablet/TableRowBuilder.swift | 29 ++++--- Tablet/TableSectionBuilder.swift | 14 +++- .../UserInterfaceState.xcuserstate | Bin 12583 -> 13343 bytes 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index 1b1cea1..daacd4c 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -44,16 +44,6 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate NSNotificationCenter.defaultCenter().removeObserver(self) } - // MARK: Sections manipulation - - public func appendSection(section: TableSectionBuilder) { - sections.append(section) - } - - public func appendSections(sections: [TableSectionBuilder]) { - self.sections.appendContentsOf(sections) - } - // MARK: Private methods /** @@ -83,84 +73,100 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate builder.0.invokeAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1) } } +} + +extension TableDirector { + // MARK: Sections manipulation + + public func appendSection(section: TableSectionBuilder) { + sections.append(section) + } + + public func appendSections(sections: [TableSectionBuilder]) { + self.sections.appendContentsOf(sections) + } +} + +public extension TableDirector { + // MARK: UITableViewDataSource - configuration - public func numberOfSectionsInTableView(tableView: UITableView) -> Int { + func numberOfSectionsInTableView(tableView: UITableView) -> Int { return sections.count } - public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sections[section].numberOfRowsInSection } - public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let builder = builderAtIndexPath(indexPath) let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) builder.0.invokeAction(.configure, cell: cell, indexPath: indexPath, itemIndex: builder.1) - + return cell } } -extension TableDirector { +public extension TableDirector { // MARK: UITableViewDataSource - section setup - public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return sections[section].headerTitle } - public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? { + func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? { return sections[section].footerTitle } // MARK: UITableViewDelegate - section setup - public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return sections[section].headerView } - public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { return sections[section].footerView } - public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return sections[section].headerHeight } - public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return sections[section].footerHeight } } -extension TableDirector { +public extension TableDirector { // MARK: UITableViewDelegate - actions - public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return builderAtIndexPath(indexPath).0.estimatedRowHeight } - public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return invokeAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension } - public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - + func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + let cell = tableView.cellForRowAtIndexPath(indexPath) if invokeAction(.click, cell: cell, indexPath: indexPath) != nil { @@ -170,17 +176,17 @@ extension TableDirector { } } - public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { - + func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { + invokeAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) } - public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { invokeAction(.willDisplay, cell: cell, indexPath: indexPath) } - public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { + func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { return invokeAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true } @@ -191,7 +197,17 @@ public func +=(left: TableDirector, right: RowBuilder) { left.appendSection(TableSectionBuilder(rowBuilders: [right])) } +public func +=(left: TableDirector, right: [RowBuilder]) { + + left.appendSection(TableSectionBuilder(rowBuilders: right)) +} + public func +=(left: TableDirector, right: TableSectionBuilder) { left.appendSection(right) +} + +public func +=(left: TableDirector, right: [TableSectionBuilder]) { + + left.appendSections(right) } \ No newline at end of file diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index 0ac2389..390e668 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -72,18 +72,6 @@ public class TableRowBuilder : RowBuilder { self.items.appendContentsOf(items!) } } - - // MARK: Items manipulation - - public func appendItems(items: [I]) { - - self.items.appendContentsOf(items) - } - - public func clear() { - - items.removeAll() - } // MARK: Chaining actions @@ -119,7 +107,7 @@ public class TableRowBuilder : RowBuilder { /** Responsible for building configurable cells of given type and passing items to them. */ -public class TableConfigurableRowBuilder : TableRowBuilder { +public class TableConfigurableRowBuilder : TableRowBuilder { public init(item: I, estimatedRowHeight: CGFloat = UITableViewAutomaticDimension) { super.init(item: item, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) @@ -139,3 +127,18 @@ public class TableConfigurableRowBuilder2&vAw)LQ#!YAdqX zsjZgU_gadgmU=B!t)d&Ht*YfcGm+qX`_29RX68Q6bD#6S&wkFz0ZWI>W;mQ?9LF4; z6SkR?9Oo$pC13;?2}(g3C%=I1Ii3XTdpe8C(Z9z_;Lga0lE4_rR~!bltTqn!VqZ8fhK5%7T5wt!YCLGV_+O?4c~%oU^46g)8M-z+r1a@eX_tAHs)m z!V!E1e}&KDbNDL0hOguA@NN7j{tG|Gf8!_kIR|nO2Xpuw6(^9R<>)yEj+tZOgnB1v)rKd0D_sAcRkw3s)bRGzS2#7&87zjdFgFc`y z$N~L8F31D@K|UBjf=DpY69Wk$Mq(mnVp$E+fg9LBCwdivpYjfTg4bi6l`Zn#7QnBz7gJ0kxnG z)Pv<<1z1VqNIYpvx{_qljl4^-eG;%X3~UD5fwCTK0iS`bU>ivwi6n`%ss}s3=hRHQ zNNe&IHBK7}V`#|O%-#IT6FK*O)T8J*DF6rB*AFfO|)CMhwoxhZPgIS>otz!7jX zC)3rTaA0|1NpXJZm|99nya0}Y@SI%!WbNjsA2?IB1^ zIuBy%z}MgcxJce19Z8z+eZK)$=#$IARdB6OT7kQ`yl_yVyR>Ioae=#%zDx&_k|)=B zcMEl5Ic|V(6MW|t3yruI-0}*A)|3VfKTxY)Bb}&KQ?h9E6uHagpi%ozeqLuEuTKN7 zgL`<%d2pYu`~dt89)d^S5@DbqgLEMvPu|JfR@>6+)TzDK1w8y0cZeSz#8Cl4oy5oa!GMnNs+r_VNtoe)Q3P08`pXpw)2U% zC4*{Udoq}++#nB%Oo6Gjup{h5hLGW8M5AnH*aawSVLHqpg=APA!R-V4l44Rqxfu#wa(|eg+hp|irKR~}>R^8m4-y-d4}=9EblEcEY9tJXg+63M zNLdXWO3Gg%EA}BPfg?x-seFa3432tZ?a{E3j3T4y+9Ar|lyQ)}!DZoiGKP#LZ|BKn z)Df?jBx}2z{lNG68cv2&;8Yq4(`aN(hcmnue!A%c0?2!0@c z8|25}u6G7M)AIqDM8>_Ap>P3Q*pQ)Q0(rk7I~$^GDNRqf4A#I};vs~v|0g{gvavCz zUdy+aB)Hz6X5-&Xv&=X1jQDfx4a9I8#avBifk)sjnMhx05}{*)FYI^u!hSk^MQKB_ z?1THg>qX%lc!1{JdQq6LfqV!a_R7S~IFRNG{S)f#FXnfGU%=x{p>%>wC9VdYr+gke z4bPBiWX3Cxor4$N@X1AZiF`<=Q;+RZ>Xc0(b`jpBMC$hXg=bgZN}o4HA;Ybm?Ms7+rdSTA%p?3M5Nu&0AK77~e&2e3z@+ z8&%HVL6Hern)FynEqS|ffl$<}A=16ysEwX*6wxHsf-HX}7L8g`b0R7Eqz1*36-|kO z5>OIlfFDSw8q|uce8p&k+WHvFNpg)JT4O4qWR%kA8Pt)ie(4#M22<-IQD>BnGRPXT zo@{J#59*4#zwRF7LOsY@vW^<#D<-_jJ*XebC7+TFlq}JNz9J8%(wqF!DVi+&vYmKO z1q(VBqfxZYq7pO$jYOrW43(n_vXyKj+sO{{IoU~etpqkyiN>I@s0zJ@#?dObn}vXd zn1u=!wq#)}tpv9<`xTSXRG)pOkUceM8re&!$E9JOhVcc>MDywRf@Y!FXbzf-yl5W! z2vwtx$v$#`93n@^7vwlONluY7tI-0q5G_KB(I;pLT8fsT8giCgAXmw^ts)~MdzQIN%OZ#8S9-f?!xgV2*ZL(7dZ%l%)UT); z{nW#G^7g*IXX{W{N`tVZv_;wI!a?P)FSOM!c=T0+)V!v9r=NMu+fCINV z)BZ=k%9AJiTlbz|t>-MdNW0emj6UcRx(w3M6>^T8r@8tyaar5bx#!6A-xkujCo!g_ zZ|;do^vyl-QPIA+r!h~yMYloda&(ib+)C%EZR8@Ir;_MI)oMBV5#6Cm@1dW_CGrhb zdxcp3LtNR(w6}FEDJm#C2gK+%bRRv)&UCdXD=#f99!xH88Le*#JrB_%n*2?@$mM6& zp@--Xkk~uZ)o|~_SblU;KYpL87&?r_#Kgu^gwgTQF|Q+hf?oXFD`S8mNXM95BiAXm z8!un^=(3>RIaQvxn5cNFF)BWZYK%*WO?piu7GmkYYLsC))u<#l$#+!at(O{4Tw7*QjKPEm)xTof1>F#G-Q!897nw={!%&` z$5825@(cNuO8-WsTNuNftuQS(^|&>D3%9{cKHK&s45o{{HN*^5TUob?9eP(LTc`TP>=o57_@0rn@RfgXK%2l`=SKv{2G_J&B@K{{MLJkYLEab6}&q4tU zg)9`YP`nC{qZ_4kOfZYb;|ajV!T?&}tSpqUP|89X3+43wZSP>yXE55UHyb?h$sJOn zXp}@m#U#HI5t|U-KH{C|sMv_OgoO5S(FsXWQAx2`m5K3r@v&Kj-G-DDyR#d95}U^~ z#=tyGi(wu92v_5eS*T>8iiPSryZ|r6i&)68FouODUk8n%J<^x*qYBH%ba#&^DJ}PI zH)m(oz|`fq7T4i=yd1A!p@xM97MfXTXJJ@V&%mqkdfzf@@LIf%g@G*8vQSrtKgApH zMivIKFqow?vdf!mS<&osyyxF!_u_p%NFgjV`XPD4t-5AM@ri$vJ&C`>r&wrVA+?{4 z>K$e^W}L^D{!R8W{sv!RVJHimv5;;Vt!?kq8IOJj0+Ss9(>Z(ti1D}hW-nSU3i8YI zyDCt=_oB5zknO4%IMD4b@OHCp52D;&Lki2?bVHV0QdCmv8j(NH{Z15+W3Sa--Oodh zXJ*nZp&6LQPK|} zF^ldM>0P7if5g9n&=u4tckw;E4*!gQ@p~qmh0UpRSQx>=7Ax?lFc?3;ztcSobx{y0 zU|}Q+qv=+rz!w#krl{}^wJ_e}p&rja)LKvRGoQ7}3x~UX)w1H=*E7zsFscFG3l3;N z;;zLnKw@r>l7jp(ru=f6U#+6!<@fxfA%_D~Yk-6xGNR#L08>|^xf~Jg*|RtjRLzlb zL25 zY9P0ItuHEHaqSJ{O_yg|Gnyei&2UM=r)-eKMq-ZQ>}ujd;){4jn5 zKawBAkLAbnbNR#g#rzTcGJXYrH2*#RRQ_!KT>dDIO=DES@UTGsNuVTB5+!LP=_pB+be3dDG9|qv z*^<7Jev&*%zGSGRT;h>@EUA~Qmu!%1l5CM|mF$)5mmHKFmK>EFliZeKX{fZVG*y}= zO_%nTdiqNHN&8C&NDHKu(y`LX(rMD^(pl0uQm=HSbfa{ubi4F(=`QIp=_%1F8^=~d}H=`$HmCX?x9W|>uHmxali%UZ~yWUXY$vJ6>Y*#KFIY=ms2tV~8^6J!%* zQ)JU*(`CzKt7V_cHp({3K9e1g9hDuEo$$!c$j-{n%Pz=n$nMDgkUfz-l|7eZIakh? z3+2Ibn>O<8Gk7|}`j%tZ&nW|P*uUes6rCOs}r#htiU9C{ZsXM5%)C1Ln)I-$6 z)Wg*!YF0f{JxA?TSF7i%7pj-5H>*Ea?^5qk?^7RDA5))Df2lsLKBK;({!x8T{j>Tv z^#k=o1~8EBDmhFr<6y#>2qub&VPcu~Ob4bTlg4<`nJ!EprXQ2X3}6bFK};Dlim7C( zm~o7Una<2&<}mY^YGyuD!>nS~Fzc94nT^aI<{)#JIm(=5PBCYgv&{F*FU%9>g$8P{ zMxYUC0yI*MUSrq9Xc9C@n%0_jns+oEG#xeBn#GzOnj@O8H5WCPHCHrOHP=0wZ#Ca( z9%vqF{?I(u{G)ju2m?8Ryg)->tH4fyxq)*6>jL)%o(w!4_*LNfzzczwv_LD-nzR(chr_R?l+2Wf|BhiZ$otF_y-JG48s zyLED%L1)yNbynSAUAfLPN>`~Ht2?Yat2?i|pt}_02#O0z2uccS9XvI-I(UBY!r;Zh z|L6sJkv>2#)eq8_=_~Z3^<(t=^k3>P=r8HN(f>z(O@CW|M}JTMv;J58ef{4Co9K#^PkdTi;mUu!ohHMYnA96h8>yYaq zKZQIB`7`8k$diz#My`=>6dJ`wiBV?M8tukN<6FiQV<%&pG2Ph3m}Ts3>|@L^<{JAO z3yq_U#5luPZJcjhXk2VuVq9rlZCqG~DDVF^x2pnJP^0n?5vsY^pb{H*GL&GHo$!HSIO+Hytz`HXSt`Gu<+a%vy6h zbDFukIomwQTw)$+E;Cn{N1KUxy!iw3B=Z#WG_%*d*u31l*}TiV$Gp#cz4j6KetXm4$Q$DU$OwWr&=*t6`t?YZ`0_ELL=z0zJ~A8(&%pJM;e zKEqyZUtq7dZ?f;O@3QZ;AFv;@pR}L0pS7R2U$x(||7?Hc$ads7+>SEGSO@Ev=~(1g z;;3=dJ61Z@IMzFMI`%mBc^n5FM;u=`jyp~|?mHQ0TW6uO)H&8U!8yq}%USJQHOY#+j-adv-4Nyedjahi!d0*3F{ozD=a&#Z&+^F w=CFNX2f_}89SygK$Arg*$A>3{PYYihUK763KcoVL{J$!|32z`YeuuCAFZ+mdF8}}l delta 6757 zcmaJ_30PBC(>_bczTDj8hG0T&l8Xr_RzQ}x7ok+kA_}6oVIomc1O;3WF(=lgb=SDm ztqLgaTdmcqtxN0I+N!Nums&qRtG3qewf?rYYX6fUXurSDPo9T+@66meb7tN%Gk4aF z+T>ZpiSUp3r^OL5FlKRDlCKa91mnPXPys4I6_@}ff=OU9s0My8AFKecf!DzXFb8Y| zTfh!559|bQfW6>ta1gu;j)M=t$KVri9()e2fa~B(@E!Ob`~ZFgccBP|K{1p-DU?Au zR6r#(!U)(3nxGj*LJQ=f6$&s0wjT^Tz!caSc7e~sRM-Rdgqbi0_Jw({2o8g8=z+sw zIUEPa!wOglC&H<)7EXtA;9NKl&W8)&a<~G%23Ny6SPvWFcDMt+0T04M@GyKIo(SZ@ zq|R34K(QzRxllLM1NB5Xr~vgx1JE$!MjkX8jX|Yo8uB56{AfCQ8O=a5(OfhSy^iVw z$Dqk~8l6F(pij{?^dEE+-A3P_JLp?0zx%E8^KZ6R(5aS`ia@g)AhSNj`al#1YS+Ug%F2?;DtB2`6RR@I zU0pt*DsWV8_R7u!8IS`77zDh)u>}kUL%>i_1cm`O@POfU0@?I829$!aAd|EvovG1r^yekhh>u$98CV)xCBMS!4b+I2M^S5orlxy66Go2o zhV1(cOaV1uDqX!6OaneZ0!d7!HH84;Ae}CP>ELC`ngM2lS(IH1UZvQc3+4sZGdY$N z(vgA0$$$%B0a!@I7JV2`{3h!w>p)^iGKnT}fxdEA@=B1<09Jw3U=3+Q zo+I%@eIBd>>*{aY7t11~$;;rb{tE|{NnY1Obq+QTQvU4C2B!Nb-DWFjB zxE^c{$P_|a)5}|_6BtyBQEN{js%8Ad6G(cG=SUGDR)R3b;@uG_Kgxx-cLaTe*FhV!56;O;FBx7{QeNh+sIG@L;CcprFbcMAf*%<| z1~fr06a?6YVh^^3v9KK}Bm>Ey|H2-%dkDo^GjN`P)DsePg|IaE|HBe_f+JlBYkA&~ zl|3euloop{0=3GvzBHhK>0lbn0B`lr$$QS@uJjI~*9vc`yQ*ZOmx9Jk5}S6~3%=AZ zC$C@Mta{iBxSD8LFuRD+<>X~gs0zaTsT&$#R?rbmJMB%Q33Ev?Q5P{>O-;yqvDTXS zcvla4?~0GFt$h+^m=6nqV*~653t)dZfQ%p`$tY5?0S<(NKs_8nMw4;$1WqNM0a@M= zRRty9NdceAm@%*^d1aRudkg!Pj2so>H0vyeB|)8DI0BA@qsSOiO2(414ImR_!%`4M z;~huJgV{Ckp{kaz0txF|UEXTw*>L^6qD>8iSO#6q~_Z`=S}N~*~e%8k=R_*TMILtEUKT2bMy zZh$L6GH^93Ujttc8nTwu)`4tlu&0R8rj?gfmX~@nN=mD|6~VnX3pcKJQHNlI)1J+dL8MST=$ zAO+3qI#CSu5K@!1b*K&5&=OD74z;HYu$8p;)uA}D@hPVRN(yr7NZY!QEzJ->9Z~0& zMY@npPZ#Nqp8p$IP#SunIW8!JY9>&`T&2Ws$992ie^en@HLwpx&tOv%x`m zD4%R2+o_+6}Fcf4q?|m$qKodSHL*-~38jmVa zC8{ECl6~YYvY#9vZig1O9n-Cp=^1ii0Krn+G~s&?NerBh(K)J!Zez`GRjMfE6-6pT}NM{8-=tERaRA$l#L|k_l}C}0DZU6S4E7b zB~9jqm<{L_`WmHt!kT7ah=K(oR>&|g#``V&1wkI-XsmHeArBmdce0frzGV{)B* zNfq9p(A&eWj!|LuAEkAewjkI*ZjrC3^w(5+g0+p$jBWp9EVg5T8he#|L+(&%>cP;y zM{b)W9T41YFfdQd!)-847XLTCI1b0t1v`-M$oEvm4^LFM2PE{P@udL{#@CUQTw6#3 zoIrC{T#LqzIG9UtC-PGr?m~X12U=^l^-9Gr0d_O)fzxn0egS9T7jaMAi`*r@l6&NT z$bIq~`JFu2j5FzHLMG0^y>Tw?L+kG!^yKD~KgmP#h&-nE1%X%WZ^F1hS0U2ZAt@m~ zqhq?OT}E8TyhfpNa>KCmhMVSEtu>|E=o=;D9IgFUgj-qx}?M= zH1FSoM*v3y9*&E#*AIaoLO(S0@{kxr{>7-!-s*Rk%nYHK7gm-gZNM=FcE&(ipItdO@3%@#8W{%K7x-@gX?LW zNUR@5`XNu-%-A3*>@BDWJdEZ7-$(m=C#kbO!XF2nRaG+98%m3-zNzi%hn6PuPUAC8 zmU!#&Y2X@~Uta94wz{imj_j0>#C#iSbnrRouLCNANKMo8Md;r|%g_S+Ilh9H;;U#0 zEkp16q2PzD$wz+Zq!p=#=6`*2&yH^dler(#ujrOk&$bj7e7lM32-Y0#Df#;*a`e-x z5+%Yv<6i=GZNq)bXp!5DcB4axRt0nteN4wD=g?>9B6@`N*hX_k0#2kO5f|=+yU?LX zHa*3Ca2_3t^rs_{L3A8aiWlLtA|SGhx`_%!<3&?MwIZL$FPbA-CVE}eDB31^Q*=!9 zndqYEvgnHFs_2^Ny6A@JmgsBI1JR#8(Ie4cVK5Abg@sANWMPUhRait=Y*?qT(P6b= z+ry58oe8@w#$u6JD~=L7#L?n5;#l!>;y7`FI8mG|?j_C?XN!A_`-tvVDzj&dzQM^a|f%seTV~JK`m!wGgNJ=GTl5vs>NtI;2WVvLmWQ)XiN^)6pMRHYg zO>$jwLvl;1)ze(lyf8rQ4)$Ne@fkl^&HI zmtK?JmWgEwSsPi3tfQ>6tg9?t)<>2n>nH0k^T^6&HL{tq*|JwIa&P)t%( zE9w+G6?+tW6>ljHC=M!)C{8KPD=sK5DLz+RSKLtCQhcrWMyXfED$|wO%3Nh%Wxmp_ z9H*>MRw*YcCo88Yrz)o@=PMT~7b^qGWy%%GmCDu1wMySs;thu52N%Onr56wf(V+JrXM!~2U4WngrOgxjrjA!OB0cI()oM~Vhna#{L zW(Tv2d5<~8oMp~47nn=TEyj0;`HuO4xy#&R?lZq@#o7q1UE5ac(stE$*QRPSv^}*i zX|uEi+9K^J?Ii6q?Og2w?ILYJyG*-6yG?sQ`?mI=_OSM(_LTOF_N?~2_Ja0~_OA9f z?E~$f+DELM)v#Jt#~RsIteLg2(QG{1jZI@;U|(dj*c>+3$M$85*|F>twwCp=)7cs9 zEOsHglwHog#;#&FvD?|5>~3}+yPtiVJ;WYnPq63MOYGPG7(>1OC=>0Z&z(aqB>&@Ixf)veRj=^At!b(?fsblY^tb!T-q z^*)I{S>I3Z(R=kH^`rHr`Z7Jy&(|-~FVQd4uh6g5Z_w}2AJ8AvAJ)ICKcW9Xe^URk z{6SZ29qJm5N}8}xD1^P-3_URG{Xyq0fyCv&4&Gkw+)93 z?--64jv3xFoG^T5xM;X+xMH|!xMuj$aLe$u;Zb<2aA&x$Tlo0!m&0EV-xj_ze0TWX z@O|O?!>@<`5dJXyu@M-NQDhVwrAE0i!e}x^8hNA5C>UECoyHhrve9MiWb9(BHqJ7> zVw_`~XS{Cw!T6K$7vrxHT_awK$co5`$c?Cr*cq`q;*E$mO~|A%X-zs4XR0#!O)r~f znr53$`%G6%H%(ueZkz6yzBAo3-8cPi`or|l^w=yh>&?75)|_JQXzpz8YVK}MHD{S~ z%(>>i=6rL3d4Snt9%G(ho)ozua!2Hm$bUtC5_viDM&zBy`;mWHpaomPED{T2VJ&)# z!D6(uvIv&;mX4MTOK(dbOP-~lrN3pE#pkgUTSiz$Sw>rCTDDsbT5edrv)r>h;^n-K z=lF0wf;aI|yn~PC+wigcb9@S)&gb$&_!0alel%aom+_PMYQBcA<$b)LpTh_E_52oo z8^43!#qZ${@`w3%`J?=C{(b&5e}%ur|H9wn@AD7%Klw*ih1KA*3f4qxvejknWbI<@ zW_{k;!`r?ddpmo3dl!3}J;UD1o@LLo z7uXB!gYCYd_SyD*_Al+<+JCV>6l4M;=mdihAy@@La0oF%TOmgis=k5vqhq!gOJwuv}OvtP$1;jlvdTyRb{xBODZt2_FgP9LbK3jvkI&M}Nmq z#~8