From 63e0486ca13f2fc444eec195105727f52b25b06b Mon Sep 17 00:00:00 2001 From: Steve Coast Date: Thu, 24 Jan 2008 16:03:56 +0000 Subject: [PATCH 1/1] Lots of documentation updates, plus split out potlatch libraries in to lib --- README | 44 +----- app/controllers/amf_controller.rb | 233 +++++++----------------------- config/environment.rb | 2 +- doc/README_FOR_APP | 33 +++++ lib/osm.rb | 69 +-------- lib/potlatch.rb | 189 ++++++++++++++++++++++++ 6 files changed, 278 insertions(+), 292 deletions(-) create mode 100644 lib/potlatch.rb diff --git a/README b/README index 7d3fb4c5d..70a915804 100644 --- a/README +++ b/README @@ -1,43 +1,5 @@ -INSTALL -======= +Documentation +============= -* get rails working (http://www.rubyonrails.org/) +Try `rake doc:app` and see /doc/ -* make your db (see db/README) - -* install ruby libxml bindings: - - # sudo aptitude install libxml-ruby1.8 libxml-parser-ruby1.8 - -* install primary keys plugin for active record (minimum version 0.9.1) - - # sudo gem install composite_primary_keys - -* make sure you have a MTA listening on localhost:25 if you want mail - -* script/server - -* thats it - -API CHANGES FOR EDITOR AUTHORS -============================== - -See - -http://wiki.openstreetmap.org/index.php/REST#Changes_in_the_upcoming_0.4_API - -HACKING -======= - -log in to your site (proably localhost:3000) - -create a user and confirm it - -you want to play with the API (probably at localhost:3000/api/0.4/node/create etc) - -Lots of tests are needed to test the API. - -Lots of little things to make the site work like the old one. - -Also see the 'rails_port' component for bugs: -http://trac.openstreetmap.org/query?status=new&status=assigned&status=reopened&component=rails_port&order=priority diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 9def5104e..876dbd10e 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -1,8 +1,10 @@ -# AMF Controller is a semi-standalone API for Flash clients, particularly Potlatch +# 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). # +# See Also Potlatch::Potlatch and Potlatch::AMF +# # Public domain. # editions Systeme D / Richard Fairhurst 2004-2008 # @@ -13,10 +15,11 @@ # 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' + include Potlatch + session :off before_filter :check_write_availability @@ -31,35 +34,35 @@ class AmfController < ApplicationController # ------------- # Parse request - headers=getint(req) # Read number of headers + headers=AMF.getint(req) # Read number of headers headers.times do # Read each header - name=getstring(req) # | + name=AMF.getstring(req) # | req.getc # | skip boolean - value=getvalue(req) # | + value=AMF.getvalue(req) # | header["name"]=value # | end - bodies=getint(req) # Read number of bodies + bodies=AMF.getint(req) # Read number of bodies 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 - args=getvalue(req) # | get response (probably an array) + 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]=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 '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 '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] - results[index]=putdata(index,r) - when 'deleteway'; results[index]=putdata(index,deleteway(args)) - when 'putpoi'; results[index]=putdata(index,putpoi(args)) - when 'getpoi'; results[index]=putdata(index,getpoi(args)) + results[index]=AMF.putdata(index,r) + 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 @@ -75,20 +78,16 @@ class AmfController < ApplicationController end } RAILS_DEFAULT_LOGGER.info(" Response: end") - end private - # Return presets (default tags and crap) to potlatch - # Global is set up in config/environment.rb on startup, code is in lib/osm.rb - def getpresets + # Return presets (default tags and crap) to potlatch. + # Uses POTLATCH_PRESETS global, set up in OSM::Potlatch + def getpresets #:doc: return POTLATCH_PRESETS end - # ==================================================================== - # Remote calls - # ----- whichways # Find all the way ids and nodes (including tags and projected lat/lng) which aren't part of those ways in an are # @@ -98,7 +97,7 @@ class AmfController < ApplicationController # 2. maximum longitude # 3. maximum latitude # 4. baselong, 5. basey, 6. masterscale as above - def whichways(args) + 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 @@ -129,7 +128,7 @@ class AmfController < ApplicationController # 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) + 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 @@ -166,8 +165,7 @@ class AmfController < ApplicationController # # 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) + def getway(args) #:doc: wayid,baselong,basey,masterscale = args wayid = wayid.to_i @@ -207,7 +205,7 @@ class AmfController < ApplicationController # [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) + 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 @@ -248,7 +246,7 @@ class AmfController < ApplicationController # [0] version, [1] db timestamp (string), # [2] visible 0 or 1, # [3] username or 'anonymous' (string)) - def getway_history(args) + def getway_history(args) #:doc: wayid=args[0] history=[] sql=<<-EOF @@ -281,7 +279,7 @@ class AmfController < ApplicationController # 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) + def putway(args,renumberednodes) #:doc: RAILS_DEFAULT_LOGGER.info(" putway started") usertoken,originalway,points,attributes,oldversion,baselong,basey,masterscale=args uid=getuserid(usertoken) @@ -441,7 +439,7 @@ class AmfController < ApplicationController # 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) + 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 @@ -479,13 +477,11 @@ class AmfController < ApplicationController # ----- 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) + def getpoi(args) #:doc: id,baselong,basey,masterscale=args; id=id.to_i poi=ActiveRecord::Base.connection.select_one("SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lng,tags "+ "FROM current_nodes WHERE visible=1 AND id=#{id}") @@ -498,13 +494,12 @@ class AmfController < ApplicationController # ----- 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: - def deleteway(args) usertoken,way=args RAILS_DEFAULT_LOGGER.info(" Message: deleteway, id=#{way}") @@ -552,12 +547,7 @@ class AmfController < ApplicationController [0,way] end - - - # ==================================================================== - # Support functions for remote calls - - def readwayquery(id,insistonvisible) + 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 @@ -569,12 +559,12 @@ class AmfController < ApplicationController ActiveRecord::Base.connection.select_all(sql) end - def getlastversion(id,version) + def getlastversion(id,version) #:doc: row=ActiveRecord::Base.connection.select_one("SELECT version FROM ways WHERE id=#{id} AND visible=1 ORDER BY version DESC LIMIT 1") row['version'] end - def readwayquery_old(id,version,historic) + def readwayquery_old(id,version,historic) #:doc: # Node handling on undelete (historic=false): # - always use the node specified, even if it's moved @@ -629,7 +619,7 @@ class AmfController < ApplicationController rows end - def createuniquenodes(way,uqn_name,nodelist) + def createuniquenodes(way,uqn_name,nodelist) #:doc: # Find nodes which appear in this way but no others sql=<<-EOF CREATE TEMPORARY TABLE #{uqn_name} @@ -654,7 +644,7 @@ class AmfController < ApplicationController # deleteuniquenoderelations(uqn_name,uid,db_now) # deleteitemrelations(way|node,'way'|'node',uid,db_now) - def deleteuniquenoderelations(uqn_name,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 @@ -669,7 +659,7 @@ class AmfController < ApplicationController end end - def deleteitemrelations(objid,type,uid,db_now) + 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} @@ -684,7 +674,7 @@ class AmfController < ApplicationController end end - def removefromrelation(objid,type,relation,uid,db_now) + 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 @@ -706,11 +696,11 @@ class AmfController < ApplicationController ActiveRecord::Base.connection.execute("DELETE FROM current_relation_members WHERE id=#{relation} AND member_type='#{type}' AND member_id=#{objid}") end - def sqlescape(a) + def sqlescape(a) #:doc: a.gsub(/[\000-\037]/,"").gsub("'","''").gsub(92.chr) {92.chr+92.chr} end - def tag2array(a) + def tag2array(a) #:doc: tags={} Tags.split(a) do |k, v| tags[k.gsub(':','|')]=v @@ -718,7 +708,7 @@ class AmfController < ApplicationController tags end - def array2tag(a) + def array2tag(a) #:doc: tags = [] a.each do |k,v| if v=='' then next end @@ -728,7 +718,7 @@ class AmfController < ApplicationController return Tags.join(tags) end - def getuserid(token) + def getuserid(token) #:doc: if (token =~ /^(.+)\+(.+)$/) then user = User.authenticate(:username => $1, :password => $2) else @@ -738,147 +728,26 @@ class AmfController < ApplicationController return user ? user.id : nil; end - - - # ==================================================================== - # 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 - - def getint(s) - s.getc*256+s.getc - end - - def getlong(s) - ((s.getc*256+s.getc)*256+s.getc)*256+s.getc - end - - def getstring(s) - len=s.getc*256+s.getc - s.read(len) - end - - def getdouble(s) - a=s.read(8).unpack('G') # G big-endian, E little-endian - a[0] - end - - def getarray(s) - len=getlong(s) - arr=[] - for i in (0..len-1) - arr[i]=getvalue(s) - end - arr - end - - def getobject(s) - arr={} - while (key=getstring(s)) - if (key=='') then break end - arr[key]=getvalue(s) - end - s.getc # skip the 9 'end of object' value - arr - end - - # ----- getvalue parse and get value - - def getvalue(s) - case s.getc - when 0; return getdouble(s) # number - when 1; return s.getc # boolean - when 2; return getstring(s) # string - when 3; return getobject(s) # object/hash - when 5; return nil # null - when 6; return nil # undefined - when 8; s.read(4) # mixedArray - return getobject(s) # | - when 10;return getarray(s) # array - else; return nil # error - end - end - - # ==================================================================== - # AMF write subroutines - - # ----- putdata envelope data into AMF writeable form - # ----- encodevalue pack variables as AMF - - def putdata(index,n) - d =encodestring(index+"/onResult") - d+=encodestring("null") - d+=[-1].pack("N") - d+=encodevalue(n) - end - - def encodevalue(n) - case n.class.to_s - when 'Array' - a=10.chr+encodelong(n.length) - n.each do |b| - a+=encodevalue(b) - end - a - when 'Hash' - a=3.chr - n.each do |k,v| - a+=encodestring(k)+encodevalue(v) - end - a+0.chr+0.chr+9.chr - when 'String' - 2.chr+encodestring(n) - when 'Bignum','Fixnum','Float' - 0.chr+encodedouble(n) - when 'NilClass' - 5.chr - else - RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s) - 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 - - 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) + def lat2coord(a,basey,masterscale) #:doc: -(lat2y(a)-basey)*masterscale+250 end - def long2coord(a,baselong,masterscale) + def long2coord(a,baselong,masterscale) #:doc: (a-baselong)*masterscale+350 end - def lat2y(a) + def lat2y(a) #:doc: 180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2)) end - def coord2lat(a,masterscale,basey) + def coord2lat(a,masterscale,basey) #:doc: y2lat((a-250)/-masterscale+basey) end - def coord2long(a,masterscale,baselong) + def coord2long(a,masterscale,baselong) #:doc: (a-350)/masterscale+baselong end diff --git a/config/environment.rb b/config/environment.rb index bf80499f7..02d99f20c 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -70,6 +70,6 @@ Rails::Initializer.run do |config| end # This has to be after the above block for some reason (doesnt pull in /lib/osm.rb?) -POTLATCH_PRESETS = OSM::Potlatch.get_presets() +POTLATCH_PRESETS = Potlatch::Potlatch.get_presets() diff --git a/doc/README_FOR_APP b/doc/README_FOR_APP index 6ec308173..129a6f24b 100644 --- a/doc/README_FOR_APP +++ b/doc/README_FOR_APP @@ -1 +1,34 @@ This is the OpenStreetMap rails server codebase. Documentation is currently extremely incomplete. Please help by writing docs and moving any SQL you see to use models etc. + +=INSTALL + +* Get rails working (http://www.rubyonrails.org/) +* Make your db (see db/README) +* Install ruby libxml bindings: + sudo apt-get install libxml-ruby1.8 libxml-parser-ruby1.8 +* Install primary keys plugin for active record (minimum version 0.9.1) + sudo gem install composite_primary_keys +* Make sure you have a MTA listening on localhost:25 if you want mail + sudo apt-get install exim4 +* Start the server + script/server +* Thats it + +=API CHANGES FOR EDITOR AUTHORS + +See + +http://wiki.openstreetmap.org/index.php/REST#Changes_in_the_upcoming_0.4_API + +=HACKING + +* Log in to your site (proably localhost:3000) +* Create a user and confirm it +* You want to play with the API (probably at http://localhost:3000/api/0.5/node/create etc) +* Lots of tests are needed to test the API. +* Lots of little things to make the site work like the old one. + +=Bugs + +See the 'rails_port' component for bugs: +http://trac.openstreetmap.org/query?status=new&status=assigned&status=reopened&component=rails_port&order=priority diff --git a/lib/osm.rb b/lib/osm.rb index 6e9346bb4..24df7a35d 100644 --- a/lib/osm.rb +++ b/lib/osm.rb @@ -279,7 +279,7 @@ module OSM def initialize(feed_title='OpenStreetMap GPS Traces', feed_description='OpenStreetMap GPS Traces', feed_url='http://www.openstreetmap.org/traces/') @doc = XML::Document.new @doc.encoding = 'UTF-8' - + rss = XML::Node.new 'rss' @doc.root = rss rss['version'] = "2.0" @@ -425,72 +425,5 @@ module OSM return "#{tilesql} AND #{prefix}latitude BETWEEN #{minlat} AND #{maxlat} AND #{prefix}longitude BETWEEN #{minlon} AND #{maxlon}" end - class Potlatch # crazy shit - - # ----- getpresets - # in: none - # does: reads tag preset menus, colours, and autocomplete config files - # out: [0] presets, [1] presetmenus, [2] presetnames, - # [3] colours, [4] casing, [5] areas, [6] autotags - # (all hashes) - def self.get_presets - RAILS_DEFAULT_LOGGER.info(" Message: getpresets") - - # Read preset menus - presets={} - presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[] - presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={} - presettype='' - presetcategory='' - # StringIO.open(txt) do |file| - File.open("#{RAILS_ROOT}/config/potlatch/presets.txt") do |file| - file.each_line {|line| - t=line.chomp - if (t=~/(\w+)\/(\w+)/) then - presettype=$1 - presetcategory=$2 - presetmenus[presettype].push(presetcategory) - presetnames[presettype][presetcategory]=["(no preset)"] - elsif (t=~/^(.+):\s?(.+)$/) then - pre=$1; kv=$2 - presetnames[presettype][presetcategory].push(pre) - presets[pre]={} - kv.split(',').each {|a| - if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end - } - end - } - end - - # Read colours/styling - colours={}; casing={}; areas={} - File.open("#{RAILS_ROOT}/config/potlatch/colours.txt") do |file| - file.each_line {|line| - t=line.chomp - if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then - tag=$1 - if ($2!='-') then colours[tag]=$2.hex end - if ($3!='-') then casing[tag]=$3.hex end - if ($4!='-') then areas[tag]=$4.hex end - end - } - end - - # Read auto-complete - autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={}; - File.open("#{RAILS_ROOT}/config/potlatch/autocomplete.txt") do |file| - file.each_line {|line| - t=line.chomp - if (t=~/^(\w+)\/(\w+)\s+(.+)$/) then - tag=$1; type=$2; values=$3 - if values=='-' then autotags[type][tag]=[] - else autotags[type][tag]=values.split(',').sort.reverse end - end - } - end - - [presets,presetmenus,presetnames,colours,casing,areas,autotags] - end - end end diff --git a/lib/potlatch.rb b/lib/potlatch.rb new file mode 100644 index 000000000..b2f8eb479 --- /dev/null +++ b/lib/potlatch.rb @@ -0,0 +1,189 @@ +# The Potlatch module provides helper functions for potlatch and its communication with the server +module Potlatch + + # The AMF class is a set of helper functions for encoding and decoding AMF. + class AMF + + # Return two-byte integer + def self.getint(s) + s.getc*256+s.getc + end + + # Return four-byte long + def self.getlong(s) + ((s.getc*256+s.getc)*256+s.getc)*256+s.getc + end + + # Return string with two-byte length + def self.getstring(s) + len=s.getc*256+s.getc + s.read(len) + end + + # Return eight-byte double-precision float + def self.getdouble(s) + a=s.read(8).unpack('G') # G big-endian, E little-endian + a[0] + end + + # Return numeric array + def self.getarray(s) + len=getlong(s) + arr=[] + for i in (0..len-1) + arr[i]=getvalue(s) + end + arr + end + + # Return object/hash + def self.getobject(s) + arr={} + while (key=getstring(s)) + if (key=='') then break end + arr[key]=getvalue(s) + end + s.getc # skip the 9 'end of object' value + arr + end + + # Parse and get value + def self.getvalue(s) + case s.getc + when 0; return getdouble(s) # number + when 1; return s.getc # boolean + when 2; return getstring(s) # string + when 3; return getobject(s) # object/hash + when 5; return nil # null + when 6; return nil # undefined + when 8; s.read(4) # mixedArray + return getobject(s) # | + when 10;return getarray(s) # array + else; return nil # error + end + end + + # Envelope data into AMF writeable form + def self.putdata(index,n) + d =encodestring(index+"/onResult") + d+=encodestring("null") + d+=[-1].pack("N") + d+=encodevalue(n) + end + + # Pack variables as AMF + def self.encodevalue(n) + case n.class.to_s + when 'Array' + a=10.chr+encodelong(n.length) + n.each do |b| + a+=encodevalue(b) + end + a + when 'Hash' + a=3.chr + n.each do |k,v| + a+=encodestring(k)+encodevalue(v) + end + a+0.chr+0.chr+9.chr + when 'String' + 2.chr+encodestring(n) + when 'Bignum','Fixnum','Float' + 0.chr+encodedouble(n) + when 'NilClass' + 5.chr + else + RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s) + end + end + + # Encode string with two-byte length + def self.encodestring(n) + a,b=n.size.divmod(256) + a.chr+b.chr+n + end + + # Encode number as eight-byte double precision float + def self.encodedouble(n) + [n].pack('G') + end + + # Encode number as four-byte long + def self.encodelong(n) + [n].pack('N') + end + + end + + + # The Potlatch class is a helper for Potlatch + class Potlatch + + # ----- getpresets + # in: none + # does: reads tag preset menus, colours, and autocomplete config files + # out: [0] presets, [1] presetmenus, [2] presetnames, + # [3] colours, [4] casing, [5] areas, [6] autotags + # (all hashes) + def self.get_presets + RAILS_DEFAULT_LOGGER.info(" Message: getpresets") + + # Read preset menus + presets={} + presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[] + presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={} + presettype='' + presetcategory='' + # StringIO.open(txt) do |file| + File.open("#{RAILS_ROOT}/config/potlatch/presets.txt") do |file| + file.each_line {|line| + t=line.chomp + if (t=~/(\w+)\/(\w+)/) then + presettype=$1 + presetcategory=$2 + presetmenus[presettype].push(presetcategory) + presetnames[presettype][presetcategory]=["(no preset)"] + elsif (t=~/^(.+):\s?(.+)$/) then + pre=$1; kv=$2 + presetnames[presettype][presetcategory].push(pre) + presets[pre]={} + kv.split(',').each {|a| + if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end + } + end + } + end + + # Read colours/styling + colours={}; casing={}; areas={} + File.open("#{RAILS_ROOT}/config/potlatch/colours.txt") do |file| + file.each_line {|line| + t=line.chomp + if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then + tag=$1 + if ($2!='-') then colours[tag]=$2.hex end + if ($3!='-') then casing[tag]=$3.hex end + if ($4!='-') then areas[tag]=$4.hex end + end + } + end + + # Read auto-complete + autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={}; + File.open("#{RAILS_ROOT}/config/potlatch/autocomplete.txt") do |file| + file.each_line {|line| + t=line.chomp + if (t=~/^(\w+)\/(\w+)\s+(.+)$/) then + tag=$1; type=$2; values=$3 + if values=='-' then autotags[type][tag]=[] + else autotags[type][tag]=values.split(',').sort.reverse end + end + } + end + + [presets,presetmenus,presetnames,colours,casing,areas,autotags] + end + end + +end + -- 2.39.5