diff options
Diffstat (limited to 'dashboard_website/db.py')
| -rw-r--r-- | dashboard_website/db.py | 174 |
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 |
