import time, math # time since last ping before deactivating/deleting BIKE_TIMEOUT = 60 # 3 minutes BIKE_DELETE = 300 # time before bike deletes itself # data structures class Point: def __init__(self, lat, long): self.longitude = long self.latitude = lat def toJSON(self): json_dict = {'longitude' : self.longitude, 'latitude' : self.latitude} return json_dict def setCoords(self, lat, long): self.longitude = long self.latitude = lat def move(self, d_lat, d_long): self.longitude += d_long self.latitude += d_lat def __str__(self): return f"{self.longitude},{self.latitude}" def __repr__(self): return f"{self.longitude},{self.latitude}" def distanceTo(self, pt): # distance between points in miles lat1 = self.latitude; lon1 = self.longitude; lat2 = pt.latitude; lon2 = pt.longitude; R = 3958.8 # Radius of the earth lat_d = math.radians(lat2-lat1); lon_d = math.radians(lon2-lon1); a = math.sin(dLat/2) * math.sin(dLat/2) + math.cos(radians(lat1)) * math.cos(radians(lat2)) * math.sin(dLon/2) * math.sin(dLon/2) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)); d = R * c; # Distance in mi return d class Clue(Point): def __init__(self, lat, long, name, info, status): self.longitude = long self.latitude = lat self.name = name self.info = info self.status = status # UNVISITED | ASSIGNED | VISITED def visit(self): self.status = "VISITED" def toJSON(self): json_dict = {'longitude' : self.longitude, 'latitude' : self.latitude, 'clue_name' : self.name.replace('"', "'"), 'clue_info' : self.info.replace('"', "'"), 'clue_status' : self.status} return json_dict class Bike(Point): def __init__(self, lat, long, name, status): self.longitude = long self.latitude = lat self.name = name self.last_contact = time.time() self.target_name = "N/A" self.cluster = [] # list of clues this bike team is responsible for self.status = status # ACTIVE | INACTIVE def setTarget(self, clue_name): self.target_name = clue_name def setCluster(self, clue_cluster): self.cluster = clue_cluster self.updateTarget() def updateTarget(self): if len(self.cluster) <= 0: self.target_name = "N/A" else: self.target_name = self.cluster[0].name def visitTarget(self): self.cluster[0].visit() self.cluster.pop(0) self.updateTarget() while len(self.cluster) > 0 and cluster[0].status == "VISITED": self.cluster.pop(0) # skip next node if it has been somehow visited self.updateTarget() def ping(self): self.status = "ACTIVE" self.last_contact = time.time() def disable(self): self.status = "INACTIVE" self.target = "N/A" self.last_contact = 0 def checkStatus(self): if time.time() - self.last_contact > BIKE_TIMEOUT: self.status = "INACTIVE" self.target = "N/A" if time.time() - self.last_contact > BIKE_DELETE: return -1 return 0 def toJSON(self): json_dict = {'longitude' : self.longitude, 'latitude' : self.latitude, 'time_since_last_contact' : time.time()-self.last_contact, 'team_name' : self.name, 'team_status' : self.status, 'target_clue' : self.target_name} return json_dict