various ruby bits

This commit is contained in:
Steve Coast 2007-05-20 21:10:51 +00:00
parent b56b9609e2
commit 07cb7fea1a

View file

@ -1,5 +1,4 @@
class AmfController < ApplicationController
#=begin
require 'stringio'
# to log:
@ -19,7 +18,8 @@ class AmfController < ApplicationController
# Parse request
headers=getint(req) # Read number of headers
for i in (1..headers) # Read each header
headers.times do # Read each header
name=getstring(req) # |
req.getc # | skip boolean
value=getvalue(req) # |
@ -27,7 +27,7 @@ class AmfController < ApplicationController
end
bodies=getint(req) # Read number of bodies
for i in (1..bodies) # Read each body
bodies.times do # Read each body
message=getstring(req) # | get message name
index=getstring(req) # | get index in response sequence
bytes=getlong(req) # | get total size in bytes
@ -51,7 +51,7 @@ class AmfController < ApplicationController
results.each do |k,v|
ans+=v
end
render :text=>ans
render :text => ans
end
@ -70,7 +70,7 @@ class AmfController < ApplicationController
presettype=''
presetcategory=''
# File.open("config/potlatch/presets.txt") do |file|
# File.open("config/potlatch/presets.txt") do |file|
# Temporary patch to get around filepath problem
# To remove this patch and make the code nice again:
@ -78,7 +78,7 @@ class AmfController < ApplicationController
# 2. fix the path in the above line
# 3. delete this here document, and the following line (StringIO....)
txt=<<-EOF
txt=<<-EOF
way/road
motorway: highway=motorway,ref=(type road number)
trunk road: highway=trunk,ref=(type road number),name=(type road name)
@ -141,7 +141,7 @@ viaduct: railway=viaduct
level crossing: railway=crossing
EOF
StringIO.open(txt) do |file|
StringIO.open(txt) do |file|
file.each_line {|line|
t=line.chomp
if (t=~/(\w+)\/(\w+)/) then
@ -159,7 +159,7 @@ StringIO.open(txt) do |file|
end
}
end
[presets,presetmenus,presetnames]
return [presets,presetmenus,presetnames]
end
# ----- whichways(left,bottom,right,top)
@ -175,12 +175,10 @@ StringIO.open(txt) do |file|
" AND node_a=current_nodes.id "+
" AND (latitude BETWEEN "+(args[1].to_f-0.01).to_s+" AND "+(args[3].to_f+0.01).to_s+") "+
" AND (longitude BETWEEN "+(args[0].to_f-0.01).to_s+" AND "+(args[2].to_f+0.01).to_s+")")
ways=[]
waylist.each {|a|
ways<<a.wayid.to_i
}
pointlist=ActiveRecord::Base.connection.select_all("SELECT current_nodes.id,current_nodes.tags "+
ways = waylist.collect {|a| a.wayid.to_i } # get an array of way id's
pointlist =ActiveRecord::Base.connection.select_all("SELECT current_nodes.id,current_nodes.tags "+
" FROM current_nodes "+
" LEFT OUTER JOIN current_segments cs1 ON cs1.node_a=current_nodes.id "+
" LEFT OUTER JOIN current_segments cs2 ON cs2.node_b=current_nodes.id "+
@ -188,11 +186,10 @@ StringIO.open(txt) do |file|
" AND (longitude BETWEEN "+(args[0].to_f-0.01).to_s+" AND "+(args[2].to_f-0.01).to_s+") "+
" AND cs1.id IS NULL AND cs2.id IS NULL "+
" AND current_nodes.visible=1")
points=[]
pointlist.each {|a|
points<<[a['id'],tag2array(a['tags'])]
}
[ways,points]
points = pointlist.collect {|a| [a['id'],tag2array(a['tags'])] } # get a list of node ids and their tags
return [ways,points]
end
# ----- getway (objectname, way, baselong, basey, masterscale)
@ -201,24 +198,22 @@ StringIO.open(txt) do |file|
def getway(args)
objname,wayid,baselong,basey,masterscale=args
wayid=wayid.to_i
points=[]
lastid=-1
xmin=999999; xmax=-999999
ymin=999999; ymax=-999999
wayid = wayid.to_i
points = []
lastid = -1
xmin = ymin = 999999
xmax = ymax = -999999
readwayquery(wayid).each {|row|
xs1=long2coord(row['long1'].to_f,baselong,masterscale); ys1=lat2coord(row['lat1'].to_f,basey,masterscale)
xs2=long2coord(row['long2'].to_f,baselong,masterscale); ys2=lat2coord(row['lat2'].to_f,basey,masterscale)
if (row['id1'].to_i!=lastid)
points<<[xs1,ys1,row['id1'].to_i,0,tag2array(row['tags1']),0]
end
lastid=row['id2'].to_i
points<<[xs2,ys2,row['id2'].to_i,1,tag2array(row['tags2']),row['segment_id'].to_i]
xmin=[xmin,row['long1'].to_f,row['long2'].to_f].min
xmax=[xmax,row['long1'].to_f,row['long2'].to_f].max
ymin=[ymin,row['lat1'].to_f,row['lat2'].to_f].min
ymax=[ymax,row['lat1'].to_f,row['lat2'].to_f].max
points << [xs1,ys1,row['id1'].to_i,0,tag2array(row['tags1']),0] if (row['id1'].to_i!=lastid)
lastid = row['id2'].to_i
points << [xs2,ys2,row['id2'].to_i,1,tag2array(row['tags2']),row['segment_id'].to_i]
xmin = [xmin,row['long1'].to_f,row['long2'].to_f].min
xmax = [xmax,row['long1'].to_f,row['long2'].to_f].max
ymin = [ymin,row['lat1'].to_f,row['lat2'].to_f].min
ymax = [ymax,row['lat1'].to_f,row['lat2'].to_f].max
}
attributes={}
@ -235,7 +230,8 @@ StringIO.open(txt) do |file|
def putway(args)
usertoken,originalway,points,attributes,baselong,basey,masterscale=args
uid=getuserid(usertoken); if !uid then return end
uid=getuserid(usertoken)
return if !uid
db_uqs='uniq'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquesegments table name, typically 51 chars
db_now='@now'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # 'now' variable name, typically 51 chars
ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
@ -244,7 +240,7 @@ StringIO.open(txt) do |file|
# -- 3. read original way into memory
xc={}; yc={}; tagc={}; seg={}
if (originalway>0)
if originalway>0
way=originalway
readwayquery(way).each { |row|
id1=row['id1'].to_i; xc[id1]=row['long1'].to_f; yc[id1]=row['lat1'].to_f; tagc[id1]=row['tags1']
@ -261,10 +257,9 @@ StringIO.open(txt) do |file|
# -- 5. compare nodes and update xmin,xmax,ymin,ymax
xmin=999999; xmax=-999999
ymin=999999; ymax=-999999
insertsql=''
nodelist=''
xmin = ymin = 999999
xmax = ymax = -999999
insertsql = nodelist = ''
renumberednodes={}
points.each_index do |i|
@ -484,12 +479,12 @@ StringIO.open(txt) do |file|
ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}")
way
end
end
# ====================================================================
# Support functions for remote calls
# ====================================================================
# Support functions for remote calls
def readwayquery(id)
def readwayquery(id)
ActiveRecord::Base.connection.select_all "SELECT n1.latitude AS lat1,n1.longitude AS long1,n1.id AS id1,n1.tags as tags1, "+
" n2.latitude AS lat2,n2.longitude AS long2,n2.id AS id2,n2.tags as tags2,segment_id "+
" FROM current_way_segments,current_segments,current_nodes AS n1,current_nodes AS n2 "+
@ -497,9 +492,9 @@ StringIO.open(txt) do |file|
" AND segment_id=current_segments.id "+
" AND n1.id=node_a and n2.id=node_b "+
" ORDER BY sequence_id"
end
end
def createuniquesegments(way,uqs_name)
def createuniquesegments(way,uqs_name)
sql=<<-EOF
CREATE TEMPORARY TABLE #{uqs_name}
SELECT a.segment_id
@ -511,14 +506,14 @@ StringIO.open(txt) do |file|
WHERE b.segment_id IS NULL
EOF
ActiveRecord::Base.connection.execute(sql)
end
end
def sqlescape(a)
def sqlescape(a)
a.gsub("'","''").gsub(92.chr,92.chr+92.chr)
end
end
def tag2array(a)
def tag2array(a)
tags={}
a.gsub(';;;','#%').split(';').each do |b|
b.gsub!('#%',';;;')
@ -529,9 +524,9 @@ StringIO.open(txt) do |file|
tags[k.gsub('#%','=')]=v.gsub('#%','=')
end
tags
end
end
def array2tag(a)
def array2tag(a)
str=''
a.each do |k,v|
if v=='' then next end
@ -540,57 +535,57 @@ StringIO.open(txt) do |file|
str+=k.gsub(';',';;;').gsub('=','===')+'='+v.gsub(';',';;;').gsub('=','===')
end
str
end
end
def getuserid(token)
def getuserid(token)
token=sqlescape(token)
if (token=~/^(.+)\+(.+)$/) then
return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND email='#{$1}' AND pass_crypt=MD5('#{$2}')")
else
return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND token='#{token}'")
end
end
end
# ====================================================================
# AMF read subroutines
# ====================================================================
# AMF read subroutines
# ----- getint return two-byte integer
# ----- getlong return four-byte long
# ----- getstring return string with two-byte length
# ----- getdouble return eight-byte double-precision float
# ----- getobject return object/hash
# ----- getarray return numeric array
# ----- getint return two-byte integer
# ----- getlong return four-byte long
# ----- getstring return string with two-byte length
# ----- getdouble return eight-byte double-precision float
# ----- getobject return object/hash
# ----- getarray return numeric array
def getint(s)
def getint(s)
s.getc*256+s.getc
end
end
def getlong(s)
def getlong(s)
((s.getc*256+s.getc)*256+s.getc)*256+s.getc
end
end
def getstring(s)
def getstring(s)
len=s.getc*256+s.getc
s.read(len)
end
end
def getdouble(s)
def getdouble(s)
a=s.read(8).unpack('G') # G big-endian, E little-endian
a[0]
end
end
def getarray(s)
def getarray(s)
len=getlong(s)
arr=[]
for i in (0..len-1)
arr[i]=getvalue(s)
end
arr
end
end
def getobject(s)
def getobject(s)
arr={}
while (key=getstring(s))
if (key=='') then break end
@ -598,11 +593,11 @@ StringIO.open(txt) do |file|
end
s.getc # skip the 9 'end of object' value
arr
end
end
# ----- getvalue parse and get value
# ----- getvalue parse and get value
def getvalue(s)
def getvalue(s)
case s.getc
when 0; return getdouble(s) # number
when 1; return s.getc # boolean
@ -615,22 +610,22 @@ StringIO.open(txt) do |file|
when 10;return getarray(s) # array
else; return nil # error
end
end
end
# ====================================================================
# AMF write subroutines
# ====================================================================
# AMF write subroutines
# ----- putdata envelope data into AMF writeable form
# ----- encodevalue pack variables as AMF
# ----- putdata envelope data into AMF writeable form
# ----- encodevalue pack variables as AMF
def putdata(index,n)
def putdata(index,n)
d =encodestring(index+"/onResult")
d+=encodestring("null")
d+=[-1].pack("N")
d+=encodevalue(n)
end
end
def encodevalue(n)
def encodevalue(n)
case n.class.to_s
when 'Array'
a=10.chr+encodelong(n.length)
@ -653,51 +648,50 @@ StringIO.open(txt) do |file|
else
RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
end
end
end
# ----- encodestring encode string with two-byte length
# ----- encodedouble encode number as eight-byte double precision float
# ----- encodelong encode number as four-byte long
# ----- encodestring encode string with two-byte length
# ----- encodedouble encode number as eight-byte double precision float
# ----- encodelong encode number as four-byte long
def encodestring(n)
def encodestring(n)
a,b=n.size.divmod(256)
a.chr+b.chr+n
end
def encodedouble(n)
[n].pack('G')
end
def encodelong(n)
[n].pack('N')
end
# ====================================================================
# Co-ordinate conversion
def lat2coord(a,basey,masterscale)
-(lat2y(a)-basey)*masterscale+250
end
def long2coord(a,baselong,masterscale)
(a-baselong)*masterscale+350
end
def lat2y(a)
180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2))
end
def coord2lat(a,masterscale,basey)
y2lat((a-250)/-masterscale+basey)
end
def coord2long(a,masterscale,baselong)
(a-350)/masterscale+baselong
end
def y2lat(a)
180/Math::PI * (2*Math.atan(Math.exp(a*Math::PI/180))-Math::PI/2)
end
#=end
end
def encodedouble(n)
[n].pack('G')
end
def encodelong(n)
[n].pack('N')
end
# ====================================================================
# Co-ordinate conversion
def lat2coord(a,basey,masterscale)
-(lat2y(a)-basey)*masterscale+250
end
def long2coord(a,baselong,masterscale)
(a-baselong)*masterscale+350
end
def lat2y(a)
180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2))
end
def coord2lat(a,masterscale,basey)
y2lat((a-250)/-masterscale+basey)
end
def coord2long(a,masterscale,baselong)
(a-350)/masterscale+baselong
end
def y2lat(a)
180/Math::PI * (2*Math.atan(Math.exp(a*Math::PI/180))-Math::PI/2)
end
end