From 4b1a3dff296aa9681c92a0e1afe113f3c523cdc5 Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Fri, 2 Nov 2007 09:28:00 +0000 Subject: [PATCH] Potlatch 0.4c: bugfixes, history in progress --- app/controllers/amf_controller.rb | 141 +++++++++++++++++++++++++++--- public/potlatch/potlatch.swf | Bin 74324 -> 75471 bytes 2 files changed, 131 insertions(+), 10 deletions(-) diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 950fd848f..9c8d4cc6a 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -38,13 +38,16 @@ class AmfController < ApplicationController args=getvalue(req) # | get response (probably an array) case message - when 'getpresets'; results[index]=putdata(index,getpresets) - when 'whichways'; results[index]=putdata(index,whichways(args)) - when 'getway'; results[index]=putdata(index,getway(args)) - when 'putway'; results[index]=putdata(index,putway(args)) - when 'deleteway'; results[index]=putdata(index,deleteway(args)) - when 'putpoi'; results[index]=putdata(index,putpoi(args)) - when 'getpoi'; results[index]=putdata(index,getpoi(args)) + when 'getpresets'; results[index]=putdata(index,getpresets) + when 'whichways'; results[index]=putdata(index,whichways(args)) + when 'whichways_deleted'; results[index]=putdata(index,whichways_deleted(args)) + when 'getway'; results[index]=putdata(index,getway(args)) + when 'getway_old'; results[index]=putdata(index,getway_old(args)) + when 'getway_history'; results[index]=putdata(index,getway_history(args)) + when 'putway'; results[index]=putdata(index,putway(args)) + when 'deleteway'; results[index]=putdata(index,deleteway(args)) + when 'putpoi'; results[index]=putdata(index,putpoi(args)) + when 'getpoi'; results[index]=putdata(index,getpoi(args)) end end @@ -230,7 +233,7 @@ EOF " AND current_ways.visible=1 "+ " AND "+OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")) - ways = waylist.collect {|a| a['wayid'].to_i } # get an array of way id's + ways = waylist.collect {|a| a['wayid'].to_i } # get an array of way IDs pointlist = ActiveRecord::Base.connection.select_all("SELECT current_nodes.id,current_nodes.latitude*0.0000001 AS lat,current_nodes.longitude*0.0000001 AS lng,current_nodes.tags "+ " FROM current_nodes "+ @@ -244,6 +247,29 @@ EOF return [ways,points] end + # ----- whichways_deleted(left,bottom,right,top) + # return array of deleted ways in current bounding box + + def whichways_deleted(args) + 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] + + waylist = ActiveRecord::Base.connection.select_all("SELECT DISTINCT current_way_nodes.id AS wayid"+ + " FROM current_way_nodes,current_nodes,current_ways "+ + " WHERE current_nodes.id=current_way_nodes.node_id "+ + " AND current_ways.id=current_way_nodes.id "+ + " AND current_ways.visible=0 "+ + " AND "+OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")) + + ways = waylist.collect {|a| a['wayid'].to_i } # get an array of way IDs + [ways] + end + # ----- getway (objectname, way, baselong, basey, masterscale) # returns objectname, array of co-ordinates, attributes, # xmin,xmax,ymin,ymax @@ -252,8 +278,7 @@ EOF objname,wayid,baselong,basey,masterscale=args wayid = wayid.to_i points = [] - lastid = -1 - xmin = ymin = 999999 + xmin = ymin = 999999 xmax = ymax = -999999 RAILS_DEFAULT_LOGGER.info(" Message: getway, id=#{wayid}") @@ -272,6 +297,102 @@ EOF [objname,points,attributes,xmin,xmax,ymin,ymax] end + + # ----- getway_old (objectname, way, version, baselong, basey, masterscale) + # returns old version of way + + # Node handling on undelete (historic=false): + # - always use the node specified, even if it's moved + + # Node handling on revert (historic=true): + # - if it's a visible node, use a new node id (i.e. not mucking up the old one) + # which means the SWF needs to allocate new ids + # - if it's an invisible node, we can reuse the old node id + + def getway_old(args) + objname,wayid,version,baselong,basey,masterscale=args + wayid = wayid.to_i + xmin = ymin = 999999 + xmax = ymax = -999999 + dellist=[] + + # get version (if -1) and timestamp + if version<0 + historic=false + row=ActiveRecord::Base.connection.select_one("SELECT version FROM ways WHERE way=#{wayid} ORDER BY version DESC LIMIT 1") + version=row['version'] + else + historic=true + end + row=ActiveRecord::Base.connection.select_one("SELECT timestamp FROM ways WHERE version=#{version} AND way=#{wayid}") + timestamp=row['timestamp'] + + # get node list from this version + sql=<<-EOF + SELECT cn.id,visible,latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags + FROM way_nodes wn,current_nodes cn + WHERE wn.version=#{version} + AND wn.id=#{wayid} + AND wn.node_id=cn.id + ORDER BY sequence_id + EOF + ActiveRecord::Base.connection.select_all(sql).each {|row| + points<<[long2coord(row['longitude'].to_f,baselong,masterscale),lat2coord(row['latitude'].to_f,basey,masterscale),row['id'].to_i,row['visible'].to_i,tag2array(row['tags'])] + 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 + } + + # if historic (full revert), get the old version of each node + if historic then + for i in (0..points.length-1) + sql=<<-EOF + SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,tags + FROM nodes + WHERE id=#{points[i][2]} + AND timestamp<=#{waytime} + ORDER BY timestamp DESC + LIMIT 1 + EOF + row=ActiveRecord::Base.connection.select_one(sql) + unless row.empty? then + points[i][0]=long2coord(row['longitude'].to_f,baselong,masterscale) + points[i][1]=lat2coord(row['latitude'].to_f,baselong,masterscale) + points[i][4]=tag2array(row['tags']) + end + end + end + + # get tags from this version + attributes={} + attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM current_way_tags WHERE id=#{wayid} AND version=#{version}" + attrlist.each {|a| attributes[a['k'].gsub(':','|')]=a['v'] } + + [objname,points,attributes,xmin,xmax,ymin,ymax] + end + + # ----- getway_history (way) + # returns array of previous versions (version,timestamp,visible,user) + # should also show 'created_by' + + def getway_history(wayid) + RAILS_DEFAULT_LOGGER.info(" Received history request for #{wayid}") + history=[] + sql=<<-EOF + SELECT version,timestamp,visible,display_name,data_public + FROM ways,users + WHERE ways.id=#{wayid} + AND ways.user_id=users.id + ORDER BY version DESC + EOF + histlist=ActiveRecord::Base.connection.select_all(sql) + histlist.each { |row| + if row['data_public'] then user=row['display_name'] else user='anonymous' end + history<<[row['version'],row['timestamp'],row['visible'],user] + } + [history] + end # ----- putway (user token, way, array of co-ordinates, array of attributes, # baselong, basey, masterscale) diff --git a/public/potlatch/potlatch.swf b/public/potlatch/potlatch.swf index aec1b8bc85d530711a1f817be469520a86f8dce8..13016113593a68ece8860b1893215f29b99c66af 100755 GIT binary patch delta 16282 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 HL$CcmEhQ=s -- 2.43.2