From d9d625f65186e846d12431cefede8999f65ca4e5 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sat, 10 Nov 2007 22:01:23 +0000 Subject: [PATCH] 0.5: NUNS! REVERT!!! --- app/controllers/amf_controller.rb | 196 +++++++++++++++++++----------- public/potlatch/potlatch.swf | Bin 75471 -> 77399 bytes 2 files changed, 126 insertions(+), 70 deletions(-) diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 9c8d4cc6a..3df6da6fa 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -4,6 +4,15 @@ class AmfController < ApplicationController session :off before_filter :check_write_availability + # AMF controller for Potlatch + # --------------------------- + # All interaction between Potlatch (as a .SWF application) and the + # OSM database takes place using this controller. Messages are + # encoded in the Actionscript Message Format (AMF). + # + # Public domain. Set your tab width to 4 to read this document. :) + # editions Systeme D / Richard Fairhurst 2004-2007 + # to log: # RAILS_DEFAULT_LOGGER.error("Args: #{args[0]}, #{args[1]}, #{args[2]}, #{args[3]}") @@ -259,14 +268,17 @@ EOF basey = args[5] masterscale = args[6] - waylist = ActiveRecord::Base.connection.select_all("SELECT DISTINCT current_way_nodes.id AS wayid"+ - " FROM current_way_nodes,current_nodes,current_ways "+ - " WHERE current_nodes.id=current_way_nodes.node_id "+ - " AND current_ways.id=current_way_nodes.id "+ - " AND current_ways.visible=0 "+ - " AND "+OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")) - - ways = waylist.collect {|a| a['wayid'].to_i } # get an array of way IDs + sql=<<-EOF + SELECT DISTINCT current_ways.id + FROM current_nodes,way_nodes,current_ways + WHERE #{OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")} + AND way_nodes.node_id=current_nodes.id + AND way_nodes.id=current_ways.id + AND current_nodes.visible=0 + AND current_ways.visible=0 + EOF + waylist = ActiveRecord::Base.connection.select_all(sql) + ways = waylist.collect {|a| a['id'].to_i } [ways] end @@ -301,75 +313,37 @@ EOF # ----- getway_old (objectname, way, version, baselong, basey, masterscale) # returns old version of way - # Node handling on undelete (historic=false): - # - always use the node specified, even if it's moved - - # Node handling on revert (historic=true): - # - if it's a visible node, use a new node id (i.e. not mucking up the old one) - # which means the SWF needs to allocate new ids - # - if it's an invisible node, we can reuse the old node id - def getway_old(args) + RAILS_DEFAULT_LOGGER.info(" Message: getway_old (server is #{SERVER_URL})") + return if SERVER_URL=='www.openstreetmap.org' + objname,wayid,version,baselong,basey,masterscale=args wayid = wayid.to_i + version = version.to_i xmin = ymin = 999999 xmax = ymax = -999999 - dellist=[] - - # get version (if -1) and timestamp + points=[] if version<0 historic=false - row=ActiveRecord::Base.connection.select_one("SELECT version FROM ways WHERE way=#{wayid} ORDER BY version DESC LIMIT 1") - version=row['version'] + version=getlastversion(wayid,version) else historic=true end - row=ActiveRecord::Base.connection.select_one("SELECT timestamp FROM ways WHERE version=#{version} AND way=#{wayid}") - timestamp=row['timestamp'] - - # get node list from this version - sql=<<-EOF - SELECT cn.id,visible,latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags - FROM way_nodes wn,current_nodes cn - WHERE wn.version=#{version} - AND wn.id=#{wayid} - AND wn.node_id=cn.id - ORDER BY sequence_id - EOF - ActiveRecord::Base.connection.select_all(sql).each {|row| - points<<[long2coord(row['longitude'].to_f,baselong,masterscale),lat2coord(row['latitude'].to_f,basey,masterscale),row['id'].to_i,row['visible'].to_i,tag2array(row['tags'])] + readwayquery_old(wayid,version,historic).each { |row| + points<<[long2coord(row['longitude'].to_f,baselong,masterscale),lat2coord(row['latitude'].to_f,basey,masterscale),row['id'].to_i,row['visible'].to_i,tag2array(row['tags'].to_s)] xmin=[xmin,row['longitude'].to_f].min xmax=[xmax,row['longitude'].to_f].max - ymin=[ymin,row['latitude'].to_f].min - ymax=[ymax,row['latitude'].to_f].max + ymin=[ymin,row['latitude' ].to_f].min + ymax=[ymax,row['latitude' ].to_f].max } - # if historic (full revert), get the old version of each node - if historic then - for i in (0..points.length-1) - sql=<<-EOF - SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags - FROM nodes - WHERE id=#{points[i][2]} - AND timestamp<=#{waytime} - ORDER BY timestamp DESC - LIMIT 1 - EOF - row=ActiveRecord::Base.connection.select_one(sql) - unless row.empty? then - points[i][0]=long2coord(row['longitude'].to_f,baselong,masterscale) - points[i][1]=lat2coord(row['latitude'].to_f,baselong,masterscale) - points[i][4]=tag2array(row['tags']) - end - end - end - # get tags from this version attributes={} - attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM current_way_tags WHERE id=#{wayid} AND version=#{version}" + attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM way_tags WHERE id=#{wayid} AND version=#{version}" attrlist.each {|a| attributes[a['k'].gsub(':','|')]=a['v'] } + attributes['history']="Retrieved from v"+version.to_s - [objname,points,attributes,xmin,xmax,ymin,ymax] + [objname,points,attributes,xmin,xmax,ymin,ymax,version] end # ----- getway_history (way) @@ -377,7 +351,6 @@ EOF # should also show 'created_by' def getway_history(wayid) - RAILS_DEFAULT_LOGGER.info(" Received history request for #{wayid}") history=[] sql=<<-EOF SELECT version,timestamp,visible,display_name,data_public @@ -399,9 +372,17 @@ EOF # returns current way ID, new way ID, hash of renumbered nodes, # xmin,xmax,ymin,ymax + # ** needs to be updated so that nodes with visible=0 (i.e. undeleted) + # no longer cause a problem + # best way to do this would be to know which version it was recovered from; + # then replace readwayquery with historic query. Line 506 would also need + # to check if visible had changed, and update if so + # (a side-effect is that merging/splitting ways will need to be forbidden + # for undeleted ways, I think) + def putway(args) RAILS_DEFAULT_LOGGER.info(" putway started") - usertoken,originalway,points,attributes,baselong,basey,masterscale=args + usertoken,originalway,points,attributes,oldversion,baselong,basey,masterscale=args uid=getuserid(usertoken) return if !uid RAILS_DEFAULT_LOGGER.info(" putway authenticated happily") @@ -409,20 +390,34 @@ EOF db_now='@now'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # 'now' variable name, typically 51 chars ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()") originalway=originalway.to_i - + oldversion=oldversion.to_i + RAILS_DEFAULT_LOGGER.info(" Message: putway, id=#{originalway}") # -- 3. read original way into memory - xc={}; yc={}; tagc={} + xc={}; yc={}; tagc={}; vc={} if originalway>0 way=originalway - readwayquery(way).each { |row| - id=row['id'].to_i - xc[id]=row['longitude'].to_f - yc[id]=row['latitude' ].to_f - tagc[id]=row['tags'] - } + if oldversion==0 + readwayquery(way).each { |row| + id=row['id'].to_i + xc[id]=row['longitude'].to_f + yc[id]=row['latitude' ].to_f + tagc[id]=row['tags'] + vc[id]=1 + } + else + readwayquery_old(way,oldversion,true).each { |row| + id=row['id'].to_i + if (id>0) then + xc[id]=row['longitude'].to_f + yc[id]=row['latitude' ].to_f + tagc[id]=row['tags'] + vc[id]=row['visible'].to_i + end + } + end ActiveRecord::Base.connection.update("UPDATE current_ways SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id=#{way}") else way=ActiveRecord::Base.connection.insert("INSERT INTO current_ways (user_id,timestamp,visible) VALUES (#{uid},#{db_now},1)") @@ -468,7 +463,7 @@ EOF elsif xc.has_key?(node) nodelist.push(node) # old node from original way - update - if (xs!=xc[node] or (ys/0.0000001).round!=(yc[node]/0.0000001).round or tagstr!=tagc[node]) + if (xs!=xc[node] or (ys/0.0000001).round!=(yc[node]/0.0000001).round or tagstr!=tagc[node] or vc[node]==0) ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{node},#{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{lat},longitude=#{long},timestamp=#{db_now},user_id=#{uid},tags=#{tagsql},visible=1,tile=#{tile} WHERE id=#{node}") end @@ -655,6 +650,67 @@ def readwayquery(id) " ORDER BY sequence_id" end +def getlastversion(id,version) + row=ActiveRecord::Base.connection.select_one("SELECT version FROM ways WHERE id=#{id} AND visible=1 ORDER BY version DESC LIMIT 1") + row['version'] +end + +def readwayquery_old(id,version,historic) + # Node handling on undelete (historic=false): + # - always use the node specified, even if it's moved + + # Node handling on revert (historic=true): + # - if it's a visible node, use a new node id (i.e. not mucking up the old one) + # which means the SWF needs to allocate new ids + # - if it's an invisible node, we can reuse the old node id + + # get node list from specified version of way, + # and the _current_ lat/long/tags of each node + + row=ActiveRecord::Base.connection.select_one("SELECT timestamp FROM ways WHERE version=#{version} AND id=#{id}") + waytime=row['timestamp'] + + sql=<<-EOF + SELECT cn.id,visible,latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags + FROM way_nodes wn,current_nodes cn + WHERE wn.version=#{version} + AND wn.id=#{id} + AND wn.node_id=cn.id + ORDER BY sequence_id + EOF + rows=ActiveRecord::Base.connection.select_all(sql) + + # if historic (full revert), get the old version of each node, + # and use this (though with a new id) if it differs from the current one + if historic then + rows.each_index do |i| + sql=<<-EOF + SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags + FROM nodes + WHERE id=#{rows[i]['id']} + AND timestamp<="#{waytime}" + ORDER BY timestamp DESC + LIMIT 1 + EOF + row=ActiveRecord::Base.connection.select_one(sql) + unless row.nil? then + nx=row['longitude'].to_f + ny=row['latitude'].to_f + if (nx!=rows[i]['longitude'].to_f or ny!=rows[i]['latitude'].to_f or row['tags']!=rows[i]['tags']) then + rows[i]['id']=-1 + # This generates a new node id if x/y/tags differ from current node. + # Strictly speaking, it need only do this for uniquenodes, but we're + # not generating uniquenodes for historic ways (yet!). + end + rows[i]['longitude']=nx + rows[i]['latitude' ]=ny + rows[i]['tags' ]=row['tags'] + end + end + end + rows +end + def createuniquenodes(way,uqn_name,nodelist) # Find nodes which appear in this way but no others sql=<<-EOF diff --git a/public/potlatch/potlatch.swf b/public/potlatch/potlatch.swf index 13016113593a68ece8860b1893215f29b99c66af..1f7becb4888e08564b6771f5780537db1e300111 100755 GIT binary patch delta 27996 zcmcJ234B$>_5Yho$a^DJUATS{GE713UpY z7O^0Th+?f(v5R&Qi+1s6D=OMrv_BEhx>oZ4o-=dbyEh47+yAd0`)=;cnKNgfGs_)* zcQESBx1*xZzi2|>qAq)*vx0$}la=rG4LQHqR~DSxPW9ZkE`L+BJ^!ki*EB3#bjAFA zm8B)^&cFPsh8YXT){j`^o87SZ+8N7y`2Q6%eOJw&G4uR|^RGU);i`tk4KsZ+8?IW| zu&8nVyqOIP4dgUn@@Z7__DwAxrIO|^p3|_9am+%?#`%l({kU^%9R0S}ke;6AfVk?4 zMT>pc&bi|9Ie1w#4b{?%l!W`Cyxu=a%U5+9EMFiHwAu|FeEys9r$0sECklVrH`Awm z3+iuG{%8gP^&s~LUbk3l zR`e?k+y){5*F<~z4OYo?qF;7WvI+|JN>$h4e#P~v4|4?g*q7{SEsQULwblb56su|FjP_D*jY_xp&7KpHiQu4>C^zg(28v1cM z<=vcE^P=MNWEJJh-2mAnDnIztevR8#VknNi$`Za9`nb%UY(&=Kv2`RX;5WYT;=q;LFXl8YxKgb zT|ymeZc}&Au9`8{?GXv))dt(N+AONCEmh@oP3`5X13h?iiAq^JxFq#oLa@e|p$4+h zOF>Ec+C$M)bAcZXrVg$+4Z`~eH>!L}7?L-}OBm2>PVmibST?=^4!RhE=%l zimWFCbSZZbVE5SNTmJYX@hVKiANvVUwGF zV4?>k0=dM1aQM@UDv&Fly;TKc9Uq7vz*PrSAWyt#CX^7%W9V?6^Eh{12$74Zh2ZosJ0 zi=>@nLu(8YPh5P7Do11oOpttu>PFtybuc!H=)0H;p!H%VO zM@KGuMsYHioTeC64zw6^dTafHn3pMGOj+eCddRmy4(pIdd9KsycttD|As~{Our+Htlad*mYEQ5IiI6`bgPFmHl^Re@GSe=k)U?LHot5 zh}|4Ikj&|0Wk1wr545qqL_JF{)@OD3hw^t~oy71D8(3>%AoP#5(Go?EtqeY^g7x8n zE?b=Ae@)zfmg>gNRG-kku_YspsXA9exWM53)RYE-qgk7HWp7GB$HVmd7{T2)LdmC8 zI4-65Q|#Y?>ix+}dnen!Bc{en78$cy5} zbYfH%HO`5qD<;gT|I+a|-4TG{RzqA}b91D}&-f1?J{-=TK@yiEPu<^MITGYTDwvql zvsv=DO)ZchCVr*tuT`KnC}R9Z4P#P==(lgFabmVQNh>E_)Tyfy1Pj_k@Grz|-Q+uN zBJ6>V-%#@WY~=aFE~rdn(pvT=z=A)U8i)D;`O6C`@P6Wgyh?@#@h8|oM6jZ|Qz(V% zB#q_jQ)*28=3<&&oJkWdOh-O*<%Lz2vS{Ol)l-!vVh7`KvGojW3hIQB_P!0uXAN?d z*CWN{U|%meZV1+4{}%oe?XxY5+lpk~6V;=K(u)d^xc?dYY2 zsWkTX7<%v0#B9!mul5NiMxNyw$}*BVcu|(pO(2h^3RTA~d_E^}L(HmYQk-y%4x%h* z%k|#gf-YU}(H2xA?6*tDCh6FziYiJ*g~#JtQ3EY+5m?Q_btDuEc=B&W?H9o-NNC2)N{w1B1U~ z=;)-kPvcmq3;y9-`+EX0w6u0*j zCrB|QUtd?hIn}qQVev$I>XMEsk>0$dhm~ZleZQIx&5EWWlc%ZsXzS!sBm#q3AT}Q8 zt%DUfB8ig>;K|m&0bJR^l6h5u4EK0pJ_Nv+?vL5M#19|?lO3_i=~-jj*%4@b7oJ7K zrldF7O8y4bFdOtIIfv5+h!E4Vbj|C1i)J9pUaFpy=7B&8SoCMI>DXcsPeFsr%O2iGPE*wDmK1MOB5jj$}pap zU|e&y^pj2Hm*%J}2_T3DC5Q&xO*W$g^LKgTNH_83EQupUEg;7L5}fL=gftNBYpgmf zrPMkoInbboEZ7NC!tQSyyaBLgs(|XScsMgA6j6_9rM<&%rquCmL<~k0$Esqk5zb^y zVC5-pn@OvurKP7>EIsDx@85B0iWMBRxqvFWWW_6A_lgosLXP@8*_sgb zyx}HwioR7561NenWO;@y|ZWGen$)sKOfX2l{M{%ZS)w3IwNqP!KP4#hlXim0j zrswALQ)O5d4AP;&Hch)CT|GcGS7wX3n35)L0z!`IBtb~iNh(($Jvj#KI{kHy)GQfZ^*xSmMDWz$TJ9y zZwpU1!4qdj1xO+nxx?j+nNi3JE9if(Dj0nFj)p01mVmz$*_-wcsX;{w;Y7(+lMsP~Q2pQ-D!43$X3Vc_quxR2rvvjp&(iraWYy70d2}fA)4|3H<)^P3tNJ=={c(_u z5L{#dI6OgtWtkSnJ~&VqD4MpQJN;}y&`ESVS(5LT>qlq(sL+o}{ixE9Mt>}##ch+p$xN)P5Y-LWa81NOGEitAOb8>0*k|?@*VZQ2we627= z#yU6(d!p{P+*8iUtS;}&yP8OD|@pQe$ z@q2}?E;rS#*Ek;dB@qoI3W_e)_*_;%m1P&ZkTwB}>s_#xc(J-(+r|nMRh(Z(P=QXN z*I?#XH)hZ&)xg}@uo2r9YQ3RVrOBzJ>lf#o6Qd`Vr6zHQLxZO>i{~d{ISZeq7Kjp> zq@jwT4;L4zL4W9MVwYEdFFDUapG(ljb75(*}i*Vp`X?*sXo7q6WB!F z{uztC)J536_4&Sw+JKN(tqm(sB%OA(#t&dj)u=~RaJWpalXdW_rkHCk&O<4a%n-44 zIxpvZI#;H2)pXM}sYsVF8-`e`>HcdjQr+mE*9^m+)xc|qsP1&rwWaDHJ#y_x{GPn_ z64isoEFGfGq18*rsGjuB(h_X)L@g^(y{YrEU``(l8ez^paZj>eqZ!LmM)$S!>PfH2 zj>TeZS?G1#Gc*P!1jUXR)Zy`(^?r0CioGs4@T_fkY6Ouz0+Goi z2D4d5Te&pzx?vE}?&}KG0DA4Z(wu=U;{n6UWOEQDUZ34zF-!@_lFEF(cu7%esQ>l3 zs+KF&Vp@ECm$_v+B@TQ8>i~ZkMPq&TV6AA*XjnJ#YJC0XBwxe4nM3Cvv}$OO0?S~EU!Icyl4NqqR%H*NUdszIhU#91T0-Iw&gcPtE?vF6hdPh8 zEKjq~=ctQNJ&ayl-mhnsl06uEm=%n3C76hmprA_|m1sGfy4;YfhEcB@ixLM}1D$5z zU?kmmLv|0~igyYDK1u`&Dn=r84$Cys4j`lHw>RXrY&XVfH`>*%Hqs9L)ltrk*$plF zt9RPfwQL8L#u}lHvj&P}#zRn!O-yi=Y4zbZtxn)3(xw|9Ne6_(Sd1@FrW34jbWzjY z>H^xayV$zWqSY%hspzKuxv#pt#^XX4Sp!L}Nuh$9Q`*b6Jq;d^skgZ&-aItGyU>YP zAmM%KgcM$waR|(y+7;V6pAm5c_%-z(_wvTgRqEokKlmq>_@C%Af@*FlZ9fU?g9B*B z)9K}tbna*4EQdQy)LD#FBE)u4_OrC}mM2wznsRGp;1WG)noO&2eM4PFm;bO+?i5Rw z{HE&Vh4_eP^6oV)_#lm*|6yKvfesjn>>pm=&P9E8+muoLYoy2qajxX@B_~v@;JnQJe)#(1Vf$b3AY46~Y6d3OfPy|BP zl@e}EIqPgPU3&Wg%*ylc=uRK6jHi7oJ7Dlwa7U4frhlx=!{1NcQB}`08}EfpRY)qm zN=}Cy5jyQ~9IFTlRwgJ#bt|)r+nM>Q4;vSbfqUEpCot&H$}%I-msb{RiKb#qm!(&i&AdjrcU7f% z3_~Awz%+l_T|HrP>+dSexZJGW8%ANh2tCs+I`Y?4HG|&2tB-n>a_-J+5@k6g$zcjD zW&9#8Lg&hm?xJ8O7ZX0~ zEY+KQbZl`t?ORo5Uu8}OoT3j_4NXXOjFFteKq5r^ztZvKxrN)9J-Exhjnguj!*^QTp0JYBpW4b_jm&U0a6YTYRO{&-zCbp?IAE(d={ukVB3n)QP&x>(i4hwVHO4vC(1&WxHkCi^K+5Z}W4 zu0*)=`r}+{e4MK-{b7A&rQmksV{|;pj%Ty;c1D#ON>Z+Bh4yNix#2Q3h+e^OEp-k} zt)7P=4me?1z%d4q*!D#qx$c&l>r)>e7Au3>d^bcry?1YFQKP$PR9lS}(5ib2%NK^> z&_${qD;K%T2I;cJ)aTxF{!d96_`OMSlUJk3TSDD74r{t5JX&x_vai*z1B~=gvQ(Ei zt_FEtqer%-uCZhqToJ>}bsE-QX4MLY_9Fl5IR+uNNMd=N4(Ee;j0diud0%enP3DCb zAGi_7QHsVrm=+5e^Rbc~pPfTJHg#?qrI!GLi~zChM$0UF-C))6IC8cLD|c!Z32xMe zY|gp-T+X?0nT8N2Yyztwpo^r^_bK>SlYNtgPCZag*Us`V#!S75w5Zh)8?)4Vlc(!* zrE4xj*MJCjjn@@ASqO69_RW^v)B?=u+sv(a$k%;WyY_SRERknZz<9H#?_bE^&Sj_q zguCw_=)Uih8RRXNwB*^a1LpL7t5$oY?^|2-eXH)^7Ej;jO5a=tq=0bu{X@fdOAt8; zDE4t1U4CEBruE9cT_dnbUdaNo&0fe_m|4-EQR2~fu%?_wYfAa`pfFscmj?z`Qs z(cfdi;DBtE<#fpGH!|uvPBqqOU~DtB=l<8x=KFIKBZXYHo?f{>x5-py7EFtK-3=1HM}v*-26BkX&CM9z zh-=ZsCbWQ)6v!4Fcgq`Qylh&5l?TA0(=Y>=xJHJNYpLslY2h(k4rfm3A}Tc@Ne+3+ zs3Yt5OQAvxWvn_Gah6&-+0=v5X@V$g&dJDMd@xuX0h694>x_K9c!dKfq~v-?agKsI zAOu_p^@0O&JB*8iwh8%;(!g^rPVdfcTsm?7MK~P~^0!C10_)ih5Q+fU0=YZ9nD9D1 zie7strrglL5!eF=c$7uFax^X&RC~?Q{2= zg~JCTud=TApniYIRBwsAVp$PPnE;JP98UZq&TX}9;Nq%j+92H+r3reB70_)LST+#5 zU|XR__kabmtr`vwA#0m{#iRA=CUxFXs|wpp3n zPAhk0_kCDnWKUtM?ci+LqHnGei{wSbJ1ypNhb5(4N$>2)XnMr5(H9fifdvd(;CO({ z0{*X>{z^3?4N*E#Lj?{&Lf;X0>Xr0!M=Xr;eLSTj7jy52=ZyLA0dqdC`WYmw8?ia% zA~u$zF)Ty2VGhi29eC!D%QChf<8e3^g}Zg#Lb~BcnN16o?mk_*e^genW$}8qWuuN$ zjw(4b^C(&wjqui%KJ~+ePWX4(1sXN@IP@9ga7^G1UR#W?0@gFaAzb2v;cz4|SZAvU{n^u1>?B4Euy+;0R!Flzrhs37p^S=)wcLx^-}rDfY^ed5VtgN*m=A z^H^_|3NgQM1pOpf1gJP5p8NDG+OSOC32R9NT1tZ-&B+?6PIIc4mONULvEOoV;1DgA z0bs{ZTlSN*_tAnf*KuBSHBwIvQDmw@Hw^wp!e0oDp+@eJkeF7I)vjG(va$aa%H z-{~BS)J=hJzaGILLlo80inr3~i6zlZ<{f9o0W%D72CF{!dd>M(&F5Px`TUQ)M)6~G z4>Vq*_=jwcK5MzLc!z?I7PPRTfG@R9v&SgduqG-F$O%tygGIc)R;UuaE~ zN};01i)_rk`E!!MM|7lrkhkf0^==r=d%U1Me4uMH9e6K;KHr@*0LArTX7R$a->?{X z{){qa0P_2Z<+q{tz?;I(hd92wXm@wL6s#_!-|o)J0KDGI$w5XH#!^q;?ygd!=x@6_ z(x}JclAiO5=Q*1FSnu&IC4mXvPaWZi5w<0qzqo|crfews@!9x}Xx`)JclxPUt}jcf zuH}lR&FD>xx0K#~yht^#-4n#wkla1Jlba>r~;VRm=rzoHs z*j2RmqEva2F96@$b7cpvfn8RpNP{U)jHYjP$5ehFH9V))@I1ZqL`OA-)ZVlzsLq+5 zV}0!cv+MyKx=JrJr6XwQ-pMig%Qzqcg(4c`FmMq}tVPZkz9-|G!D zg}hIP_&Ql{)74va=<|$h2M8^-<~zHq!yi@+q)ks2gu5A}F^=MH!iAjbu>DcrC(FX^ z2GJEyb_&1M(3E}o*hIkjR9f(O8m-?Ksp~~A@5}#>q|)iBzA?PuF9tS==04R~O`;7? zl@!SGKCHM=2petqFV_s#@mb5K(*b(&sZNOw=mG&9Nxylj3^n7PF2(QCrw7|o5AJ%= z&z|n7UZAg@?t$OR{X@I_jHfZq4`_H;5Whh8@9&6)2lkhbc)=v| zFERq{YY{lEgF&p~1=kkHUy8uP?#J3M?Cbu_{pso}I&|;?wVw(OXW(mB9!PJ)D$La# z2d8USJ}OTCML79kh({a(y(_bbJ)8sZ>I^9QmR7!2(~Gxx@S=-8=2f}CcQT0#n9uc^ zWx6Dv>tPv)+uJ@x&97yuFDdhP_o%P-J@UIWmHMq-EV^BK1~$l4(V;_`Nfx597`-lR z$AwW*D5UDwv#HDL@m92=dtNWZA@*snk8O%Fi`oaH4OxuHwMMULMWM5*%?tO4Nq%Qp z+Bsb@fJ+13(v!&k5HH=^9B}(sh1MdHK#(TAk{H3x!SmdWi4<+!2;OWL>#UAYg@LQqCGAQaCkA(2Ptb<zJ4)>d&`ggBWlQMz;XIX%53EZ+V@0tHKsR{n+@^rKvVao0 zhFJrAIW2!@axrg6>Da^{WBgsR*6OeZWw5HIZ{O)3#elSTNIH#uw<|s-y6N3s!>e_V z-Ibr0-XaN`kmKpAhryUEiR(FD{O8cAcekfjD3hZ~(qGT4bfx|8RSiE!_tMjR>=#Z8 zTldn-;7ya6P;YN9y{Y0zw(3LYA1TD|v6I<2j28`N;$je5akRD%+?JBx&9-N8wig&| z_o0`L3xAe@IyVBCZl;h5rzSeP zRl2oEG0@vckrF;As)$Gp*40~&LajFHHRm+tgT)En%|&|WgW{BLC9q6)g^CJF`)k+H zXE8iu1TCZrD$H28+=cM$V__=quI9UUS6d*40rC(zcs%}yFpU>y$eb)+^nbsQ;vEL* z&A(OYQ4gYza};vIHR1TbANp)(L_E#VM_WIvQeElLhy4;=35wW!*54PF_J^~D1%@Q% zcw0fQmVJ6yt=p#utIcplWiC1STKr&$*AIqhc<(gvZj1JORG6(N&oU26h26^dFFRA6 z7!In&_J{lk3OGX%nDM+F#kDi0j@!-*O zVg`i0own>rlaH^^g8F?FN68;mVl6iR^FlgsG$p>q0pufs^w4X$j5!Ksxt-Ktd5MP6 zoU6vui|?iJ>el(1KNt>xaFiZJ%rZoKo|1*27IDfWzhP=KzIwHc{LJMqzI)m+mf>DG z4sSz_$-W!`b%lK+n)Vp!wmFhXYWl*&I+hLs1?&{(v|ZAdxZC19_7c}D6s)9hfI&v!~1{sji4(_T+<$)#N0dA!mIiS>yPl=bF9)`!_8?Xt1 zj%w-kk5l3vX&2eHrsE%{HjUQbkjo0}7=5I004rGI+{#H=t;GeGiX)&HxXh9CI#tK@ zzn2KxMt!}mpLM$Wv8t{UBlucAI~%9`ufF=KPi82v;&4wgKPaOo{*l^+*FWTy7wJGp z_)FK^@T@OF9kw+7Q6XP-piImf&o)1JL(kVG(%7Mi7{A41{J645tzT?L_)62)ovDSC|*o3SL0OE{9?(^Fh(v(ljDlgPZ zW*{eSC5nYzgpE~{@Tno^AQA2P^cM-9XkSh%j;C1fD0=;1D(yO+kt-dXZY6?VI^LtZ zH(j2fII>JK=M1OSij7~QzsL6OjX)hym_`qZcd)PIf|*e)YXZ+icY=x#ntX%ahm?N8j~V!K3zYO6ZA6)56ERY zy?U}xO-G*I9lwR24aD!X&xS@#$CeDe{&{)_{2>WR2<)Oq5z$?#8##KG+O4>R2L$YU_ zq2$J6=`D<-f^xs?9DAv@iy6uvL&+Z$-~imBFB`{rrs_LAbL`GOUemxl^bX`wI+@Us zSI%AIkf00P3~|+8bvw;T)8mKJ%E8WMdfE1JVG{4PAWBCL{F+Jn-`ev^BK_&B0alUz zv)9*!s(~*4y4vck;e;EGjZ_;tjk}sX(w^QGws5#~>K4rFB<1(sVK`Xv3 zrYpZqS6AY%-fAwtbFO=(7ZfG4bQHJ(SIU8rkuu#jWpj1edlE|Kc;K#aml?PieTN5# zpCGm9izObAUo1;f(p;MkejCGaWp?Ow3rlm;m)LyO2<;i*SK}muOZqOp?Rx(>jT9et zW-=Da{jOBn)th!bR3|KM(DUDQQ|0_e>ZuY|M7=DR;r5D_riCjLvq6cuGI0nZ0Eop@ z*cjL?rzYd1?0csMHDLj%RbyU7a`Og6Ft`#PK@eJYeRy`NBHiyOnRv~b2zd&UP6&!{a=zB$iboSIdZT6rE-tlX|(dKIOmeL zP%ouss{GJqrShkEMUCAHj6`xcizlyc(Sfjut^F3IDQa^(&$edzW-MOT*x<{sSf=xo ze`#nW1_4YMa9xi^ zw&sj>^YNX6I+WI#dtyJ+aI)diXcVJExieh*LdV;wwEUL93%tO*ub1280m7<%l>*=H zFE{m}_?BS!1mvt>m}!3O?b013WQYiazGTNL> z@_?!_^23#!@hJV6T&puAa(Z6prRIY-$&{I6{==iJC83GYYB+!LIBrcbja?H(vj?Qn zJ!|}-_oG#n>J>`zs~+Aowo_=FU**lZ!kuGra^(nA2NA4W^A1faW?W9Xd5sp2Sj`+d6{s; zfKX*y8vm8vy$|gTsEodbm5A0w`>u&8B!%xffUN~&NZG333=>+k%W{$tO$#GoR8OR7bTm^j3^I zFCk(YAm{o}Wvr@cqb#$D)xTU*CQ*tzx!%M{K7Pz$-V#N&s@5xPMjowd*%89hY*ot! z&bP~jlHyeS6!r?2o0W+1@aNBM1qL&*!@d)`J{=H$P^VLm(6TtSQQa6yiC4w#F#OVc zAEbur;#CJ#8=4WXQZk*bv$fvo+gjNuTC26HC*~A-JYMzffh#8+rD1<$0UslF-XY8l z3jetaVDD;)|$TD6^*zQ zeTwwkfWU!rE*0D|e+f54sn1@+`3-2-fegg(ip`KPEsiY7@e4dN1qQGjn}w#SoEE;ReXDv zBhqEKA$Mw!d4)WfaT%<%JaXN|d|JyTCO}KcX^I7t)`n;;(YbL~^SmLHo~%lnoPODz z+UQq4D~NnsASlqUKu3xlDy2l~!d4KL3KC9S$I0dHEoGjxY!Oe`;`M|h$!f?vvogF@ zuUKruLt6vvyAj`lguS2*H`$K!tq}nD&BHAVb|`xXLpW-EL~MTaBQOGFcB>*+xMRrN zq*tE4_nAxZ0>*ZPzU+V$lp{ByPZC&{FYH)Av8;bd;!Q0V%2{lFM_7`J8nmXEBJgeQ zd5@H#2LKyy-=VwY0w-9Yo|_gqaNx>&rzY3x%FuyaRoFN39u65{@7tt_Xx%#y+!snp zRRvSSvBiyttI-r+?Y;Wy@tT8Jz>edr?fO&yUM8|5ba$%Cn(4-jXcmrMppLQrsF}41 zN%Gyz+SVcjgB5c-_EslOFjLSBw?N(lBiRO<2*sqSl48@7cGrjaYV*JX|0x{7lsgNg zi|kNix=OEG#V+c2v$+pBZ2l}?zB3t*(^WZF1G-$bzV*GpP6t0i7LIfzLq?~q=BqTG z(hlQXF;)`Dt;z;iF3W<=%HA0YrmL*}UXkq73T2UmmCR+JR5Lx$9iy1jk!R)<6!K>~ zt@%W}kned|XeN9~KI(@Q^?5&|2GgPoi|E;}>eMp=sB61Ld*{&wU zXtyQJ0Bu|r zVX7|lQVOm%cL6{pJYu)h%&yR&Ow~s{8oD-9l_u?$Q6~)Zm>isIQ79(}x;*ZJgqiPA zxEwniJ)v>7_As99p`0vLl+dDVbe5Vk+!Lf9H^UoF?S|W$M*4PupS7;g(%Bw*Ay*Yi zs13K=&f6<^i?EFmW4l@L*Uk3g_K{XyIT)Gd8ZXTej4}#&h=0@&U+x;4cZLpTD||Tu zVaN#JzJHhtvGBCOe}a!;n@;h`w49%DP6ig>YZge85AtEqSmz8HrU(IRy%TvD9g3gi z`=Cv=lZ*D&$PL6kXpVW#lNe%-2(HKJT%MGSa0@uJDM#gI0Ybi60|i zT;dFKy=4*8HGuG1q%?B*xNfOa8dm{J8F=yF2y-TBiME^Si9=0U9` z@{Ey)K415=>#K0RDD$)kg$EaXX%mbJ?CeJ=IF!LyE^t7Zfn?i~`w{ees9S+b%LNg# z=rGb{GhuZ}t`=}!Lw6OZ%!uMcxml{PwQ9rieICh5m@5QW+`%u_?Kw9< z2i>U?uKbZm2eSd-?~I^bw~rhW+L6=@gv{*M4dvR(IE``Aoi`#iK!h8$S?3JU!Ds(L z*}qr*Z=nhQH`u9nE|y>*z`lV8^d!rjzwnUb0EAxasIsoW8#Z*&pClcBJVSqPD*I2$ zpA0zk*Rs1mo~^q-hQ=1DvPABVdmF@j|Bs?+&!qFb>3>2G6{%`78Bc-QQ0?ZK%sx&JAunfe&!^(a~ZGt{!2@>w3=3gPbH{r?ZkFQ-#@=lm&QfW!7R{f#VE*F3{3RF7T!iwy-&Z9j1uvVqXz`r+^Qd*t!EF}JT)bfZ zycshWakES3EM7v(d;T=5NHwgt0-;ctf6r`aSl=pOXVJp?tX%xjQe_TZ*=v-lqT716 zQ`PiouW&+*3Vj@2pAoQYDXsT3wTTw?ZmR*>R;&0xBVz_YTp)B$>@5_q`zm_1cOA9u zlUI3_3a?KN*jFlhnF?BgKp-@A;QI7H@Ou0i%ux7=!(aB*G_6l@V?+g8GYEJFkJq3B zcr4fbcw}6T>5jh&ZxPk7&I)u5td9?bUbL@Oh0M{T@rt%S*q*-VQy#hwOaN{f75A-I zX-<8T%E`ccnhFbrYSoaw*$SLV2fxorkiz(YU9G67z97j1)}3DOd!hO<^{N|e%~!PW zwp=>AB7^R)yCStxjmz0!1=?C*!5*ZjWLXAfpIuBB^sDZjrs4vH>mijC6-4Ls->K$r zG)fOJZ>efj7>$FFNMLxOlsMP5Qdx1#0KM0*rmHXpfo~C>Q<-cX0>!~r!?Ay(4B0Yg*rG-~OnT}m|ICUpZ93>5O#QgsIXd~ipaJ@}lI zf!-c=rmqIKwTcwI`*a?49#X50()mNqOfLnA^@)K{L#RR9{4x6JkbHF`{b@*r`UxEy za=o!aEyj&QtD|DxjfWQ4H>t3=o_1|--9mc> zJu$3ZHXxy@o0(NSS8DTLNo$4|o2qcrDp*Qe-Kx-21p_;Qf06_XThnP_VkEqHm}~eL zq#7T1I))fP98%yyj319!m}!f;rzMJP3~+P;Qt7$&FZ*WawrrK%FU)Fn4F#OR&)EI! zLM{hBaD?BME0Rf#&T}?rtDNjx40wz@Q>V=%^Ft=&Jx$M!Y&+{`tO)c&Xe|Fh{Qx3_ zO9aEc5)2nWgyBLqnuU-U{zBJSV8N%Ke%jZydg&Va!yUIFZhzl^7UE?opR6j@y@+%V z;jT=FxVmVFD{B_w$~4kv@POd%ZWzIlrmtc`TxG&r68|A_(XD_ESSTI^>W(v(h&G;3 zgUx6)Ch-RD0T30Tp%{$mN*(t&%7JN+n3Tx4d>Z0$$VCT9#dEu#H&3d0m0GN!OPY6@%U{ZZLU8?_2k%ING|F=1Fo8!#F?gMYMTJM~2>+nHaj zlErpyQ7*_nN0HGL-JaLuwGBcnE*_$}PRspyF+>bUGAcjM)B*ErI{)RO!UTk|U@gel z>%DF(0k~TGEu?_V>F>(^o3alo`+eHf*sYI8d4S(1 z7IiE8Ib<)1&_9%YSBn%VVN99YOP$B$b^JgDD_KPe{KK}@oEfO$AKG4TrOU_Eg!l50 z;fAh!@rw^loZm~&j+vo8qSCQtk&jh_C#hR#@P1-SL*Y@ZU%av-Wq|N-{XSZ7_l|J_ z5b@SRLY$@FCr! ze<|%yp9*p~4|w{F?i<%ZeMYa2>sBps6ViqEVx;(7a#*~6rn`nxyfljBJ5uNI(?bUB zVcIahNd1hS9KW*f5!dB3c0j<926^aln_wWcKlsi&??m%p@Nq~vB?T%24Bs}Pp!;#j z$nI*=4zl<{+5c9dfnkx~f7EbhX^?*Vk`7MDNBi$5Oswpv1i``<5qzaW^}5N|+(f#8 zK=2|>zc?RB`jcnZWHFabsR^*)&!@EagMjRDPW4#~2_9a8CF1d1m~DkaE~od>Es@th z*zH!(v{LzzD%HT*aUkI43y5WnOx}&h zKzdw3b)NSVtXR)`z=EEn%g5BPn;=x~>PU3$eW9x?o*sbVW14?uA+ZPF5X`92EP*r- zM>Wd%(F-OaIl8~tvb4B5iK)QG0m|wz4HE+PcZvo~s?70HLFFhlj$uaA@=3WBLK<(z zY(7)L6)RQ*cvwk4q1Dc?H_|hcDpJ@(qOqY-`GLhQ~2=NtR5Tie;R~3-d1k#!Me$R}z~?-%YB-rlx0uEvHK0?L9;rBnup45JrqR*t{*%UM!P9Fbk_I3Sio<^Wdgz z19EzX-z_1A?-fluFI>c3#aQ+&8U=5KK!S|Jc72oXI9nzY z?l@b>WQsd7L$v+;bSuM>Kv0H2z{D~cDf+)EAmf(_AQ!OOsVVBh!l({iB-iN zhazOIf6H-hn@(z4R(7(*0^}}zbc{=rt#JR1#k8Pf-UJm`uxMsrL91rM2O9^Q%Ra_g zOTx_&G?}zvTJMl6A$oIKb?(WSr^4x_g)St-(n8f8 z-UZ!)T4`U=kpbm&;DQX5$s8A*jAO+yeH_-1GHKw2#o178OH9wZAdk}O+tAhvhb3fL zcD99)EEu5MevwD^i~%Z#M$Ra)axHrPmzi|!jGiGAYv$6kGm1LT)$vkRlYU6dpj|)8 zr;3>wc@iB&Z(>`S5)kGpyNt%qEDg=oBTpGcW){mR3nLYG&P$ax(b$zpuguH}MVaJoFi5Y zIz~>X$~KXE0uZf-v%20>-njNRcZj9GF34yNFer?kS(HP&_q3+nX9rVQfndwf1jiNA z{6+s;wmmtnVU&7a(zTW5qmc90<~$&+txt$(Zav)nZ&``u>tFk22CHpk58?1?x3aLf zm=#z=gD%ZYFuq%^>dBrpB@ZlxEKH#wF&$a@NQf_2wCDPa2|3@%)C|n&*Tv z;yAt$XPjwi%w8`6b`j%mZAJmesF3#jEgOo8i$nfbMd!^ewluLCA*MydvEK|o<^KHi z5n0VHqo2>M9ghIQb~06s9EB*Cs)s96SYWkKh&&a5{VZuIOxHMiur z#SBJ#y+6ZXICbx(J?)v7Z)sX-o=)q!!}GFC*a4IWjdEFayil#bwp=YZT+QRpfo997hA12YvreR^2K&0E1!LU9ZNIPzIi1lr@FEv2;c~s=^~=s@z70 zt17zcvU7`2%C^A}i48j2<}A5TCTdl5T>}gT8^P=h|sHn%4Ih{`1@C`jh(L8jgtFH_f zoT3fwy|M&p>YuJ04#^Z=Rib*(fUC+2dNz#_+-NYEU>{6yv@8*%7hp=)S9qbFhiZRQg%MVjU;vcC>Y|X>9dYILVVS0vH_Cwor+dgAkFf&8Um+v!QLW z+ZNS>MX=yv5OUwBOs#${2zow*KEEcvYm;_E-F8D-ZU@xEsBU>-({{t%cEddF`uOOL zpjFHBk<>hMP5XMOLFdji;y%mjCo&ra5rSJ709KbgWm>WL&1w+121<2wpG)hm?Hm4$*NuEWHP)h624~WVYct|y)16A{bM+4Eudg2* z;!WgKEC=wua!NWczqtHm)1K?LcQ_SZj~Bn7{#zo0Z>Uw{XyFZCVi`ZJ_ek3P$sVJ+h4nV2wJJ_ZcS8YqvZ^}?@Y3WV9@%!ja zm4nWe#URWVVP@x=P>X;qIV0QjW!h&^Cjp(wggzA?TBBWQHKpAKf-CxA0JwBTRm$ZM zJX&8Y;Z};&*>qsVb1IM4-h76Nqufhmn}IJ zp(Tx9*fvZ)VA%I?a6UTi27@S^+f5JLR1X~1G)H0s)Yyjb!Y)K-uTIOE;*LyTco%`= zXw2#?y80u#DpqUpHVYt;l*A|96-gZkIQmIDg zNU|!Yrw-@S+MPlA@V4G4M@y|bkA#a_6fEx}#lg&0g@H)N_y>AE{JvgSrB zK&ZbS2#K)geX#Jvm+&RDl}uIfT!yZLnU1o`x=CR+6tSDFNfvKH9&Mft$-v z1qd(gYc%amGBaFmNlRIXGhi<5h&F>5?MO4)5lvvZkMn#>=h!k9?Ra*PET38Fg z_8U8htR3n+;uZ~zjiGp^znYS^6sE=sxoi#f+EN(tm#x(_kIQtF6Ov$vedMqr;vICI!QETmAM&q=dIz=7?@bi**eXhFYXWp1P?ie2lsSlv<^rR?4>ax zcN7VSZ4>leHKCVFG}VNzb{XOb#z5piYaU0oxL4 z3=h0G=K}=1L|IoocVNm$uddCeTegi=ed(QTrNKHCeEylkC$Ml^K*zVWruVkB8`58w z$>3$;ZH&K`<83ptwC0`;YA!u>Pfd>)cOoGPzD9S_7oX1DQDH6>Y#(5q%_pG4aTtU8 z(&6m|g?%wFH6vw$`CNK@dtbV0dxx~91gUaIU;4bIinN^tbYOciUAUu#R%tu;MZ#Rnc zyf&AhUNW_JYQacObg%n2I4M)yt!RLXIgfirCBmHP^g zZvmhYn_CV%`dbELXNGOlIdq1Rqt6_6S*iAYJQgRS@LpYaDSdW-Zq=nqlg}3NJ7tAh z7N+mDY}9euQ7b21c2egDGAHiT2)P%oUQP6z8Q|z=tii3jfmaPskb*K1+adJ_3WjWE(u&DJ7o`|N`Ec$0EHh6;~*LU(tr!c6ZyNX`q4kq`RHqlz_Ji>_@GW9KWRxA1XV4kLBXR zX;;kkVZ6I7o2g}+{G%91f;RuK`Isr5=SVKNdDJ9Q915T$#B-ow%rxiW!Vs$t0(*>B zKir`*#_xE~C@`ER zKH84DKU$K5`J~>vC_t8>VZq#Bn)_&O+Frjo?WH>&?K$>wEA*~-DLQ60#GY`AL_cDB zkNY#vw`3!=Og>P;YW64g<568SI9-yl%>VEsA*$OwRSl#~yN6Xi;cxyMNnE4NkK0d} z=9I9fJ!A4`g#KY& zoY(KiQ)GWR+T6RpUayg(tUDdv-(Bse@+Z6Eck+{iJ3h^+y_=9fr7iJiI(gsV9%KO< zJB8SO`u&sb(D1V-JB-|K(%mN+fwq_!9M?e-Yj}0B3G$!D;Nd)D?EQPEJ+(R8defpK zUuROrD+8@N6>U47jgK$+EW{i|FP|u^#$Wfk?D!WPvEIeb%j*-M|J}G8XG}cS=MKHn zp@H`xRT6V@-81y%E1L1@YW4Nr zf4`cgGQZR7Dl4QO_#xT=6~C36reG7YsG|!lDQx8yhB(&X%-qV z(C4pbd* zj@JDC&D^XkV=QBunP84^RulUi% zHI>f3AU-DD`c?}4>ccE*{dT@8q>{I>?)_G%sKIp$NbIWyC{>@I*YpAei&Yjacsoyh zMJwMPfIYDn-(D)aQ0TGVIlEUcM)F37%N1-DIU}ztgo?$eiopq+Q3(tPzIsTz`MeMWe!nq=KYET@O)0H8kwu%|vayke zPj*NAo1=&6GnnttqCh&fBoHnH&swpSly`7SDes-=NWvcjd?a~Sr|8C)j5wX>&Vzkh z0g$@v&!n2ar_#3v+gnwNp8YVNdi||nL?@sHBVAOG7nVYA2$2sBmp+w~-NdH0nVJrvAHfBCsL!0w*>hgsz%)H}gT-DQI^$)Usqc(8Eu= zhn9?g;$TS<*3)H3a=kii5&rw{Z4!F&H{m>S-9;sXbEwnbQ-e4viqb~fbuiza#pz$D z-tI}~|D&JkNt^!BGY^$KO~vQ$_@dtv|Ep>Bv0BReAWcqK1E3dm`5+5NK!$%%<`Hv< zd1NuuLm#xqv6urN6enokfEYT`w;wD?@$ZV!RUejSV61~)r+ETE6+QN0r%|V|OJfpZ zXE6;z>Sj>8+Jo?aGN_rI!EEddHo=Wf@F+K=U5p%x+~IBtwr1Vauo65*dWSnm#XE#S zgbD6Acf^yawmgo}kdJHspAK9!;FDVDYwjm~Qazak+coX`WKpD#8&|mFh+&6Yif;pS zoj<;DVbq-ms*UhIrLVULd?H3(?>F*#4evMdv}**^gswq2d(vfgHXZ&~It~73B^~{& z8$M&}{CPL51NJ*wLWe)kpz1?5%{f#<)9`%b^BVfY=QjQEP9Nk7SRJ7ncoh7j7;+2sBX#{OU%l*U7zAf(fN$lS zle1LtrI%g`NKO|$`wl?KshS)%ULBRZ)I!)CIHO;?6(ZRJ%RXjhr2vIg`0rBwQjZ%* z8J@h5kH=`=H!$Gm^2;xmbY%vAP-f>N$U#s->MZ>jh6fUH`Kne^^K2kO!6T$+(T1)V zBYxIc3{3yO#O6oFLO&g{vp9gBgf~AnR`IE^(ewXl=<407&`bL~vNT`)<5IKuM}xks zR%JBr%P@X#`LdwBXR86+Ern}9Br(IrO9TDx%UUdpob^=|m3-Afjlo~z@qYJLIrw}3 zR~0p5v|1XqS|q7T6@86`hM}m(c`(-{<0#?lU$yh$uT&ec$s=DfEuOjPvYEIaC-6K{ znNC#qP3JTGX~lTO-Z~Mnqg3b}^)Q9KOP$uzu3-;R3hjM!Un@k)g=Bckc zLoC-^i#1}wliAiEMB|%vZqhbxgIp&omFM_ldZ&e za%s)Cb}Jy^sb@-_=$hftw~6%Zw^03naBN)q zBag}YElodC@ql|x_GKo8>uLOV=?Rl#i3xu)boldhPE1hRNYnq($C|9@nkl99{dYyJ zP{u1!nY8Phkls7#ceIotB}=KJ>4!?(s(y6fb9qSy+5Rrs*0l9#L9{_N9XXnf6N1TI zizRQ0Ue5DBypZR{@B5~@(;PF^q66P|XjT?HR$JQyPP49ULKZkr9EW#c{sgYIg>{nd zLBXzt`M=9p9u1Z9-Qy(rlA=wljnzsw@Dw`UPrzf(Rz`CZWpiR3zC{_b#)$s+RIqL%vJxh8Z zHd#SgRe%R5ObKqr9RfO$&}ijUCZ<0ga2+#fw!#3f)nohN!7`EL5GXu;RmzcRZ;ILp*H)V{g;eU72 z@qJe9oSkv1JY*^w@!4jW(%xz9jE+-Pm|9}yNDF=&biU!&N`7@l#H%vaMk8wj^Xe5% zZ3a+T`RECsZv#hzba2L$LYt2BWW1W9dOMk|RsTp!?RgffHK+RnRIsNq9$XNP-9)J_5~QfM>tOhRni%{K#m*yz%ktU zHmJ-X-U_3agH?vM?xju6#UV9A6*&h&sx2O$hg5DA&kMYgg76xedm&2Goi4V@ioZw& zuLw9}JE*GSWZ9FOqwI@yuP#wKkH8ik8|ECjyzKDPaTS_%*2O8)59bYAwXFctCjRk* zQA3YBOJ~=NDtL}ln4t3QIqWt7D{}@WsH}l#8{49lJl@yF1?DG~Q5SMv1&qy|+<^jr zoPE5xg)Y+;dfalBB&r^*dC}k(mN{S1y@L!*QMx+q@efMB)q@h>tyeLWmEgJ$AN_*{ zPj}W0*$=w~A7>jOOBQ4JlRW30WR-TF=mm1+!*GycQ?auK`5*>&ZRH94RG-jeDMO+T zQ-hW`mYa#7dT?CSOM{6mXan-3XpHv}xd3C3bc?ezlXA{;ew?g|)qH1XvKpc0BNP?k zyln!#fv?fmZjW<1ryv-1cc!PPu5Dt25{Ol(jbW!gU1jueuXjAdn^)nJQRZawwr+r0V>u)Y?wJySo(4Ck$5{KO`Se2NRB&(sWFrvpH&MgoE#2R3@O+4%qkMN1Xtt1=Mp z+;T%NLlGT-jQOr>v4McZB<1$jTm-{YV=u-i!q~@c{i6E!_TwfP^5_VEe-;-QErDu@ zS0OH$;lm|zHItKgDb84UQJOY=c+{^tZmJM}w)6F%hDpHRBME5=w{?osRa%PAHx@hn z(^WgQ$eEt5hNf`8(L_htr4H^^%5`2!R~0Q(gz*`xSVat;BQRWnk05f;wpy;1`I(15 zL(DX0e~+r58ESS;z6*-Om$NBD+1cz_9t_>&lutEf!1 zL0#c&%tR{H;5?V9DjQfdl3ld0p|Hw7Ut6U?{p)XB2&VON`mIinEY*9$YBL%^r}7aS z4gtD4hFh*x_}5!-o3d}`g7*5-uiy*la_}gBnV8Ifu>|Z0-_SJ{H?cCt7i}^Kn%yMD z5MYNdn!=#6&b<*qH^ip~CT8}9>vF&oK-<1}Qe{B%dI;o2Viz#>oXWi&V0jrQGP zxK1k}6}-vG6PBL7s1YL#mx8vasRamxnp9_cHFoBvo*7DYuWQr};5bD&h;#bh1<1+p zYc70Pi<@L)_pIp_rfP%9Gkt}CXVZ}p#aD5g*hJII9{~c{;dr~VFGr=;F-kEUpN=;e zqZr^>jb1L2tK}?1PrNC|gl6ATP)Ld0g(@d@F}7 zZEVRqxX|MrbMn+6jA1hPZqkplOomFWud=V5_pXGK8zz zZHC#XYS%kcvz0w+8!Q8XbB*s_<#l>->Ia|FLg&!&txg1co~q2*jK@rq9I*K0fF{4g z1m#m~tuiK!9-9l7V`V@EVB_HE1morcH+0~Yn{uhswm@ZtqHlEts(o+wjZpx-xoS?M zU#Cenrv+r|ojVIuab7f3c=1T}s|AvHh!LMMRWahg1N6^ z`%kdeAUD3@Q=3?n;SP*N-#m&tQjP6%uP_jB6C_KphRsmEb32wtUC}Ieo(-#lbMuV7 z&j6&{xu(72W-fL;_GCA&g71@6HNTWqbAJzVY-A@nGB9m2=_AiThqL$+CCl8TY=9MV zkJ(i0?Xe!4p0+HD?OKy8il|(-t7&2uItumkM4|tt-w+5N-1qmo$vvfI60{MjM4}j} z%!diCL|G2@CTDAr${gno8@dd}0hRHDF_A?d4KVz|qn(g7N^K4i!y9%U%~tWVgb%nE z7A@R}$X1c3?^PB$n#K;ZH>@qnNYUqlTn1(D5Tn8nYdjF~rop+bL}j=406_FU|8lFG z-?UY|)K2F_TUDNRuM8hiE!`(4e3}%>wrR)vJ&-Wt2bBF_EXo^ji`x03?fqt)!Xd;c+&1U@5|x|gZ;MQ*e}O8IkQjyB!rK^li**x`e~VeX*Ft;< zcLjJ*`}tuWtDDksG0JG-V|J%g-%e#jSdO^%lVn$|337?n`Ww_}Sm4ZUVekkH(1ZlA zjf(-ms=F0jjAQALARj-%gln}M;7t)yq&03d0kg8x_AuXCXzKmB19t}%k3d`8?;?rN zj2VS%a6FJF^&`E~Rt<9d1kT^VqB#+gTaWppUX5QqPeDt!IwE(6tid&(h!dMm@VJ3S zu3>8{K}(aE?vm@Zdb-okEel$MpJgM=c<*=cG#qe7|6+KLzwn1CMdV&JgVcW z{JmS>>#J8{@Xfs&`gds+?qR(`8we<0&v2z=K0oQ^C26ZaIk>o4eja#(+A@{@mln z#f{%QF7XeN_B?P18MJ4Ylly17>lwOf&;F#%xfSN4Tb)nKkq@|aPELhtpMjf6`m@im zxAfN%aa6g=oUD%|J=$!==TQ-ZIHP;P9~jt;Qt%|>w|uXSG6TsrBp*q;@6={}Mj_}* z^D{kG5_JMGj}FmS*DeqVu#)C>NSqI3b|`0Ou__ta3_L32{TTbB%0@uMz1mH)c8uS0 zJNu2we$u(SQssqyE&a5ApHiA_INAyVQ0{~=Z(@K^|48MH6ZfxFg;1n#ps_a)(unol79XvE; z;lSxwIN$8)lL2kArY1R=y2bfx zwJPpqE{!+6dQA(@_kVZcGRW$A-$m?ybh^~2j*-_-(eFPi`%fxZfqu8p?blD&Z3c)* z9#(x% -- 2.43.2