From 50c0333ea6ae96ecbed574c2e2704e1005037d05 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Wed, 9 Jul 2008 23:31:00 +0000 Subject: [PATCH] Revert Potlatch 0.10 from the trunk - we will keep it on the potlatch_010 branch for now until it has been reviewed. --- app/controllers/amf_controller.rb | 1207 ++++++++++++++++---------- app/models/node.rb | 4 - app/models/old_way.rb | 29 - app/models/old_way_node.rb | 3 - app/models/way.rb | 18 +- app/views/site/edit.rhtml | 6 +- config/environment.rb | 4 +- config/potlatch/localised.yaml | 621 ------------- config/potlatch/relation_colours.txt | 3 +- lib/potlatch.rb | 7 +- public/potlatch/potlatch.swf | Bin 148900 -> 140596 bytes 11 files changed, 757 insertions(+), 1145 deletions(-) delete mode 100644 config/potlatch/localised.yaml diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 4ec4e660e..11ddc3f7c 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -1,33 +1,20 @@ -# amf_controller is a semi-standalone API for Flash clients, particularly -# Potlatch. All interaction between Potlatch (as a .SWF application) and the +# AMF Controller is a semi-standalone API for Flash clients, particularly 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). # -# Helper functions are in /lib/potlatch. +# See Also Potlatch::Potlatch and Potlatch::AMF # -# Author:: editions Systeme D / Richard Fairhurst 2004-2008 -# Licence:: public domain. +# Public domain. +# editions Systeme D / Richard Fairhurst 2004-2008 # -# == General structure -# -# Apart from the talk method (which distributes the requests from the -# AMF message), each method generally takes arguments in the order they were -# sent by the Potlatch SWF. Do not assume typing has been preserved. Methods -# all return an array to the SWF. -# -# == Debugging -# -# Any method that returns a status code (0 for ok) can also send: -# return(-1,"message") <-- just puts up a dialogue -# return(-2,"message") <-- also asks the user to e-mail me -# -# To write to the Rails log, use RAILS_DEFAULT_LOGGER.info("message"). -# -# == To do +# All in/out parameters are floats unless explicitly stated. # -# - Check authentication -# - Check the right things are being written to the database! - +# to trap errors (getway_old,putway,putpoi,deleteway only): +# return(-1,"message") <-- just puts up a dialogue +# return(-2,"message") <-- also asks the user to e-mail me +# to log: +# RAILS_DEFAULT_LOGGER.error("Args: #{args[0]}, #{args[1]}, #{args[2]}, #{args[3]}") class AmfController < ApplicationController require 'stringio' @@ -36,214 +23,312 @@ class AmfController < ApplicationController session :off before_filter :check_write_availability - # Main AMF handler: processes the raw AMF string (using AMF library) and - # calls each action (private method) accordingly. - + # Main AMF handler. Tha talk method takes in AMF, figures out what to do and dispatched to the appropriate private method def talk - req=StringIO.new(request.raw_post+0.chr) # Get POST data as request - # (cf http://www.ruby-forum.com/topic/122163) - req.read(2) # Skip version indicator and client ID - results={} # Results of each body - renumberednodes={} # Shared across repeated putways - renumberedways={} # Shared across repeated putways - - # Parse request - - headers=AMF.getint(req) # Read number of headers - - headers.times do # Read each header - name=AMF.getstring(req) # | - req.getc # | skip boolean - value=AMF.getvalue(req) # | - header["name"]=value # | - end - - bodies=AMF.getint(req) # Read number of bodies - bodies.times do # Read each body - message=AMF.getstring(req) # | get message name - index=AMF.getstring(req) # | get index in response sequence - bytes=AMF.getlong(req) # | get total size in bytes - args=AMF.getvalue(req) # | get response (probably an array) - - case message - when 'getpresets'; results[index]=AMF.putdata(index,getpresets()) - when 'whichways'; results[index]=AMF.putdata(index,whichways(*args)) - when 'whichways_deleted'; results[index]=AMF.putdata(index,whichways_deleted(*args)) - when 'getway'; results[index]=AMF.putdata(index,getway(args[0].to_i)) - when 'getrelation'; results[index]=AMF.putdata(index,getrelation(args[0].to_i)) - when 'getway_old'; results[index]=AMF.putdata(index,getway_old(args[0].to_i,args[1].to_i)) - when 'getway_history'; results[index]=AMF.putdata(index,getway_history(args[0].to_i)) - when 'putway'; r=putway(renumberednodes,*args) - renumberednodes=r[3] - if r[1] != r[2] - renumberedways[r[1]] = r[2] - end - results[index]=AMF.putdata(index,r) - when 'putrelation'; results[index]=AMF.putdata(index,putrelation(renumberednodes, renumberedways, *args)) - when 'deleteway'; results[index]=AMF.putdata(index,deleteway(args[0],args[1].to_i)) - when 'putpoi'; results[index]=AMF.putdata(index,putpoi(*args)) - when 'getpoi'; results[index]=AMF.putdata(index,getpoi(args[0].to_i)) - end - end - - # Write out response - - a,b=results.length.divmod(256) - render :content_type => "application/x-amf", :text => proc { |response, output| - output.write 0.chr+0.chr+0.chr+0.chr+a.chr+b.chr - results.each do |k,v| - output.write(v) - end - } + req=StringIO.new(request.raw_post+0.chr) # Get POST data as request + # (cf http://www.ruby-forum.com/topic/122163) + req.read(2) # Skip version indicator and client ID + results={} # Results of each body + renumberednodes={} # Shared across repeated putways + renumberedways={} # Shared across repeated putways + + # ------------- + # Parse request + + headers=AMF.getint(req) # Read number of headers + + headers.times do # Read each header + name=AMF.getstring(req) # | + req.getc # | skip boolean + value=AMF.getvalue(req) # | + header["name"]=value # | + end + + bodies=AMF.getint(req) # Read number of bodies + bodies.times do # Read each body + message=AMF.getstring(req) # | get message name + index=AMF.getstring(req) # | get index in response sequence + bytes=AMF.getlong(req) # | get total size in bytes + args=AMF.getvalue(req) # | get response (probably an array) + + case message + when 'getpresets'; results[index]=AMF.putdata(index,getpresets) + when 'whichways'; results[index]=AMF.putdata(index,whichways(args)) + when 'whichways_deleted'; results[index]=AMF.putdata(index,whichways_deleted(args)) + when 'getway'; results[index]=AMF.putdata(index,getway(args)) + when 'getrelation'; results[index]=AMF.putdata(index,getrelation(args)) + when 'getway_old'; results[index]=AMF.putdata(index,getway_old(args)) + when 'getway_history'; results[index]=AMF.putdata(index,getway_history(args)) + when 'putway'; r=putway(args,renumberednodes) + renumberednodes=r[3] + if r[1] != r[2] + renumberedways[r[1]] = r[2] + end + results[index]=AMF.putdata(index,r) + when 'putrelation'; results[index]=AMF.putdata(index,putrelation(args, renumberednodes, renumberedways)) + when 'deleteway'; results[index]=AMF.putdata(index,deleteway(args)) + when 'putpoi'; results[index]=AMF.putdata(index,putpoi(args)) + when 'getpoi'; results[index]=AMF.putdata(index,getpoi(args)) + end + end + + # ------------------ + # Write out response + + RAILS_DEFAULT_LOGGER.info(" Response: start") + a,b=results.length.divmod(256) + render :content_type => "application/x-amf", :text => proc { |response, output| + output.write 0.chr+0.chr+0.chr+0.chr+a.chr+b.chr + results.each do |k,v| + output.write(v) + end + } + RAILS_DEFAULT_LOGGER.info(" Response: end") end private - # Return presets (default tags, localisation etc.): - # uses POTLATCH_PRESETS global, set up in OSM::Potlatch. - - def getpresets() #:doc: - return POTLATCH_PRESETS + # Return presets (default tags and crap) to potlatch. + # Uses POTLATCH_PRESETS global, set up in OSM::Potlatch + def getpresets #:doc: + return POTLATCH_PRESETS end - # Find all the ways, POI nodes (i.e. not part of ways), and relations - # in a given bounding box. Nodes are returned in full; ways and relations - # are IDs only. - - def whichways(xmin,ymin,xmax,ymax) #:doc: - xmin-=0.01; ymin-=0.01 - xmax+=0.01; ymax+=0.01 - - if POTLATCH_USE_SQL then - way_ids=sql_find_way_ids_in_area(xmin,ymin,xmax,ymax) - points=sql_find_pois_in_area(xmin,ymin,xmax,ymax) - relation_ids=sql_find_relations_in_area_and_ways(xmin,ymin,xmax,ymax,way_ids) - else - # find the way ids in an area - nodes_in_area = Node.find_by_area(ymin, xmin, ymax, xmax, :conditions => "current_nodes.visible = 1", :include => :ways) - way_ids = nodes_in_area.collect { |node| node.way_ids }.flatten.uniq - - # find the node ids in an area that aren't part of ways - nodes_not_used_in_area = nodes_in_area.select { |node| node.ways.empty? } - points = nodes_not_used_in_area.collect { |n| [n.id, n.lon, n.lat, n.tags_as_hash] } - - # find the relations used by those nodes and ways - relations = nodes_in_area.collect { |node| node.containing_relations.visible }.flatten + - way_ids.collect { |id| Way.find(id).containing_relations.visible }.flatten - relation_ids = relations.collect { |relation| relation.id }.uniq - end - - [way_ids,points,relation_ids] + # ----- whichways + # Find all the way ids and nodes (including tags and projected lat/lng) which aren't part of those ways in an are + # + # The argument is an array containing the following, in order: + # 0. minimum longitude + # 1. minimum latitude + # 2. maximum longitude + # 3. maximum latitude + # 4. baselong, 5. basey, 6. masterscale as above + def whichways(args) #:doc: + xmin = args[0].to_f-0.01 + ymin = args[1].to_f-0.01 + xmax = args[2].to_f+0.01 + ymax = args[3].to_f+0.01 + baselong = args[4] + basey = args[5] + masterscale = args[6] + + RAILS_DEFAULT_LOGGER.info(" Message: whichways, bbox=#{xmin},#{ymin},#{xmax},#{ymax}") + + # find the way ids in an area + nodes_in_area = Node.find_by_area(ymin, xmin, ymax, xmax, :conditions => "current_nodes.visible = 1", :include => :ways) + way_ids = nodes_in_area.collect { |node| node.way_ids }.flatten.uniq + + # find the node ids in an area that aren't part of ways + nodes_not_used_in_area = nodes_in_area.select { |node| node.ways.empty? } + points = nodes_not_used_in_area.collect { |n| [n.id, n.lon_potlatch(baselong,masterscale), n.lat_potlatch(basey,masterscale), n.tags_as_hash] } + + # find the relations used by those nodes and ways + relations = nodes_in_area.collect { |node| node.containing_relations.visible }.flatten + + way_ids.collect { |id| Way.find(id).containing_relations.visible }.flatten + relation_ids = relations.collect { |relation| relation.id }.uniq + + [way_ids,points,relation_ids] end - # Find deleted ways in current bounding box (similar to whichways, but ways - # with a deleted node only - not POIs or relations). + # ----- whichways_deleted + # return array of deleted ways in current bounding box + # in: as whichways + # does: finds all deleted ways with a deleted node in bounding box + # out: [0] array of way ids + def whichways_deleted(args) #:doc: + xmin = args[0].to_f-0.01 + ymin = args[1].to_f-0.01 + xmax = args[2].to_f+0.01 + ymax = args[3].to_f+0.01 + baselong = args[4] + basey = args[5] + masterscale = args[6] + + 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 - def whichways_deleted(xmin,ymin,xmax,ymax) #:doc: - xmin-=0.01; ymin-=0.01 - xmax+=0.01; ymax+=0.01 + # ----- getway + # Get a way with all of it's nodes and tags + # The input is an array with the following components, in order: + # 0. wayid - the ID of the way to get + # 1. baselong - origin of SWF map (longitude) + # 2. basey - origin of SWF map (latitude) + # 3. masterscale - SWF map scale + # + # The output is an array which contains all the nodes (with projected + # latitude and longitude) and tags for a way (and all the nodes tags). + # It also has the way's unprojected (WGS84) bbox. + # + # FIXME: The server really shouldn't be figuring out a ways bounding box and doing projection for potlatch + # FIXME: the argument splitting should be done in the 'talk' method, not here + def getway(args) #:doc: + wayid,baselong,basey,masterscale = args + wayid = wayid.to_i + + RAILS_DEFAULT_LOGGER.info(" Message: getway, id=#{wayid}") + + # Ideally we would do ":include => :nodes" here but if we do that + # then rails only seems to return the first copy of a node when a + # way includes a node more than once + way = Way.find(wayid) + + long_array = [] + lat_array = [] + points = [] + + way.nodes.each do |node| + projected_longitude = node.lon_potlatch(baselong,masterscale) # do projection for potlatch + projected_latitude = node.lat_potlatch(basey,masterscale) + id = node.id + tags_hash = node.tags_as_hash + + points << [projected_longitude, projected_latitude, id, nil, tags_hash] + long_array << projected_longitude + lat_array << projected_latitude + end + + [wayid,points,way.tags,long_array.min,long_array.max,lat_array.min,lat_array.max] + end - nodes_in_area = Node.find_by_area(ymin, xmin, ymax,xmax, :conditions => "current_nodes.visible=0 AND current_ways.visible=0", :include => :ways_via_history ) - way_ids = nodes_in_area.collect { |node| node.ways_via_history_ids }.flatten.uniq - [way_ids] + # ----- getway_old + # returns old version of way + # in: [0] way id, + # [1] way version to get (or -1 for "last deleted version") + # [2] baselong, [3] basey, [4] masterscale + # does: gets old version of way and all constituent nodes + # for undelete, always uses the most recent version of each node + # (even if it's moved) + # for revert, uses the historic version of each node, but if that node is + # still visible and has been changed since, generates a new node id + # out: [0] 0 (code for success), [1] SWF object name, + # [2] array of points (as getway _except_ [3] is node.visible?, 0 or 1), + # [4] xmin, [5] xmax, [6] ymin, [7] ymax (unprojected bbox), + # [8] way version + def getway_old(args) #:doc: + RAILS_DEFAULT_LOGGER.info(" Message: getway_old (server is #{SERVER_URL})") + # if SERVER_URL=="www.openstreetmap.org" then return -1,"Revert is not currently enabled on the OpenStreetMap server." end + + wayid,version,baselong,basey,masterscale=args + wayid = wayid.to_i + version = version.to_i + xmin = ymin = 999999 + xmax = ymax = -999999 + points=[] + if version<0 + historic=false + version=getlastversion(wayid,version) + else + historic=true + end + 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 + } + + # get tags from this version + attributes={} + 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 + + [0,wayid,points,attributes,xmin,xmax,ymin,ymax,version] end - # Get a way including nodes and tags. - # Returns 0 (success), a Potlatch-style array of points, and a hash of tags. - - def getway(wayid) #:doc: - if POTLATCH_USE_SQL then - points=sql_get_nodes_in_way(wayid) - tags=sql_get_tags_in_way(wayid) - else - # Ideally we would do ":include => :nodes" here but if we do that - # then rails only seems to return the first copy of a node when a - # way includes a node more than once - points = [] - way = Way.find(wayid) - way.nodes.each do |node| - points << [node.lon, node.lat, node.id, nil, node.tags_as_hash] - end - tags=way.tags - end - [wayid,points,tags] + # ----- getway_history + # find history of a way + # in: [0] way id + # does: finds history of a way + # out: [0] array of previous versions (where each is + # [0] version, [1] db timestamp (string), + # [2] visible 0 or 1, + # [3] username or 'anonymous' (string)) + def getway_history(args) #:doc: + wayid=args[0] + history=[] + sql=<<-EOF + SELECT version,timestamp,visible,display_name,data_public + FROM ways,users + WHERE ways.id=#{wayid} + AND ways.user_id=users.id + AND ways.visible=1 + ORDER BY version DESC + EOF + histlist=ActiveRecord::Base.connection.select_all(sql) + histlist.each { |row| + if row['data_public'].to_i==1 then user=row['display_name'] else user='anonymous' end + history<<[row['version'],row['timestamp'],row['visible'],user] + } + [history] end - # Get an old version of a way, and all constituent nodes. + # ----- getrelation + # Get a relation with all of it's tags, and member IDs + # The input is an array with the following components, in order: + # 0. relid - the ID of the relation to get # - # For undelete (version=0), always uses the most recent version of each node, - # even if it's moved. For revert (version=1+), uses the node in existence - # at the time, generating a new id if it's still visible and has been moved/ - # retagged. - - def getway_old(id,version) #:doc: - if version<0 - old_way = OldWay.find(:first, :conditions => ['visible=1 AND id=?', id], :order => 'version DESC') - points = old_way.get_nodes_undelete - else - old_way = OldWay.find(:first, :conditions => ['id=? AND version=?', id, version]) - points = old_way.get_nodes_revert - end - old_way.tags['history']="Retrieved from v#{old_way.version}" - [0,id,points,old_way.tags,old_way.version] - end - - # Find history of a way. Returns an array of previous versions. - - def getway_history(wayid) #:doc: - history=[] - way=Way.find(wayid) - way.old_ways.each do |old_way| - if old_way.user.data_public then user=old_way.user.display_name else user='anonymous' end - history<<[old_way.version,old_way.timestamp.strftime("%d %b %Y, %H:%M"),old_way.visible ? 1 : 0,user] - end - [history] - end + # The output is an array which contains: + # [0] relation id, [1] hash of tags, [2] list of members + def getrelation(args) #:doc: + relid = args[0] + relid = relid.to_i - # Get a relation with all tags and members. - # Returns: - # 0. relation id, - # 1. hash of tags, - # 2. list of members. - - def getrelation(relid) #:doc: - rel = Relation.find(relid) - [relid,rel.tags,rel.members] - end + RAILS_DEFAULT_LOGGER.info(" Message: getrel, id=#{relid}") - # Save a relation. - # Returns - # 0. 0 (success), - # 1. original relation id (unchanged), - # 2. new relation id. + rel = Relation.find(relid) - def putrelation(renumberednodes, renumberedways, usertoken,relid,tags,members,visible) #:doc: - uid=getuserid(usertoken) - if !uid then return -1,"You are not logged in, so the point could not be saved." end + [relid,rel.tags,rel.members]#nodes,ways] + end - relid = relid.to_i + # ----- getrelation + # save relation to the database + # in: [0] user token (string), + # [1] original relation id (may be negative), + # [2] hash of tags, [3] list of members, + # [4] visible + # out: [0] 0 (success), [1] original relation id (unchanged), + # [2] new relation id + def putrelation(args, renumberednodes, renumberedways) #:doc: + usertoken,relid,tags,members,visible=args + uid=getuserid(usertoken) + if !uid then return -1,"You are not logged in, so the point could not be saved." end + + relid = relid.to_i visible = visible.to_i # create a new relation, or find the existing one - if relid <= 0 - rel = Relation.new - else - rel = Relation.find(relid) - end - - # check the members are all positive, and correctly type - typedmembers = [] - members.each do |m| - mid = m[1].to_i - if mid < 0 - mid = renumberednodes[mid] if m[0] == 'node' - mid = renumberedways[mid] if m[0] == 'way' - if mid < 0 - return -2, "Negative ID unresolved" - end - end - typedmembers << [m[0], mid, m[2]] - end + if relid <= 0 + rel = Relation.new + else + rel = Relation.find(relid) + end + + # check the members are all positive, and correctly type + typedmembers = [] + members.each do |m| + mid = m[1].to_i + if mid < 0 + mid = renumberednodes[mid] if m[0] == 'node' + mid = renumberedways[mid] if m[0] == 'way' + if mid < 0 + return -2, "Negative ID unresolved" + end + end + typedmembers << [m[0], mid, m[2]] + end # assign new contents rel.members = typedmembers @@ -251,297 +336,491 @@ class AmfController < ApplicationController rel.visible = visible rel.user_id = uid - # check it then save it - # BUG: the following is commented out because it always fails on my - # install. I think it's a Rails bug. + # check it then save it + # BUG: the following is commented out because it always fails on my + # install. I think it's a Rails bug. - #if !rel.preconditions_ok? - # return -2, "Relation preconditions failed" - #else - rel.save_with_history! - #end + #if !rel.preconditions_ok? + # return -2, "Relation preconditions failed" + #else + rel.save_with_history! + #end - [0,relid,rel.id] + [0,relid,rel.id] end - # Save a way to the database, including all nodes. Any nodes in the previous - # version and no longer used are deleted. - # - # Returns: - # 0. '0' (code for success), - # 1. original way id (unchanged), - # 2. new way id, - # 3. hash of renumbered nodes (old id=>new id) - - def putway(renumberednodes,usertoken,originalway,points,attributes) #:doc: - - # -- Initialise and carry out checks - - uid=getuserid(usertoken) - if !uid then return -1,"You are not logged in, so the way could not be saved." end - originalway=originalway.to_i - - points.each do |a| - if a[2]==0 or a[2].nil? then return -2,"Server error - node with id 0 found in way #{originalway}." end - if a[1]==90 then return -2,"Server error - node with lat -90 found in way #{originalway}." end - end - - if points.length<2 then return -2,"Server error - way is only #{points.length} points long." end - - # -- Get unique nodes - - if originalway<0 - way=Way.new - uniques=[] - else - way=Way.find(originalway) - uniques=way.unique_nodes - end - - # -- Compare nodes and save changes to any that have changed - - nodes=[] - - points.each do |n| - lon=n[0].to_f - lat=n[1].to_f - id =n[2].to_i - savenode=false - if renumberednodes[id] - id=renumberednodes[id] - elsif id<0 - # Create new node - node=Node.new - savenode=true - else - node=Node.find(id) - if (!fpcomp(lat,node.lat) or !fpcomp(lon,node.lon) or \ - Tags.join(n[4])!=node.tags or node.visible==0) - savenode=true - end - end - if savenode - node.user_id=uid - node.lat=lat; node.lon=lon - node.tags=Tags.join(n[4]) - node.visible=true - node.save_with_history! - if id!=node.id - renumberednodes[id]=node.id - id=node.id - end - end - uniques=uniques-[id] - nodes.push(id) - end - - # -- Delete any unique nodes - - uniques.each do |n| - deleteitemrelations(n,'node') - node=Node.find(n) - node.user_id=uid - node.visible=false - node.save_with_history! - end - - # -- Save revised way - - way.tags=attributes - way.nds=nodes - way.user_id=uid - way.visible=true - way.save_with_history! - - [0,originalway,way.id,renumberednodes] + # ----- putway + # saves a way to the database + # in: [0] user token (string), + # [1] original way id (may be negative), + # [2] array of points (as getway/getway_old), + # [3] hash of way tags, + # [4] original way version (0 if not a reverted/undeleted way), + # [5] baselong, [6] basey, [7] masterscale + # does: saves way to the database + # all constituent nodes are created/updated as necessary + # (or deleted if they were in the old version and are otherwise unused) + # out: [0] 0 (code for success), [1] original way id (unchanged), + # [2] new way id, [3] hash of renumbered nodes (old id=>new id), + # [4] xmin, [5] xmax, [6] ymin, [7] ymax (unprojected bbox) + def putway(args,renumberednodes) #:doc: + RAILS_DEFAULT_LOGGER.info(" putway started") + usertoken,originalway,points,attributes,oldversion,baselong,basey,masterscale=args + uid=getuserid(usertoken) + if !uid then return -1,"You are not logged in, so the way could not be saved." end + + RAILS_DEFAULT_LOGGER.info(" putway authenticated happily") + db_uqn='unin'+(rand*100).to_i.to_s+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquenodes table name, typically 51 chars + db_now='@now'+(rand*100).to_i.to_s+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}") + + # -- Check for null IDs, short ways or lats=90 + + points.each do |a| + if a[2]==0 or a[2].nil? then return -2,"Server error - node with id 0 found in way #{originalway}." end + if coord2lat(a[1],masterscale,basey)==90 then return -2,"Server error - node with lat -90 found in way #{originalway}." end + end + + if points.length<2 then return -2,"Server error - way is only #{points.length} points long." end + + # -- 3. read original way into memory + + xc={}; yc={}; tagc={}; vc={} + if originalway>0 + way=originalway + if oldversion==0 then r=readwayquery(way,false) + else r=readwayquery_old(way,oldversion,true) end + r.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 + } + 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)") + end + + # -- 4. get version by inserting new row into ways + + version=ActiveRecord::Base.connection.insert("INSERT INTO ways (id,user_id,timestamp,visible) VALUES (#{way},#{uid},#{db_now},1)") + + # -- 5. compare nodes and update xmin,xmax,ymin,ymax + + xmin=ymin= 999999 + xmax=ymax=-999999 + insertsql='' + nodelist=[] + + points.each_index do |i| + xs=coord2long(points[i][0],masterscale,baselong) + ys=coord2lat(points[i][1],masterscale,basey) + xmin=[xs,xmin].min; xmax=[xs,xmax].max + ymin=[ys,ymin].min; ymax=[ys,ymax].max + node=points[i][2].to_i + tagstr=array2tag(points[i][4]) + tagsql="'"+sqlescape(tagstr)+"'" + lat=(ys * 10000000).round + long=(xs * 10000000).round + tile=QuadTile.tile_for_point(ys, xs) + + # compare node + if node<0 + # new node - create + if renumberednodes[node.to_s].nil? + newnode=ActiveRecord::Base.connection.insert("INSERT INTO current_nodes ( latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES ( #{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") + ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{newnode},#{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") + points[i][2]=newnode + nodelist.push(newnode) + renumberednodes[node.to_s]=newnode.to_s + else + points[i][2]=renumberednodes[node.to_s].to_i + end + + elsif xc.has_key?(node) + nodelist.push(node) + # old node from original way - update + if ((xs/0.0000001).round!=(xc[node]/0.0000001).round 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 + else + # old node, created in another way and now added to this way + end + end + + # -- 6a. delete any nodes not in modified way + + createuniquenodes(way,db_uqn,nodelist) # nodes which appear in this way but no other + + sql=<<-EOF + INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tile) + SELECT DISTINCT cn.id,cn.latitude,cn.longitude,#{db_now},#{uid},0,cn.tile + FROM current_nodes AS cn,#{db_uqn} + WHERE cn.id=node_id + EOF + ActiveRecord::Base.connection.insert(sql) + + sql=<<-EOF + UPDATE current_nodes AS cn, #{db_uqn} + SET cn.timestamp=#{db_now},cn.visible=0,cn.user_id=#{uid} + WHERE cn.id=node_id + EOF + ActiveRecord::Base.connection.update(sql) + + deleteuniquenoderelations(db_uqn,uid,db_now) + ActiveRecord::Base.connection.execute("DROP TEMPORARY TABLE #{db_uqn}") + + # 6b. insert new version of route into way_nodes + + insertsql ='' + currentsql='' + sequence =1 + points.each do |p| + if insertsql !='' then insertsql +=',' end + if currentsql!='' then currentsql+=',' end + insertsql +="(#{way},#{p[2]},#{sequence},#{version})" + currentsql+="(#{way},#{p[2]},#{sequence})" + sequence +=1 + end + + ActiveRecord::Base.connection.execute("DELETE FROM current_way_nodes WHERE id=#{way}"); + ActiveRecord::Base.connection.insert( "INSERT INTO way_nodes (id,node_id,sequence_id,version) VALUES #{insertsql}"); + ActiveRecord::Base.connection.insert( "INSERT INTO current_way_nodes (id,node_id,sequence_id ) VALUES #{currentsql}"); + + # -- 7. insert new way tags + + insertsql ='' + currentsql='' + attributes.each do |k,v| + if v=='' or v.nil? then next end + if v[0,6]=='(type ' then next end + if insertsql !='' then insertsql +=',' end + if currentsql!='' then currentsql+=',' end + insertsql +="(#{way},'"+sqlescape(k.gsub('|',':'))+"','"+sqlescape(v)+"',#{version})" + currentsql+="(#{way},'"+sqlescape(k.gsub('|',':'))+"','"+sqlescape(v)+"')" + end + + ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}") + if (insertsql !='') then ActiveRecord::Base.connection.insert("INSERT INTO way_tags (id,k,v,version) VALUES #{insertsql}" ) end + if (currentsql!='') then ActiveRecord::Base.connection.insert("INSERT INTO current_way_tags (id,k,v) VALUES #{currentsql}") end + + [0,originalway,way,renumberednodes,xmin,xmax,ymin,ymax] end - # Save POI to the database. - # Refuses save if the node has since become part of a way. - # Returns: - # 0. 0 (success), - # 1. original node id (unchanged), - # 2. new node id. - - def putpoi(usertoken,id,lon,lat,tags,visible) #:doc: - uid=getuserid(usertoken) - if !uid then return -1,"You are not logged in, so the point could not be saved." end - - id=id.to_i - visible=(visible.to_i==1) - - if (id>0) then - node=Node.find(id) - if !visible then - unless node.ways.empty? then return -1,"The point has since become part of a way, so you cannot save it as a POI." end - deleteitemrelations(id,'node') - end - else - node=Node.new - end - - node.user_id = uid - node.latitude = (lat*10000000).round - node.longitude = (lon*10000000).round - node.tags = Tags.join(tags) - node.visible=visible - node.save_with_history! - newid=node.id - [0,id,newid] + # ----- putpoi + # save POI to the database + # in: [0] user token (string), + # [1] original node id (may be negative), + # [2] projected longitude, [3] projected latitude, + # [4] hash of tags, [5] visible (0 to delete, 1 otherwise), + # [6] baselong, [7] basey, [8] masterscale + # does: saves POI node to the database + # refuses save if the node has since become part of a way + # out: [0] 0 (success), [1] original node id (unchanged), + # [2] new node id + def putpoi(args) #:doc: + usertoken,id,x,y,tags,visible,baselong,basey,masterscale=args + uid=getuserid(usertoken) + if !uid then return -1,"You are not logged in, so the point could not be saved." end + + db_now='@now'+(rand*100).to_i.to_s+uid.to_s+id.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()") + + id=id.to_i + visible=visible.to_i + if visible==0 then + # if deleting, check node hasn't become part of a way + inway=ActiveRecord::Base.connection.select_one("SELECT cw.id FROM current_ways cw,current_way_nodes cwn WHERE cw.id=cwn.id AND cw.visible=1 AND cwn.node_id=#{id} LIMIT 1") + unless inway.nil? then return -1,"The point has since become part of a way, so you cannot save it as a POI." end + deleteitemrelations(id,'node',uid,db_now) + end + + x=coord2long(x.to_f,masterscale,baselong) + y=coord2lat(y.to_f,masterscale,basey) + tagsql="'"+sqlescape(array2tag(tags))+"'" + lat=(y * 10000000).round + long=(x * 10000000).round + tile=QuadTile.tile_for_point(y, x) + + if (id>0) then + ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{id},#{lat},#{long},#{db_now},#{uid},#{visible},#{tagsql},#{tile})"); + ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{lat},longitude=#{long},timestamp=#{db_now},user_id=#{uid},visible=#{visible},tags=#{tagsql},tile=#{tile} WHERE id=#{id}"); + newid=id + else + newid=ActiveRecord::Base.connection.insert("INSERT INTO current_nodes (latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{lat},#{long},#{db_now},#{uid},#{visible},#{tagsql},#{tile})"); + ActiveRecord::Base.connection.update("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{newid},#{lat},#{long},#{db_now},#{uid},#{visible},#{tagsql},#{tile})"); + end + [0,id,newid] end - # Read POI from database - # (only called on revert: POIs are usually read by whichways). - # - # Returns array of id, long, lat, hash of tags. - - def getpoi(id) #:doc: - n = Node.find(id) - if n - return [n.id, n.lon, n.lat, n.tags_as_hash] - else - return [nil,nil,nil,''] - end + # ----- getpoi + # read POI from database + # (only called on revert: POIs are usually read by whichways) + # in: [0] node id, [1] baselong, [2] basey, [3] masterscale + # does: reads POI + # out: [0] id (unchanged), [1] projected long, [2] projected lat, + # [3] hash of tags + def getpoi(args) #:doc: + id,baselong,basey,masterscale = args + + n = Node.find(id.to_i) + if n + return [n.id, n.lon_potlatch(baselong,masterscale), n.lat_potlatch(basey,masterscale), n.tags_as_hash] + else + return [nil,nil,nil,''] + end + end + + # ----- deleteway + # delete way and constituent nodes from database + # in: [0] user token (string), [1] way id + # does: deletes way from db and any constituent nodes not used elsewhere + # also removes ways/nodes from any relations they're in + # out: [0] 0 (success), [1] way id (unchanged) + + def deleteway(args) #:doc: + usertoken,way_id=args + RAILS_DEFAULT_LOGGER.info(" Message: deleteway, id=#{way_id}") + uid=getuserid(usertoken) + if !uid then return -1,"You are not logged in, so the way could not be deleted." end + + # FIXME + # the next bit removes the way from any relations + # the delete_with_relations_and_nodes_and_history method should do this, + # but at present it just throws a 'precondition failed' + way=way.to_i + db_now='@now'+(rand*100).to_i.to_s+uid.to_s+way.abs.to_s+Time.new.to_i.to_s + db_uqn='unin'+(rand*100).to_i.to_s+uid.to_s+way.abs.to_s+Time.new.to_i.to_s + ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()") + createuniquenodes(way,db_uqn,[]) + deleteuniquenoderelations(db_uqn,uid,db_now) + deleteitemrelations(way_id,'way',uid,db_now) + ActiveRecord::Base.connection.execute("DROP TEMPORARY TABLE #{db_uqn}") + # end of FIXME + + # now delete the way + user = User.find(uid) + way = Way.find(way_id) + way.delete_with_relations_and_nodes_and_history(user) + return [0,way_id] end - # Delete way and all constituent nodes. Also removes from any relations. - # Returns 0 (success), unchanged way id. - def deleteway(usertoken,way_id) #:doc: - uid=getuserid(usertoken) - if !uid then return -1,"You are not logged in, so the way could not be deleted." end + def readwayquery(id,insistonvisible) #:doc: + sql=<<-EOF + SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,current_nodes.id,tags,visible + FROM current_way_nodes,current_nodes + WHERE current_way_nodes.id=#{id} + AND current_way_nodes.node_id=current_nodes.id + EOF + if insistonvisible then sql+=" AND current_nodes.visible=1 " end + sql+=" ORDER BY sequence_id" + ActiveRecord::Base.connection.select_all(sql) + end + + # Get the latest version id of a way + def getlastversion(id,version) #:doc: + old_way = OldWay.find(:first, :conditions => ['visible=1 AND id=?' , id], :order => 'version DESC') + old_way.version + end - # FIXME: would be good not to make two history entries when removing - # two nodes from the same relation - user = User.find(uid) - way = Way.find(way_id) - way.unique_nodes.each do |n| - deleteitemrelations(n,'node') - end + def readwayquery_old(id,version,historic) #:doc: + # 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 + # - if it's in another way now, generate a new id + # - if it's not in another way, use the old ID + + if historic then + rows.each_index do |i| + sql=<<-EOF + SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags,cwn.id AS currentway + FROM nodes n + LEFT JOIN current_way_nodes cwn + ON cwn.node_id=n.id AND cwn.id!=#{id} + WHERE n.id=#{rows[i]['id']} + AND n.timestamp<="#{waytime}" + ORDER BY n.timestamp DESC + LIMIT 1 + EOF + row=ActiveRecord::Base.connection.select_one(sql) + nx=row['longitude'].to_f + ny=row['latitude'].to_f + if (!row.nil?) + if (row['currentway'] && (nx!=rows[i]['longitude'].to_f or ny!=rows[i]['latitude'].to_f or row['tags']!=rows[i]['tags'])) then rows[i]['id']=-1 end + end + rows[i]['longitude']=nx + rows[i]['latitude' ]=ny + rows[i]['tags' ]=row['tags'] + end + end + rows + end - way.delete_with_relations_and_nodes_and_history(user) - return [0,way_id] + def createuniquenodes(way,uqn_name,nodelist) #:doc: + # Find nodes which appear in this way but no others + sql=<<-EOF + CREATE TEMPORARY TABLE #{uqn_name} + SELECT a.node_id + FROM (SELECT DISTINCT node_id FROM current_way_nodes + WHERE id=#{way}) a + LEFT JOIN current_way_nodes b + ON b.node_id=a.node_id + AND b.id!=#{way} + WHERE b.node_id IS NULL + EOF + unless nodelist.empty? then + sql+="AND a.node_id NOT IN ("+nodelist.join(',')+")" + end + ActiveRecord::Base.connection.execute(sql) end + # ==================================================================== - # Support functions + # Relations handling + # deleteuniquenoderelations(uqn_name,uid,db_now) + # deleteitemrelations(way|node,'way'|'node',uid,db_now) + + def deleteuniquenoderelations(uqn_name,uid,db_now) #:doc: + sql=<<-EOF + SELECT node_id,cr.id FROM #{uqn_name},current_relation_members crm,current_relations cr + WHERE crm.member_id=node_id + AND crm.member_type='node' + AND crm.id=cr.id + AND cr.visible=1 + EOF + + relnodes=ActiveRecord::Base.connection.select_all(sql) + relnodes.each do |a| + removefromrelation(a['node_id'],'node',a['id'],uid,db_now) + end + end - # Remove a node or way from all relations + def deleteitemrelations(objid,type,uid,db_now) #:doc: + sql=<<-EOF + SELECT cr.id FROM current_relation_members crm,current_relations cr + WHERE crm.member_id=#{objid} + AND crm.member_type='#{type}' + AND crm.id=cr.id + AND cr.visible=1 + EOF + + relways=ActiveRecord::Base.connection.select_all(sql) + relways.each do |a| + removefromrelation(objid,type,a['id'],uid,db_now) + end + end - def deleteitemrelations(objid,type) #:doc: - relationids = RelationMember.find(:all, :conditions => ['member_type=? and member_id=?', type, objid]).collect { |ws| ws.id }.uniq - relationids.each do |relid| - rel=Relation.find(relid) - rel.members.delete_if {|x| x[0]==type and x[1]==objid} - rel.save_with_history! - end + def removefromrelation(objid,type,relation,uid,db_now) #:doc: + rver=ActiveRecord::Base.connection.insert("INSERT INTO relations (id,user_id,timestamp,visible) VALUES (#{relation},#{uid},#{db_now},1)") + + tagsql=<<-EOF + INSERT INTO relation_tags (id,k,v,version) + SELECT id,k,v,#{rver} FROM current_relation_tags + WHERE id=#{relation} + EOF + ActiveRecord::Base.connection.insert(tagsql) + + membersql=<<-EOF + INSERT INTO relation_members (id,member_type,member_id,member_role,version) + SELECT id,member_type,member_id,member_role,#{rver} FROM current_relation_members + WHERE id=#{relation} + AND (member_id!=#{objid} OR member_type!='#{type}') + EOF + ActiveRecord::Base.connection.insert(membersql) + + ActiveRecord::Base.connection.update("UPDATE current_relations SET user_id=#{uid},timestamp=#{db_now} WHERE id=#{relation}") + ActiveRecord::Base.connection.execute("DELETE FROM current_relation_members WHERE id=#{relation} AND member_type='#{type}' AND member_id=#{objid}") end - # Break out node tags into a hash - # (should become obsolete as of API 0.6) + def sqlescape(a) #:doc: + a.gsub(/[\000-\037]/,"").gsub("'","''").gsub(92.chr) {92.chr+92.chr} + end - def tagstring_to_hash(a) #:doc: - tags={} - Tags.split(a) do |k, v| - tags[k]=v - end - tags + def tag2array(a) #:doc: + tags={} + Tags.split(a) do |k, v| + tags[k.gsub(':','|')]=v + end + tags end - # Authenticate token - # (could be removed if no-one uses the username+password form) + def array2tag(a) #:doc: + tags = [] + a.each do |k,v| + if v=='' then next end + if v[0,6]=='(type ' then next end + tags << [k.gsub('|',':'), v] + end + return Tags.join(tags) + end def getuserid(token) #:doc: - if (token =~ /^(.+)\+(.+)$/) then - user = User.authenticate(:username => $1, :password => $2) - else - user = User.authenticate(:token => token) - end + if (token =~ /^(.+)\+(.+)$/) then + user = User.authenticate(:username => $1, :password => $2) + else + user = User.authenticate(:token => token) + end - return user ? user.id : nil; + return user ? user.id : nil; end - # Compare two floating-point numbers to within 0.0000001 + # ==================================================================== + # Co-ordinate conversion - def fpcomp(a,b) #:doc: - return ((a/0.0000001).round==(b/0.0000001).round) + def lat2coord(a,basey,masterscale) #:doc: + -(lat2y(a)-basey)*masterscale end - - # ==================================================================== - # Alternative SQL queries for getway/whichways - - def sql_find_way_ids_in_area(xmin,ymin,xmax,ymax) - sql=<<-EOF - SELECT DISTINCT current_way_nodes.id AS wayid - FROM current_way_nodes - INNER JOIN current_nodes ON current_nodes.id=current_way_nodes.node_id - INNER JOIN current_ways ON current_ways.id =current_way_nodes.id - WHERE current_nodes.visible=1 - AND current_ways.visible=1 - AND #{OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")} - EOF - return ActiveRecord::Base.connection.select_all(sql).collect { |a| a['wayid'].to_i } + def long2coord(a,baselong,masterscale) #:doc: + (a-baselong)*masterscale end - - def sql_find_pois_in_area(xmin,ymin,xmax,ymax) - sql=<<-EOF - SELECT current_nodes.id,current_nodes.latitude*0.0000001 AS lat,current_nodes.longitude*0.0000001 AS lon,current_nodes.tags - FROM current_nodes - LEFT OUTER JOIN current_way_nodes cwn ON cwn.node_id=current_nodes.id - WHERE current_nodes.visible=1 - AND cwn.id IS NULL - AND #{OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")} - EOF - return ActiveRecord::Base.connection.select_all(sql).collect { |n| [n['id'].to_i,n['lon'].to_f,n['lat'].to_f,tagstring_to_hash(n['tags'])] } + + def lat2y(a) #:doc: + 180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2)) end - - def sql_find_relations_in_area_and_ways(xmin,ymin,xmax,ymax,way_ids) - # ** It would be more Potlatchy to get relations for nodes within ways - # during 'getway', not here - sql=<<-EOF - SELECT DISTINCT cr.id AS relid - FROM current_relations cr - INNER JOIN current_relation_members crm ON crm.id=cr.id - INNER JOIN current_nodes cn ON crm.member_id=cn.id AND crm.member_type='node' - WHERE #{OSM.sql_for_area(ymin, xmin, ymax, xmax, "cn.")} - EOF - unless way_ids.empty? - sql+=<<-EOF - UNION - SELECT DISTINCT cr.id AS relid - FROM current_relations cr - INNER JOIN current_relation_members crm ON crm.id=cr.id - WHERE crm.member_type='way' - AND crm.member_id IN (#{way_ids.join(',')}) - EOF - end - return ActiveRecord::Base.connection.select_all(sql).collect { |a| a['relid'].to_i }.uniq + + def coord2lat(a,masterscale,basey) #:doc: + y2lat(a/-masterscale+basey) end - - def sql_get_nodes_in_way(wayid) - points=[] - sql=<<-EOF - SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,current_nodes.id,tags - FROM current_way_nodes,current_nodes - WHERE current_way_nodes.id=#{wayid.to_i} - AND current_way_nodes.node_id=current_nodes.id - AND current_nodes.visible=1 - ORDER BY sequence_id - EOF - ActiveRecord::Base.connection.select_all(sql).each do |row| - points << [row['lon'].to_f,row['lat'].to_f,row['id'].to_i,nil,tagstring_to_hash(row['tags'])] - end - points + + def coord2long(a,masterscale,baselong) #:doc: + a/masterscale+baselong end - - def sql_get_tags_in_way(wayid) - tags={} - ActiveRecord::Base.connection.select_all("SELECT k,v FROM current_way_tags WHERE id=#{wayid.to_i}").each do |row| - tags[row['k']]=row['v'] - end - tags + + def y2lat(a) + 180/Math::PI * (2*Math.atan(Math.exp(a*Math::PI/180))-Math::PI/2) end end diff --git a/app/models/node.rb b/app/models/node.rb index d61293e82..abfa44d67 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -20,10 +20,6 @@ class Node < ActiveRecord::Base has_many :containing_relation_members, :class_name => "RelationMember", :as => :member has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation, :extend => ObjectFinder - # Atomic undelete support - has_many :old_way_nodes - has_many :ways_via_history, :class_name=> "Way", :through => :old_way_nodes, :source => :way - # Sanity check the latitude and longitude and add an error if it's broken def validate_position errors.add_to_base("Node is not in the world") unless in_world? diff --git a/app/models/old_way.rb b/app/models/old_way.rb index 63265d6bf..1abb23bbb 100644 --- a/app/models/old_way.rb +++ b/app/models/old_way.rb @@ -110,35 +110,6 @@ class OldWay < ActiveRecord::Base return el1 end - # Read full version of old way - # For get_nodes_undelete, uses same nodes, even if they've moved since - # For get_nodes_revert, allocates new ids - # Currently returns Potlatch-style array - - def get_nodes_undelete - points = [] - self.nds.each do |n| - node=Node.find(n) - points << [node.lon, node.lat, n, node.visible ? 1 : 0, node.tags_as_hash] - end - points - end - - def get_nodes_revert - points=[] - self.nds.each do |n| - oldnode=OldNode.find(:first, :conditions=>['id=? AND timestamp<=?',n,self.timestamp], :order=>"timestamp DESC") - curnode=Node.find(n) - id=n; v=curnode.visible ? 1 : 0 - if oldnode.lat!=curnode.lat or oldnode.lon!=curnode.lon or oldnode.tags!=curnode.tags then - # node has changed: if it's in other ways, give it a new id - if curnode.ways-[self.id] then id=-1; v=nil end - end - points << [oldnode.lon, oldnode.lat, id, v, oldnode.tags_as_hash] - end - points - end - # Temporary method to match interface to nodes def tags_as_hash return self.tags diff --git a/app/models/old_way_node.rb b/app/models/old_way_node.rb index a6e65da85..85a6f3c1c 100644 --- a/app/models/old_way_node.rb +++ b/app/models/old_way_node.rb @@ -2,7 +2,4 @@ class OldWayNode < ActiveRecord::Base set_table_name 'way_nodes' set_primary_keys :id, :version, :sequence_id - - # Atomic undelete support - belongs_to :way, :foreign_key=> :id end diff --git a/app/models/way.rb b/app/models/way.rb index 59988d88b..64b11cf67 100644 --- a/app/models/way.rb +++ b/app/models/way.rb @@ -236,7 +236,13 @@ class Way < ActiveRecord::Base # delete a way and it's nodes that aren't part of other ways, with history def delete_with_relations_and_nodes_and_history(user) - node_ids_to_delete = self.unique_nodes + node_ids = self.nodes.collect {|node| node.id } + node_ids_not_to_delete = [] + way_nodes = WayNode.find(:all, :conditions => "node_id in (#{node_ids.join(',')}) and id != #{self.id}") + + node_ids_not_to_delete = way_nodes.collect {|way_node| way_node.node_id} + + node_ids_to_delete = node_ids - node_ids_not_to_delete # delete the nodes not used by other ways node_ids_to_delete.each do |node_id| @@ -252,16 +258,6 @@ class Way < ActiveRecord::Base end - # Find nodes that belong to this way only - def unique_nodes - node_ids = self.nodes.collect {|node| node.id } - if node_ids.length==0 then return [] end - node_ids_in_other_ways = [] - way_nodes = WayNode.find(:all, :conditions => "node_id in (#{node_ids.join(',')}) and id != #{self.id}") - node_ids_in_other_ways = way_nodes.collect {|way_node| way_node.node_id} - return node_ids - node_ids_in_other_ways - end - # Temporary method to match interface to nodes def tags_as_hash return self.tags diff --git a/app/views/site/edit.rhtml b/app/views/site/edit.rhtml index 9c3c78fda..a3896bc48 100644 --- a/app/views/site/edit.rhtml +++ b/app/views/site/edit.rhtml @@ -65,9 +65,9 @@ fo.addVariable('token','<%= session[:token] %>'); if (lat) { fo.addVariable('lat',lat); } if (lon) { fo.addVariable('long',lon); } - <% if params['gpx'] %>fo.addVariable('gpx' ,'<%= h(params['gpx'] ) %>');<% end %> - <% if params['way'] %>fo.addVariable('way' ,'<%= h(params['way'] ) %>');<% end %> - <% if params['node'] %>fo.addVariable('node','<%= h(params['node']) %>');<% end %> + <% if params['gpx'] %> + fo.addVariable('gpx','<%= h(params['gpx']) %>'); + <% end %> fo.write("map"); } diff --git a/config/environment.rb b/config/environment.rb index 6cf8b261d..495f94d80 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -78,6 +78,4 @@ end # This has to be after the above block for some reason (doesnt pull in /lib/osm.rb?) POTLATCH_PRESETS = Potlatch::Potlatch.get_presets() -# Use SQL (faster) or Rails (more elegant) for common Potlatch reads -# getway speedup is approximately x2, whichways approximately x7 -POTLATCH_USE_SQL = true + diff --git a/config/potlatch/localised.yaml b/config/potlatch/localised.yaml deleted file mode 100644 index f61bdc18a..000000000 --- a/config/potlatch/localised.yaml +++ /dev/null @@ -1,621 +0,0 @@ -a_poi: - "de": $1 einen Ort von Interesse (POI) - "hu": POI $1 -a_way: - "de": $1 einen Weg - "hu": Út $1 -action_addpoint: - "de": Am Ende des Wegs Punkt hinzufügen - "es": Añadir un punto al final de una vía - "fi": pisteen lisääminen tien perään - "fr": Ajout d'un point à la fin d'un chemin - "hu": pont hozzáadása az út végéhez - "no": adding a node to the end of a way - "ru": добавить точку в конец пути - "sv": lägger till en punkt på slutet av en väg -action_cancelchanges: - "de": Änderungen an $1 abgebrochen - "es": Cancelar cambios - "fi": peruutetaan muutokset - "fr": annulation de la modification - "hu": cancelling changes to - "no": cancelling changes to - "ru": отмена изменений к - "sv": avbryter ändringar på -action_createpoi: - "de": Einen Ort von Interesse (POI) erstellen - "es": Crear un punto de interés (POI) - "fi": "POI:n lisääminen" - "fr": créer un POI (point d'intérêt) - "hu": POI készítése - "no": lage et POI (interessant punkt) - "ru": создаю точку интереса(POI) - "sv": Skapa en POI, "punk av intresse" -action_deletepoint: - "de": Punkt löschen - "es": Borrar un punto - "fi": pisteen poistaminen - "fr": suppression d'un point - "hu": pont törlése - "no": deleting a point - "ru": удаляю узел - "sv": Tar bort en punkt -action_insertnode: - "de": Punkt auf Weg hinzufügen - "es": Añadir un punto a una vía - "fi": pisteen lisääminen tiehen - "fr": Ajouter un point sur un chemin - "hu": pont hozzáadása úthoz - "no": adding a node into a way - "ru": добавляю узел в путь - "sv": läggertill en punkt till en väg -action_mergeways: - "de": Zwei Wege verschmelzen - "es": Combinar dos vías - "fi": kahden tien yhdistäminen - "fr": Joindre deux chemins - "hu": két út egyesítése - "no": slår sammen to veier - "ru": соединяю два пути - "sv": Slåsamman två vägar -action_movepoi: - "de": Ort von Interesse (POI) verschieben - "es": Mover un punto de interés (POI) - "fi": "POI:n siirtäminen" - "fr": déplacer un POI - "hu": POI mozgatása - "no": flytter et POI (interessant punkt) - "ru": перемещаю точку интереса(POI) - "sv": Flytta på en POI, "punkt av intresse" -action_movepoint: - "de": Punkt verschieben - "es": Mover un punto - "fi": pisteen lisääminen - "fr": déplacer un point - "hu": pont mozgatása - "no": flytter punkt - "ru": перемещаю точку - "sv": Flytta en punkt -action_moveway: - "de": einen Weg verschieben - "hu": út mozgatása -action_pointtags: - "de": Attribute (Tags) für Punkt zuweisen - "es": Parámetros (tags) un punto - "fi": pisteen tagien asettaminen - "fr": Paramétrer un point - "hu": setting tags on a point - "no": setting tags on a point - "ru": установка тегов для точки - "sv": lägger till tagger på en punkt -action_poitags: - "de": Attribute (Tags) für Ort von Interesse (POI) zuweisen - "es": Parámetros (tags) en un punto de interés (POI) - "fi": "POI:n tagien asettaminen" - "fr": Paramétrer un POI - "hu": setting tags on a POI - "no": setting tags on a POI - "ru": установка тегов для точки интереса (POI) - "sv": lägger till tagger på en POI -action_reverseway: - "de": Wegrichtung umkehren - "es": Invertir dirección de una vía - "fi": tien kääntäminen - "fr": Inverser le sens du chemin - "hu": út megfordítása - "no": reversing a way - "ru": ищменение направления пути - "sv": Byter rikting på en väg -action_splitway: - "de": Weg teilen - "es": Dividir una vía - "fi": tien katkaisu - "fr": Scinder un chemin - "hu": út kettévágása - "no": splitting a way - "ru": разбиваю путь - "sv": delar upp en väg -action_waytags: - "de": Attribute (Tags) für Weg zuweisen - "es": Parámetros (tags) en una vía - "fi": tien tagian asettaminen - "fr": Paramétrer un chemin - "hu": setting tags on a way - "no": setting tags on a way - "ru": установка тегов для путиs - "sv": lägger till tagger på en väg -add: - "de": Hinzufügen - "es": Añadir - "fi": Lisää - "fr": Ajouter - "hu": Hozzáadás - "no": Add - "ru": Добавить - "sv": Läggtill -cancel: - "de": Abbrechen - "es": Cancelar - "fi": Peru - "fr": Annuler - "hu": Mégse - "no": Avbryt - "ru": Отмена - "sv": Avbryt -createrelation: - "de": Eine neue Relation erstellen - "es": Crear una nueva relación - "fi": Luo uusi relaatio - "fr": Créer une nouvelle relation - "hu": Új kapcsolat létrehozása - "no": Create a new relation - "ru": Создать отношение - "sv": Skapa en ny relation -delete: - "de": löschen - "hu": Törlés -deleting: - "de": löschen - "es": Borrar - "fi": poistaminen - "fr": suppression - "hu": törlés - "no": deleting - "ru": удаляю - "sv": Tar bort -dontshowagain: - "de": Diese Meldung nicht wieder anzeigen. - "es": No mostrar este mensaje de nuevo - "fi": Älä näytä tätä viestiä enää. - "fr": Ne plus afficher ce message - "hu": Ez az üzenet ne jelenjen meg újra - "no": Ikke vis denne meldingen igjen - "ru": Не показывать это сообщение снова. - "sv": Visa inte detta medelande igen -editingmap: - "de": Karte editieren - "hu": Térkép szerkesztése -emailauthor: - "de": \n\nBitte maile an richard\@systemeD.net eine Fehlerbeschreibung, und schildere, was Du in dem Moment getan hast. (Wenn möglich auf Englisch) - "es": \n\nPor favor envíe un mail a richard\@systemeD.net con un informe del error, describiendo lo que hacía en ese momento. - "fi": \n\nLähetäthän sähköpostia, jossa kerrot mitä olit tekemässä, osoitteeseen richard\@systemeD.net mieluiten englanniksi. - "fr": \n\nMerci d'envoyer un e-mail a richard\@systemeD.net pour signaler ce bogue, en expliquant ce que vous faisiez quand il est survenu. - "hu": \n\nPlease e-mail richard\@systemeD.net with a bug report, saying what you were doing at the time. - "no": \n\nPlease e-mail richard\@systemeD.net with a bug report, saying what you were doing at the time. - "ru": "\n\n Пожалуйста, отправьте сообщение об ошибке (на английском языке) на электронную почту: richard\@systemeD.net, с указанием того, какие действия вы совершали." - "sv": \n\nVänligen e-posta richard\@systemeD.net med en felreport, som beskriver vad du gjorde när felet inträffade. -error_connectionfailed: - "de": Die Verbindung zum OpenStreetMap Server ist leider fehlgeschlagen. Kürzliche Änderungen wurden nicht gespeichert.\n\nNochmal versuchen? - "es": "Disculpe - la conexión al servidor de OpenStreetMap ha fallado. Cualquier cambio reciente no se ha guardado.\n\nPodría intentarlo de nuevo?" - "fi": "Yhteys OSM-palvelimeen epäonnistui. Tuoreita muutoksia ei ole tallennettu.\n\nHaluatko yrittää uudestaan?" - "fr": "Désolé, la connexion au serveur OpenStreetMap a échoué. Vos changements récents ne sont pas enregistrés.\n\nVoulez-vous réessayer ?" - "hu": "Bocs - az OpenStreetMap szerverhez való kapcsolódás sikertelen. A legutóbbi módosítások nem lettek elmentve.\n\nSzeretnéd megpróbálni újra?" - "no": "Sorry - the connection to the OpenStreetMap server failed. Any recent changes have not been saved.\n\nWould you like to try again?" - "ru": "Извините, соединение с сервером OpenStreetMap разорвано. Все текущие изменения не были сохранены.\n\nПопробовать ещё раз?" - "sv": "Tyvärr har vi tappat kontakten med OpenStreetMap serven. Ny gjorda ändringar har inte kunnat sparas.\n\nFörsöka återansluta?" -error_nopoi: - "de": Der Ort von Interesse (POI) kann nicht gefunden werden (vielleicht hast Du den Kartenausschnitt verschoben?), daher ist Rückgängigmachen nicht möglich. - "es": El punto de interés (POI) no se puede encontrar (igual usted se ha desplazado a otra zona?), por tanto no se puede deshacer. - "fi": POI ei löydä (ehkä vieritit siitä liian kauaksi), joten peruminen ei onnistu. - "fr": Le point d'intérêt (POI) n'est pas trouvé (éventuellement sur une autre page?), il ne peut être restauré. - "hu": The POI cannot be found (perhaps you've panned away?) so I can't undo. - "no": The POI cannot be found (perhaps you've panned away?) so I can't undo. - "ru": Точка интереса(POI) не найдена (возможно вы отошли в сторону?), поэтому невозможно отменить. - "sv": "POI:n kan inte hittas (du kanske har flyttat den utanför bilden?) så det går inte att ångra." -error_nosharedpoint: - "de": Die Wege $1 und $2 haben keinen gemeinsamen Punkt mehr, daher kann das Aufteilen nicht rückgängig gemacht werden. - "es": Las vías $1 y $2 ya no tienen ningún punto en común, por tanto no se pueden dividir. - "fi": Ways $1 and $2 don't share a common point any more, so I can't undo the split. - "fr": "Les chemins $1 et $2 n'ont plus de point en commun et ne peuvent donc pas être recollés : l'opération précédente de scindage ne peut être annulée." - "hu": Ways $1 and $2 don't share a common point any more, so I can't undo the split. - "no": Ways $1 and $2 don't share a common point any more, so I can't undo the split. - "ru": Пути $1 и $2 больше не содержат общих узлов, поэтому невозможно отменить разделение. - "sv": Vägarna $1 och $2 möts inte i någon punkt längre, så det går inte att ångra delningen. -error_noway: - "de": Der Weg $1 kann nicht gefunden werden (vielleicht hast Du den Kartenausschnitt verschoben?), daher ist Rückgängigmachen nicht möglich. - "es": La vía $1 no se puede encontrar (igual usted se ha desplazado a otra zona?), por tanto no se puede deshacer.. - "fi": Tietä $1 ei löydy (ehkä vieritit siitä liian kauaksi), joten kumoaminen ei onnistu. - "fr": Le chemin $1 n'a pas été trouvé, il ne peut être restauré à son état précédent. - "hu": Way $1 cannot be found (perhaps you've panned away?) so I can't undo. - "no": Way $1 cannot be found (perhaps you've panned away?) so I can't undo. - "ru": Путь $1 не найден (возможно вы отошли в сторону?), поэтому невозможно отменить. - "sv": Vägen $1 kan inte hittas (du kanske har flyttat den utanför bilden?) så det går inte att ångra. -gpxpleasewait: - "de": Bitte warten, während die GPX-Aufzeichnung (Track) verarbeitet wird. - "es": Por favor espere un poco mientras el track GPX se procesa. - "fi": Odota. GPX-jälkeä käsitellään. - "fr": Patientez pendant que la trace GPX est traitée. - "hu": Kérlek várj a GPX útvonal feldolgozásáig. - "no": Vennligst vent mens sporloggen behandles. - "ru": Пожалуйста, подождите — GPX-треки обрабатываются. - "sv": GPX loggen bearbetas, var god vänta. -help: - "de": Hilfe - "es": Ayuda - "fi": Ohje - "fr": Aide - "hu": Segítség - "no": Hjelp - "ru": Помощь - "sv": Hjälp -hint_drawmode: - "de": Klicken um Punkt hinzuzufügen\n Doppelklicken oder Eingabetaste zum Beenden der Linie - "es": Clic para añadir un punto\ndoble-clic/Return\npara terminar la línea - "fi": klikkaa lisätäksesi piste\ntuplaklikkaa tai paina enter päättääksesi tien - "fr": clic pour ajouter un point\ndouble-clic/Return\npour terminer le chemin - "hu": kattintás pont hozzáadásához\ndupla kattintás/Return\na vonal befejezéséhez - "no": trykk for å legge til punkt\ndobbeltklikk eller enter\nfor å avslutte linje - "ru": кликните для добавления точки\nдвойной клик или Enter\nчтобы чтобы закончить путь - "sv": Klicka för att lägga till en punkt\n Dubbel klicka för att avsluta vägen. -hint_loading: - "de": Wege werden geladen - "es": Cargando vías - "fi": ladataan teitä - "fr": chargement des chemins en cours - "hu": utak betöltése - "no": laster veier - "ru": загрузка путей - "sv": laddar vägar -hint_overendpoint: - "de": Überlappung mit Endpunkt\nKlicken zum Anschließen\nShift+Klick zum Verschmelzen - "es": Sobre punto final\nclic para unir\nshift-clic para combinar - "fi": päätepisteen päällä\nklikkaa sulkeaksi\nshift-klikkaa yhdistääksesi - "fr": sur le dernier point du tracé \nclick pour joindre\nshift-click pour fusionner - "hu": végpont fölött\nkattintás a csatlakoztatáshoz\nshift-kattintás az egyesítéshez - "no": over endepunkt\ntrykk for å koble sammen\nshift+trykk for å slå sammen - "ru": над конечным узлом\nclick для соединения\nshift-click для слияния - "sv": över en slutpunkt\nklicka för att sätta fast\nshift-klicka för att slåsamman -hint_overpoint: - "de": Überlappung mit Punkt\nklicken zum Anschließen - "es": Sobre punto\nclick para unir" - "fi": pisteen päällä\nklikkaa yhdistääksesi" - "fr": point du dessus\nclick pour joindre" - "hu": pont fölött\nkattintás a csatlakoztatáshoz" - "no": over punkt\ntrykk for å koble sammen - "ru": над узлом\nclick для соединения" - "sv": över en punkt \nkicka att sätta fast" -hint_pointselected: - "de": Punkt ist markiert\n(Shift+Punkt anklicken, um\n eine neue Linie zu ziehen) - "es": Punto seleccionado\n(shift-clic en el punto para\nempezar nueva línea) - "fi": piste valittua\n(shift-klikkaa pistettä\naloittaksesi uuden tien) - "fr": point sélectionné\n(shift-clic sur le point pour\ncommencer une nouvelle ligne) - "hu": pont kijelölve\n(shift-kattintás a pontra \núj vonal kezdéséhez) - "no": punkt valgt\n(shift+trykk punktet for å\nstarte en ny linje) - "ru": точка выбрана\n(кликните с нажатым Shift на точку\nчтобы начать новую линию) - "sv": En punk är vald\n(Shift-klicka på punkten för att starta en ny väg) -hint_toolong: - "de": "Zu lang zum Entsperren:\n bitte in kürzere Wege aufteilen" - "es": "Demasiado larga para desbloquear:\nPorfavor divida\nen vías más cortas" - "fi": "liian pitkä vapautettavaksi:\nkatkaise\nlyhyempiin teihin" - "fr": "trop long pour débloquer la situation:\nscindez le chemin en\nchemins plus courts" - "hu": "too long to unlock:\nplease split into\nshorter ways" - "no": "for lang til å låse opp:\nvennligst del opp\ni mindre veier" - "ru": "слишком длинный путь для разблокировки:\пожалуйста, разбейте его\nна более короткие пути" - "sv": "för lång för att låsaupp:\ndela upp vägen\ni mindre delar" -option_background: - "de": "Hintergrund:" - "es": "Fondo:" - "fi": "Tausta:" - "fr": "Arrière-plan :" - "hu": "Háttér:" - "no": "Background:" - "ru": "Фон:" - "sv": "Bakgrund:" -option_custompointers: - "de": Stift- und Hand-Mauszeiger benutzen - "es": Usar punteros de pluma y mano - "fi": Käytä kynä- ja käsikursoreita - "fr": Utiliser le crayon et la main pour pointer les éléments - "hu": Use pen and hand pointers - "no": Use pen and hand pointers - "ru": Использовать курсоры пера и руки - "sv": Använd penna och hand pekare -option_fadebackground: - "de": Hintergrund verblasst - "es": Atenuar fondo - "fi": Himmeä tausta - "fr": Arrière-plan clair - "hu": Fade background - "no": Fade background - "ru": Обесцветить фон - "sv": Mattad bakgrund -option_thinlines: - "de": Dünne Linien in allen Auflösungen benutzen - "es": Usar líneas finas en todas las escalas - "fi": Käytä aina ohuita viivoja - "fr": Utiliser un trait fin à toutes les échelles - "hu": Use thin lines at all scales - "no": Use thin lines at all scales - "ru": Использовать тонкие линии на всех масштабах - "sv": Använd tunna linjer på alla skalor -play: - "de": Ausprobieren - "hu": Kipróbálás -point: - "de": Punkt - "hu": Pont -practicemode: - "de": Übungsmodus - "es": Modo prácticas - "fi": Harjoitustila - "fr": Mode d'essai - "hu": Gyakorlás mód - "no": Øvelsesmodus - "ru": Тренировочный режим - "sv": Tränings läge -prompt_accuracy: - "de": Fehlerfreiheit ist wichtig - Trage nur Orte ein, wo Du warst - "es": La precisión es importante - Mapee solo zonas en las que ha estado físicamente. - "fi": Tarkkuus on tärkeää; muokkaathan vain paikkoja, joissa olet ollut. - "fr": Précision importante - Éditez seulement les lieux que vous avez visités - "hu": A pontosság fontos - csak olyan helyeket térképezz, ahol már jártál - "no": Nøyaktighet er viktig, bare kartlegg steder du har besøkt - "ru": Точность важна. Составляйте карты только для тех мест, в которых вы были. - "sv": Noggrannhet är viktigt - kartera bara ställen du varit -prompt_addtorelation: - "de": $1 zu einer Relation hinzufügen - "es": Añadir $1 a una relación - "fi": Lisä $1 relaatioon - "fr": Ajouter $1 à la relation - "hu": $1 hozzáadása egy kapcsolathoz - "no": Add $1 to a relation - "ru": Добавить $1 в отношение - "sv": Läggtill $1 till en relation -prompt_dontcopy: - "de": Kopiere nichts von anderen Karten - "es": No copie de otros mapas - "fi": Älä kopioi muista kartoista - "fr": Ne copiez pas d'autre cartes - "hu": Ne másolj más térképekből - "no": Ikke kopier fra andre kart - "ru": Не копируйте информацию с других карт - "sv": Kopiera inget från andra kartor -prompt_enjoy: - "de": "Und: Viel Spaß!" - "es": Y páselo bien! - "fi": Pidä hauskaa! - "fr": Et amusez-vous bien ! - "hu": És szórakozz jól! - "no": Og ha det morsomt! - "ru": Приятного вам времяпровождения! - "sv": och ha roligt! -prompt_help: - "de": Anleitung für Potlatch, diesen Karten-Editor. - "es": Encuentre cómo usar Potlatch (éste editor de mapas). - "fi": Kuinka käytän Potlatchiä, tätä editoria? - "fr": Découvrez comment utiliser Potlatch, cet éditeur de la carte. - "hu": Nézz utána, hogyan kell használni a Potlatch-ot, ezt a térképszerkesztőt. - "no": Find out how to use Potlatch, this map editor. - "ru": Узнать, как пользоваться редактором. - "sv": Information hur man använder Potlatch, den här kart editorn. -prompt_introduction: - "de": Wähle unten eine Schaltfläche zum Editieren. Wenn Du "Start" anklickst, wirst Du die Karte sofort direkt bearbeiten - Änderungen werden meist jeden Donnerstag sichtbar. Wenn Du "Ausprobieren" anklickst, werden Deine Änderungen nicht gespeichert, also kannst Du hier das Bearbeiten üben.\n\nDenk an die Goldenen Regeln von OpenStreetMap:\n\n - "es": Seleccione uno de los botones más abajo para empezar a editar. Si pulsa "Empezar", estará editando directamente el mapa - Normalmente los cambios se mostrarán cada Jueves. Si pulsa "Jugar", sus cambios no se guardarán, de esta manera podrá practicar la edición.\n\nRecuerde las reglas de oro de OpenStreetMap:\n\n - "fi": "Valitse haluamasi tila. Jos valitset aloita, pääset muokkaamaan karttaa suoraan - muutokset päivittyvät pääsivun kartalle yleensä torstaisin. Jos valitset harjoittele, tekemiäsi muutoksia ei tallenneta mihinkää, eli voit harjoitella editointia\n\nMuistathan OpenStreetMapin kultaiset säännöt:\n\n" - "fr": "Choisir un bouton ci-dessous pour commencer l'édition. Si vous cliquez sur 'Start', vous éditerez directement la carte principale - les modifications sont visibles sur celle-ci généralement tous les jeudis. Si vous cliquez sur 'Play', vos modifications ne seront pas enregistrées, ainsi vous pouvez vous exercer sans risques.\n\nEt gardez en tête ces règles d'or d'OpenStreetMap :\n\n" - "hu": "Válassz az alábbi gombok közül a szerkesztéshez. Ha a 'Kezdés'-re kattintasz, akkor közvetlenül a főtérképet szerkesztheted - a módosítások általában minden csütörtökön jelennek meg. Ha a 'Kipróbálás'-ra kattintasz, akkor a módosításaid nem lesznek elmentve, így gyakorolhatod a szerkesztést.\n\nEmlékezz az OpenStreetMap aranyszabályaira:\n\n" - "no": "Velg en knapp nedenfor for å redigere. Hvis du velger 'Start' redigerer du kartet direkte, endringer blir vanligvis synlige hver torsdag. Hvis du velger 'Lek' lagres ikke endringer, så du kan øve deg på å redigere.\nHusk OpenStreetMaps gyldne regler:\n\n" - "ru": "Выберите кнопку. Если вы нажмёте «Start», вы начнёте редактировать карту. Основная карта обновляется по средам. Если вы нажмёте «Play», ваши изменения на карте сохраняться не будут и вы сможете практиковаться в редактировании.\n\nЗапомните основные правила OpenStreetMap:\n\n" - "sv": "För att börja editera, klicka på en av knapparna nedan. Om du klickar på 'Start' så arbetar du direkt mot huvudkartan, och ändringar sparas automatiskt - ändringarna syns normalt varje torsdag efter huvudkartan uppdaterats. Om du klickar 'Play' så kommer inget att sparas, ett bra sätt att träna på att använda programmet.\n\nKom ihåg OpenStreetMaps gyllene regler:\n\n" -prompt_practise: - "de": Bearbeiten üben - Deine Änderungen werden nicht gespeichert. - "es": Mapear en prácticas - Sus cambios no se guardarán. - "fi": Harjoittele - muutoksiasi ei talleneta. - "fr": "Essai de cartographie : vos changements ne seront pas pris en compte." - "hu": Térképezés gyakorlása - módosításaid nem lesznek elmentve. - "no": Øv på kartlegging, endringer blir ikke lagret. - "ru": Тренировочное редактирование — ваши изменения не будут сохранены. - "sv": Träna på kartering - inga ändringar kommer att sparas. -prompt_revertversion: - "de": "Früher gespeicherte Version wiederherstellen:" - "es": "Volver a una versión previamente guardada:" - "fi": "Palauta aiempaan versioon:" - "fr": "Revenir à une version sauvegardée plus récente :" - "hu": "Visszaállítás egy korábbi mentett változatra:" - "no": "Tilbakestill til tidligere lagret versjon:" - "ru": "Восстановить ранее сохраненную версию:" - "sv": Gå tillbaks till en tidigare version -prompt_selectrelation: - "de": Bestehende Relation zum Hinzufügen auswählen oder neue Relation erstellen. - "es": Seleccionar una relación existente para añadir a ella, o crear una nueva relación. - "fi": Valitse olemassa oleva relaatio, johon lisätään, tai luo uusi. - "fr": Sélectionner une relation existante pour l'ajouter, ou créer une nouvelle relation. - "hu": Select an existing relation to add to, or create a new relation. - "no": Select an existing relation to add to, or create a new relation. - "ru": Выберете существующее отношение или создайте новое. - "sv": Välj en befintligrelation att addera till, eller skapa en ny relation. -prompt_start: - "de": Kartographieren mit OpenStreetMap beginnen - "es": Empezar a mapear con OpenStreetMap. - "fi": Aloita kartan muokkaus. - "fr": Démarrer la cartographie avec OpenStreetMap. - "hu": Térképezés kezdése OpenStreetMappal. - "no": Begynn å kartlegg med OpenStreetMap. - "ru": Начать редактировать карту OpenStreetMap. - "sv": Börja kartera med OpenStreetMap. -prompt_taggedpoints: - "de": Einige Punkte auf diesem Weg tragen Attribute (Tags). Trotzdem löschen? - "es": Algunos puntos de esta vía tienen parámetros (tags). Seguro que quiere borrar? - "fi": Joihinkin tien pisteisiin on lisätty tageja. Haluatko varmasti perua? - "fr": Certains points de ce chemin sont tagués. Souhaitez-vous les supprimer? - "hu": Ezen az úton van néhány címkézett pont. Biztosan törlöd? - "no": Some of the points on this way are tagged. Really delete? - "ru": Некоторые узлы данного пути содержат теги. Действительно удалить? - "sv": Några en punkterna i denna väg är taggade, vill du verkligen ta bort den? -prompt_track: - "de": Deine GPS-Aufzeichnungen (Tracks) in (gesperrte) Wege zum Editieren wandeln. - "es": Convierta su track de GPS a vías (bloqueadas) para editar. - "fi": Muunna GPX-jälki lukituiksi teiksi editointia varten - "fr": Conversion d'une trace GPS en chemin (verrouillé) pour l'édition. - "hu": Convert your GPS track to (locked) ways for editing. - "no": Convert your GPS track to (locked) ways for editing. - "ru": Конвертировать GPS-трек в путь(заблокированный), для редактирования. - "sv": Omvandla dina GPS spår till (låsta) vägar för editering. -prompt_welcome: - "de": Willkommen bei OpenStreetMap! - "es": Bienvenido a OpenStreetMap! - "fi": "Tervetuloa OpenStreetMap:iin" - "fr": Bienvenue sur OpenStreetMap ! - "hu": Üdvözöllek az OpenStreetMapon! - "no": Velkommen til OpenStreetMap! - "ru": Добро пожаловать в OpenStreetMap! - "sv": Välkommen till OpenStreetMap! -revert: - "de": Vorherige Version wiederherstellen - "es": Volver - "fi": Kumoa - "fr": Revenir - "hu": Visszaállítás - "no": Tilbakestill - "ru": Восстановить - "sv": Använd denna version -start: - "de": Start - "hu": Kezdés -tip_addrelation: - "de": Zu einer Relation hinzufügen - "es": Añadir a una relación - "fi": Lisää relaatio - "fr": Ajouter à une relation - "hu": Hozzáadás kapcsolathoz - "no": Legg til i en relation - "ru": Добавить новое отношение(relation) - "sv": Läggtill en ny relation -tip_addtag: - "de": Attribut (Tag) hinzufügen - "es": Añadir un nuevo parámetro (tag) - "fi": Lisää uusi tagi - "fr": Ajouter un nouveau tag - "hu": Új címke hozzáadása - "no": Legg til tag - "ru": Добавить новый тег - "sv": Läggtill en ny tag -tip_alert: - "de": Ein Fehler ist aufgetreten - Klicken für Details - "es": Ha ocurrido un error - clic para detalles - "fi": Tapahtui virhe - klikkaa saadaksesi lisätietoja - "fr": Une erreur vient de survenir - cliquez pour plus de détails - "hu": Hiba történt - kattints a részletekért - "no": Det oppstod en feil, trykk for detaljer - "ru": Произошла ошибка — нажмите для получения подробностей - "sv": Ett fel har inträffat - klicka för detaljer -tip_anticlockwise: - "de": Geschlossener Weg gegen den Uhrzeigersinn - Klicken zum Richtung Ändern - "es": Vía circular en el sentido contrario de las agujas del reloj - clic para invertir la dirección de la vía - "fi": Vastapäivään sulkeutuva tie - klikkaa kääntääksesi - "fr": Circulation dans le sens inverse des aiguilles d'une montre (trigonométrique) - Cliquez pour inverser le sens - "hu": Órajárással ellentétes körút - kattints a megfordításhoz - "no": Sirkulær vei mot klokka, trykk for å snu - "ru": Замкнутый путь против часовой стрелки - изменить на противоположный - "sv": Vägen är rund, riktad moturs, klicka för att vända rikting -tip_clockwise: - "de": Geschlossener Weg im Uhrzeigersinn - Klicken zum Richtung Ändern - "es": Vía circular en el sentido de las agujas del reloj - clic para invertir la dirección de la vía - "fi": Myötäpäivään sulkeutuva tie - klikkaa kääntääksesi - "fr": Circulation dans le sens des aiguilles d'une montre - Cliquez pour inverser le sens - "hu": Órajárással egyező körút - kattints a megfordításhoz - "no": Sirkulær vei med klokka, trykk for å snu - "ru": Замкнутый путь по часовой стрелке - изменить на противоположный - "sv": Vägen är rund riktad medurs, klicka för att vända riktning -tip_direction: - "de": Richtung des Weges - Klicken zum Ändern - "es": Dirección de la vía - clic para invertir la dirección de la vía - "fi": Tien suunta - klikkaa kääntääksesi - "fr": Direction du chemin - cliquez pour inverser - "hu": Út iránya - kattints a megfordításhoz - "no": Veiretning, trykk for å snu - "ru": Направление пути — изменить на противоположный - "sv": Vägens riktning - klicka för att vända vägen -tip_gps: - "de": GPS-Aufzeichnungen (Tracks) einblenden (G) - "es": Mostrar los tracks de GPS (G) - "fi": Näytä GPS-jäljet (G) - "fr": Afficher la trace GPS (G) - "hu": GPS útvonalak megjelenítése (G) - "no": Vis GPS sporlogger (G) - "ru": Показать GPS треки (G) - "sv": Visa GPS spår (G) -tip_noundo: - "de": Es gibt nichts rückgängig zu machen. - "es": Nada que deshacer - "fi": Ei kumottavaa - "fr": Rien à annuler - "hu": Nincs mit visszavonni - "no": Ingenting å angre - "ru": Нечего отменять - "sv": Finns inget att ångra -tip_options: - "de": Optionen ändern (Kartenhintergrund) - "es": Opciones (elegir el fondo del mapa) - "fi": Asetukset (valitse kartan tausta) - "fr": Options (choix de la carte d'arrière plan) - "hu": Beállítások módosítása (térképháttér kiválasztása) - "no": Sett valg (velg kartbakgrunn) - "ru": Задать настройки (выбрать карту-подложку) - "sv": Ändra inställningar (välj bakgrunds karta) -tip_presettype: - "de": Wähle die Art der Voreinstellungen, die im Menü angeboten werden sollen. - "es": Seleccionar que tipo de parámetros (tags) preestablecidos se ofrecen en el menú. - "fi": Valitse millaisia pohjia on tarjolla valikossa. - "fr": Sélectionner le type de paramètres proposés dans le menu de sélection. - "hu": Choose what type of presets are offered in the menu. - "no": Choose what type of presets are offered in the menu. - "ru": Выберете какой набор тегов отображать в меню. - "sv": Välj vilka typer an inställningar som syns i menyn. -tip_repeattag: - "de": Attribute (Tags) vom vorher markierten Weg übernehmen (R) - "es": Repetir los parámetros (tags) de la vía seleccionada previamente (R) - "fi": Toista tagit viimeksi valitusta tiestä (R) - "fr": Recopier les informations du chemin sélectionné précédemment (R) - "hu": Az előzőleg kiválasztott út címkéinek megismétlése (R) - "no": Repeter tagger fra siste valgte vei (R) - "ru": Повторить теги с предыдущего выбранного пути (R) - "sv": Kopiera taggarna från den senast valda vägen (R) -tip_revertversion: - "de": Version zum Wiederherstellen wählen - "es": Elige la versión a la que volver. - "fi": Valitse versio, johon palautetaan - "fr": Choisissez la version vers laquelle revenir - "hu": Válaszd ki a változatot a visszaállításhoz - "no": Velg versjonen det skal tilbakestilles til - "ru": Выберете версию для воосстановления - "sv": Välj version som ska användas -tip_selectrelation: - "de": Zur markierten Route hinzufügen ?Route or Way? - "es": Añadir a la ruta seleccionada - "fi": Lisää valittuun reittiin - "fr": Ajouter à la route choisie - "hu": Hozzáadás a kiválasztott útvonalhoz - "no": Add to the chosen route - "ru": Добавить в выбранное отношение - "sv": Addera till den valda rutten -tip_splitway: - "de": Weg am markierten Punkt auftrennen (X) - "es": Dividir la vía en el punto seleccionado (X) - "fi": Katkaise tie valitusta kohtaa (X) - "fr": scinder le chemin au point sélectionné (X) - "hu": Út kettévágása a kijelölt pontnál (X) - "no": Del vei i valgt punkt (X) - "ru": Разделить путь в текущем узле (X) - "sv": Dela upp vägen i två delar vid den valda punkten (x) -tip_undo: - "de": $1 rückgängig machen (Z) - "es": Deshacer $1 (Z) - "fi": Kumoa $1 (Z) - "fr": Annuler l'opération $1 (Z) - "hu": $1 visszavonása (Z) - "no": Undo $1 (Z) - "ru": Отменить $1 (Z) - "sv": Ångra $1 (Z) -track: - "de": "to track: Weg aufzeichnen, the track: GPS-Aufzeichnung (Track)" - "es": Track - "fi": Jälki - "fr": Trace - "hu": Útvonal - "no": Track - "ru": Трек - "sv": Spår -way: - "de": Weg - "hu": Út diff --git a/config/potlatch/relation_colours.txt b/config/potlatch/relation_colours.txt index 557563fe2..03398fb71 100644 --- a/config/potlatch/relation_colours.txt +++ b/config/potlatch/relation_colours.txt @@ -4,5 +4,4 @@ lcn 0x0000ff 50 10 rcn 0x28c9fe 50 10 ncn 0xff3333 50 10 -foot 0x228022 50 10 -trail 0x228022 50 10 +ldp 0x228022 50 10 diff --git a/lib/potlatch.rb b/lib/potlatch.rb index cf8f5903d..4dfba12ef 100644 --- a/lib/potlatch.rb +++ b/lib/potlatch.rb @@ -83,7 +83,7 @@ module Potlatch when 'Hash' a=3.chr n.each do |k,v| - a+=encodestring(k.to_s)+encodevalue(v) + a+=encodestring(k)+encodevalue(v) end a+0.chr+0.chr+9.chr when 'String' @@ -195,10 +195,7 @@ module Potlatch } end - # Read internationalisation - localised = YAML::load(File.open("#{RAILS_ROOT}/config/potlatch/localised.yaml")) - - [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,localised] + [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths] end end diff --git a/public/potlatch/potlatch.swf b/public/potlatch/potlatch.swf index 63a04bf51c6f3451bdb6b88bad6110028a887549..721840fe4ec4d006d7b62d134313f7e90fffee54 100755 GIT binary patch literal 140596 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 C(O_Eu literal 148900 zcmdqKcVLu7{y#ojLUsd4N5B9}34|7kbSVi0k^m`$&}?y&-6RW}-LShMi8XfYfK<^_ zK@mH8ieioB6i+>SZ+NF?zw=JdF8RLR@0od?XE#OEkH0^D+?nTj=9ziVd*1WzGtcb& zsse;A1T-T{*cm8;RFDS&@)1i#&-Bgxo=-^= zJ0HCuuxqdVI5B#~mM_NjPP2LEU9jw(BJpzL@ZL*BO3zLEyQ0=EZ(iM2sx>*dwctzC zI%)S)xt|nK|3~QlyXgLRqPuQl(P@tjtZ5XTCUEBy#7#Hd)I34#*s%kDFS_U={5|#5 zQ}H(#4C3zzC!B!4`T6@civI$cpVBgJ-G*&);h?CAR<9cs9GA zfZgmW#!0WE8(Dq%KX@T_7*y-CL-dGyb_%#RvUVo5PZGW2o;!%%anH%($hc>h=o9zs z7JcKMQ$)YG=Z@m2xaUqH)qECWhHHSBx8REj&%+hmAuPUEZ}?t4M~sMg;Csz~bmPCr zlJ6CKBjc)r@Vy?%-?-t$YsmNMuYI2Z1XYNsE{~Y^XxfY8q-&{txrqk{N7C&V=5A~n z;YnF>-R88Dy01vul2@C#($jl{@1o-w)<6x*BViro8Z2g>+q)-8K zz$b?Lgy?a}8&5h9E-36+@b^Z57_LF2OAxbNbAZZ7QMkX?pXT8m{x#c%@TFT?@|M0m zZS#hXYwWo`X>@Txr@ijc_NRxw)Hr&5$DVi2nOJ0-vv$Db6DJRzTn5M^G~|&Qasj}M z7Rwhr*PQ>crf083FCBSx*0E3IfB42JnSlo9>z4-4>v;YfcNhPZJVcEC{^%ly|Ih_R z?nco&6Bs(DifzKy(_WG(-n)3pyJEC!j99+!?hc5J0kxKMk({i#h!pIz&_GPCa{d(YE9sBB6XGhJgv z(WjN`^N1mN(tC|Q_qMF}FH8S$&z9pINw=SK&4)sqvfp*8zpUqJXFfVkY&fU<`fl|F z?(EX!m&M2KQF`Q~1&NnkjNz+8WboA~#!8Azca0Z|-rq3Qhx%unaRy<3bYq8_q>q1m zcJuI_2Zt{ZN$Wmw)g<2_2JJ1M7V2`R{gjg&H%2bMK&%r3ToXj$Q?}DPm?J+T>%oJc zUHaqtV@|f&g~xTYC=gFwnF-j6GSeSVK4HO**Lq&Ex_9`x3~|ssPUAUV;R#&@d>!Iw zjo+l-jNeGtWRd&HkaPQ*{U?`fU->8TX=bnYXIACp9^aHVF6okYpV)D==i|i{C2QyYGdd80nfS@}GXI{yXz^?>koBabV{9+FhN~FHE^BcgtT-x&6bZ zhIT)@vA=7YC|nU(`JP!fweIJerXE+dZ}NG62B_(xpyaICh34z-H|_7b^77qT!{)sE z+GEZ?KlA)kX>V1YzP&fFI!5HbcT<-WGYBwTrmMF|T!AfH1l%MbZ?zrXqCVx*Po+Aof?^;RR`P2Plk3D<$!^0kY_thNd zEsOR(HTbx`r*B;btmcZ`2m4t`{MlRI+#am{y5g-9G>Kc zZ<^mUX#BOFVB_#>@2sjlIPd-07nC)9d3n*)`2)Us>83_Rxw!z7BMPz~3FMn#em?l^ z6}`Hp*mLa=#*tLNK=>-s-BTx>hbH+X%r5|C`X z#%$QcJf0Ohh$(eU4qu%Dl;PRS<7)@8fUn77p`N|`-#mK*Tm|i7I2&9qM4`z4-!ai# z;HhT!r!Q+S^-lU`=C?DRdi%ULr~feKs-lq}9l84-lkOgU=?!0aj&3|+$OliAynWQk z-dp;eehu{KB0a`@#@!CZE5}%<$FTS}k72BBGRKgv0= z`vdb=KQv)w_PgixdE(ABr#4)djd@=p3Rdj8e<6@kM#cTmwx^E$D){cpwI3b%@cONn zU9@=epL@)|v-|x|_FgXrxk|*GQ_?!$YgA8JI`xOMFP+$_{^I&4%bz>B5mlCotes1D z7a3JLe7o(3bB<6|ocK?Aqqync8$fj zrMz*~%inxBcJ21PUtRa+J)?Kr*7?Z}pFf>n4cYTzl2?j?N4mvEnM6##=x@h$yzTZa z|L7F_`#+w%+@E2e;W+)m`$x|D_qNOK{lGi$lNk?m8IttMx>q*ahuYKEU9fZL@Qa`8 zlh#4p{mFuN``R`yF-_4vz+?>r!0cOR>fIZh#S zyhh^0UqAvpEK0@lewTkb_&Z@6z(Qe5>v8#?lD?`9JTfQrl5N4+({AqJy?p7xbl>jH znf7zjGP3O#WTwAfe8PvHi!Du^cci`aK+*-7D@NQ|JROt%y88r;%!vw_QjLtaU1UbM z%0#|z?DA=7uY8yp3m!gw>HfP@N3H06#j9t&nzHQWGamfm4I$E9u)Z zr~Tv{c6ZiYXC2z|$g9a6?mnaLtJ^(dgv%!ukGpyG*_tTy9fUJ^nG*S$(^Jz2M<9@*+rR}({jE#1sv*35Nv>}qTP|q#@q{0DV9BR`@aV@ z8XZqQbC~avi5p$-uHCZKvH1H{h?MSU`%iCxCoJANboN94ZhmF)wX>cdIu6X^M_H9v_WY&i>^jNlAot@7w%pb) zt3rs|`dzqS!Lfrs32ymY^T6x2-gnMcaeUgY3G-KM*g9m{_Wga{Szloj#r-b09u2mxI=m)MkV7zs{cv{I@Dbx4u8`U(xwOSN5tz7t+Fi@PGa>H@MR=#pt zw6gNP%ntZX0cP@Xm@`nYpe>h3aU_>n2wD;4UnI_C5mN{Hco^@i`_pj`AZ^`Vv?H|YG zj<|fz1&^f_kL!4ER!Y~#^&LicFIq9>i;bTRK6L!RZ#HiYjH{{}@?uiwZ}LuC-<;9q z#|2Mq`1$_b@BZ`quKjLUfAYKoVw5W?asvy4AD9S@JaN9`z-^!Iez57C|6SI9>ow1u z?WjuG@^w)x}R95t( ze|^30i0ZqZJ#+@WT`OkoeL2H?`@iV(lWtSBD7m z)hV!$g!f5e4PQHm2w#&$l&>xko4aXO_ElBqHxKUedE=ue z3?18NWA+c-Jt?^phkTd4XO2Cy*WPWPA9twh*o$WWb!>iBlhZy}te7~+xo6I!UDGdo z?1_;L_g3TXBIopR;>dN=<~vW&!J2);ohgu{B+!D6B^$g-1PAo z{XCtwojzdf+uz;%&$9b}JjeTYECO{eLRx3N=wTmjPv0IW|E^|)urI!@udtsxai~b9 zxVqk+DNc1CbJwhEr+(acSEw@ROb$jDXR9WHfDvHW;FTD4_ zRkzJPJN=@rMPOc7d2zB>T)gGSvrNe!-PmEAW8?YnU$_0m_cpD{9^_xtXLnw=T{rIh z;mxh*b-a4llV7Iqt-1E`J((kI?hYl9vWfn6wj+99xbBJD@Q$(D+anw z6*EHp4m9d^JzpQPNu)Flo$md5Lr>=lpgadCpC)oLe=dSfP{75cmBRk*pwIR=%HPcF z^L$zFInVTUUGkUr#ndxhgKLghcYTJ(dEf;5I7j57o9{ev*#n;=sc^c;{A%F$Feeg5 z&*#RkKkBk?vQHiQN&Zb&{eARLAAfQC0VJi)fVz19Es_D%SFf_|(8`Ux?v1JG3(%iZYe@_C+iv;UH+$k=Hm|>R^@lIt z_r!>CFa6Lo!gaP-F!P_*n(6<&EpycDm0g}4@2?nD{C#c49TzT|Xx|H3!xI+gh-Le3 zsGhUl0GxN(vzO$JIGAT> zIo${M`0M{m_|*)o;$W5y>5?xK!fYv%!=&uI_|mj$-$|I zE*1|T?6mQ3v4=9n-*Qj;Vf0Pg8b|JYrpvmSpQhb;V{XCD6Q}hVd$AZYc*-?fo*%Q? z_r~nYFM6+d%!IrS^9Gd7>U8nIpLYJ(`JDe;*JWPDwr)eZ9vbK9aN(wu!bivSSuiZi zm7D&2|B#qA{i|n&I$rtw+?PHad*x~0UwFx58-|>|`1K~|+R0zey7-u@4>nyaZg~H( zbw7y{#k83>U*T{5wt78W!3#9GF680cF(MxR6xStU(ZQ#tPQZJe3cGaeNv_J%8@l{Y z49^ty^S^t1?}U?*_iWfczKa;%BxY{w^K(%VOv|OB;HyXKx|=lluKWKoLNDLlJ#=$p zf7fLq|Luhjn6Y~==RH@I?ASc!xE&WBgwuYp#^(}+&!v2Ih|45ilU*A`_EA^PZ8Fdj z-TIb@qMaqHGt)QOFG@+pAq)q`>nx=l}G{{awXy*A_9a+e0-g3?BN=4YhA4rQZ`4!C{{{O3VJbu<6n7&iGCY zb8Qs`&#YPX6fjkqpm)u*-q(LQxyRjSExyCQ`<`rV==s})|? zNW5l4?+I}o;=3~8PM3p&^20wUzqya*eDF-u!0RX9x$UOjzH4{AW6Rh(VA-Zw!M4oo_~)S_02yg2A5-sZV-i^+tZc_fjvZLopn~TEzOfu zy7t=*JN6uZj_BjsBbHZ<7<{0KUeow&X(#L)`*r~u-YAxD>o?@W?_@c$?pZshy}s>@ zxvy8f@gRb}>orol6%B7tG~B~ir?^ogd-LHVdrSMs-r6Rzx3!0?$920XI^g##ME1p@ zMmcxz3vWI(HRZhQ9;=6VkeIni59ekzoLkgzZdJp%jju`Kc0H^+4u4p8wm+;tw>hl4 z+8fpY*WIG%^W%negx)rW_2~FFd`WZ8I&<#<3~H|))E#P2cd9}CSqHqM zdaoRIrOns4;`)u-6l2ON91^CAJGNi$Dvi7w?WuN#2@s=0^yKwh}Hgv zwccQ@UpT3>+FxDfkBB5u6A9PU1wy`Xo#=oEf7BnV_J?W_3Gu}x%B%e4tINXm!Yv|R zUmz?}gts;p79B-(*yjz3PO`W(Tu~v8(Dxy%$=6i{B0K*p9iX@p~~`RJjVJ_40O?sPcw<;(Afz4~d)T zZ@t({mzrR0RP3X>uy}wj(Xg29_^h8@tozGkS5ijCSZ_^W?6{0cW4+ZC0{69;BTH$t zu3~H~;w@i|`3l9NL@}yS6^qqOA3IjWssd3_N+n}Ov?dsc39juQi;DGBEMkG6p9mbN z7h`L}F|c2G)!2q=Z_R`Zz!nYOsxSzQ_CAa%qrN&wEu*y+)L==>Tj>|ks&HLCv7k2? zs0@jcMVLr$(4Qan`9&zagziC=Xy9c3qChm}4}pyf%U1czV~Os8|sULqJFz@Rl$E!^zjRHK3b+E?)Zp8yr+n%YqD&(^H6ugnNCh@Z-MR9~Dcg zFc6=jQ>8z)C=5D^Sa>y1sg3$0@(#!b{2~^CmVml2s1^<_^fzRO>q1mo1lmXaK7k_9 zP#5q4-3CR`29jYB1iJFBtg;?j0n`&^l@02S86XIG0SLZFmoa@Gp^2fHm9GSF_D1=y zBp_IYlotzslAaV_+ z9m)nw6b=Rp*MhB3X56b{=p|i>TNL_(K+$hBp9iT7hw{Vdgb7BygJ_r%CR!BL%VWzi zQ-mcyVC+)X^b_W>JX{N%h?{7{zoyoY>4$pZr*eN_Egmp*SqC?kI`T=?0aOL2Do|c! z0VE$)t!%IpPZ`v8c@=fSPg1~yFXF8v3Bk3FvE-Ktcdpn8U{S2c&G-3D;5s= zBd{udQ5LB5`zrmVLE|oB+?5%3F%k6=6{BDSvTRElK;ddp?yd2b1)$Ud;F6#>R9Q>v zh;BrY(qx`-8RN%^DD)B;1-~FACd$A7L2m;X24)7DF9guOKy?|kXk`R5>BCr~v2e8- zAt})iX^SYt6-v|_t?Np%ZxEr%_r^e-XB2nA$V zy+EmPTNjnudO4`Sgw(bNQ{?f+JembPjGHHY#R!nMrj%7Xs)#@dEDq_v`5-rD2S&>8 zjpzr%4hKqofe09zJPoK-Wt~gc2BLv7XzNmMu%^n3S%pwV{e(oeuI>p}FfL;}@JBl zVCd|41WNf5fnFh|5Cvgkfl3-IzaWx_h*84qp#)0FPa*!!DOv)}9j^1>#=~Yg>PgR$ zb3}EZR^Z75O68U8N?{F6LUg$_eM|f?55$W~Jn3+{;9z)SReldd+GDb(gs19}{Ia(Z zDAjjL5=kl`u>MGazb*^@NT941sw2zi^LRa|>Vfg*IfK2WTNFVZ0XcPJ_BS^igyJ=y z#gg2-`6VI{WsNBv9-{-Of1j@;T&x{g>JN1Df=!fbOVmRh4##3gyj)w;h`H|FVN89i87ekpg&ZJOE~BwIU-q$ zg~Og;SaTA|!t|6HHb@>8VGmSlI0X(>1h7dmqJq5bQnaIH)NKiFK|!!v`D*AblJ5}d zUnqPSwaDtZT%c7KR1NeEyGx`Q<_BPcMRhG85X*}?xFyRYuoq>xfwqwNdr1edUJrz7 zNMDinQXPgt1{=WDVZ|a_NY+qgdD-X+?r@bi5P|PRo`!NXpfm#^R!xjWID*gsV2Q2R zd#DJ*e3nAJLqw?Rl4>s;HNGuo-;W&)Sx^!P!5UMo6KmKH3jzn& z^C(}}K!?Xb;aZqEVoF$PLT0T$yOy3X`Q*t_fnpc26p9cCfoP->G4P;2=4TERKEJ>XoJop$xPidmr_rdVq>Fi#`Ek9hTlP{0;V&VI^rs%Y_%q=aQR!rDY8w zipT`$#o$Clro&_O`RfZSL>7muMdY3cgZK*N<>ZIK`vJFMx-f!RxF#E-LnH^rh!v{I z6-2-wuRI{xBfaK3If|mfJmF;vT57&uRU48W zqMnxM$eLk!w3CyD=7$g^0U2B*IM`(@28TYe^NAnlMOKB%@%M z7dZC(Aj!@q2$qOjrTD_NP;qkDV~hRp3_~ffQ9#zRa#c zuBaC|HVI4P915Tdsf}di!U_#Q)nB6H!7z+fAmk0!3w_sMay7v>nA)O46iZ_+l<+T6 zsSM}_(ys}sRSX>uP0H;{31k%MrjS@ew<@0EK_jl>M`goHWAYJU0h#pDhg6zTKb~{7ijq)j05K!SOWQu z-$q3>{?8F|k=CrnXbA&wIM z9^6c%%|)GHgQOKx&?0P#92zdkpBg%R?TEmn894?-EU;n}vrtsQoL0(dZo?3*hJ%qE z@CL&OU@!}Mpwwb6)D=)Imlw3>*aw0WAC90iBoZkifqSbN3duf5loV-?7g0hzbTe5Z zT|*m`Sa`Gtp@MV)RA8m+WY9new!~H!i@FH>Ru-VS?3pJtQyz{{od=8oQI`}9A});j zLmnx26ig+6XLaqXBOi~~0+iQCK_#XT^E+n_W*ah16M=XNN`n0g-N{DpKU0H}q zsu2-N1=^wwry)5Qp>UHtCv<6uEGak=csQpNF3_W771H$_AuyVzt4EK^@gGgCWFc?@ zQb%xgq({Orq?h9y@GJxa2~fdd97YExnZiuC&qz5&5!Y8MgUx!hSSu!pjFCv=8x^ov z&@tX4BP7?9m>x=mcsRs7XaUX-Bcx(_(Wqb^X=afgQ3EsTQEr23LIW{9Nz%kI9%3Uz zTOt}M2fx&Yq?ZILVk|*+Lg@xM2D)JG1u>5-r#pHqE5h&?tOhs@E+bSDn1inY>^7GIDAoqNWFIAYqHB;rp_vA= zGA0XO0er4l;}e`6tsoD!y`JbAaKPDJaxHQBU81Y1>$`Cd*F%Xh3cIW=!84MvJ%Ypv7y!A#&| znqYex%oeIZ6jKJ4{A9jJ=UA1=3!5RBCvPMeK$O5~a*tBO)3vIQ&9!n?S4KhI!%jzq z2fmt^Yvvr)JL*9Kz#V*q8l>p(DyCj5-1L(&1{!}JB4)-MnK5XUCh&=+dBwa;Ep0u* zLXw3B`r`{1hURjvoMb~rv}#N-O29~?n@cWFC1uxmxtp>%>IR%DSHPF%&DD$IGRaV( z<8){>io4LJv<5mCc96n8X*bCyTAG&+j}IRxXjfk7v@0cVk#31$H3PUT=WG{QY8mgr zz*oz=Qh8y?fPW$vQ2@msV#r+1cgETjmI$I)43lv+zhXj=h)Dr6u;<1lAhs+gai>-M z@~S1!2r>~-sxoj$7kYyw;hbQ&3@OWM&SN5%his-?bCM;HOd7*{Dkqh>j5i>#cBEltWepqStv)=9G4U-jHq?mL{QzL#w5)DT%>ur$UVHk+Vc1f&a=i zTbhL|C>}5Y?$p$iuO~1mVXWp>3CS;ExsqJQ3=!nN{(8<1a!zjvtxckiVjH={h)I_> zMc_*;71IpY=-mJ`e#A70CGjc`Iv5;YLDU2$;Tmka2nj6H;SX{y+){4RfFFhW6!}E8 z5RqPoULk;_VPp-N&W7oMh^;RPgQv zMpOxJ9df=N_MnVjqwG*%MHe{%9~3OR9RwzWC0c@F`-xjo!vS0kR`AdZ{u1#Z9c)CI zBl1FOVLA)xQzk;J0w|NQr|S5RA%NLAKaP|zFDp@!6>baGwm7SZ)!Z0)n35;wQbdZ6 zCF<%0l7UneT8UAhd)8Jpa3nYc1CG*=7c1cKfeY)U;=lrPIq8?E(j)Q` zjg~{7$~;{*WmQ#H7dNzQ%(##@;gj4KUMTYkroJ2`T%fA%w*bBg45nCb~=^GkgJ|7AcUhqU1{|JX(0GT z6X+J=k7w{7T@cn&y38z(a6M>SESO{S2xr@P@tj;Ms9BDyz>Xm_tdv_oKuM@vRuwC0 z>kup826Dq_;@JNY4d_Nc5+n*iqevZuL)?TWk`^~89FVCW-ghGBns2q~XvoLX70E7X z`BmPvUec;HvFVcO5iYEbrsL!eT6f110-K={40Lg=ACdtoOA^W2i>NkGVS9sww%Q3G z$0NPEI%!6Uqwtjs!nFSi z1do#PQuiWj2^gQ08SFo_bbi)~Me~-;TO<$zP~F0Ct-427#IsZu4lRwKfWL`xycr8R+iYE{n*3N`NQH|!%J~=TgHq%Sl z1Goz^XU*fMbP2hJ=+NB7Lr((xQ;5e%^4S2PtXOUsiYhROt2t8#`(OnC!+~g*U`WqJ z!7U-69Cy$ityE)-#f!jdUf*0wno@zxm&-d)S8WZX=L~W~y?z+UAowC99H|^j#nG|j zGsb0%8yoj_%(QXirj0*(tjJhZgJpENzt8{z_36h(R0Tw2)PQEXj<<^YiLX+^{c!u5 zs+zHfQyI`9(y@%V`c<$m{sSaCF2`5hl5tt} z@B$@lB-={L8wP^D0?yH}WRGWKQ~)ANNuPk=WVO6Knr@?hgxaJ6Cejo9SGbE&e-S4Z z>+o2I#1!&+98S+A*bGnFUW6(l+E9%;NR&2IW7!@VGjKmWOFx-6#2{0L2xOJC@_Kuh zz}{z4k&J$QIWiu!&{~4M!YG_y8w{>QWK8$DycmF+{6GlH6>vexgL~hqBLDM`w?VGzq-M8YqXQ@DDx6$)z7F_pOkd#6%(WPT4MciPUu{9P^aF-$Qv>YTK*rJQfr&s`&%L`wqF-(+l?$Ek=*)A}CDnd2dZ-ohGwMcbA2eq+AwZ?u|_ULlu zPGja?NE_{cKqR~bi3ViT>g3)58H}=FSAD8#a6YJ-+G0R?lR~Ih7!YX2d~eMlGP|@I zpy22*(d&_sET$RRX=(;P(xcW=GCX+|G}|7z>^po3Ej|w)?GeNQ!631QswqP{?27R~ zF?nSE4OwICXW|S>)KeR+dGfQ z%}@b|b9v(AU&5n?*$|5d@nkSpjJOeyZGbJHKbpF_?U*)Zh9e#WjGh$i!wS}jT>3K~ znFSA)Y(2yVU^eV_@o05A8WTmM0-cDf!Vv=yw^uf@F0eY#iW%kYH*B0WI6+&fkokd{ zrHr9K0v?)ku6&aC8~Y>)m2|nMZ3N3FR33Ic$Q4Bc4a1_9gh`EIMF1hxJXwj*7ODZ= zLg3XK(4OK6NyBpNrldr&BuzPdF+AV{2XZ{=LIDX|Y&-+R95WOMhvtzVKOX_KU$F4V zThbv#tYBbPcma#_JX}29kWK+9Erl#8%9=Zm_czEui7gd5`)YR#`~7m$5xIx?7=beJ zxaFu8nQDC-L-sQkv+T&M1%(4az0X%}&@RW0WPet4PJsL}q~vH{6ZS5`8e!@wuP~Q} zj%yb79R~!ZtB`Gta4BL-wR(j+nQ9hAIY@^TNYpkz5(NSlryxC8mcxKN6#z|(f?2T5*ujm+ z(x3$EEa@*m&q_s*lCnHp8}u={!N6)@2-xV8Rn%m{^lwH&Ey0d7N-2L}_}5E=R5$0Mq!eK1y+cjL!pTSc%*nC%K^J#|u*yr>iu4sYL_|Xp7aD!~G|+IP3xO z8HGW#9*zgFa43MYe)ypOI`dIgVj$V<}E_zrZzSvTrq}> z5{Kk*FKJ#&5I~T)Sk_z2q0l73b!6>dflv}|MunJ<8;@B>6M)`ZN`aoNzLa;4!yBLy zq<>=`$d88;9tbtrqb`NASKl>IZD7SdA+0h=2M}Spt{V42MAVvVS&J?FO6Dlph7h?P z?!3SjHhAllHs8@p?nQOR?N;@QEq38bO5M^yxQE;D|I|XWAl-&4))r95bS8rA_*k(eSt6n;3@D(!&$jX4bQ>-^)mD7u zVOKsKm3MTpZectO++BiF!9wiOgG>>aVjh_5)J#2Cr*M6dWYbTWvCA=^`VlWbH=pow zlZ`m6hj4GUbr7O&CcukiAO5KEW-viIqoCuKP9m8;^yNRUu}rVCi#yYpsaTavC?=kv z{+yx^Lj<{zdgSb&5Fs0Nwg3ODs~P6ZVPY_U%L?LH7So3@-p4F!%(1RX6L}x8sU(A( z%oZ;pe4A}RIn^>O@Zh#)v+Ifi;?a$Q2;?FHbtQ60c%WZAea16uw@c8Ln4+XY%F|E_ z;~BV`uZI+nd^^y;`_HzSM?${MC3hkIZ6jUsfX#hBWLN8f>uob|%nI*>9^dtfJ7fk2xE#lf*Esy|h z9D_NF3 z)DDAkSeK#It-#@J{+TilVmUp@YBpF zo$ZiEV(2W%-F)e6Pi37tDUS$nq}T!<=v&vM{sd*X&Glg_xs>H%5jF9`FGZzss?tn*Z%_r%r}+y#CxO(_9jczJ3bS*I@2Iw}2tLh3zeA zPfz=fPB;WfZR8Q38AXgtkY?nW>@UVxj52F*5*1s1-W9k(p_ zUG4m$8_^5Ry4%U)*NoB4o|+3ZdfBKg9#DfhhLQV$xvYoXRiCK<%!8x15Cdz@i-CD3RxqSQ%IV8YBD}_<|b8>tMoD*BFT* z^8{ax;3(d8kE6*{f+UA-YtK?>xZg>Ry!i0t5#bx)lOozne4A3eHKhXG4x4S)+cxsT?;s%p&l%=R=t^Jc(dlt{;NHv=y zF`J!f8r?s~%_L~4<`8}K#9X7&k#=_%y9@<(&!mFhc6Tqc0KJo6GG|LSk$f?3l1GCS z$xd^^f{{T$tq9UTldK*TBh*Q{; z5$}*}uxb9Uq?Qs70r7ym^s_0)K-6~k zw*!GL@O#_??d}0)ZHNXTh`5nSdsr66^sP)~k-(ZyAad8Bi&@nu3W< zZjU6ao(a+mDRHFfBJ6heV7q&ei9L7^(2taQDS4qL97kVzYLt#6M%vMl++gxpgt$_B zz;5CCC+js!?A)pYjOqJDkC&tYUNsU8A2UoHZv)^E=@?mhfm#>}jce*Bw8ZSC*@0;< znbj?j-^D7A+K*gzP_dG+gRgj0oy(^4haOCbgTgBGB} zq?UTO#1L@qjOxl@OTK83(I{-8*0EDt=-XE6!_PJvSarAw6m*zIqTgn(JR26;8DP+o z(lW|ev7+RZjD!R#)G8{NityhcQg`JJonmvJY%{bMM#VXe&k#fRA{S(y{#I5^$!aHh za^GlooyPh@VzIM@gHT&gAYBq!0qG@UVAjeXneiS)K_i(*;b7|7OaPCeo&#oq4JiEO znk0a#SJ19jY5z8QFQgm>rN5+P82zHhDfVKHs0Ujk$G_^!3q3T4aXF9}rw^(vOCD$EaDXV1#eByKgcL z6JF4JD_@~UWoZrGJ~fjdOqYN%B-34MXWq9s!1pm)vw#-TIM!1bg!pSB*(6b0OG}?& z5}$P-2{&6FM#`8bU@QZhkC3S%kMS7REb_f1lfm06Qzhwac`%SjOW>0hWCksXjog<~ zj&%}L;G`W0#tG+kpL}F7CpD8|$vyJ?{cSltLmKB6aY7FbG7LGrev);Jk8Pxt3C^#LuQLw3&U~ZF|7jHQw*^%Mg zVh5;HM*h}zo8hfYlv3yll77g-fVLK3w@P3j(0hmQXX_z_4b9;xOfqX9R4S1`J78sz zI!Lh|nUxVGc>sgSbUUdZRI}(ME6H^=QXNQ#^S3{|F+zxAJ19Yg3lx#<*JQG6d<|+U zE~}E6+sB80*;B)+JGwciMMQ5QTp{!*@y!*lv@_1+37}NfT!{CBE!e)))>+4wcrx zzXZ2Uu(_`Qw`muvKb8I2uFHr63%Kkqql{ED%7DX!_~hR!934~gkK>|Ac+b?Kd=-19 z2@?(^CZ)<8)@GKM1VJk)-ot~Jpyfwv+%tK-FEb)4)3 z<6j0@cKX08k*tbQo0<#{rfS3kG@n@ws+9UBeTJ0I-6}~kL~4?qhBT8acrI}n>Y|D6 z2c_q!QgmS{JztfgFH7kk|AAFKdZ5{SVm4 z>8*gE5ow=7u8zLdVhz>eOrUlS+)O5eGUFo+BLw1G?Iwdo&3Tpvz~VU6N9n_o*{zb> zq95rePzQ(80R3>-NF5}ota!-tB|=zzHalpy!EQ?fa|E>3-EK4VV|IWM{9*(2!%onW zcKo?`ZyEi=sRnE!wsrm2G(Eij3)2IIFtHV<9}wcHL(4d%eWA02yB1Ce8uDWBhM(1N z|IdX14m=&NAkP4{(H16byO5-XyYANuH6LoRA+zxzr~RQ;;@nn?wCyBm0}v}q!u2hn zEhTm4=1C#uI*5S#;ys*wt$H|bvjioiw(qgGm)gD$fLdg-QLx|czSoTUFb<+JQhb!$ zJ{GshJutAA$?bb2D{^vsh}>tB`~y{Y(;u2N8O$z`s!Y*9CdO6UW~l%vVGTSUu)FU! z@sLEv-xe)Eq9y1%E-MVJ|DchZ)Lu6VA2JFH(ZGFKV!U%%i+G3DWYL4wH>A0vP!a-n z1-txlFHxBnCgDj+hXVx<+jCj~vD9NL%r%-&Q3vA>%8BM+9F-rEkFDWj0R=L{phGam zHBn|8(vweX+<5+jMCC543TB4;omHu)z9sV%|} zbeIrUJZSNcpk{teSaBN9v#P--pEVX973B;Iba(~yG{F( zx}(j4$@pO}r32Ft_o9?KlYdw<4zrX_pjTWvT$XmDg4RnJjI}No#Fv8KsKAvDXrMIk zC5P`=+5?GSKjdXW{GyR1t<5^eo#c>`PxUcRY6Xy<03^v#fI;Um+hG|n$suziU7+Z+ z>S=vx4++U3$z#x+`(1l#M+)x<`_3E!caS|{ODw6y(}jT^uLDwIE_pH`N-f;U?V*?K zAg|Nya?l`wE(VYS`z=g_sx!rQSin80wnmECTC#E5 z%nf>@Z$g#xBV7m)(u4-@q5>7RT>-sO1&h#-cvzSlAqAcD!C%;*BDQ1qQk~9sFiT4e zrb{}{a}*O>yNYR;Ie5Tjl!I26`q5qhyA%Rd`4|U>oRdugm{54uUIBdppqJzhltn&PC+@_>?K{|s-VYT?xM*@pQ=tj8SBNj7zKP# zrPX)w(6BX#WP-d1_b>;t&VvmUjiXu|^f{6IFlaS)gngoRMwRNAo2@9<4|2FQGG#flrnb10z?PQ zPkWG56%!?Fr$XR?&64=k49o{-46K!JCv}l$w=j*lRUw{r;@Lwpo0_2bs%JXX0>HnR zBjR7i!vULFxuuG^Wu4;}R*A80frSeUah;S0#Vzq20gLID&^V5+eQn&U+JGi|y}%I{ zLK)M_9bItv9VIf6IR(3{TrtC_@h`7#~qm(U<>YO8)9o*LUfI9Vbx-@p$igf zfP>C-fQeG+^B8P-RY%IOV(Up-qeLGvZpSw>Wnz{kv zf%&6vtV{!i5e;D*l8YYoiy}$-UXHv@IXuy-DZa*vZ;Hq zbiP?Y`^avU{yur@j3JQe$Xi*>)hrZUzzAUk%t0OVI$_W#wu1X>+u&NM{d~K%u|-D? z&N#&1MyE!#;MHpt6pl4`2(ZMMI2aOq23NI6{ul{;3717aiu+Q@7R(a~AH(581(9oU3^q(X|1ZHwZU3*}Lu_c|0QsJ$kB2D3*yUj=FUq0xGW z%PJBaUszsm(65`B_^FmCMAyPpK&$ie&lb`x#?;8tq3*4TrSR%E*?8)Kb84sfCV08I zm6t&E!T7};DFhVgbRvcYq|Qb-b*<^(K=d{`;yy;Y++lb>fci+=P$5zrJ#C_E9ENM>0NDMh1$I{hJDwdJ6%e7ru7ODy zD_t~B@N%4b1SU#&W-5Y9qxOpmJWkWmWU9md=r9elJ1}BmcZ&0Wb9ayu>P~)#tIprV zm%iExVT{*UqWW**_N^@9eUK-a0sFP&E`tUbG!*epEoM+P5G4*&cf~2Z>vRo>wytqK z)kqOZ>YMM~CP)DGkP2{rp%;zdlpx+1stlfC(auL#WP|XDu}Lo3^nJTw9WCz?oEvJS z(s0P};Y$HxD49MfhfRNpyQ!lu74iNOFA~5@2)k zZ97@=SuKZ++3N%EPlLo`U;SwH5#9!%j;*%70dvo-jp}j`fJCowK`N9kaM{`4ru7QL zn^Uy_pv4rCB=)w}1>6zwd+rvq5A}-v08k2&T)KJ%d6R7Fc8`M>8u0xJXb*7Oi8QNG ztwZpc;e1_d`6ye4t?)RENs%Q(c!7d6gKMI}%h);;mC&&P48npSkI%f|Q!|CwuRTe0 zbtA|DkeXaL-T+b45F@}sjhn1B43?EiUwjlK@d1Th-YIat%$BageXI0rrN}}c*;l&FkwdaT zRF*Fw%f<_Xj2Q*SDjZSq3Wy@s80Y{|{Gz82FX<7Y0hFTAY>ZqCyo)E&vUTqF?5}g; zlO`oy#&j#g!VV^sH`_!>DP#VvRiJP!RiqXtJ;t_|w1WF~$`*DqewmaLug0iGTSk~6 zN4SbU21<%|^uUIgB%qT+V!>v~q>ONF2)#n-{=_u}g6 z#5z-V?^UUeJ0uU$C|y^}>_?{bA!g&Exr>AYU7->-*icLT@Mr78T?*#i4*tx{vP*KG zwc0&+z$e7=5R@hAS6#7us?V3b-;zQBIY5Yer4Y%P%K(#upD71nh>t77je+QAOh|j} ztjP&0Q;sg6gg8EmH74{bQV%N1rOYQBrxx$}f+m)ZtpLZg0Jyy!fcl*kAXL#g){O&l z>f4D7J2NWN*>Bju?6`#zImpnb&MwX& za$v`^BnP5n1yvsML92>tuhVV1j+_+yP1x&%jVw@qwAX0{^+J8eNwH-|3mVIB^B=OP z_7B-BnVx78b~59X(z3xXevP1+`83*q&PlyF<|$^huD^l@VNex%W+NQ}Vt%uQS76iq zrosi=>ydu;s|9ScH0T*`y6I^#btC3B5W$?)Nuxp-dea3xn@iv z39?#^#|(8v5*39+R4xRu(af+F@nVEGrr4-gfYHa!Fi1}^j1?B~)S_q=DU^Xgw*q~u zK%x{R7!pSlbSR65#ufiQUs8?_f|HZn9Vn~8W)v81N^8S3sj`sSX_$ph((Ua+sX?ok z3d+D+1h6A4PI^HBEMTUB1`;k*XYWXg!zTrYv#K?w0Bl2h)&Xs=rO&fibmOO2`V2Vt zLyi#8&q`nblOIbETIb4~@7AYGGl*u{`@yn6HHi)sp*5F&;NJMN$ZbNN!~L1& z5)822kb+jf^+)bVzLu!utCc{?pLxJh%q!<5(!5;2>o0g9{jrB*1oXAj0sjeCRsJA{ z9C*Ht$|dFSH`ijRbFiKR9L~{%MdgPLdm|xAzplU4uWPba0dQHxg(_(Bh{O;X0ZlkU zM;p^thW4mja>W{0yb8==Ev6b0m_$W%Khd<=-8SK>0aC4NI%?lDL5$AIB} z+=9zLj8qz?I#&rxjzKC=wy6~gqWEE5Oax~>XzgTmA*>5GEl`UetT`xyY5#(uK_e%g zeJ4aOC*|aK*xgTHFc|fdaylf419(8$Q}XgxdBK-e^sP5U7?crqwB9gmH;V9A4u{pnv%jtj^z=6emdTL?ru+h(-hP~&Rvw;nBQMta$kba<@PS4JbK;FQPEaHmCdng!sC{arE)Ln4|S1|$DN za_|Sgnvp+r;D{LE;2!~?9|XW*mdgV8Jxu!j(lD!3ISc=kkUv6H3B*69$OhL>pG-zaC89z?J?@suu^q3ydcmS5KxHIbDr!!B62Ym820vMCz9G~X)4JB=W-Nx&4?6L$5}@YK0uHORIrloOkp&zK zjE(kJ!Dd`$bB#_VO2|(o6SfYc-WWY<`PJzJMKE2OU_njiMRozeH|W3sl>b3$8Ey5U zcmAjJjyfI@b{N(E+oIZ6EvljI_bm$1_D9v$$g602Jj@@E{@U?Q(JlzaV-8O90r_Hv zH>kGd{vKVol_vs44np^HrkluH;O3mmjLJz*Pa}> zqnKL&Pgl}h{F8KAk8TF7K0QQCL^~A~A^z)-i5g3?;%AD>dP9+{sm1A_G^NIJEk0NU zspso_jvN@)N2yCJo)T>K(&!)+6j>L8l&I>>>0e2ym%d;efdI!!AV4Q=N7*|Z2aD)ySO7 zs!)}yiQkx5f0L}wTnga$9tTi~`VtSiw9T2=W2KD`kx_G$noH7);HeK(sKdLiests$ z$R8aAMdyPqg`k;}ncmV7@qC-QOrm9|O@sSQfzUN@RYbDN0`=315FElNhnE-4-EY@Cn zi)p+W$2O_Y8~GVB%*Q$X*O9NaJqGqash$WZp4y&c#iOY6gNhy1^b+?IJ|xi-NzwAB zQ`i24PZumdAtc1bze(9I(*bfK)ye3`onkqh;nPve{S$nY94RAoLb6WP6P7rZna4cI zj&J|r)mWSrOACyQ1lL?wwzdK_ECOgbFu)>ymQsuGSxOT`4JD5WaLVfPpo-}Udop$CL;Pn-S|x$c-!GzV&M|Jk!|ZDHIR zSsZqw!wNXeFAaX%@VZ)l1`B>Oe!Y*zQV6Cpv{75s>Z~bi47=kj$O}z|+UXDz53&*6 zZ!>9RXeJBQWRJX2z%Y`nPEcp$LNP^&8x=YUe9CojHYSd&V`5lGyAsd?y#Oo7of(#S z#w*n57&rGQqn!)1H-LsiKO1Hj^p#90e@PghtmBj^aSi8|vZZI!iFv~Ao%9q6C|P`-eFL4|)0K z|6jwz{B*YteO6mTN0eav9GA`bF}stJ=>ybWPIphIWEvdGX;4mXpXlL~{vhTDowfKt zSk^`)+}p_+RDFaYh>!T=NLgrczj{k>M><*cf^q4K=t3h+@RmAW&pLOD4X^ho;XVt; zjLY?}=4Q18fxqaAn{BiJu5STlptm2q4{xWh(@4$qLFahkl1Cu*b;h|>`FwP6s*@HT zksUuuj=AQ{Il3F- zM4xe$bk8}7-*)H32mXMoT*M)9J(qLOR3>ZioKVkr9O|Ssbq_~$t=AaoWaPfHQD%6Q zg*XT&)12;vMjF>V`B}Po?pB`VL|u9Amil@pEe_Z5yl6yaKn^vmxIQC4M8ZySyc>lo zz~C7hkcg{1S`KWCQ?4^5yj8=_kb{Z?mErtNpvJZWYTR!FHNF*46WRj>HM*0}>mq7^ zC<&9XNJdzD>`cYhUp|OBaI92T#E_kV5+G$m&`Bz1W&iJI`*EJi)~9HgBnD1^#WW9Z zK?TidYS+KXXtcSXd`6C)IFF0{{Y0GM7!qVniDNc*O=Wn68dgS2mtAA0iE5^+Xw5Rh z$;+&lQO2qZ{i*p0fBy3$)gKtI#k?x`q~H*}ThD~T<0+|&`CGkHa6}Zu>(`zQ#SnNo ze+c^Jp|EDb@JXSY3yp0Y4P~|;n%JJmXSQ$SWGK}h6NH195)hzB%~+>IMQQ%!mrSRC z+(?&x9=H15N(K6$QEF+XQi#KSo>(fyQBI)x2F@7LaFykWvzBynIMurTdt?kPKjLcB zKfgNBNt1^74r&lQfuZcNyN{N%H06hv%5F$}0omzK5<{K4CrX|W39qAeNY03k|^29#;JXgnsjj@;akHYt%)b2KvV$ z_XJsi8;3a=;FQ~fJrCOjo$h-lYdA|b5|)7aZrg`br{vPPdVqH%Y^_$c^4Xf;Ys14t zyH&KKQ|#wqMb`~eJEiK4zz=UHz$;cgxOU# z4aZy?Q?1BHwb5ucn530gtZtauGM##(32WN;lgbm0S@}K3kYkKF_T<@fx@g5tXi3eF zjfA+Tv&vCvo;~@I2fs9qSZTe|{KJ8?TSKC*%~cq=#M!zB-72L}sK~rco$bbyI$56S zezL*%sCOEVc1`a{z%`sza2;0!B?2j~2ocNk# zMI9Vvi#~ac3s2VA&a8%@Cr5wLkvKDiFuY0G77r$uG2nPKwK9>J+VRCY_(bbOxaf0U zJAKlzcE6?13BS2*F~^DB`(T>6=3^&%&X&*f)a&`?qx>pV`R}-N>ddR1IZiiVQBzvXOn}Ha zFZ774Gu)zFryFoBRa-zu@2CnOIkFxuj8(3D#06Mr(s!bOEZ)kPIRZ4<5u*FJEZQ`@i`j{oo>~@cxixy8w*-3a=NKEkfKg0C4z^n z2j1ly?-nA}LJiG#1;#twj^%>e6&mk!JM-P84uIwU7OAPXJn|eA%GU+zwdJw3IpOq7 zkt84AFV^=Mz-2ZXl^$`M5|kBW+Dx||6^R8)McuvTNk zSm+%_Ox!_KbQe42kK-+tuht|S+I@LycIM%MojJ4^K{aMaKxDy6VdR zGd-Ye7Tl+$Azzq(B^!-li@~hehXyWQBIk@gg|hw*xe!zN{O^SGAbU95JP*=^Qy^MDu7yLPCDxflg^v-2{k&D*fo^*q0;ibyWFXCb!*LAWQhUNrxKt_ zRrn;=C7j`RvvwsRI{x^B#I+g6n^cEBMv{fW@}{@(hDc}R0nlc=aojkO$@*rR@rL{w z;|(@36zXm$nloMiSccIJtvy-aykj6uTws0kp7Dm}*ZSsN;|+Z`X?^2&Y78iZHQr## z2eac-0Y9Afe;N4-;&kI%PyP8J$t8c>sR^Yj@r2UQ3b){#QRctL@WkvZ|0MFCYN%Ka z7wI)pk9dVy2h)t;ZwGO7Tb0vYX{;)+Tqi>=wT$w~czSbSK-DwB0k&GRGRx3KfcdhI zjgDR8Uv$C}t%@D3$F99b!yx2cbf%#Gbm>JZhyzD_3aI+CRsIx}j4n5&lhs-oA~jeg z15lzJ8|gm?G7vXMqRv4?mx-m?ccQZmTUP@>ndS(iF(qG>;R0coa{eq}C-8{*dT287 zVC%1;59AT;@j#(hapnij)AnM#y_${V{SX$!u4skk$a%(U< zJy?4$HaTiFfsnufBZIbHpd)7F{uK1yVDBKB@-l%9lo{BNZY=3DbZ%X%-ztyPx1bm# z__|#+9(X9E$6(1ql7rpW^HTANFn)VJTD7D+;`h^Mukuuv1X~hr&z2i@SDX%4KrDv`OZLa#xL&9N zI>Qg(LENz!7n)N3WF0Z^E-z(1L1qySkXpe~nwP9!pf9i^=QS}!#rC`n9!n{W^#t!UET6FFg2 zm#1L}74Z>{WQO!9n7=R$Zg@&gcf{$AVyPEnj>$`{ysX7V>ntqaLfKz9T!^E&WMHHhmiaYM>sHii3j-x0#Zp^r$s30zg-~w)t z@At3jKBxPf^WJ+C&~Luyf!urhbXQkZS65e8S67Sp%X@>%3PdF)Qgb6bnHoAD-X-n9 zT9az+R;`Ohmo8X-{%DyRYnzxIgPvH9`Io#{aW!W2577X>F!b!5cs0p1-;q6DqpN{jD!uD{v=y-nFGCPet${6P4M-r&lz0EDNFhwv4XLs-?S2nU`P2-_5U z#e@j|Q*ZF95=bGy{zhTJj$YElaEi)AZnP|G9EN7 zuI` zrHj%c3W=sjDN$)d8bYUxHvimHCMpf7kxdq<)Zu#ZeEv$x6^WbII{V?)bU zot885cAQv3N%t;!X`HI;U2wf{OK{%urAz1VvOLv_j5@FzzcDnP#eHnXlTK z=*>3t-X{id{g0;k6s_#rl&k`-{KPV(&IvAM1r0=@nd81Vod?IFce^U1$OKmV6rBo_ z!XVbL^fAsbJk{?Gu4&RP(ba_sD`%73f@;%^xRbo6_sDA-+2Lm+d(E?W(CO)6S!g=L znx5=UZy4Hi22J7Lc=hysJQPHnSy1mqTOl8#%NCX+{Lx4hK+bK)hxnparEqCd7`cQj zXf&#Pi=VTEJXxk4B{T^Gj+z)Ny+`nJJtUt8L3F1UDira)aLJ-Ytu^-Vi=*J7-ri$= zLgP*0zoPhtSbTDLDQmbWL*kmq9uV9v9rIWFEx3L*w4sI%?Q22}ji5`E!O-tisFWZ` zNKRa=5VlW;j!n#tH(7~Y9$x_niR2?nZ!wlJY@9AB!CV&YUz>% z=b=OXSkqC(Y%`7MoB*{beu>I_pVrsFD{4epOlrJ8sbL~j7-;Ju0;q9nFN>E=Pb%I} zQ}Oax90i8j=!Vk^l@k%n6^1Kf>Cwfbau1ws@uaDuqW)pQm;)qicyTENu0Hl5P8iq5 zs`iMz!2uM%^#UuhFqhNYv!@(4Q^;NrkzM9qH(#J2DAP=|Cmn({SQ#5EPa8mLV*?sq z;2KK-7FY>d4>$3L$R5ke!1t9+-Ua(vzzdYZB4)_Z4xx}c=`Sg;BjTfVQ5iL@&gu5SbX1`-8L~xMt#~rRgxIFp z`o%}k&J7GW9^||zV$@W0iJ8b^^dO0RK-Ze3_)Iqrwk?;i_otNVbw_wK!RLd5+Wf~5 z0F&#lCtn+QD2jO?Y7?Gw7@S+aO%<20=ZH7}z>Q?jMjOuzex^2AwS<|~r&o&|9pY+^ z%eZhY5_DuH@OH8OEJncCy+%c`x~1nbl@NAv!4A}MCcFI{BYHlv(>-?M7 z-RfVZC{pm!A~u3{YrojI$?heo80{?sEH%oCW*qCRFzF?&1-79VnsWqb#Qd$K*|I$G z)YRWRz0-$SDv&BOZhm&iG~$w1FS~Gb$I`oUGLK9m|J%o{1#-h~N-KcENuu-vg!Flhq+mDsl;#7EnkW;S3^G4UqC7JUovw4>FWhsTL zG5w=$&-jTRh6km`1pCQL|5c^*bPQ7m@tO~bAD(9-h+HR_UFJGTzLf=!RrOcheA0vjUn? zF>IuRfG}8O2Zsb*^MQmLLCJ%>cX7BrtbU&LO`nwEz>BpDaIZz)WR#GkEti<#O>RbD z2!)mvbWX$+432YukpKeE@B9R;l*+(L6BGJq-$|3iIABlr$+{$Hd^kcfpw2WJda=$% zBTaY_#_nLgxkb3M6Ml#BgHn1HpOqg2dKV?dlwMYJ5A#+ChG*Fb*GO3yExS)ot-4D^dP zQ)XL;x{c?n3~>5U;~N^|c{zH%Z|hrNoeofaCinfi$Ey0N;=K`&!P^BQv-Q#exlmdqxWP-vS?! zA^rC#Unafpq8p=V`*Jjkxq(dSbcP?>F>T;6ch~jT^6+Zj=iNt}2*T%WC_WC$sP=#S zGtS6dTJNZ3X!?TVbg8%d4{w*?{6+tMrhorW|4y(;b-87#BY?gh++rB->P@~>1NmhK z`3V1hlYb`!%BKqdE-rnu&Jb4tZ!@sp_Q%Y^-6B@CoWf5V9-pzQ@Aj%+DUi;qX4)yR zd9^oro@d9OUWJ}g$r8r69PJIbLM7pJjbid6wGuVT1KMB;}<`_3vZn&eB!0SFzP@C_h9Fve|$~k&);}`NOA`@RDe4${m zLz3YfA-!dikm$th;a{6a)=ut@TE2RjJoc>rm`7I^?xna@z|sG8_eb;5>=t}L3LC|r z>uv3I^R>0+H2kkx!$1TSeLdWf(xk0ZZvjjC1Pl+zO;0QC#q9`)aPqN}qxDSBt44j} z*f)BfmSNlW33^No1Mz6yV;>u3JGF56{H04<*C*i&=1+NYSA(FXT5-^c6-Xb;HB)Y z7aK0oo~B^6;aoihMo4IKngO^>0OHzY-cK|@khk9!yJ)I=67eDHj)g}0N-nuW6dyJp6FaU#ul}UC;7nE00KzH z*o3LzYYoA~lE_CXk`oFn&b0V|*`2}c(rHFp(_~Jc%VF`*rpC+O70r8Ss3pP)U}xfn z_t#skUnJY*(zugPfh=Mp9wv zhI?fE0>Io>Xl^No6DbbF8Q}SmjJI*PZ)Cky^xDzAL`7K=gj>FmBzNvR$^qS@_;{25wrxG zaabn5%am4U@LfO1)|CtEW~xHIw_?)OFJ0WyGZkt6=1>=EJUnx|*2rH#ZA4M{9#m)c zc+>rh0452Q1=uaDeZ@e#yCA7Yg=+jG(L&DpQ|GT-M$`)Z-eXg7^5g^c`*h0+v`uI5 zy})qzK#;@>MaINjAOOZT3L8#3o&T^m_(3t+>&b-2=S(gf30YUzh6_{}rXy;T?C05}xCq}sUnCG}GL zNZP-|)JzYPwzXuTR-C={&pxgHvB^HCJ@`>?swsnT)$B)%in*Y&C$2_)s$q^M%lkjg zjt^;o+njjnIjpMr66x%?@Y(|U(FFr?|SjJ<4I#ecGE+6sxg5gb0%9#Y4y zBjOHKO2L>&!_-Ou6Vg`j#DJOUss?an2xj!}B)b&U%6!mnSzoAcx^scux}#8e6h{e| zT6645UOA`cAG+GmW=4nGRN-BSJA%u&@Y~T5p?9iO@fS7v z+omTjid`a&MA78wlW0=d0QRI}v<`kP>tKB5L6P3bC`azHIPLOwmzgU0i;QhYtlR2e z*3rw0arFBN=0b4oHVN`!Y!v$y`VfJwGSQ@DicN{+y^@vjOTDgDO&kb$m}j`f7E_xq zNp#4$;Z>FFHRZkXS40f3#rbcP%9%xL#>PrjFpW;r}GcB zBJ%>_=lXdtwXT368lPTrFRZC-4u_P>SBx&3vqC1ps^VSJ+s#!`F_M1J8D=ATINes| z-iINFetVV+K~Jp5Xf^H7XgmI(V|+8)F@_D#g|@1}cz3UUw<@$v3`VS`dwPT44z-$+ z79e{!lEnPCm1CN&ae%6h|NGw>Y~OHoCTR@gWhW1O)7}~U3rppWB(?4h{@feJyb=3>8h$yvBAQ5A+6qE4d5anxe)uLuDA=Q1Mq^3~Zo5 zTvQGoTu;QGQbYXO;*OGg0`@3%gI-vS1nC*XjArP+)(C2CG+37rG;^{9J(v&#BYGOP zd)99t>UXYQSJ0F4{&j|GXQM%TBloT14x>w(Clc6kc@L?alrsWiy+x9(JntwXMwa2F zoZmViQEM;vHQ4=&hv_Z{UOMcs?nbhm5BibF8XKUu2 zBn)c`A?G&vE%b^;E<@hk?PYgyMNU5_L0QCLdFXo9-Yb~6*V;1};qb=3M=5QJ(E|NN zW-(gSllx_L^VZ6I5gbLf%hMKot%UZhUZIQ&C)w~=yuwqf&MT)fA)}zb^m>Iwee3j; z|9Z0te&eEYX(Byw`OXr*;+aVOCx+^rvYSxLh(^}^&S$xh?{vSK(g4Od^j%s^zack9@ z)~Z#l57|60#eDXp=K);ed57Lc#ibu-6TQo#;Ny(JM*0|MeXF>l??MTMp)L(~WNG5B zjr}z!{lG@hmdnmSB=JE~vsOw6m$!m5!zzbNY#Hp(c*9yv2E(M&(AQ*J)yA0iVl2$s z8Kt-xs%&({QOj4XK__0)dYhdy9UG3R!uv8;w==o_7nX_^n3jgR|*U| z#BFRO`h!{;N>8jjm}RXt>60vp){pFyiiw|__cya`DN%a-wPm=$;D2q^-`b3S|7)B6 zqZCiof3#_#{$mce$^B^S^096iZc>3TMkukL;WcuxcMOqtG3x;oNPm|UJ#iWa z?P?=5Q@`$Jl-jSm+ud&a^-1<-oJqs!{)da&!Br! z35bc%>YqHc<|$=OWf15;V`$A&%bKsi(CnW!tfmi5_B1cbgTZ@Nb}@@GMj~9$PgK?! z<=q^?124x zVQ7g*>>`#dFu&NyvR~Jfzg}YT2UhyrPzv}<9lRD~z&}4MUoX&4bFtZvg}~+OtQ2>B1N2>#V!_OeXx%`gyz*%bWXe z8rsjBhxDV+%Vh8J<{|wMK$#d76*mNQZm<5|+J8&hzc0vHpt~2nHN{0{O`usXEG4+a z%3^e&ytw;8(eNm_1k)5o&~T5_t;YU4`fqpTimxFqT<^+=OqUijRmD+YMs{Q#;;HNs-5UvOz?9yNu|M^*=f(qP^*G zqIVV1pXh&lQbd1ZLx{#Pv_V9ByNu{h_WyNKM0?XAL_aDV{@;A_&A#2Kldk7;FyCjx z8}r?Hr|C$BjfB;(3vP{D02Ip;#ortIpRRY(pjd7ce+fEg+Dy0oQkY+70%W|&bmO=z zE<$Q+lgZmUGXlTR|38x=(3=h?a7PjN#r}Uxioh?X1RgN~fnOX#;D0s{=yfv!zuf=QqzLq; z!wGzX2>eR_rb!X_m6X7bFd4!Ko^7;NM(`^}U@)>xhq`H&PB4!|Cq}zArrtUu`Ro0! zO^Rf1I-KO)Me;ZL|1~L+zaf$ddpDs?NR~P<>c2U1sKz|_66vfXh`+`t~B;>mUT zyxw{vkeuI1S#JSlQ`4gnukec^Kv_Po^An``Uc=MN3^jU#UD1MeU<&@GyL14@LD_d3 zzv}<8CP!Q#nIl&v20urb{@H=bRkcGn|GZjZ1y9jGF9Z?GxZJ-tjTID{C!{ed4K;;<*cDMI~ca!>>ulG8`1vfp}qZi!+YCO#C%!*D2~>% zn{q#d3*-&G{YBBr`x{lZ5HO*>Idb>i>wMZ9VHEv!t>91uRIR1^uD4r&6FUh^}2RUu220?*Ff@jUe`dDrJ=5YEK36p2C^(wUG5{b{McyF zZXa$@d9Ajx2Mju1Y!`MzQMYYA^P-58_Fj7+?+aiyu7KIN4ki=pp6N*yo zRFr|4QUNoi0CVM)S2~zbl!8%F24<5A7|*br@hTJn=8=&o6_sG%l?pf-+_W7=@{tv= zk1Vj0>===uD8)`i8CVshU^lCP-K+px@GcakU{#cXRY3}N^9tC_3$O*Yp(q8bq71AG zQm|W8z;021EwBwmDOeR{U{#QU-Le99%MxtlZ752?swe}if)wml6|h^CV53}yq78bOc6a#vz{?zz2~bv^Ndfur0WZoJ8+Z1o;;o& zAk5IRz{;7l2&!fI92@TU?EL`*7`trx!+;gK&p zwLK%i#fAZ3i$U7Q*=5fyd9&ivzR9OJrb0FDFWdqhj>7&LMrTD^{l9J)QuwgqrLTIEepGPAu_0b!HD4?&ZnA-pH? z?FY&sp77qUl;1OBtU*5$&HEIS~hyo#rkJWYsune%U6zG zM1C_*FHP5A#LKRSwLL7$3wRIqa1|goM=*P8BAkT@ZEY{L`pqb&#glzn%!H;mMatK! z_O3kvzJ62WgoiLi*!eqpnx7Ke^P||NX>c@!Ap6L6$mg^7WaSDz9?{ms7U&<@Tc<}5 z!&Ds=U?0_9OMrr1_n&LLJGvbnZD%&yCgoDYVW&boXtb+`a`~*^CH-S({-AI~uG8wy0d56=ZK44A3n8%5qs4V*c5#aV$%|+=whDx6 z&d$}t*3)@{6L?RD7c6OexF`-z(36v)m>*g}0319V+jm(GvOJTl4r!uKsyf%_(hl`5 z9pkB?c5to5SL*C%K%+vB>wtU>XPFOWs9!R5SfrqGhs9kc`6VLs=xTcPYzymodVvcR z3e%#(g;WqzcclgbBJ_26O$^apoTA=E{@Ctk*a=Fz9v-I}>`1evMt6v#a)uOnUKH{h zuvd4`sMQM#T%$V`U)M$MRv|lcfmX-}M9wR3${It;Adh)=)*M(~X$iSA@lZvo>>f5P z|1PhVLx$yH13n@N^GF;Lsqr%YbSVDyx!lxiQJ|dSra2!wVRHaDOq$d6Zmlb96MNEA!G> zURu=E;vy;9)EgzKn+;U@S&F~!%~!P*%DTvsCi}Qd?_X-YyVPHwEMP8SEF*r|6%)f$ zT^!CyHp5Jb%^)gUKEWi|{6$xRwcwj#;wHal;S^uS9s@Pp4Y8LZY;yX->Q5IeGHVUD zLXvw(EI2-{C>7{M=jF0uIfAL?v&EO6xWI&LEz^=i5l?mlde{VXv?thkWB%n^@%u2E zXu}=nqMCyf0cHq2tw>Bacy4=eNuwSKjhSbwhv-n4|2&ic_R)f*s}!U0`2gtkT*1k* zi+aAWJy>0$42_eK8+ff@9fYlr4e|31udi5R$!krqvW-zwwl|gK%^y7BjKk9t17gc7hp3)^XY53=d z&VJUs`$^JaJ-Rh`As!LW1)^zS-nPNz&Tw1n_B18q(eLt2B5 z7NOf4eH0EuL*<;|-x&rL>iIo+ouTM}VsFJ=g$8E7AY(SIkfGDs%0=Z{lbrp-mM13M zW^ux?Bw6;$YG)u4PMhD_pu6ahfLBrxfgIAVX zCz@~=Ttciu;*+e!%iDvO4Q=s?D*ZVv;k=(a6mgNz)k|YkUNLMp-&I=7>8Sj|lTs45 zhCm>1E-vhRB2+CsMe^6H+_QPL`(}pjEE!l&_vbwwxL%9ggAeQIXc2y21tOHDEbzI> z0?3dh`w&zllJjcGm$Qar-sV(&rGAY}vsb046V&oBS%y=fO#3?Z`qnnqc_ zwprFy9Aupz2L?^@WwRNemoiOR=JbKSU3tAm)_D=W1t&vDp&SxhJA1gl3@7)kb8?Y; zP7*m({x65C)M>|AI;1xQY!od+XK!#+E01Zv#^(K-g7YLiicX5YnQB5FFJV9o5r2el z%IyWqr49yfF60!FND>`t1(MuZ-GHQ1SL}Byt!D3-?Fso>y2I!OWl#5JH7FOT^OAp2 z{IUEkMLCVd|EL#yaoQ{KgB)tIA=aQT{-y2L_>=c}O)&C7ep_Jc7mUeo&zb!8Mkb%0 z*pNfXMh$RfR$PXEqOT!^)2tu-o)@4Fr8cp`OuocQ_pz9)?6bsfp`4f*)q&^W%Y zXbb#9o?+a>V z$Xvcm4&?qK0m}pLz>2d+0S@_PQ=Dycb4-Hk4pvhQz>UW^B5pdVjKk+TqO1vMdu|0% z>*@ml^45BuwL~72{>M3k+ZphbvDo>q?ZGF4S;!sBLTsdg>CRNB{CxhQ zj#AM;STMfQ#vxnp!EUt3qX0S|_wOcjLxl>hFt2eV_eEc0tH;GE26pJ;KZ77XU`O_Z zi*t&8L-P@|3c`Q^R<*M#0QeHPjDM~=_I#;;Ge9P34b>UTN_Feq<5O~az7^m zFl}sYbnDL*KF4;-)8rX5nnr{_@B5d&-;zL@^71% zd^Z=9?>36bmmeP276bLYg7r2~CQa!MSJL&pxGOJG{z7&tUTFi{`LZjg(GVHo%fqy# z<){HnN_CF%%eJ)sky5gh{#)TUV~5Dv?X~r#sYd$T12uXAb>Xp5A$;@o$A#KHbl_@gqJF zNMsZO#Pf&cXUj)^ISJB>23GRJ_Ta}!3B>8FZSX_N5U*qWM>uM;lQl=;2R=eNRHOE7 zkuV0%qB4IHA~YfF5r*bZFh1s*8S)bcd7F32Z8|MWH=EZ>Wpql7VrCmv`}wi_?&-m| z%eY7SRodBX(Lov(3E(PU84Mg+@an*!P>E)$w=1AtX#@?2DtgW~>A%#-snm2h>VVh< z;W0ri#a=Qy%m8=Z|I~GuCxx6B{Y1`?aZoq?G0)kKT@C`_kL2(&>tG+di?(03B8|gv z6H$nPBr=NeFM*0dKYNHrN$=1qbz*~{>EspJyvk3?%4pxKYSF$|IfVrZ^c95cIdM?Z z?qLHh#zQczF%&<}c#-v`3J~4w0rSNqiUkNiwe3r%b#ZG=>%8{0TPfG!#;w+450^OF z$#%Kjf@$OKuA(&fYP!!naalJ~$UjI=yZ9u!x;=G@{@gkFGd9eousEAFGlO)(W+97Y z*;}RAtcuWvajZ3~Ai06f%BQ9?+TzK3J{CV~ld6)fWRZPTj~yZt-W2sJew-cRgg0vW zk*I%1ss2Y>-!i*`Z)Wq*Ebr;|_F66#wp&EQpUra>Q%!T+!HA&Y_e-br&)f5wtkj>k z*CGkL8NO!4sNTD{#kP0X2TV=b(&wF+mduR_bS_9U|>@hi!W<7^jO zPV;c`ocdq4d4DINe&zC|qpb@}9cP1I(9SP+VMk47?XAf{g$ZwX_?U2kr?>z% zF~z^DU{jDR7&*zm-C&Y`U(uR7NDMb>+w~O}6M9N;{X_HU{Gq*;`;esyI)DDk^NwD! za%@fOrn(ja?)BNNmv@-#|HLvI>tm(^H&CfO-A=fqXr-Hr1=eBPjXC7+k1pJgv}rt^ za3eP-G%26^a;Y4?X#KvKZ}(Tm*Z~wmk{Gf>0Q@Ozv$yU^QT|zbi9moV zZjAUdjNsePz(ouZXM-h`dhhj&jDoY{C7iTXc@QzpCRf_-ZvxBkRUY*CW_#F!9*(DC zRR#~bt$L&qEvy5rk=KB*`y$7Rf}Ez>f+Pu$kyA9U5}_|SCqx1mtMrROhDTJPYZO?8P&&v3cACAKXT zJ!KN<9f3!w-M%g}QG`4aR(hpaY!Vi7PTV30&7~!TP`3hCrBR}GZlZ)#;a?qWpjV>OR6+!PXnHRE@a@MC^bak`6=4t}`64Z<_*@hlto(A7<52hDdE z32#~;3)FTYGGZlImI|!ofVat#9SzL_R&CXs=cw3Ran=GaY_RhH(I!@`6;HOT^XeQ z47r4pCq4WV?<9e!e`>cnhw87yx6EJpo%EeLM>x9rw+elj!`Zj@(IwsFa87CrcR1&j zer^;WS#Ft{DHcIH^6s)kpMAbWOWOqZA8DWO{v+-0shM(B6ox(i-EG-W+&0d>8>1TVtND&XBIY!)I3l(Z2VkE2m~||Ub^fFq$JM3~9-zL+-4Q!= z5Z|PegXqLwR^O>}!Zhh?n=ivegND0E?4YQC&F=~RtU@z7WG0yW!OgB=;j4zN=4y7g zjyxFc7Oz0A;-R$GD|(`0_l_?j;k<2k*UXjkwkbUs6AwAOk?s;TiBQxI>4tM9ZVZRl zz+n1CR3jRK`f*yqWEAElf30 z#JRYX1dl^ zqvR3{3i4_@<)Xiz`?6no%ZQ7QRPuLZD{S@a@t|pqr2*~CK|aTwYhy5^vTj&h<@@zS z#R4##SsvLR=ggArqNdbfPv3coW3&vXnLljXMr)?<+RLrR^r3@mWj>tT(wW6xormkp zLWY6u3VPCI6o*F1`s_+uY8@XOu$H zxYm|r$4NSbs^fKlkKxiXgUV%!{X|h7jJavOTpDLCV8%T%hS3dG(j!^9g3>X7FrLBK z(q-ShNlYgn+Cht{^(Var(y|BrOm4}R3eO&6z76@;G?E4Jaz7y`lRtwl5C-kAKRv~U zwn8!@V(WoqB|9W90Hifig7Hy-?;6eTQt~vO=zzGe%6A0< zh_WmIlT#(;yC{fEJA#MF{z}l2mNTj&l(vNaAuX9n*Tm?X6e1g)*O4o%Gqtp{Wy>vm zP|R@DWiSzU?FZ3=BJMh|E6%hB%Mb7Ey|N0A}ggx zR4WCy01_t3mu#XqqG3Is>5c*%LJ)UgXK+Zz{L~Yz#k{T>>@q`pP8{FalU|Cq163yy zh6H46x#rJ9!=k&T^>SdRU&5D-v)WEA(IS2}m-F_pz}qv;v6wSKn<%MV<;nV1R}>uH zsY=K=j5pEJoTW}>Ud3UERe0eG=trzK^yWF4L8pqnDhBSwt`PGElD71f@rbmX;_Z{w z%FkhL2pKxrDfrr9?2c(VbI^@X~^u*yW# zhg!1nR`&AE0 zr+nBz@U zsy&$HjvH;Rea>nLggw&tc3ScHphv^z(G`E9?9F|Bd?y9Og%wzRybFD<-wdShRF3ya z-DC{X8ob;{Y1U@cC~PNcOleSfj>34BP6|XiYm*6}JQP$4dYbiT4V7?xAs@e(@}b`; z%sii8PYrHf|0`eN*Eb7S6wwn^j$@pGj;Sy1s8MWlkV{m7 z9}&i=yBbpBT`^|&ip1?9Rg#bb2*0{Ge3xi9I^CC;@_9z5*P1C-ZPkfKpQ_<4G@=LkU1cRFVM4uZU9r**!JU?N$VwkzJCsDKX^~D8 z|N7+%u~j*2o^7otbTe!Xo98#1T>Es^eif}h-sLMC9j69ork*ZfKQ%%81wA$N>c%;& zO+Q0!VV?;V^pvo++>70o0-sdf0~c&h&0phykkJ%DghWi^)RvtVYrlm{;0%qq`OxOE z_*5Tr#Y`~DTdfPogLc^HtAZ0mS-M8=e~8Lm7<_dO7tc-$p?1khQ-FZA{u?$84chgo zVXgk>(r@R(HyzzhH(_93pwP!SI>C*j8lYy`v#5DW@Zp|<57(LRw+$@d)v+y99o6N` z8ZNOmB0vcb5j>}M{=~Olp$fk>7Bu|f?KgjSO5u3fhdz@z5>`=oitSSIaA54 z;N>(3G8zS)l7mt6{0Nb6&qQ7r@kAaf*)fuJAD|(2k9g*+2mWwjx&!;zbkbJr6o9M! zV)(RrcF6MHRNRzw($hhn5#mQ*;+l82meQk=AMa&bVM$4^2f@EsY8z`ftzR7o&XQRbp5;@nxHOz|EMz*`rpH{30mrjL#*3ke6pe+CD>hqU z98)f*+c762$>a+?ujy)p#_wQL?;vu)K!(gpF3d`4kap@r8#aMWy_zZO1#{A*qfET^JlfwoIu27oP}^4m^{mk-w~nT{Ui_Nlg3H~G|_Yx|y0*}jMKqntWDVL+X^Wx2Bw zMGV9c;ze8gGkfn~oO)szK<|kY6NV-GbK&T({Wyce20f0vdnLn^HDwkD*BHcOPR4)J zPsXhSg&^Mz&{xuPw|)#FqgW*CB6Hi5GN1eT5ERSiYIF;UmM<4{r-6HwJ) ztaqX=hJcl8fuj2~IR58CTgdnmGWohe8T%8h2f{Hm*VcOMB+HHE>FR&Ml=A64$Csn> zWe{4Qj@J#xFsS?k(`eCek??+Ka(qoBdGDig8iqZ%kL->x`RlMD%l@bvk8+C%4y#K# z0t`rsf*>fac9Y>b_mj^}8T<8loQ(bPvrs8B_S+&*rYZ!Zg?`YMVvG0`Z=_ITf!EkM z-#_y~x(q8fdB%jUs?iIT8ZiOw%pTgUY6K4{r30Z zDqYW*Y}X6|{0VZmNlor*4mNNmUiLpE=JE_sc(?&X`}NyBNt~>O+bVRV;)N^kz|{{i2xITcbf&^*##DI zazv8%@EC|+hFypV-(&XE#WGbg=d<4`KEFdwLuR+`asqJbCYFitLoKVTyNnHW#fh@+ zi@mM}tD&yV#RBeWURRIGH`G<6ZV7jHuZu?Wx{tO^YQ#6M+d|9Yyk5~6Eb|GuyyGY5 z7xhp?c(L?ycJ1rHO#5CE5opM46G$}PBYCLGf# zt^rVyz)k>6DjaSo25|G5_TcE57h{go3I+z-+`JsAd89%NKQz>el)R4<8UGz zq2ksB_E2ir6|L+H|BU>bOMO-6aGTXzGnfpYZET0ago>5e6#N+T&FU9DZBeqR1EsgE zMSwf470Z__8`JZy^T)o3Lk1@EHg+kojA56`bSuBwoa;4vQ}k zm|e}I6&$~7+|jVc9Sy0M8?b9aN}XI}`M~iL|5gRI_^<|nW^{jE;ux8U57q|nCcS9Z zcv087wX>C7V*qBwSF4Dn>G{xRJu|K}y$LDdw<3&D)>Fiy-|_38l{5P17iaYKIPHAc z>CaO{k`N$Du8sQb{w^nsYtk&uZGPh(r!jMNX>g;I`J%=P7iehpZ-#>*Qj9&~U>PcC zLWL+4;kKn$&p(62UxjpMY-K?23Ilol*W;AVY$q;>IKtV8~X&&13>h&$_L@>wcCF>1-MXh|s@=p5=Hr^JMky6gdq-{XW^hk2| z2+k7t1=?jVkq8nN%-Mk3Oh6>h1f)9;!-=d|Z2%iS=)%`t%}tsRn=KX1WvwPijg-X0 zE^Uk(0cvItd=myQg)6Vh3390SS|?ag$>p6or)JNZWy?;LU{Co;Dv=ao=;dJTKK6ew zAL2=@B42*!tH|B$c{T?wPRBjn{-^r1c~J=qkrN!6ng*P>X;_bTwe=_nUD~T>hC7TVW*03u+vOSx-qN9DefNCQ=*6e!X?L2e3Wz- z&2*xQ6cKM5HL`=-!PJx=p(&wJ!xrwc&f0AoRQ{@!3s#J^cC&Cwsis61o?#+&Y0Xdr zFA$0gf*(I##zh2V>W9XKQ1%Khd%cxinbn(@mW6tp zcv_M<2G*HLA0pi)7y@Lqn#(~vq0jK3-bU?1X|j7M&6956bc8-gZ>9Bncn`Z~J&a$y zI&~o91D=v%_ZT`wQ7ZjXNw)Atvxm8vpL%P~a+Q>JOjlHgJ(XL5B6VXS>OP}a&*tJm zoaDufgX~vI3FRMBE7dtDH%?lKc4mLlCl#8N7iQU2oxwkqW|>!}E7OEcR_Ck6F|Mk7 z1cgN%Pmp-=!X=9qwbt0bJDKJQrltf+hFT!l1$O=qedh36mTCFJ9)^$~`enV!@D zSje?|botV z!8&DCU`In)sr79^V%EofsZ20Pv~@a_Ticj9T9)1PJX@My+kE})IUSGqR%S_ZyKZIs zk!w7}_jUf`TL1BS|M3R@ah?BoqyGp}b*u*iul2$=`HwgIkALO|NL`crP&g5?D^st_ zi#fiTCimoZosF-%?mdUS@w)4-n+Dy3H^y5k4?!RchT1q>X4m?TZ4ZlgH0;(6xzH6s z&6*9m824}L4A#0>1u;C9A!2Cx%Tg>4{kVy0g|9)pLsR}ro7O*WQttEd008D+I`a&f zH+NvRl~k~(ms!r;d((#++2j*vhUlMBs)JxM|OWLh+=rt*A>ecsWZ+5)j z)S0?z91qJxZMxK1vI0K~h+RiU04)$#nBDM3yVe(*0E+>G326|ns0Z8$^rCrE5^0mV+!U%KHkq}l5p``RL0IU&!5K1~CTHF2 zi*})}yj>juKPEWlZ|dVM^bs}W8~HtI?wVRdXZot`sejaty6`6YBwkMm0I&5Q0j_)& zgD17|%(~8v%W`b$-Dq*olji^kY?^KjpB+Ml4+(c=Ek>&rhDAS%1HPA3cRGY)&CwFP zk7wD#r7|;M7xnu-t~_kdM8$pciq3|`rJHi!q#t|BP0cdrm8M?9DLn!`?<;y?p+SiAj*dMw&wV3M$5I8<0uEOO&gRiM(q zGS>4)tdj@qZJojOrKtsC0i@U)r%jW|_11AruG(3-6LY=U9u^WCMXR8aj+5g<{!)lx zgX#A6&e|!u73%JOwu_MP4({29v*>poBBE2jFSxr@Q=V?Tz5LQRBGkbo^S12!BF7Zw z46bG;HF4o7*i-Sl(^9%S3m^fVW=kY;!Y#T3){W&NN<`!<7MM~iBm-7;I*iFTLBUYpE zE49L2Yw*=hXO6i?zXUzRmsbp-m9nvDM2H8{PmTF8YId~Y5-YggmTr`j>I8{Qk{z1vm9RoWABN% zXDiazIh!z6=fn^<#EM3?_|_ijmTfr(w41%MY~&r!GAmSxu#JYSop+cUL7N4LVGpGh zfT%*Oo#mauH#z~3|M_2J^PpC!9DXc!i82)dX>^n&U!hhAH!L~oFw%4>v6e;h1+K<@7EnVj2bniA5q?XLa^KQQy{Y7FXQuWQC^K-%dRuJ5f^zvKO zZ4fRMgIo}^W>SYVYlv;CY^jz4B?uj7r_Y7rJ zjbuUR*V_D-7JRic__j{Vahr%R-!L|dO)0bAaq$fI9hODC1Nyg^SkgyO5c->9y@{AP zJVI4|{I{GLg&>vnE36J5oZ~U8-MZQvUAf{HY!mjJx&IvowDd_gs*f~p9way=1w)&za3&+lB-8kaP!!8Ej z;=X|Ip|zZ0lb8|A{4GMb2$PyA^8IST4?2S%s792!9|odbFNHj4t`L5RxMMK9Pa*f{ z&0BqyktYWIX7bW}!sxrop!?`d=!Yn_IkLt^6i#F*NlZ_o_!Z-{N!&70W~5LAx-Od+LZvcB#`Gl|*tRW#V@cE=R7mSV=C`uY@bn`Qp5Gj~k_YZg zShlDs&a^IY?Y=QTZ*|H`UPh$&`6F;7R`KSW?>X#iH{X0SvGS}b9EM`O+#2nR3fO8B z@&3gRY8+vQrhMVY0>0Y95Dh0RAXl)Efzhh#!xK_e|2XXE{UQ(*DTvV+w7jijxmH6< z+`N>1&m_nPRWOUeQRrC3;bhP^TA+*H3J4et|I$G){p-Tox%)FF4A!Uipp)! z%F&7o3ty5kOnD!BM=nB*F#3WNrBAFWUq=fG64MH@t;z}-b?{VVYJ{N5wF)VOybD1{ zvE+AYt)O-o&}$#-Cnu(zqEzcYIibNbB*zP!gAZu_k{3@J){XD>BuRD=@VB^vKRIsXP-tkKoyIJyoyRJa@I z6pywrAz5d7Q~Ye+d9j6TYNT1C+NKF+A2@@za@f1Nl1juMOC3NbqoyT_MR`~BX|$j*@FXXsq*k7mkm-Qf70 zL<6BQTjXcNv=$5n+47HHnUs4iAEsYW!k}Is9hUj%{ywC!Tc(F03y?!*=R;5j=-S*f zKmq%M+*RmsPVikpoFCtopWzR|dljbgAIwr^D$DN=(>UNX5TTs;?B$$r7Uhi- z`Hvc{ID%>oFb;k^U_0crE{jXXv$%VmZIYnTP*EDd{PlXp8F*!J**?rP_sL2jxOKma zEhqdvc+f1=lrV3qI@#ZmqY)=NI)8d1o{5~;VmyvqCROQ1CJb7lSavB&Dj2MB z7WSlSfK?3f{m~gHh9OtmH*V+u6!;hXSAU{zga1m!z%O_AyUKrcQR|%6b5@UyX;YtX z=9iAnzi@QL{AI*c9aSbXl*JXT_dhpT@8W&Bb7S(CJ8)*_Uu^po6(LQ-ART)*;TfznsO_4?CIv* zbfarMb{lFgif~;_F>nsSw4ru!h_2qNvmSWW{`9c18lU;F1eJLZ+aT&CA>BMtr<~&WOt6pI>$knJFY&U4MO- zeD?WR)B(rgqm@_`Nx=YmmWRt91byBlnu2Msrd#S+Y#p0F03SOMdRUZ?sK-3(`?Ubn0_vmBeh z`K5bq&p~*%i~e#L$!hxNj@*|YEZ5)YCXk3rGbS6w`UX?G!#D(P#6buJCYjpTS-;lp zc%L`GjbK9{@DL!Xg4|`cl0Ml;rv{Yo%Sm)%F1~gb%f#H>9sL%Uu*d}SmE3sajT15< zHXPz70nZ^{)}Qo3?9jUp1W#0cZm>x=dn{{{Zlm5+F?f}F7mqC`xfiu=Fmc(mtGRnn zb&74-HAz(>qhjQJs%}+&Va*wh>ld1I(=Pv^IO&a_nh1~VG7;k3qy`rmH|xf~skXw+ zI@=FA^v%1q4!5Alfaa8J-Sso+3+FFgJ=%JcUUTrpc+0NVsmjR^!uon7UGuUKsmDMG zNIlxnHmp0dP47Mm?2B5PI=!1}k6aXjxbbHjYBF7Tc4=mJ0@dos_2!r?X z^f+w}{%P3uSh3C7XuZ(4X^F?h@;cuFmfLoDYy`$W4%Nx9;;QgJG=>S6w-%Q3X9lE)97>BgY+}qvaFesNct_Yj9W}$Ndz#%@VKrvkWpp1urxr_ zcIcTFJP3_6CLvLrTS-SEkcxg6hKfz}M}<}jUc)eL9){^orA;+`H`uB>n3fDg8Pe&p zm7PN}Sx~#&&cFzpZkLgDqnQo3jMzvkywap9wHwEYIdWma+sw{!xt+#z5B*(j*%We=qz3}Hc}xE}zX>9;6P z1@TM)GoUfXk(F7NZi~5NQf?mKE0WV&^iBnslA1fr!`SoW+%_GQc2w{&o0ZJ9$_GhZ zgA6^U>(>KTtQ>8<+rs>I=nf{YW1hftv#SBqyQGpZw0E!~@So8=qJn&wVwT>R3e&q; zl+}%P9x|h=D65?4&~8W9b~DN;ZhN!+*qhZaekIt5nbwG(<;^eVrw`?jnzSf&YQO+x zr}bI-d+@}rrC7BX=mV;bolsvFUYcn+OJ9m{Ou&QVwH%O2_aqtFJd)^on}~$>6a&fn z`^Ye*^7VJ8eEr=CVjA{6DyBoNzu-qfKEZW7ZZPWE6a7z6I2D|$pP4U8gD1;7Y z);z6OOp__1r(>JCgwcklMuf5ZJJb$ugNMk7)+ z;JRB^p(CHR286)7A7c;KrrB)G*Y91sijD?MB|3ho0rHEE0WFBd?+|Z|*!D8HGA$T; zq6oaQVb8^G0~{4hxv_bY4{5k~^itjU^h*d6V%~%+aZcC@6XB}OWgW-I8IJnKRMWZ% zldWFB4KHdmb;F0fWHKN-`?&1HW_x$pt5LjfmoKvUY^YpcJ-H}T4~3vnd%y1B$zEG0 zoppDOFjl|LdlZ#zH1@QDGA@lu`!Uj?&xxcASS}Eujc{_2R?g(mVZ>j5Bli=*jGl=7 zgMOd`x+(n)K-u3cfWK+1`qN=k+=qyM2owD!UjFWg9lQ!p-!c9utzuB&)*rL@t z6X(>|ELl+NRhdQs3vK>le|c$KUcxJ5uqN!rgT8@LVKdiFjx%7Fc&}7hU^hfM0G-%+ zcC{(?=0kjdgq6v`t4m&hwlIU`_*j4fn5m8qbgz`F5wbbta7;%HS|Jnc!3-Hqo+992 zkFJ5D%llJgk{%ZKK~&fo8shvokQFRc2A_kX-KZ+m4C;BC?rg#v5hl|vGlvV)OcSQH z^9Z<~pjA^`U{-2FT0&6W$RUkuU8c?FpM zqW)KSUMmHN*s^(Gl~Pm6QF}Nv)30%YAML}lv%`5@gj0)k2##cOV-+%nk$7CAiGF+# zxin+xrX5ta8C1tJ-VGMJiW#!tG5brnX6fdZUl--;QzeVVh>b8}#UD>|W#lAkI|I?t z9YxESIgsxN@l(5YT40Gfx4pv zMdl~rxVPi@O~-M&8Z4k}jOYbmG*B+Ng5BZHL*x(x5H37e#wobv!h2%Z*T)lcFTzJG z9n7D(t7TIl<%p;9IMHX&pIKimCg*vHg*P{y9r}aGJFlBgkf(bMIno%qlOr;!n=f%E z$=m5PL1$>@m{VCg6qEa8aEWGpq<2{D8L_r)SWFfZQYyXI`vYt;xf?s75Nl6#og%tS z&gOJa&^XQM&YpV(9Sh0w+Rp?~p3yC0Yz>x}6qXKiWzX$eRLtQIs!Jx1a|bVv?W|8N zcGjj3cg%;GC5c9-nX?EqPJ@wgDLvH(IP4a0S|8A)S=b#cSRV`)C(Lqe%%*F?<~ieI zb5&+uJkPLM+#M`hA8e}j$9T*c9Uq-&NavDuQrONcX`OGo=AHe7r5GuMweGhwSKu!7 znupo8jhkkLd`qiw6HR}A4jHq!7me z*siX#{I*CF+ImSe+A={3YlXQ8lHGjctTd&6ZUm#AIq`Zuc~sZf~|7sE4Ip!yE$6>rUMyvXBqw7ax{(r}_)xK94q+Cb8hQ+ivqcm}?#k3f!D;tBf53 zDgQ74%+@kOCLTRdFP2>K6(~JHsg^SeDlezeIJZ=zO(Wm2vn`ToKB#_T$I3Qh48jq? zhZDUYFTp$`DGQEtO*#y!=^A4iPfwT}YMigpMEqs=Z&D6H_`0miU5L0W0Kl{9J8w$> zp_zYwq*D$^O{5@P%WZm7p%@mm373HgXY?;*6gam{`qRi2ue?HSO$zeW<`&P1wQ%{^ z{KczUKkkWvA;r~>L;>*EiM3#Wd?hkFjC#QgT5a3A)S<$+3!Lq#gXCqlg3c#GGrAKj z|CGB_CTdb>UOXU*F#2d_`tXFC|h_?`?&T z1hmm&66`A^aEhNI{?=2cJFD0u041GBxF*#?5(RoTI`{hidox(dSMMVzV zL<0i)tgzYTFdfugTLym@EcH`|+_CI3l`aHiW`1Ub%eriq>~cL+#*e!gT-f z1pl$he~j@1gW|xLeE^f?3Dt9WffSS(r#9B ztXm410aAFIDf;QgXiCC+NeXf^x8!u!yuUZ2XO&xO;X}3o#7JPgJh+Wt#-g#6#I#wn zF)SNP-GZ2Us1a5Ds*gSy2KGZ3=uZWdMM}A-DdMT~*>z@^U2ljhrvrm| zGu5iH;-Mp9v3$eft1+zfVk#W$NsYWp9iG4~g9Sx5VbWO{H$G3jOwbNT8dc9}lSp6d@c6(NmjnkmWj{%Rf7z6f} z7~Cs#)JZ}M-5@AK2AEZxQ17aUA8gY5`+qXwdnC(#G+Zpy0L0R=wr<@(!-d_!MJ_4( znj`<>?kr8U$Ai$mX+{Vz5N&J1&Jmw|ZcYZXRU6KrWjGbN9GVI{m(~HuB>_k$+Tjt= zB#H$Ncx0cL?sxJH;P*TMu-!euU4*Il4OYr*e2Qx2Ci?`4Jh0Zbg9^>S+zEHR}-*f{#^ zX_E8fx;jNSuO@XMUng*(C%9&t=c2K`*E3J&d<=gn4tGv5!#q?;Gwe7zb!%vw;WJFG zIB&<`JpR>Wm24R`54L=KEo`V zY};g$El?CE8_Tsakk z=758#f(>JysE}6`x*$$sg(sDwFj*-CW9f{cVmJwP=kv251zcIvM#Gw>i^Jub#$d*U zY~zN7EG=8#g-k4pYO$opxqDfcBpbtoFz`00;Zg`S_~|1ts#ljHy1cxrRXPe$ycv%tScc57SFJU89%$r;pReTBr`@pA{ ztVi^cbQm#&<|BDqw&~nE!h!^PuWT>XF1T1?^M&bd6LZQj@z%I0>J9ew{z7ok_DKus zmSIIHior|v5_Azbz1BnLiT-7Ny`(#MY1fQjzWOF6XX`n^?!3laIGaWtS~7HI;4+Y> z8@`*mMIR1XC}XwPEYb_;i75biLGVPmMGQ0y>p50mIp^la+ z9K6ENbnw&>gdqo_R}>da<@TqCfIS`AE&VH8f18yY4;ZFt4{(LsCj2a2@m^sc(&?9g z#0HCXQpLy#{ZgJNgf8V(PitC*1QHH#OI#7E<1LpzoSrmbesF1M<`#z!>>ets9eUn!XplZbgSQplUL*O8;2n(7i?Am!(1JTitgy)-6j_H^zFt zvbG$>t?Y$@VoM9ZxcQ!LWf_@QA`J+zcC?Ib%>U#|?w@^E^NluVU3~mhNDh^K{FXif zzzYQppzM|~AI_G}C}ZgFBVazP?nH^3>^`Ewe%LH2Gy4H}b137-m)o<7eRDU0xy5{l; z2)xS9qYw-ex_zQJjEw0wvueiQflbC993*2G9UE!chS-A$-nN?L!i@uY5~5j%2!`$wBOYO+Jhi_wnftZG#nfl63V$A4ZCre!`Q(iVoY$45 z8&s<&3~?ur%~Vb%Wcrx$FZNC|(@ZyKOyh7yl&r~^wr2&Z^KNM4 znJMpft+aI(*4uK%5?I(EJg*AIQiC<#%m+-*iK#c|PDcIx2rtx+X4LO!u!hM?XtGaA zGsYvm4-=OAyb}pa)Y@*A?qI`IdD1YE63ohTx@MIi6v4tcN8SSdR5dgQLFLBU+*Wyl zFDLhQm7KrR8e6h-v^BbN659RrH}0ErwR0?EdaruJN^B;n4Ql$J$Gi^H-hMS}}j+{PW9n-NZV&C{q38UPG8F zUtI`K>KQv9>!Wp+v-(VaASULaRNq$HhKlO;j>1VjA0o9&R2mh39k?VC0K-%~N_JA|r*GnqgC-@`^~G=%5_wQ+mZ|nn^!E z7;DKeAnlWSGrlP8Vb+8DI>_xgrLbO{Xr{0qQVvB)WT=xYLdqM5(Q@irzLez*{B?Nw zlGoqAVY2o~_)Fs{id9$?hnoVQ&^H=k!Q5ge3M18kaNJXSgJ<-7Xd4ojq)Gu8oVL8* zVw!Z8dfNECaMgWEtN*$FXI&di61Z%n8ogk9Sy;Nav`%e=5Cs#1rs{7EFWH58@JU+$ z_Gu3!&_Q|-36$BsMVaJ;GWrVH>i219r<^C*0<3HQ){y+-;Y}tB;845pmXQ7~OlGB} z;?vv1;er0dm#0T;;o!fNxBWvsyJi>_&57KIZJ6j|ZI4I_v~l_h9jEmww2g?44&~N= zcyTNIr8mRkeD)Fc7qr6Xos<*~(Rm`f3}c7oG&(*RZr?BR4!nQ1;4gcaH(yL@)u>+F z(oN)<;^*cA#&HANnEfg=fzy7-EJ`Mz6 z;fssV={}V6JM&-x>HL7L&-~CArt(?6!I?dCL-v!|HhEU;RK_m~Fcj&aDN1ALYsmPW z-OYsZv%|;F-9&;8*P58_U&1UY2F+QVo_tXP?ZSttR1710ct|2)sZknc-E(pR?{6d! za^~kUG}8$c(HGkUayr;NfIClRnWiw$aVluG#8R_?34!E-FFt>nX?)O|Vi9bp_m5!B zXwDk)+rfu<1s|9xL9xzjn8nrBh?$nM-7QJapL%Gg`iA=3>oiR-^Q?%>^NzqseYFJbI8Hu8G zy{wAV59&EMnTKlj02#)aTu$03e-d4lQy(e&3G>&3NK9c#h@cf%yMaW^FrzRZa0hK+vlC34^&F64{zMd|yE+6xT^knsXXZk3na;>+ z7HO6Hrv&z%0((ILLAO^EZRecggEr)II2*2i*bg1mpie49Ign6y0)Qc01(JA>9*}q9!mkGTj>~w8`CKbq!X!Sqs-kpQn zhtE_LfHtE2uPWX#89d)iXTug9X1MCNv(Sy{Bg<$S&h_!g@GIo-^4K&5d|68H(Y7)h zP6!uV3CV2+tQDpN9K~>v*1q`1;&dV0Hu-RU?~q5gzA<