1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
import math
import time
import datetime
# time since last ping before deactivating/deleting
BIKE_TIMEOUT = 60000 # 3 minutes
endtime = datetime.datetime(2024, 11, 16, hour=18, minute=45)
# 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(lat_d / 2) * math.sin(lat_d / 2) + math.cos(
math.radians(lat1)
) * math.cos(math.radians(lat2)) * math.sin(lon_d / 2) * math.sin(lon_d / 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, assigned_team = 0, required=False):
self.longitude = long
self.latitude = lat
self.name = name
self.info = info
self.status = status # UNVISITED | VISITED | DISABLED | ASSIGNED
self.assigned_team = assigned_team # 0 = to be assigned algorithmically
self.required = required
def visit(self):
self.status = "VISITED"
def unvisit(self):
self.status = "UNVISITED"
def toggle_enable(self):
if self.status == "UNVISITED" or self.status == "ASSIGNED":
self.status = "DISABLED"
elif self.status == "DISABLED":
self.status = "UNVISITED"
def toggle_required(self):
self.required = False if self.required else True
def set_team(self, team):
self.assigned_team = team
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,
'assigned_team' : self.assigned_team,
'clue_required' : self.required}
return json_dict
class Bike(Point):
def __init__(self, lat, long, name):
self.longitude = long
self.latitude = lat
self.name = name
self.deadline = endtime
self.last_contact = time.time()
self.target_clue = None
self.time_modifier = 1 # factor by which to modulate expected arrival time
self.cluster = [] # list of clues this bike team is responsible for
self.status = "DISABLED" # DISABLED | ACTIVE | INACTIVE
self.clue_assignment_time = 0 # when clue was assigned, so that upon clue visitation we can determine speed
def setTarget(self, clue_name):
self.target_name = clue_name
def setCluster(self, clue_cluster):
self.cluster = clue_cluster
self.updateTarget()
def setDeadline(self, new_deadline):
self.deadline = new_deadline
def timeTilDeadline(self):
return (self.deadline - datetime.datetime.now()).total_seconds()
def updateTarget(self):
self.clue_assignment_time = time.time()
if len(self.cluster) <= 0:
self.target_clue = None
self.status = "INACTIVE"
else:
self.status = "ACTIVE"
self.target_clue = self.cluster[0]
def visitTarget(self):
print("clue visit time: ", time.time() - self.clue_assignment_time)
self.target_clue.visit()
self.cluster.pop(0)
self.updateTarget()
while len(self.cluster) > 0 and self.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 = "DISABLED"
self.target = None
def enable(self):
self.status = "INACTIVE"
self.target = None
def tripTime(self):
return datetime.datetime.now() - self.deadline
def toJSON(self):
json_dict = {
"longitude": self.longitude,
"latitude": self.latitude,
"time_since_last_contact": time.time() - self.last_contact,
"team_deadline" : str(self.deadline),
"team_name": self.name,
"team_status": self.status,
"target_clue": self.target_clue.name if self.target_clue else "N/A",
}
return json_dict
|