summaryrefslogtreecommitdiff
path: root/dashboard_website
diff options
context:
space:
mode:
authorAnson Bridges <bridges.anson@gmail.com>2023-11-18 06:18:23 -0500
committerAnson Bridges <bridges.anson@gmail.com>2023-11-18 06:18:23 -0500
commitc560de266caad6db97e58757ca43e8558c103c01 (patch)
tree852deb7079d616042a255c906a9196b135ca0bba /dashboard_website
parent939f7a093dadfa89ac1bbe43b0c9fded404c1ad5 (diff)
csv import, manual visiting
Diffstat (limited to 'dashboard_website')
-rw-r--r--dashboard_website/__pycache__/datastructs.cpython-311.pycbin7348 -> 7356 bytes
-rw-r--r--dashboard_website/__pycache__/db.cpython-311.pycbin11189 -> 12642 bytes
-rw-r--r--dashboard_website/__pycache__/router.cpython-311.pycbin18525 -> 18700 bytes
-rw-r--r--dashboard_website/dashboard.py35
-rw-r--r--dashboard_website/db.py68
-rw-r--r--dashboard_website/dirt.csv68
-rw-r--r--dashboard_website/router.py7
-rw-r--r--dashboard_website/savefile.csv1
-rw-r--r--dashboard_website/static/js/controls.js42
-rw-r--r--dashboard_website/static/js/dashboard.js20
-rw-r--r--dashboard_website/templates/controls.html26
-rw-r--r--dashboard_website/templates/index.html2
12 files changed, 244 insertions, 25 deletions
diff --git a/dashboard_website/__pycache__/datastructs.cpython-311.pyc b/dashboard_website/__pycache__/datastructs.cpython-311.pyc
index 43fc8d9..95d05af 100644
--- a/dashboard_website/__pycache__/datastructs.cpython-311.pyc
+++ b/dashboard_website/__pycache__/datastructs.cpython-311.pyc
Binary files differ
diff --git a/dashboard_website/__pycache__/db.cpython-311.pyc b/dashboard_website/__pycache__/db.cpython-311.pyc
index 48ee159..2312bc2 100644
--- a/dashboard_website/__pycache__/db.cpython-311.pyc
+++ b/dashboard_website/__pycache__/db.cpython-311.pyc
Binary files differ
diff --git a/dashboard_website/__pycache__/router.cpython-311.pyc b/dashboard_website/__pycache__/router.cpython-311.pyc
index 1e21e0e..f94a179 100644
--- a/dashboard_website/__pycache__/router.cpython-311.pyc
+++ b/dashboard_website/__pycache__/router.cpython-311.pyc
Binary files differ
diff --git a/dashboard_website/dashboard.py b/dashboard_website/dashboard.py
index 06af267..7d0d920 100644
--- a/dashboard_website/dashboard.py
+++ b/dashboard_website/dashboard.py
@@ -215,6 +215,15 @@ def getLatestInfo():
return jsonify(data)
+@app.route("/addClue", methods=['POST'])
+def addClueWeb():
+ content = request.get_json()
+
+ if not ('clue_name' in content and 'longitude' in content and 'latitude' in content and 'clue_info' in content):
+ return jsonify({'status' : "ERROR 1"})
+
+ return jsonify({'status' : "OK",})
+
# main page
# GET = get main page
@@ -223,6 +232,32 @@ def siteIndex():
#clues = db.getClues(); bikes = db.getBikes()
return render_template("index.html")#, clues=clues, bikes=bikes)
+# add csv, download as csv
+@app.route("/controls", methods=['GET', 'POST'])
+def siteControls():
+ if request.method == "GET":
+ return render_template("controls.html")
+ if request.method == "POST":
+ cmd = request.form.get('command')
+ print(cmd)
+ if cmd == "downloadSave":
+ print("send")
+ db.save()
+ return send_from_directory(".", "savefile.csv", as_attachment=True)
+ elif cmd == "loadDirty":
+ dirty_csv = request.files['dirtyfile']
+ dirty_csv.save("dirt.csv")
+ if db.loadDirty("dirt.csv") != 0:
+ return jsonify({"status" : "ERROR"})
+ return jsonify({"status" : "OK"})
+ elif cmd == "loadClean":
+ dirty_csv = request.files['cleanfile']
+ dirty_csv.save("clean.csv")
+ if db.load("clean.csv") != 0:
+ return jsonify({"status" : "ERROR"})
+ return jsonify({"status" : "OK"})
+
+ return render_template("controls.html")
if __name__ == "__main__":
diff --git a/dashboard_website/db.py b/dashboard_website/db.py
index 6a638e7..166ac7a 100644
--- a/dashboard_website/db.py
+++ b/dashboard_website/db.py
@@ -48,6 +48,7 @@ def updateRoutes_background(): # run in thread due to long runtime
def updateRoutes(): # if necessary
global currently_updating
if not currently_updating:
+ save()
currently_updating = True
t = Thread(target=updateRoutes_background)
t.start()
@@ -155,18 +156,20 @@ def deleteClue(clue_name):
def visitClue(clue_name):
+ global clues_last_changed
for clue in clues:
if clue.name == clue_name:
if clue.status == "VISITED":
return 3 # already visited
clue.visit()
clues_last_changed = time.time()
- # updateRoutes()
+ updateRoutes()
return 0 # OK
return 2 # no clue found
def visitClueTeam(team_name, clue_name):
+ global clues_last_changed
b = None
for bike in bikes:
if bike.name == team_name:
@@ -185,6 +188,7 @@ def visitClueTeam(team_name, clue_name):
return 5 # clue not found
# 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
@@ -195,6 +199,7 @@ def visitClueTeam(team_name, clue_name):
# otherwise
c.visit()
clues_last_changed = time.time()
+ updateRoutes() # must be updated due to unexpected visitation
def load(filename=None):
@@ -204,8 +209,9 @@ def load(filename=None):
:return: None
"""
# if there is no filename, wipe all clues
- if filename is None:
+ if filename == None:
clues.clear()
+ filename = "savefile.csv"
# otherwise, load from file
with open(filename, newline='') as f:
@@ -215,13 +221,46 @@ def load(filename=None):
next(csvreader)
for row in csvreader:
- name = row[0]
- latitude = row[1]
- longitude = row[2]
- info = row[3]
- status = row[4]
+ try:
+ name = row[0]
+ latitude = row[1]
+ longitude = row[2]
+ info = row[3]
+ status = row[4]
+
+ clues.append(Clue(latitude, longitude, name, info, status))
+ except:
+ return 1
+ clues_last_changed = time.time()
+ updateRoutes()
+ return 0
+
+def loadDirty(filename=None):
+ global clues_last_changed
+ if filename == None:
+ return
+
+ # otherwise, load from file
+ with open(filename, newline='') as f:
+ csvreader = csv.reader(f, delimiter=',', quotechar='"')
- clues.append(Clue(latitude, longitude, name, info, status))
+ # skip header row
+ next(csvreader)
+ for row in csvreader:
+ try:
+ name = row[0]
+ info = row[2]
+ latlong = row[3].split(",")
+ if len(latlong) != 2: continue
+ latitude = float(latlong[0])
+ longitude = float(latlong[1])
+
+ clues.append(Clue(latitude, longitude, name, info, "UNVISITED"))
+ except:
+ return 1
+ clues_last_changed = time.time()
+ updateRoutes()
+ return 0
def save():
@@ -237,15 +276,4 @@ def save():
csvwriter.writerow([clue.name, clue.latitude, clue.longitude, clue.info, clue.status])
-# junk for testing
-with open("all_clues.csv", newline='') as f:
- csvreader = csv.reader(f, delimiter=',', quotechar='"')
- i = 1
- for row in csvreader:
- coords = row[1].split(",")
- coords[0] = float(coords[0]);
- coords[1] = float(coords[1]);
-
- newClue = Clue(coords[0], coords[1], f"Clue #{i}", row[0], "UNVISITED" if i < 100 else "VISITED")
- clues.append(newClue)
- i += 1
+load() \ No newline at end of file
diff --git a/dashboard_website/dirt.csv b/dashboard_website/dirt.csv
new file mode 100644
index 0000000..08ab5cd
--- /dev/null
+++ b/dashboard_website/dirt.csv
@@ -0,0 +1,68 @@
+Clue ID,Clue,Name,"Latitude, Longitude (right click near place on google maps, then click the coordinates to copy)",,
+A1,"1) Where Andrew, Tom, and Toby might toss a frisbee PETERS PARK BOSTON",Peters Park,"42.3430402738135, -71.0675801105357",,
+A2,2) It's not North of Washington Street.... SOWA → South of Washington Street?,SoWa Market(?),,,
+A3,"3) Blues, Latin jazz salsa, jazz xa, funk x3, 24/7/365 Wally’s Cafe Jazz club",Wally's Cafe Jazz Club,"42.340735169280684, -71.0822142949978",,
+A4,"4) Not to be confused with the Jesuit college in Worcester, this is a cathedral Cathedral",Cathedral of the Holy Cross,"42.340965725249276, -71.07004200293923",,
+A5,5) Lilli Ann K Rosenberg brainchild in the South End,Betances Mural (80%),"42.34236478201366, -71.07314991031272",,
+A6,"6) Not an above-ground railroad, she is remembered as one of the conductors",Harriet Tubman Memorial,"42.34355826498339, -71.0779098454636",,
+A7,7) Halloween's Michael + Community's Señor: ,Myers+Chang,"42.343917124461065, -71.06620549483627",,
+A8,8) This diner has a secret,Hidden Kitchen,"42.33836232114676, -71.0667887997758",,
+A9,9) Need budgeting advice? Take a page out of their book,,,,
+A10,"10) Go for the Spanish dancing, stay for the Spanish food",La Fabrica Central Restaurant,"42.363845469421676, -71.10129788828729",,
+A11,11) A place Petunia and Vernon would love to share a cup of coffee,"Dudley Cafe , Dudley Square","42.33000580911709, -71.08345739566941",,
+A12,12) The namesake of this house suggested bullets or ballots,Malcolm X House,"42.321503645221576, -71.0863561083245",,
+A13,13) A station honoring an ancient Nile kingdom → ,"Nubian Station, Roxbury","42.329719158213535, -71.08393017974034",,
+A14,"14) The sun, but in French.",soleil,"42.32995937830152, -71.08425706494715",,
+A15,15) Taking down bear proof cages is a lot harder than putting them up,old bear pens,"42.31163492909362, -71.0944883387719",,
+A16,"16) A high school for mayo, smoked turkey, cucumbers, tomatoes, and sprouts",,,,
+A17,17) Where to go when you need spaghetti in a hurry on the hill,Lily's Gourmet Pasta Express,"42.33240052352865, -71.10001875238213",,
+A18,18) The Jamaica Plain Tuesday Club is its steward,Loring Greenough House,"42.30940190779075, -71.11503165360074",,
+A19,19) Spooner finds 2020 chicago mayor at this theater (9 letters),Strand Theatre,"42.31599303331773, -71.0660247",,
+A20,"20) You won't find cows or pigs in this barn, but maybe a hot meal instead",noodle barn (?),"42.31145648101414, -71.11454193944768",,
+A21,21) The Crimson's green showcase,Harvard Arboretum,"42.30758360954152, -71.11986574437587",,
+A22,22) A not so functional seat to enjoy pond views,JAMACIA POND BENCH,"42.31703238067602, -71.1172176327592",,
+A23,"23) Grab a book from this famous labor organizer, it's plainly not a Haymarket affair",Lucy Parsons Center (Jamaica Plain),"42.32234399461923, -71.10765946762163",,
+A24,24) Go to this fire station to get an ice cold treat,fire station turned JP Licks,"42.312828161837565, -71.1142521044243",,
+A25,"25) Sorta like the death of an author, but (mil)more in bronze",Death and the Sculptor,,,"42.29783644453621, -71.10768546216663"
+A26,26) SD.2702 was recently passed here,Massachusetts State House,"42.35772690789592, -71.0636244852727",,
+A27,"27) Mae's performing here either today or tomorrow -> 158 Brighton Ave, Allston, MA 02134",Brighton Music Hall,"42.35296368437526, -71.13261242438084",,
+A28,"28) I don't know much about their baked goods, but the flag is a big plus",SWISS BAKERY ALSTON,"42.3632259246665, -71.12855843461686",,
+A29,"29) If you're looking for good Asian fusion, you'll find a bonch on Brighton Avenue",Bonchon Boston,"42.35298420423782, -71.13089261430888",,
+A30,"30) Absalom, absalom! Listen closely for the sound and the fury at this memorial","Anderson bridge: a small brass plaque, the size of one brick, that is located on the
+brick wall of the Eastern (Weld Boathouse) side of the bridge, just
+north of the middle of the bridge span, about eighteen inches from the
+ground in a small alcove. It reads:
+""QUENTIN COMPSON
+Drowned in the odour of honeysuckle.
+1891-1910""","42.36898885010578, -71.12306457136677",,
+A31,31) Don't go here for rescue from arson - even if you are only at O'Brien's,Boston Fire Dept. Station 41,"42.353802, -71.136116",,
+A32,32) CSM and IVM provide the name for this BC museum,McMullen Museum of art,"42.34038115716941, -71.16265204351588",,
+A33,33) A hammer thrower resides peacefully outside a former school named after Big Lub,Hal Connolly Statue,"42.35037729554579, -71.14555952509022",,
+A34,34 ) This Catalan restaurant will bring you to task ,Tasca Restaurant,"42.3434052435984, -71.14279038706111",,
+A35,35) The students here seem like they'll have a Bright future,Brighton High School,"42.34965767795442, -71.14606621964128",,
+A36,36) Going to the chapel and it's 1959 ,Harvard Class of 1959 Chapel,"42.36580905967968, -71.12374919164488",,
+A37,"37) This monument wasn't made by its subject, but it could have been",,,,
+A38,"38) Quack quack quack, their home on the Fens",agassiz road duck house,"42.34341395011007, -71.09317746727483",,
+A39,39) The less controversial MLK statue,MLK statue on BU campus,"42.35036326253947, -71.10650807481497",,
+A40,"40) This hotel kicked out St. George and caused a Black Sox scandal, Bucko!",Boston Hotel Buckminster,"42.348465223671944, -71.09776617622576",,
+A41,"41) Vitruvian, Viridian. Potato, potato. Find this place where all the people of Fenway can meet",The Viridian (Apartment Building that has Blaze Pizza),"42.34453026994564, -71.09720444433195",,
+A42,42) This pizza place loves fire so much they put it in the name!,Land of Fire Pizzeria,"42.34138871428725, -71.14657093175214",,
+A43,43) A BU student's go-to for Indian food,India Quality Restaurant,"42.3485725720217, -71.0942113926108",,
+A44,44) The statue of the son of the red,MAYBE Ted Williams Statue ,"42.34605480640728, -71.0960390033173",,
+A45,45) This citrus isn't supposed to be that color!,,,,
+A46,46) Boston Terriers love getting their tan on here,BU Beach,"42.35116095548625, -71.10606134524427",,
+A47,47) So she ran away in her sleep and dreamed of this rock,Paradise Rock Club (Commonwealth),"42.3518271762187, -71.11983863137432",,
+A48,48) Has better ratings than the noun motel or the adverb inn,The Verb Hotel,"42.34517137203154, -71.09676153399613",,
+A49,49) Supposedly the oldest playground in America,Cypress Street Playground,"42.3315920224197, -71.12571559999999",,
+A50,50) Ook een boek van Ann Patchett,The Dutch House,"42.335982955313646, -71.11231902990166",,
+A51,51) The home of the nation's best parkmaker,Frederick Law Olmstead National Historic Site,"42.32590914866024, -71.13228373433928",,
+A52,52) This Brookline shop might forge their own tomes,Brookline Booksmith,"42.342764551151554, -71.12168301640884",,
+A53,53) we we we we should should should should cross cross cross cross here here here here,Echo Bridge,"42.31487124359676, -71.22693938547769",,
+A54,54) This weekend it's hosting a Thanksgiving with Mary Baker Eddy,Longyear Museum,"42.32485823589608, -71.16189103410989",,
+A55,55) Steam engines so big they ll leave you crying,Waterworks Museum,"42.3320010747946, -71.15563010527421",,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,Japanese Temple Bell at 9:30 in the Fens (right across the first foot bridge),,,,
+,"42.34132619174766, -71.09428257118488",,,, \ No newline at end of file
diff --git a/dashboard_website/router.py b/dashboard_website/router.py
index 5d5a909..1a90a9e 100644
--- a/dashboard_website/router.py
+++ b/dashboard_website/router.py
@@ -2,13 +2,14 @@ import numpy as np
import requests
from sklearn.cluster import KMeans
import time
-from datetime import datetime
+import datetime
from datastructs import *
host = "http://acetyl.net:5000" # queries acetyl.net:5000, the OSRM engine
+endtime = datetime.datetime(2023, 11, 18, 18, 35) # 11/18/2023 6:35pm
# external facing functions
@@ -77,6 +78,8 @@ def cluster_and_optimize(clues: [Clue], bikes: [Bike], end: Point, time_diff=0.2
:param n: the number of routes to create
:return: a list of lists of clues (ordered by position on route), and a list of json route geojsons
"""
+ # OVERRIDE MAX TIME
+ max_time = datetime.datetime.now() - endtime
routes = [clues] # one bike = one set of routes. only need to remove the faraway waypoints
if len(bikes) > 1:
# Create a new column with normalized gps coordinates and centroids
@@ -106,7 +109,7 @@ def cluster_and_optimize(clues: [Clue], bikes: [Bike], end: Point, time_diff=0.2
geometries.append(route_json['trips'][0]['geometry']['coordinates'])
route_waypoints.append(route_json['waypoints'])
eta = time.time() + route_json['trips'][0]['duration'] + 90 * len(route)
- eta_str = datetime.fromtimestamp(eta).strftime("%I:%M:%S%p")
+ eta_str = datetime.datetime.fromtimestamp(eta).strftime("%I:%M:%S%p")
times.append(eta_str)
# Use the waypoint_index to reorder each route
diff --git a/dashboard_website/savefile.csv b/dashboard_website/savefile.csv
new file mode 100644
index 0000000..84b6c30
--- /dev/null
+++ b/dashboard_website/savefile.csv
@@ -0,0 +1 @@
+name,latitude,longitude,info,status
diff --git a/dashboard_website/static/js/controls.js b/dashboard_website/static/js/controls.js
new file mode 100644
index 0000000..3d81032
--- /dev/null
+++ b/dashboard_website/static/js/controls.js
@@ -0,0 +1,42 @@
+// uses functions in utils.js
+var host = window.location.protocol + "//" + window.location.host;
+
+function downloadCurrent(){
+ call("downloadSave");
+}
+
+// load and append dirty file
+function loadDirty(){
+ call("loadDirty", "dirty");
+}
+
+// load save file (clean)
+function loadSave(){
+ call("loadSave", "clean");
+}
+
+function call(command, formid=""){
+ var formData;
+ if (formid == "") {
+ formData = new FormData();
+ }else {
+ formData = new FormData(document.getElementById(formid));
+ }
+
+ formData.append("command", command);
+ console.log(formData);
+
+ fetch(host+'/controls', {
+ method: "POST",
+ body: formData
+ }).then( res => res.blob() )
+ .then( blob => {
+ var file = window.URL.createObjectURL(blob);
+ window.location.assign(file);});
+ //.then((response) => response.json())
+ //.then((json) => handleCallResponse(json));
+}
+
+function handleLatestInfo(json){
+ if(json['status'] != "OK")alert("Error.");
+} \ No newline at end of file
diff --git a/dashboard_website/static/js/dashboard.js b/dashboard_website/static/js/dashboard.js
index fba7196..4ce6fac 100644
--- a/dashboard_website/static/js/dashboard.js
+++ b/dashboard_website/static/js/dashboard.js
@@ -123,13 +123,28 @@ function drawClues(){
for (var i = 0; i < clues.length; i++) {
var tempIcon = visitedIcon;
if (clues[i]['clue_status'] == "UNVISITED") tempIcon = unvisitedIcon;
- var clueMarker = L.marker([clues[i]['latitude'], clues[i]['longitude']], {icon: tempIcon}).bindPopup(clues[i]['clue_name'] + ": " + clues[i]['clue_info']);
+ var popupdiv = document.createElement('p');
+ popupdiv.innerHTML = "<span style='color:black'>" + clues[i]['clue_name'] + ": " + clues[i]['clue_info'] + "</span><button style='margin-left:2px' onclick=\"visitClue('"+clues[i]['clue_name']+"')\">Visit</button>"
+ var clueMarker = L.marker([clues[i]['latitude'], clues[i]['longitude']], {icon: tempIcon}).bindPopup(popupdiv);
clue_rels[clues[i]['clue_name']] = clueMarker;
if (clues[i]['clue_status'] == "UNVISITED") unvisited_clues_m.addLayer(clueMarker);
else visited_clues_m.addLayer(clueMarker);
}
}
+function visitClue(clue_name){
+ console.log("visiting: "+clue_name);
+ fetch(host+'/visitClueGeneric', {
+ method: "POST",
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ "clue_name" : clue_name })})
+ .then((response) => response.json())
+ .then((json) => console.log(json));
+}
+
function addClue(){
var long = parseFloat(document.getElementById("new_clue_longitude").value);
var lat = parseFloat(document.getElementById("new_clue_latitude").value);
@@ -252,4 +267,5 @@ window.onload = function() {
layerControl.addOverlay(bikes_m, "Bikes");
layerControl.addTo(map);
requestLatestInfo();
-} \ No newline at end of file
+}
+
diff --git a/dashboard_website/templates/controls.html b/dashboard_website/templates/controls.html
new file mode 100644
index 0000000..2ad3adc
--- /dev/null
+++ b/dashboard_website/templates/controls.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html style="height:100%">
+
+<head>
+ <title>MMCH Controls</title>
+ <link rel="icon" type="image/x-icon" href="/static/img/favicon.ico">
+
+ <script src="{{ url_for('static', filename='js/controls.js') }}"></script>
+</head>
+
+<body>
+ <a href="..">Back</a> <br>
+ <button onclick="downloadCurrent()">Download Current Savefile (.CSV)</button> <br>
+ <form id="dirty" name="dirty">
+ <label for="dirtyfile">Choose dirty clue list to upload</label>
+ <input id="dirtyfile" name="dirtyfile" type="file" accept=".csv,.CSV" />
+ <button type="button" onclick="loadDirty()">Upload</button>
+ </form> <br>
+ <form id="clean" name="clean">
+ <label for="cleanfile">Choose save file to upload (will overwrite)</label>
+ <input id="cleanfile" name="cleanfile" type="file" accept=".csv,.CSV" />
+ <button type="button" onclick="loadClean()">Upload</button>
+ </form>
+</body>
+
+</html> \ No newline at end of file
diff --git a/dashboard_website/templates/index.html b/dashboard_website/templates/index.html
index 73f9f22..d4f8196 100644
--- a/dashboard_website/templates/index.html
+++ b/dashboard_website/templates/index.html
@@ -144,7 +144,7 @@
<div class="route-controls">
<span style="margin:-1px;margin-left:5px;margin-top:5px;" id="routeinfo">ROUTE INFO</span>
<hr style="width:100%;padding:0px;"/>
- <div id="etas"></div>
+ <!--<input type="time" id="endtime" value="18:30">-->
</div>
</div>
<div class="right-column">