summaryrefslogtreecommitdiff
path: root/dashboard_website/db.py
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard_website/db.py')
-rw-r--r--dashboard_website/db.py174
1 files changed, 103 insertions, 71 deletions
diff --git a/dashboard_website/db.py b/dashboard_website/db.py
index 7bb5a18..eec587d 100644
--- a/dashboard_website/db.py
+++ b/dashboard_website/db.py
@@ -2,10 +2,12 @@
# also manages currently available bike teams
import csv
from threading import Thread
+import datetime
import router
from datastructs import *
+
# constants
CLUE_MIN_DISTANCE = 0.1 # minimum distance between clue and bike to be considered valid visitation
@@ -16,33 +18,63 @@ bikes = []
clusters = []
routes = {"clusters": [], "cluster_times": {},
"individual_routes": []} # geojson polylines, both between all the clusters
+preview_routes = {"clusters": [], "cluster_times": {}, # geojson polylines, both between all the clusters
+ "individual_routes": [], "clue_clusters" : []} # except clue clusters which is a list of a list of clues
assigned_clues = []
clues_last_changed = time.time()
home_last_changed = time.time()
routes_last_changed = time.time()
+route_update_required = False
currently_updating = False
+minimalRouting = False # if false, currently assigned clues
+
+_bikes_changed = False # In case bikes or clues are enabled/disabled
+_clues_changed = False # during route calculation
startup = False #
+def should_cancel_routing():
+ global _bikes_changed, _clues_changed
+ if _bikes_changed or _clues_changed:
+ _bikes_changed = True
+ _clues_changed = True
+ return True
+ return False
+
+def is_route_update_required():
+ return route_update_required
# called every time a node is added
# a bike is added/removed
# determines/assigns clusters, and assigns routes to bikes
def updateRoutes_background(): # run in thread due to long runtime
- global currently_updating, routes_last_changed, routes, clusters
+ global currently_updating, routes_last_changed, route_update_required, preview_routes, clusters, routes
print("Calculating clusters...")
- routes = {"clusters": [], "cluster_times": {}, "individual_routes": []} # reset
- clusters, paths, times = router.getClusters(bikes, clues, homeBase)
+ preview_routes = {"clusters": [], "cluster_times": {}, "individual_routes": [], "clue_clusters" : []} # reset
+ status, clusters, paths, times = router.getClusters(bikes, clues, homeBase, minimalRouting)
+ if status != 0:
+ print("Aborted routing.")
+
+ preview_routes['individual_routes'] = paths.copy()
+ preview_routes['cluster_times'] = times
+ preview_routes['clusters'] = paths
+ preview_routes['clue_clusters'] = clusters
+ for i in range(len(bikes)):
+ if bikes[i].status != "DISABLED":
+ preview_routes['individual_routes'][i] = router.getRouteHDPolyline(bikes[i], clusters[i][0])
+
+ # set routes - TESTING
routes['individual_routes'] = paths.copy()
routes['cluster_times'] = times
routes['clusters'] = paths
- for i in range(len(bikes)):
- if bikes[i].status == "ACTIVE":
- routes['individual_routes'][i] = router.getRouteHDPolyline(bikes[i], clusters[i][0])
+ for i, bike in enumerate(bikes):
+ if bike.status == "DISABLED": continue
+ bike.setCluster(clusters[i])
routes_last_changed = time.time()
print("Finished calculating clusters/routes.")
currently_updating = False
+ route_update_required = False
def updateRoutes(): # if necessary
@@ -52,6 +84,7 @@ def updateRoutes(): # if necessary
currently_updating = True
t = Thread(target=updateRoutes_background)
t.start()
+ return 0
# interface functions
@@ -73,21 +106,20 @@ def getHomeBaseJSON(timestamp):
def setHomeBase(latitude, longitude):
- homeBase.setCoords(latitude, longitude)
- home_last_changed = time.time()
+ global home_last_changed
+ try:
+ latitude = float(latitude)
+ longitude = float(longitude)
+ homeBase.setCoords(latitude, longitude)
+ home_last_changed = time.time()
+ return 0
+ except:
+ return -1
-def getBikeCluePair(team_name):
- b = None;
- c = None
- for bike in bikes:
- if bike.name == team_name:
- b = bike
- for clue in clues:
- if clue.name == b.target_name:
- c = clue
- break
- break
+def getBikeCluePair(team_index):
+ b = bikes[team_index-1]
+ c = b.target_clue
return b, c
@@ -97,41 +129,31 @@ def getRoutesJSON(timestamp):
return False
-def deleteBike(team_name):
- for bike in bikes:
- if bike.name == team_name: # already exists
- bike.disable()
- updateRoutes()
- return 0 # OK
- return 4 # bike does not exist
-
-
-def addBike(team_name, latitude, longitude):
- for bike in bikes:
- if bike.name == team_name: # already exists
- return 4 # already exists
- newBike = Bike(latitude, longitude, team_name, "ACTIVE")
- bikes.append(newBike)
- updateRoutes()
+def pingBike(team_index, latitude, longitude):
+ bike = bikes[team_index-1]
+ bike.ping()
+ bike.setCoords(latitude, longitude)
return 0
+def setBikeEnabled(team_index, enabled):
+ global route_update_required
+ bike = bikes[team_index-1]
+ route_update_required = True
+ if enabled:
+ bike.enable()
+ else:
+ bike.disable()
+ return 0
-def pingBike(team_name, latitude, longitude):
- for bike in bikes:
- if bike.name == team_name:
- bike.ping()
- bike.setCoords(latitude, longitude)
- return 0
- return 4 # team not found
-
+def setBikeDeadline(team_index, datetime_string):
+ global route_update_required
+ new_deadline = datetime.datetime.strptime(datetime_string, "%Y-%m-%dT%H:%M")
+ bikes[team_index-1].setDeadline(new_deadline)
+ route_update_required = True
+ return 0
def getBikesJSON():
- global bikes
- old_length = len(bikes)
- bikes = [x for x in bikes if x.checkStatus() >= 0]
- if old_length != len(bikes):
- updateRoutes()
- return [x.toJSON() for x in bikes]
+ return [ x.toJSON() for x in bikes ]
def getCluesJSON(timestamp):
@@ -141,27 +163,29 @@ def getCluesJSON(timestamp):
def addClue(clue_name, clue_info, longitude, latitude, status="UNVISITED"):
- global clues_last_changed
+ global clues_last_changed, route_update_required
for clue in clues:
if clue.name == clue_name:
return -1 # clue already exists
newClue = Clue(latitude, longitude, clue_name, clue_info, status)
clues.append(newClue)
clues_last_changed = time.time()
+ route_update_required = True
return 0
def deleteClue(clue_name):
+ global route_update_required
for i, clue in enumereate(clues):
if clue.name == clue_name:
clues.pop(i)
clues_last_changed = time.time()
- updateRoutes()
+ route_update_required = True
break
def visitClue(clue_name, unvisit=False):
- global clues_last_changed
+ global clues_last_changed, route_update_required
for clue in clues:
if clue.name == clue_name:
if clue.status == "VISITED":
@@ -172,41 +196,45 @@ def visitClue(clue_name, unvisit=False):
return 3 # already visited
clue.visit()
clues_last_changed = time.time()
- updateRoutes()
+ route_update_required
return 0 # OK
return 2 # no clue
def toggleEnableClue(clue_name):
- global clues_last_changed
+ global clues_last_changed, route_update_required
for clue in clues:
if clue.name == clue_name:
clue.toggle_enable()
clues_last_changed = time.time()
- updateRoutes()
+ route_update_required = True
return 0 # OK
return 2 # no clue
def toggleClueRequired(clue_name):
- global clues_last_changed
+ global clues_last_changed, route_update_required
for clue in clues:
if clue.name == clue_name:
clue.toggle_required()
clues_last_changed = time.time()
- updateRoutes()
+ route_update_required
+ return 0 # OK
+ return 2 # no clue
+
+def assignClueToTeam(clue_name, team_index):
+ global clues_last_changed, route_update_required
+ for clue in clues:
+ if clue.name == clue_name and clue.status != "ASSIGNED":
+ clue.set_team(team_index)
+ clues_last_changed = time.time()
+ route_update_required = True
return 0 # OK
return 2 # no clue
+def visitClueTeam(team_index, clue_name):
+ global clues_last_changed, route_update_required
+ b = bikes[team_index-1] # Team 1 -> index 0
-def visitClueTeam(team_name, clue_name):
- global clues_last_changed
- b = None
- for bike in bikes:
- if bike.name == team_name:
- b = bike
- break
- else:
- return 4 # team not found
c = None
for clue in clues:
if clue.name == clue_name:
@@ -219,9 +247,9 @@ def visitClueTeam(team_name, clue_name):
# if visited clue is the expected one (current target)
# no need to recalculate
- if clue_name == b.target_name:
- if c.distanceTo(b) < CLUE_MIN_DISTANCE:
- return 3 # too far away
+ if c == b.target_clue:
+ #if c.distanceTo(b) < CLUE_MIN_DISTANCE:
+ # return 3 # too far away
b.visitTarget()
clues_last_changed = time.time()
return 0
@@ -229,7 +257,7 @@ def visitClueTeam(team_name, clue_name):
# otherwise
c.visit()
clues_last_changed = time.time()
- updateRoutes() # must be updated due to unexpected visitation
+ route_update_required
def load(filename=None):
@@ -284,6 +312,7 @@ def loadDirty(filename=None):
if len(latlong) != 2: continue
latitude = float(latlong[0])
longitude = float(latlong[1])
+ print(longitude)
clues.append(Clue(latitude, longitude, name, info, "UNVISITED"))
except:
@@ -305,5 +334,8 @@ def save():
for clue in clues:
csvwriter.writerow([clue.name, clue.latitude, clue.longitude, clue.info, clue.status])
-
+bikes = [ Bike(homeBase.latitude, homeBase.longitude, "Team 1"),
+ Bike(homeBase.latitude, homeBase.longitude, "Team 2"),
+ Bike(homeBase.latitude, homeBase.longitude, "Team 3"),
+ Bike(homeBase.latitude, homeBase.longitude, "Team 4") ]
#load("all_clues.csv") \ No newline at end of file