summaryrefslogtreecommitdiff
path: root/dashboard_website/datastructs.py
blob: 997d3e794858c6a87f0c8f69a21e3e5c2bd480fb (plain)
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
import math
import time

# time since last ping before deactivating/deleting
BIKE_TIMEOUT = 60000 # 3 minutes
BIKE_DELETE = 360000 # 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(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, pool_index = 0, required=False):
        self.longitude = long
        self.latitude = lat
        self.name = name
        self.info = info
        self.status = status # UNVISITED | VISITED | DISABLED | ASSIGNED
        self.pool_inbex = pool_index
        self.required = required
    
    def visit(self):
        self.status = "VISITED"
    
    def toggle_enable(self):
        if self.status == "UNVISITED" or self.status == "ASSIGNED":
            self.status = "DISABLED"
        elif self.status == "DISABLED":
            self.status = "UNVISITED"

    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,
                     'clue_required' : self.required}
        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 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 = "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