diff options
Diffstat (limited to 'dashboard_website/static/js/dashboard.js')
| -rw-r--r-- | dashboard_website/static/js/dashboard.js | 215 |
1 files changed, 170 insertions, 45 deletions
diff --git a/dashboard_website/static/js/dashboard.js b/dashboard_website/static/js/dashboard.js index b335a1f..cb941f8 100644 --- a/dashboard_website/static/js/dashboard.js +++ b/dashboard_website/static/js/dashboard.js @@ -1,53 +1,182 @@ +// uses functions in utils.js +var host = window.location.protocol + "//" + window.location.host; + +// "global" map variables var map; var previewmap; var visited_clues_m = L.layerGroup([]); // all clues var unvisited_clues_m = L.layerGroup([]); // subset of all clues - unvisited clues var destination_clues_m = L.layerGroup([]); // clues bikers are currently destined for +var bikes_m = L.layerGroup([]); // bike markers -var homeIcon = L.icon({ - iconUrl: 'static/img/marker-home.png', - iconSize: [25, 41], // size of the icon - iconAnchor: [12, 41], // point of the icon which will correspond to marker's location - popupAnchor: [0, -41] // point from which the popup should open relative to the iconAnchor -}); +var homemarker, homebase, clues, clue_rels, bikes, previewmarker; -var bikeIcon = L.icon({ - iconUrl: 'static/img/marker-bike.png', - iconSize: [25, 41], // size of the icon - iconAnchor: [12, 41], // point of the icon which will correspond to marker's location - popupAnchor: [0, -41] // point from which the popup should open relative to the iconAnchor -}); +var latest_timestamp = -1; // initially -1, otherwise set to value given by server in last successful info update -var visitedIcon = L.icon({ // for all visited clues - iconUrl: 'static/img/marker-icon-grey.png', - iconSize: [25, 41], // size of the icon - iconAnchor: [12, 41], // point of the icon which will correspond to marker's location - popupAnchor: [0, -41] // point from which the popup should open relative to the iconAnchor -}); +var baseIcon = L.Icon.extend({ + options: { + iconSize: [25, 41], // size of the icon + iconAnchor: [12, 41], // point of the icon which will correspond to marker's location + popupAnchor: [0, -41] // point from which the popup should open relative to the iconAnchor + } +}) +var homeIcon = new baseIcon({iconUrl: 'static/img/marker-home.png'}), + activeBikeIcon = new baseIcon({iconUrl: 'static/img/marker-bike-active.png', className:"leaflet-bike-marker"}), + inactiveBikeIcon = new baseIcon({iconUrl: 'static/img/marker-bike-inactive.png'}), + visitedIcon = new baseIcon({iconUrl: 'static/img/marker-icon-grey.png'}), + unvisitedIcon = new baseIcon({iconUrl: 'static/img/marker-icon-blue.png'}), // generic, becomes colored when assigned to route + orangeIcon = new baseIcon({iconUrl: 'static/img/marker-icon-orange.png'}), + redIcon = new baseIcon({iconUrl: 'static/img/marker-icon-red.png'}), + greenIcon = new baseIcon({iconUrl: 'static/img/marker-icon-green.png'}), + yellowIcon = new baseIcon({iconUrl: 'static/img/marker-icon-yellow.png'}); +var bikeIcons = {'ACTIVE' : activeBikeIcon, 'INACTIVE' : inactiveBikeIcon} -var unvisitedIcon = L.icon({ // for all visited clues - iconUrl: 'static/img/marker-icon-blue.png', - iconSize: [25, 41], // size of the icon - iconAnchor: [12, 41], // point of the icon which will correspond to marker's location - popupAnchor: [0, -41] // point from which the popup should open relative to the iconAnchor -}); -var route_coords = [[-71.055561,42.368861],[-71.052522,42.367271],[-71.056507,42.362152],[-71.054519,42.359704],[-71.051539,42.360949],[-71.045199,42.362252],[-71.041597,42.366374],[-71.041248,42.364857],[-71.038908,42.368518],[-71.035936,42.367158],[-71.035967,42.365172],[-71.033209,42.363961],[-71.040015,42.367059],[-71.037911,42.369812],[-71.037188,42.371161],[-71.033036,42.37337],[-71.031355,42.375375],[-71.034935,42.380792],[-71.029904,42.376622],[-71.028298,42.377891],[-71.016232,42.38339],[-71.014571,42.380901],[-71.011693,42.382756],[-70.999131,42.38927],[-71.005456,42.390256],[-70.999967,42.390009],[-71.000362,42.388436],[-70.997084,42.390466],[-70.994955,42.392539],[-70.99031,42.391786],[-70.994955,42.392539],[-70.992622,42.396106],[-70.98178,42.392741],[-70.976359,42.386899],[-70.980137,42.380215],[-70.977664,42.385059],[-70.969384,42.389507],[-70.973097,42.387348],[-70.980126,42.390098],[-70.993747,42.411181],[-70.993534,42.408589],[-70.991202,42.408399],[-70.985934,42.420244],[-70.987188,42.418679],[-70.99748,42.418321],[-71.007923,42.416741],[-71.012109,42.410406],[-71.01537,42.411785],[-71.012414,42.409955],[-71.014511,42.406518],[-71.028327,42.398247],[-71.030138,42.399394],[-71.036726,42.391309],[-71.038526,42.390284],[-71.039316,42.385546],[-71.038723,42.387914],[-71.032794,42.386461],[-71.033749,42.389192],[-71.032506,42.396103],[-71.035674,42.397588],[-71.041015,42.393843],[-71.042858,42.393379],[-71.051453,42.402568],[-71.051833,42.405181],[-71.048082,42.404063],[-71.045594,42.412467],[-71.036237,42.414389],[-71.031525,42.412279],[-71.031258,42.418461],[-71.029338,42.421871],[-71.027113,42.421213],[-71.029041,42.422685],[-71.043219,42.422264],[-71.050739,42.418307],[-71.055953,42.42069],[-71.054522,42.419042],[-71.063476,42.413303],[-71.062128,42.407436],[-71.060882,42.403075],[-71.058992,42.403792],[-71.063245,42.403683],[-71.07097,42.396009],[-71.072007,42.397236],[-71.073656,42.398807],[-71.06758,42.402759],[-71.061508,42.402436],[-71.061206,42.398809],[-71.061612,42.400486],[-71.074409,42.38398],[-71.090615,42.379911],[-71.093444,42.381759],[-71.094916,42.379731],[-71.094764,42.377355],[-71.089131,42.376874],[-71.086892,42.373205],[-71.081336,42.371939],[-71.08097,42.367607],[-71.080171,42.369638],[-71.075628,42.369473],[-71.073462,42.368436],[-71.069119,42.373707],[-71.064235,42.375336],[-71.063105,42.374142],[-71.064212,42.376842],[-71.060948,42.380436],[-71.060753,42.376391],[-71.060933,42.376178],[-71.056172,42.375934],[-71.055588,42.374119],[-71.062837,42.369573],[-71.065634,42.371832],[-71.064287,42.369675],[-71.06828,42.369868],[-71.061735,42.369195],[-71.059808,42.366213],[-71.062507,42.365968],[-71.068045,42.367296],[-71.072713,42.361868],[-71.073339,42.356724],[-71.077458,42.355274],[-71.075414,42.356537],[-71.085166,42.349997],[-71.089477,42.350844],[-71.094885,42.360151],[-71.090578,42.361529],[-71.094885,42.360151],[-71.096306,42.362555],[-71.101083,42.363685],[-71.10141,42.36265],[-71.101475,42.3614],[-71.111234,42.35442],[-71.111226,42.349499],[-71.116011,42.35008],[-71.116795,42.345605],[-71.121734,42.342619],[-71.119813,42.345177],[-71.121439,42.351178],[-71.124132,42.351932],[-71.130896,42.352999],[-71.131464,42.352585],[-71.137307,42.353617],[-71.146009,42.349667],[-71.146124,42.350083],[-71.143863,42.356842],[-71.148301,42.357451],[-71.145775,42.361512],[-71.128473,42.363221],[-71.116228,42.364227],[-71.116127,42.361435],[-71.1088,42.364024],[-71.113445,42.370462],[-71.118959,42.373491],[-71.120839,42.373266],[-71.119379,42.375457],[-71.114496,42.378275],[-71.115739,42.378452],[-71.115952,42.376696],[-71.110851,42.374259],[-71.102512,42.382238],[-71.097894,42.380957],[-71.096887,42.380072],[-71.102659,42.382131],[-71.110771,42.383988],[-71.112746,42.383573],[-71.117164,42.389801],[-71.110886,42.398957],[-71.112241,42.400829],[-71.111371,42.399643],[-71.116937,42.4013],[-71.122704,42.396589],[-71.117004,42.389639],[-71.119303,42.38859],[-71.119219,42.388412],[-71.133098,42.388907],[-71.132876,42.3935],[-71.143078,42.396551],[-71.147394,42.404252],[-71.15533,42.40274],[-71.16988,42.408428],[-71.171169,42.409976],[-71.168458,42.410941],[-71.171169,42.409976],[-71.179624,42.414464],[-71.183452,42.42359],[-71.194736,42.425679],[-71.203921,42.429978],[-71.206933,42.429124],[-71.208917,42.422263],[-71.218928,42.415564],[-71.231484,42.417724],[-71.234617,42.398009],[-71.242207,42.380737],[-71.251022,42.37836],[-71.253322,42.374385],[-71.270022,42.372262],[-71.274446,42.367652],[-71.290894,42.367358],[-71.293875,42.359903],[-71.305349,42.351648],[-71.305652,42.342969],[-71.312339,42.342072],[-71.33626,42.325623],[-71.351385,42.323333],[-71.359132,42.320044],[-71.363981,42.317371],[-71.359917,42.313798],[-71.340407,42.315699],[-71.341697,42.318032],[-71.335699,42.321775],[-71.327044,42.321102],[-71.321809,42.32536],[-71.31702,42.324614],[-71.30971,42.327571],[-71.303618,42.325459],[-71.296735,42.328775],[-71.268746,42.323382],[-71.262316,42.323664],[-71.253047,42.327434],[-71.24646,42.321713],[-71.230201,42.321192],[-71.225826,42.317308],[-71.227365,42.314504],[-71.223413,42.344938],[-71.21089,42.347339],[-71.210616,42.351056],[-71.191804,42.355537],[-71.189804,42.361187],[-71.18542,42.361942],[-71.174168,42.35832],[-71.15842,42.358512],[-71.154136,42.352931],[-71.159035,42.341357],[-71.162549,42.341017],[-71.165995,42.339192],[-71.16236,42.333966],[-71.155951,42.330623],[-71.163783,42.326275],[-71.16198,42.324682],[-71.163783,42.326275],[-71.15881,42.326859],[-71.155413,42.33162],[-71.142763,42.343387],[-71.134334,42.338825],[-71.12756,42.33798],[-71.124946,42.335444],[-71.127191,42.333743],[-71.125847,42.331874],[-71.1185,42.33704],[-71.112246,42.336],[-71.10963,42.336448],[-71.107283,42.338917],[-71.100903,42.336152],[-71.099284,42.338007],[-71.094327,42.341231],[-71.095003,42.342001],[-71.096959,42.344689],[-71.098972,42.346814],[-71.097658,42.350114],[-71.106096,42.351083],[-71.091358,42.348977],[-71.088524,42.348907],[-71.087559,42.346916],[-71.089677,42.346361],[-71.093834,42.339096],[-71.098267,42.332009],[-71.100092,42.332401],[-71.09715,42.331785],[-71.099348,42.33047],[-71.09454,42.325354],[-71.095222,42.328428],[-71.090904,42.329829],[-71.094082,42.331699],[-71.083566,42.339307],[-71.083465,42.34194],[-71.074108,42.343558],[-71.071196,42.34085],[-71.064372,42.339567],[-71.065791,42.335353],[-71.060504,42.329045],[-71.06221,42.324934],[-71.066844,42.327134],[-71.074056,42.320756],[-71.077746,42.320431],[-71.087997,42.294939],[-71.087449,42.296172],[-71.067024,42.289067],[-71.063921,42.284476],[-71.063084,42.285832],[-71.048464,42.290114],[-71.024029,42.274385],[-71.013808,42.278297],[-71.011144,42.277183],[-71.014026,42.27938],[-71.009534,42.276371],[-71.01439,42.26665],[-71.002345,42.251399],[-71.000444,42.245312],[-71.003326,42.243971],[-71.004555,42.236929],[-70.99396,42.215849],[-70.994299,42.211128],[-70.997173,42.211322],[-71.001295,42.207533],[-70.995563,42.209513],[-70.993966,42.216189],[-70.996548,42.22389],[-71.003502,42.228708],[-71.003762,42.23913],[-71.007108,42.244146],[-71.025531,42.250203],[-71.024768,42.253413],[-71.028501,42.254638],[-71.02619,42.25528],[-71.02898,42.25784],[-71.02785,42.25609],[-71.03122,42.258422],[-71.029109,42.260295],[-71.035707,42.269102],[-71.02785,42.27581],[-71.042098,42.285957],[-71.040715,42.28867],[-71.046941,42.293738],[-71.049526,42.300919],[-71.045267,42.309351],[-71.046352,42.313327],[-71.042371,42.313686],[-71.039672,42.316948],[-71.037188,42.316288],[-71.034131,42.314368],[-71.034107,42.315966],[-71.034131,42.314368],[-71.039672,42.316948],[-71.042671,42.314182],[-71.045242,42.316292],[-71.049959,42.3197],[-71.049204,42.325624],[-71.044144,42.329966],[-71.035189,42.329187],[-71.023501,42.333255],[-71.023658,42.3359],[-71.019994,42.338437],[-71.013043,42.338284],[-71.013043,42.338284],[-71.035497,42.338144],[-71.038829,42.344223],[-71.033918,42.344315],[-71.031832,42.345088],[-71.035964,42.347795],[-71.03588,42.34898],[-71.040407,42.347902],[-71.045311,42.349281],[-71.044959,42.351052],[-71.04333,42.352749],[-71.047121,42.353667],[-71.048805,42.350902],[-71.050269,42.351671],[-71.049726,42.35199],[-71.051172,42.352211],[-71.056257,42.352917],[-71.059567,42.350941],[-71.061676,42.353717],[-71.061249,42.355298],[-71.063037,42.355519],[-71.063514,42.354894],[-71.064556,42.352372],[-71.067311,42.352314],[-71.066839,42.352445],[-71.072038,42.348915],[-71.067854,42.349993],[-71.068086,42.353792],[-71.069259,42.356131],[-71.066568,42.356682],[-71.062749,42.357905],[-71.064277,42.358851],[-71.069242,42.357529],[-71.062171,42.358056],[-71.058565,42.357428],[-71.057201,42.358757],[-71.059255,42.359295],[-71.056995,42.36049],[-71.056994,42.361263],[-71.056819,42.361534],[-71.055569,42.364032],[-71.055582,42.365251],[-71.056164,42.366918]]; -fetch('static/js/route.json') - .then((response) => response.json()) - .then((json) => drawRoute(json['features'][0]['geometry']['coordinates'])); +function zoomToBike(team_name){ + map.panTo(bikes[team_name]['marker'].getLatLng()); +} +function zoomToClue(clue_name){ + map.panTo(clue_rels[clue_name].getLatLng()); +} +function previewZoom(){ + var long = parseFloat(document.getElementById("new_clue_longitude").value); + var lat = parseFloat(document.getElementById("new_clue_latitude").value); + console.log(long); + console.log(document.getElementById("new_clue_longitude").value); + if (!isNaN(long) && !isNaN(lat)){ + previewmarker.setLatLng([lat, long]); + previewmap.panTo(previewmarker.getLatLng()); + } +} + +function drawRoute(route_coords_osrm, team_color) { + //osrm lat/long are swapped + for (var i = 0; i < route_coords_osrm.length; i++){ + var t = route_coords_osrm[i][1]; + route_coords_osrm[i][1] = route_coords_osrm[i][0]; + route_coords_osrm[i][0] = t; + } + var route = new L.polyline(route_coords_osrm, {color: team_color}).addTo(map); +} -function drawRoute(route_coords2) { - for (var i = 0; i < route_coords.length; i++){ - var t = route_coords[i][1]; - route_coords[i][1] = route_coords[i][0]; - route_coords[i][0] = t; +function updateBikeStatus(){ + var table = document.getElementById("bike-teams-table"); + table.innerHTML = ''; + for (const [key, value] of Object.entries(bikes)) { + var name = key; + var bike = value; + var row = document.createElement("tr"); + var namecell = document.createElement("td"); namecell.innerHTML = "<a href=\"#\" onclick=\"zoomToBike('"+name+"')\">"+name+"</a>"; + var statuscell = document.createElement("td"); statuscell.innerHTML = "<span "+((bike['team_status'] == "ACTIVE")? "style=\"color:lightgreen\"" : "") +">" + bike['team_status'] + " ("+parseInt(bike['time_since_last_contact']).toString()+"s)</span>"; + var targetcell = document.createElement("td"); targetcell.innerHTML = "<a href=\"#\" onclick=\"zoomToClue('"+bike['target_clue']+"')\">"+bike['target_clue']+"</a>"; + + row.appendChild(namecell); + row.appendChild(statuscell); + row.appendChild(targetcell); + table.appendChild(row); } - var route = new L.polyline(route_coords, {color:'red'}).addTo(map); } +function updateClueStats(){ + document.getElementById("total_count").innerText = clues.length; + var visited_count = 0; + var avg_distance = 0; + for (var i =0; i < clues.length; i++){ + if(clues[i]['clue_status'] == "VISITED"){ + visited_count++; + avg_distance += getDistanceFromLatLon(homebase, clues[i]); + } + } + avg_distance /= visited_count; + document.getElementById("unvisited_count").innerText = clues.length-visited_count; + document.getElementById("visited_count").innerText = visited_count; + document.getElementById("percent_visited").innerText = (100*(visited_count/clues.length)).toFixed(2); + document.getElementById("avg_visited_distance").innerText = avg_distance.toFixed(2); +} + +function drawClues(){ + unvisited_clues_m.clearLayers(); + visited_clues_m.clearLayers(); + 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']); + 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 addClue(){ + var long = parseFloat(document.getElementById("new_clue_longitude").value); + var lat = parseFloat(document.getElementById("new_clue_latitude").value); + if (isNaN(long) || isNaN(lat)){ + alert("Invalid coordinates."); + return; + } + if(confirm("Are you sure this is the right location?")){ + console.log("yes"); + } +} + +// run every x seconds to get latest info from server +function requestLatestInfo(){ + function handleLatestInfo(json){ + if(json['status'] != "OK") return; + latest_timestamp = json['timestamp']; + // process home base + if (json['home_changed']){ + homebase = json['homebase']; + if(homemarker)homemarker.setLatLng([homebase['latitude'], homebase['longitude']]); + else homemarker = L.marker([homebase['latitude'], homebase['longitude']], {icon: homeIcon}).addTo(map).bindPopup("Home is where the club is."); + } + // process bikes + if(true || json['bikes_changed']){ // always true since we need constant updates for bikes + var bikes_t = json['bikes']; + for (var i = 0; i < bikes_t.length; i++){ + var name = bikes_t[i]['team_name']; + if(name in bikes) { + bikes[name]['marker'].setLatLng([bikes_t[i]['latitude'],bikes_t[i]['longitude']]); + if(bikes_t[i]['team_status'] != [name]['team_status'])bikes[name]['marker'].setIcon(bikeIcons[bikes_t[i]['team_status']]); + for (const [key, value] of Object.entries(bikes_t[i])) { + bikes[name][key] = value; + } + } else { // add bike + var bikeMarker = new L.marker([bikes_t[i]['latitude'],bikes_t[i]['longitude']]).bindPopup(bikes_t[i]['team_name']); + bikes[name] = bikes_t[i]; + bikes[name]['marker'] = bikeMarker; + bikeMarker.setIcon(bikeIcons[bikes[name]['team_status']]); + bikes_m.addLayer(bikeMarker); + } + } + updateBikeStatus(); + } + // process clues + if(json['clues_changed']){ + clues = json['clues']; + clue_rels = {}; + drawClues(); + updateClueStats(); + } + } + fetch(host+'/getLatestInfo', { + method: "POST", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ "info_age" : latest_timestamp })}) + .then((response) => response.json()) + .then((json) => handleLatestInfo(json)); +} +var intervalId = window.setInterval(function(){ + requestLatestInfo(); + }, 5000); + +// RUN ON PAGE LOAD window.onload = function() { - console.log("loaded"); + clues = {}; bikes = {}; + map = L.map('map').setView([42.3626081,-71.0620591], 13); L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.{ext}', { minZoom: 0, @@ -55,26 +184,22 @@ window.onload = function() { attribution: '© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> © <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', ext: 'png' }).addTo(map); - previewmap = L.map('previewmap').setView([42.3626081,-71.0620591], 13); + previewmap = L.map('previewmap').setView([42.3626081,-71.0620591], 16); L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.{ext}', { minZoom: 0, maxZoom: 20, ext: 'png' }).addTo(previewmap); - var homeMarker = L.marker([homebase['latitude'], homebase['longitude']], {icon: homeIcon}).addTo(map).bindPopup("Home is where the club is."); - 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}).addTo(map).bindPopup(clues[i]['clue_name'] + ": " + clues[i]['clue_info']); - if (clues[i]['clue_status'] == "UNVISITED") unvisited_clues_m.addLayer(clueMarker); - else visited_clues_m.addLayer(clueMarker); - } - + //homemarker = L.marker([homebase['latitude'], homebase['longitude']], {icon: homeIcon}).addTo(map).bindPopup("Home is where the club is."); + previewmarker = L.marker([0,0], {icon: greenIcon}).addTo(previewmap); map.addLayer(visited_clues_m); map.addLayer(unvisited_clues_m); + map.addLayer(bikes_m); var layerControl = L.control.layers(null,null,{collapsed:false}); layerControl.addOverlay(unvisited_clues_m, "Unvisited Clues"); layerControl.addOverlay(visited_clues_m, "Visited Clues"); + layerControl.addOverlay(bikes_m, "Bikes"); layerControl.addTo(map); + requestLatestInfo(); }
\ No newline at end of file |
