Browse Source

Move more logic into the Location class.

Douglas William Thrift 11 years ago
parent
commit
d6944b0720
1 changed files with 59 additions and 50 deletions
  1. 59 50
      locationbot.py

+ 59 - 50
locationbot.py

@@ -197,6 +197,36 @@ class Location(object):
 
 		return 'http://maps.google.com/maps?' + re.sub('%(2[89cC])', lambda match: chr(int(match.group(1), 16)), urllib.urlencode({'q': '%s (%s)' % (location, self.nick)}))
 
+	@property
+	def _accuracy(self):
+		return self.values.get('accuracy')
+
+	@property
+	def _latitude(self):
+		return self.values['coordinates'][0]
+
+	@property
+	def _longitude(self):
+		return self.values['coordinates'][1]
+
+	def has_changed_from(self, previous):
+		if self.location != previous.location:
+			return True
+
+		distance = self - previous
+
+		if distance < 60:
+			return False
+
+		if self._accuracy is not None and previous._accuracy is not None:
+			if distance > (self._accuracy + previous._accuracy) / 2:
+				return True
+
+			if distance > min(self._accuracy, previous._accuracy) and self._accuracy < previous._accuracy:
+				return True
+
+		return False
+
 	def __get_attr__(self, name):
 		if name not in VALUES:
 			raise AttributeError("'Location' object has no attribute '%s'" % name)
@@ -204,11 +234,11 @@ class Location(object):
 		value = self.values.get(name)
 
 		if info in ('accuracy', 'altitude', 'altitude_accuracy'):
-			return distance(value)
+			return self.distance(value)
 		elif info in ('speed',):
-			return speed(value)
+			return self.speed(value)
 		elif info in ('heading',):
-			return heading(value)
+			return self.heading(value)
 		else:
 			return unicode(value)
 
@@ -229,7 +259,13 @@ class Location(object):
 		else:
 			aux = ''
 
-		return '%s is%s in %s%s %s' % (self.nick, venue, self.values['location'], aux, self.url)
+		return '%s is%s in %s%s %s' % (self.nick, venue, self.location, aux, self.url)
+
+	def __sub__(self, other):
+		x = (math.cos(self.degrees_to_radians(self._latitude)) + math.cos(self.degrees_to_radians(other._latitude))) * self.longitude_to_nautical_miles(self._longitude - other._longitude) / 2
+		y = self.latitude_to_nautical_miles(self._latitude - other._latitude)
+
+		return self.nautical_miles_to_meters(abs(x) ** 2 + abs(y) ** 2)
 
 	@classmethod
 	def distance(cls, distance):
@@ -239,12 +275,28 @@ class Location(object):
 	@classmethod
 	def speed(cls, speed):
 		if speed is not None:
-			return '%.1f m/s (%.1f mph)' % (speed, meters_per_second_to_miles_per_hour(speed))
+			return '%.1f m/s (%.1f mph)' % (speed, cls.meters_per_second_to_miles_per_hour(speed))
 
 	@classmethod
 	def heading(cls, heading):
 		if heading is not None:
-			return u'%.1f\xb0 (%s)' % (heading, heading_to_direction(heading))
+			return u'%.1f\xb0 (%s)' % (heading, cls.heading_to_direction(heading))
+
+	@staticmethod
+	def degrees_to_radians(degrees):
+		return degrees * math.pi / 180
+
+	@staticmethod
+	def latitude_to_nautical_miles(latitude):
+		return latitude * 60.00721
+
+	@staticmethod
+	def longitude_to_nautical_miles(longitude):
+		return longitude * 60.10793
+
+	@staticmethod
+	def nautical_miles_to_meters(nautical_miles):
+		return nauticla_miles * 1852
 
 	@staticmethod
 	def meters_to_feet(meters):
@@ -293,7 +345,7 @@ class Location(object):
 
 class LocationBot(ircbot.SingleServerIRCBot):
 	def __init__(self, bot = None):
-		self.__config = SafeConfigParser({'min_update_distance': "60"})
+		self.__config = SafeConfigParser()
 
 		self.__config.read('locationbot.ini')
 
@@ -323,9 +375,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
 			self.__admins = self.__config.get(nick, 'admins').split()
 			self.__channels = set(self.__config.get(nick, 'channels').split())
 			self.__dsn = self.__config.get(nick, 'dsn')
-			#self.__latitude_client_id = self.__config.get(nick, 'latitude_client_id')
-			#self.__latitude_consumer = oauth.Consumer(key = self.__latitude_client_id, secret = self.__config.get(nick, 'latitude_client_secret'))
-			self.min_update_distance = self.__config.getint(nick, 'min_update_distance')
 
 		except NoOptionError, error:
 			sys.exit(error)
@@ -493,46 +542,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 			self.__latitude_timer.start()
 
-	def __location(self, nick, channels, granularity, old_location, new_location, old_coordinates, new_coordinates, old_accuracy, new_accuracy, old_speed, new_speed, old_heading, new_heading, old_altitude, new_altitude, old_altitude_accuracy, new_altitude_accuracy, old_updated, new_updated):
-		def calc_distance(lat1, lon1, lat2, lon2): # returns meters
-			nauticalMilePerLat = 60.00721
-			nauticalMilePerLongitude = 60.10793
-			rad = math.pi / 180.0
-			milesPerNauticalMile = 1.15078
-			metersPerNauticalMile = 1852
-
-			yDistance = (lat2 - lat1) * nauticalMilePerLat
-			xDistance = (math.cos(lat1 * rad) + math.cos(lat2 * rad)) * \
-			                (lon2 - lon1) * (nauticalMilePerLongitude / 2)
-			distance = math.sqrt( yDistance**2 + xDistance**2 )
-			return distance * metersPerNauticalMile
-
-		def make_update_noise():
-			with self.__locations_lock:
-				for channel in self.__channels.intersection(channels):
-					self.__locations.append((nick, channel, granularity, new_location, new_coordinates, new_accuracy, new_speed, new_heading, new_altitude, new_altitude_accuracy))
-
-		if channels:
-			if new_location != old_location: # old method
-				return make_update_noise()
-
-			distance = calc_distance(old_coordinates[0], old_coordinates[1],
-									 new_coordinates[0], new_coordinates[1])
-
-			if distance < self.min_update_distance:
-				return
-
-			if old_accuracy is not None and new_accuracy is not None:
-				avg_radius = (old_accuracy + new_accuracy) / 2
-
-				if distance > avg_radius:
-					return make_update_noise()
-
-				min_radius = min(old_accuracy, new_accuracy)
-
-				if distance > min_radius and new_accuracy < old_accuracy:
-					return make_update_noise()
-
 	def __login(self, connection, nickmask, nick, arguments = ''):
 		login = nick