Add extra visibility options for GPS traces, and enhance the API call
[rails.git] / app / models / trace.rb
index fef9983ddd69a74189c9d06bda8fde80f7af45b0..cbfd68996ff5a7944ecb5df197a01163fd670575 100644 (file)
@@ -3,9 +3,12 @@ class Trace < ActiveRecord::Base
 
   validates_presence_of :user_id, :name, :timestamp
   validates_presence_of :description, :on => :create
+  validates_length_of :name, :maximum => 255
+  validates_length_of :description, :maximum => 255
 #  validates_numericality_of :latitude, :longitude
-  validates_inclusion_of :public, :inserted, :in => [ true, false]
-  
+  validates_inclusion_of :inserted, :in => [ true, false ]
+  validates_inclusion_of :visibility, :in => ["private", "public", "trackable", "identifiable"]
+
   belongs_to :user
   has_many :tags, :class_name => 'Tracetag', :foreign_key => 'gpx_id', :dependent => :delete_all
   has_many :points, :class_name => 'Tracepoint', :foreign_key => 'gpx_id', :dependent => :delete_all
@@ -18,17 +21,38 @@ class Trace < ActiveRecord::Base
   end
 
   def tagstring
-    return tags.collect {|tt| tt.tag}.join(" ")
+    return tags.collect {|tt| tt.tag}.join(", ")
   end
 
   def tagstring=(s)
-    self.tags = s.split().collect {|tag|
-      tt = Tracetag.new
-      tt.tag = tag
-      tt
-    }
+    if s.include? ','
+      self.tags = s.split(/\s*,\s*/).collect {|tag|
+        tt = Tracetag.new
+        tt.tag = tag
+        tt
+      }
+    else
+      #do as before for backwards compatibility:
+      self.tags = s.split().collect {|tag|
+        tt = Tracetag.new
+        tt.tag = tag
+        tt
+      }
+    end
   end
-  
+
+  def public?
+    visibility == "public" || visibility == "identifiable"
+  end
+
+  def trackable?
+    visibility == "trackable" || visibility == "identifiable"
+  end
+
+  def identifiable?
+    visibility == "identifiable"
+  end
+
   def large_picture= (data)
     f = File.new(large_picture_name, "wb")
     f.syswrite(data)
@@ -58,18 +82,16 @@ class Trace < ActiveRecord::Base
     data
   end
   
-  # FIXME change to permanent filestore area
   def large_picture_name
-    "/home/osm/icons/#{id}.gif"
+    "#{GPX_IMAGE_DIR}/#{id}.gif"
   end
 
-  # FIXME change to permanent filestore area
   def icon_picture_name
-    "/home/osm/icons/#{id}_icon.gif"
+    "#{GPX_IMAGE_DIR}/#{id}_icon.gif"
   end
 
   def trace_name
-    "/home/osm/gpx/#{id}.gpx"
+    "#{GPX_TRACE_DIR}/#{id}.gpx"
   end
 
   def mime_type
@@ -130,7 +152,7 @@ class Trace < ActiveRecord::Base
     el1['lat'] = self.latitude.to_s
     el1['lon'] = self.longitude.to_s
     el1['user'] = self.user.display_name
-    el1['public'] = self.public.to_s
+    el1['visibility'] = self.visibility
     el1['pending'] = (!self.inserted).to_s
     el1['timestamp'] = self.timestamp.xmlschema
     return el1
@@ -145,23 +167,25 @@ class Trace < ActiveRecord::Base
     tarred = filetype =~ /tar archive/
 
     if gzipped or bzipped or zipped or tarred then
-      file = Tempfile.new("trace.#{id}");
+      tmpfile = Tempfile.new("trace.#{id}");
 
       if tarred and gzipped then
-        system("tar -zxOf #{trace_name} > #{file.path}")
+        system("tar -zxOf #{trace_name} > #{tmpfile.path}")
       elsif tarred and bzipped then
-        system("tar -jxOf #{trace_name} > #{file.path}")
+        system("tar -jxOf #{trace_name} > #{tmpfile.path}")
       elsif tarred
-        system("tar -xOf #{trace_name} > #{file.path}")
+        system("tar -xOf #{trace_name} > #{tmpfile.path}")
       elsif gzipped
-        system("gunzip -c #{trace_name} > #{file.path}")
+        system("gunzip -c #{trace_name} > #{tmpfile.path}")
       elsif bzipped
-        system("bunzip2 -c #{trace_name} > #{file.path}")
+        system("bunzip2 -c #{trace_name} > #{tmpfile.path}")
       elsif zipped
-        system("unzip -p #{trace_name} > #{file.path}")
+        system("unzip -p #{trace_name} -x '__MACOSX/*' > #{tmpfile.path}")
       end
 
-      file.unlink
+      tmpfile.unlink
+
+      file = tmpfile.file
     else
       file = File.open(trace_name)
     end
@@ -172,7 +196,7 @@ class Trace < ActiveRecord::Base
   def import
     logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
 
-    gpx = OSM::GPXImporter.new(self.xml_file)
+    gpx = GPX::File.new(self.xml_file)
 
     f_lat = 0
     f_lon = 0
@@ -181,23 +205,24 @@ class Trace < ActiveRecord::Base
     # If there are any existing points for this trace then delete
     # them - we check for existing points first to avoid locking
     # the table in the common case where there aren't any.
-    if Tracepoint.exists?(['gpx_id = ?', self.id])
+    if Tracepoint.find(:first, :conditions => ['gpx_id = ?', self.id])
       Tracepoint.delete_all(['gpx_id = ?', self.id])
     end
 
     gpx.points do |point|
       if first
-        f_lat = point['latitude']
-        f_lon = point['longitude']
+        f_lat = point.latitude
+        f_lon = point.longitude
+        first = false
       end
 
       tp = Tracepoint.new
-      tp.lat = point['latitude'].to_f
-      tp.lon = point['longitude'].to_f
-      tp.altitude = point['altitude'].to_f
-      tp.timestamp = point['timestamp']
+      tp.lat = point.latitude
+      tp.lon = point.longitude
+      tp.altitude = point.altitude
+      tp.timestamp = point.timestamp
       tp.gpx_id = id
-      tp.trackid = point['segment'].to_i
+      tp.trackid = point.segment
       tp.save!
     end
 
@@ -214,8 +239,8 @@ class Trace < ActiveRecord::Base
 
       self.latitude = f_lat
       self.longitude = f_lon
-      self.large_picture = gpx.get_picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points)
-      self.icon_picture = gpx.get_icon(min_lat, min_lon, max_lat, max_lon)
+      self.large_picture = gpx.picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points)
+      self.icon_picture = gpx.icon(min_lat, min_lon, max_lat, max_lon)
       self.size = gpx.actual_points
       self.inserted = true
       self.save!