]> git.openstreetmap.org Git - rails.git/blobdiff - app/models/changeset.rb
auto_link() changeset comments in the global/user/bbox/etc history too
[rails.git] / app / models / changeset.rb
index 0b214fe720a65ad42677285defbd021b51658a39..4efd4f9e7f755e0655d4ee89f55bfcf989e6ed62 100644 (file)
@@ -27,15 +27,11 @@ class Changeset < ActiveRecord::Base
   # maximum number of elements allowed in a changeset
   MAX_ELEMENTS = 50000
 
-  # maximum time a changeset is allowed to be open for (note that this
-  # is in days - so one hour is Rational(1,24)).
+  # maximum time a changeset is allowed to be open for.
   MAX_TIME_OPEN = 1.day
 
-  # idle timeout increment, one hour as a rational number of days.
-  # NOTE: DO NOT CHANGE THIS TO 1.hour! when this was done the idle
-  # timeout changed to 1 second, which meant all changesets closed 
-  # almost immediately.
-  IDLE_TIMEOUT = 1.hour # Rational(1,24)
+  # idle timeout increment, one hour seems reasonable.
+  IDLE_TIMEOUT = 1.hour
 
   # Use a method like this, so that we can easily change how we
   # determine whether a changeset is open, without breaking code in at 
@@ -46,29 +42,28 @@ class Changeset < ActiveRecord::Base
     # note that this may not be a hard limit - due to timing changes and
     # concurrency it is possible that some changesets may be slightly 
     # longer than strictly allowed or have slightly more changes in them.
-    return ((closed_at > DateTime.now) and (num_changes <= MAX_ELEMENTS))
+    return ((closed_at > Time.now.getutc) and (num_changes <= MAX_ELEMENTS))
   end
 
   def set_closed_time_now
-    unless is_open?
-      self.closed_at = DateTime.now
+    if is_open?
+      self.closed_at = Time.now.getutc
     end
   end
   
   def self.from_xml(xml, create=false)
     begin
-      p = XML::Parser.new
-      p.string = xml
+      p = XML::Parser.string(xml)
       doc = p.parse
 
       cs = Changeset.new
 
       doc.find('//osm/changeset').each do |pt|
         if create
-          cs.created_at = Time.now
+          cs.created_at = Time.now.getutc
           # initial close time is 1h ahead, but will be increased on each
           # modification.
-          cs.closed_at = Time.now + IDLE_TIMEOUT
+          cs.closed_at = cs.created_at + IDLE_TIMEOUT
           # initially we have no changes in a changeset
           cs.num_changes = 0
         end
@@ -90,6 +85,20 @@ class Changeset < ActiveRecord::Base
   def bbox
     @bbox ||= [ min_lon, min_lat, max_lon, max_lat ]
   end
+  
+  def has_valid_bbox?
+    not bbox.include? nil
+  end
+  
+  ##
+  # returns area of the changset bbox as a rough comparitive quantity for use of changset displays
+  def area
+     if has_valid_bbox?
+            (max_lon - min_lon) * (max_lat - min_lat)
+     else
+            0
+     end
+  end
 
   ##
   # expand the bounding box to include the given bounding box. also, 
@@ -103,10 +112,10 @@ class Changeset < ActiveRecord::Base
 
     # FIXME - this looks nasty and violates DRY... is there any prettier 
     # way to do this? 
-    @bbox[0] = array[0] + EXPAND * (@bbox[0] - @bbox[2]) if array[0] < @bbox[0]
-    @bbox[1] = array[1] + EXPAND * (@bbox[1] - @bbox[3]) if array[1] < @bbox[1]
-    @bbox[2] = array[2] + EXPAND * (@bbox[2] - @bbox[0]) if array[2] > @bbox[2]
-    @bbox[3] = array[3] + EXPAND * (@bbox[3] - @bbox[1]) if array[3] > @bbox[3]
+    @bbox[0] = [-180 * GeoRecord::SCALE, array[0] + EXPAND * (@bbox[0] - @bbox[2])].max if array[0] < @bbox[0]
+    @bbox[1] = [ -90 * GeoRecord::SCALE, array[1] + EXPAND * (@bbox[1] - @bbox[3])].max if array[1] < @bbox[1]
+    @bbox[2] = [ 180 * GeoRecord::SCALE, array[2] + EXPAND * (@bbox[2] - @bbox[0])].min if array[2] > @bbox[2]
+    @bbox[3] = [  90 * GeoRecord::SCALE, array[3] + EXPAND * (@bbox[3] - @bbox[1])].min if array[3] > @bbox[3]
 
     # update active record. rails 2.1's dirty handling should take care of
     # whether this object needs saving or not.
@@ -145,19 +154,9 @@ class Changeset < ActiveRecord::Base
   end
 
   def save_with_tags!
-    t = Time.now
-
     # do the changeset update and the changeset tags update in the
     # same transaction to ensure consistency.
     Changeset.transaction do
-      # set the auto-close time to be one hour in the future unless
-      # that would make it more than 24h long, in which case clip to
-      # 24h, as this has been decided is a reasonable time limit.
-      if (closed_at - created_at) > (MAX_TIME_OPEN - IDLE_TIMEOUT)
-        self.closed_at = created_at + MAX_TIME_OPEN
-      else
-        self.closed_at = DateTime.now + IDLE_TIMEOUT
-      end
       self.save!
 
       tags = self.tags
@@ -172,6 +171,20 @@ class Changeset < ActiveRecord::Base
       end
     end
   end
+
+  ##
+  # set the auto-close time to be one hour in the future unless
+  # that would make it more than 24h long, in which case clip to
+  # 24h, as this has been decided is a reasonable time limit.
+  def before_save
+    if self.is_open?
+      if (closed_at - created_at) > (MAX_TIME_OPEN - IDLE_TIMEOUT)
+        self.closed_at = created_at + MAX_TIME_OPEN
+      else
+        self.closed_at = Time.now.getutc + IDLE_TIMEOUT
+      end
+    end
+  end
   
   def to_xml
     doc = OSM::API.new.get_xml_doc
@@ -226,7 +239,7 @@ class Changeset < ActiveRecord::Base
   def update_from(other, user)
     # ensure that only the user who opened the changeset may modify it.
     unless user.id == self.user_id 
-      raise OSM::APIUserChangesetMismatchError 
+      raise OSM::APIUserChangesetMismatchError.new
     end
     
     # can't change a closed changeset