seemingly finished state
This commit is contained in:
parent
eab76d8787
commit
ab4e669f55
9 changed files with 111 additions and 28 deletions
|
@ -7,14 +7,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<!-- google maps api-->
|
||||
<script>
|
||||
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
|
||||
key: "AIzaSyBa1wDqAMfKv30BSzSdXB-AEsk4BRD9xTw",
|
||||
v: "weekly",
|
||||
// Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
|
||||
// Add other bootstrap parameters as needed, using camel case.
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="map"></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
import './style.css'
|
||||
|
||||
window.main = main;
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyBa1wDqAMfKv30BSzSdXB-AEsk4BRD9xTw&callback=main&libraries=geometry';
|
||||
script.async = true;
|
||||
|
||||
document.head.appendChild(script);
|
||||
|
||||
async function main(){
|
||||
const {Map} = await google.maps.importLibrary("maps");
|
||||
const map = new Map(document.getElementById("map"),{
|
||||
|
@ -34,11 +42,13 @@ async function main(){
|
|||
const to_lattitude_input = document.createElement("input");
|
||||
to_lattitude_input.placeholder = "42.10125081757972";
|
||||
to_lattitude_input.type = "number";
|
||||
to_lattitude_input.id = "to_lattitude_input";
|
||||
UI.appendChild(to_lattitude_input);
|
||||
|
||||
const to_longitude_input = document.createElement("input");
|
||||
to_longitude_input.type = "number";
|
||||
to_longitude_input.placeholder = "-75.94181323552698";
|
||||
to_longitude_input.id = "to_longitude_input";
|
||||
UI.appendChild(to_longitude_input);
|
||||
|
||||
const to_pos_button = document.createElement("button");
|
||||
|
@ -57,6 +67,13 @@ async function main(){
|
|||
sub_button.innerText = "Submit";
|
||||
UI.appendChild(sub_button);
|
||||
|
||||
window.paths = [];
|
||||
let clear_button = document.createElement("button");
|
||||
clear_button.addEventListener("click", clear_lines);
|
||||
clear_button.id = "clear_button";
|
||||
clear_button.innerText = "Clear";
|
||||
UI.appendChild(clear_button)
|
||||
|
||||
map.addListener("click", e=>{
|
||||
const {lat, lng} = e.latLng;
|
||||
if(from_pos_toggle){
|
||||
|
@ -75,10 +92,46 @@ async function main(){
|
|||
function submit_func(map){
|
||||
//TODO: grab the path and show the poly lines and the bus route name
|
||||
async function submit(clickEvent){
|
||||
let from_lat = document.getElementById("from_lattitude_input");
|
||||
let from_lon = document.getElementById("from_longitude_input");
|
||||
}
|
||||
let from_lat = document.getElementById("from_lattitude_input").value;
|
||||
let from_lon = document.getElementById("from_longitude_input").value;
|
||||
let to_lat = document.getElementById("to_lattitude_input").value;
|
||||
let to_lon = document.getElementById("to_longitude_input").value;
|
||||
let path = await fetch(`http://localhost:8080/path?time=e&from_lat=${from_lat}&from_lon=${from_lon}&to_lat=${to_lat}&to_lon=${to_lon}`).then(r=>r.json());
|
||||
let secs = [];
|
||||
for(let route of path.path){
|
||||
console.log(route.route_name);
|
||||
secs.push(fetch(`http://localhost:8080/time_to_arrive?service=${route.service}&from=${route.enter_stop_id}&to=${route.exit_stop_id}&route=${route.route_id}`).then(r=>r.json()));
|
||||
fetch(`http://localhost:8080/route_draw?service=${route.service}&id=${route.route_id}`).then(r=>r.json()).then(v=>{
|
||||
return {path:google.maps.geometry.encoding.decodePath(v.poly_line), color:v.color}
|
||||
})
|
||||
.then(o=>{
|
||||
let line = new google.maps.Polyline({
|
||||
path:o.path,
|
||||
strokeColor: o.color,
|
||||
strokeOpacity: 1.0,
|
||||
strokeWeight: 3,
|
||||
});
|
||||
line.setMap(map);
|
||||
window.paths.push(line);
|
||||
//setTimeout(()=>line.setVisible(false), 5000);
|
||||
})
|
||||
}
|
||||
Promise.all(secs).then(l=>l.reduce((a,b)=>a+b)).then(v=>alert(`bus ride will take ${display_time(v)}`));
|
||||
}
|
||||
return submit;
|
||||
}
|
||||
|
||||
main();
|
||||
function display_time(secs){
|
||||
if(secs > 60){
|
||||
return `${Math.floor(secs/60)} minutes and ${secs%60} seconds`;
|
||||
}
|
||||
else{
|
||||
return `${secs%60} seconds`;
|
||||
|
||||
}
|
||||
}
|
||||
async function clear_lines(){
|
||||
for (let path of window.paths) path.setMap(null);
|
||||
window.paths = [];
|
||||
console.clear();
|
||||
}
|
||||
|
|
16
BBB_frontend/package-lock.json
generated
16
BBB_frontend/package-lock.json
generated
|
@ -7,6 +7,9 @@
|
|||
"": {
|
||||
"name": "bbb-frontend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@googlemaps/js-api-loader": "^1.16.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.1.0"
|
||||
}
|
||||
|
@ -379,6 +382,14 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@googlemaps/js-api-loader": {
|
||||
"version": "1.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.6.tgz",
|
||||
"integrity": "sha512-V8p5W9DbPQx74jWUmyYJOerhiB4C+MHekaO0ZRmc6lrOYrvY7+syLhzOWpp55kqSPeNb+qbC2h8i69aLIX6krQ==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz",
|
||||
|
@ -592,6 +603,11 @@
|
|||
"@esbuild/win32-x64": "0.19.12"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
|
|
@ -10,5 +10,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@googlemaps/js-api-loader": "^1.16.6"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,13 @@ to run you need a file called GOOGLE_API_KEY in the dir the app is run in which
|
|||
|
||||
## TODO:
|
||||
|
||||
- test with OCCT buses
|
||||
- test with BC buses
|
||||
- Make buttons change color to indicate toggle
|
||||
- Prevent buses from going backwards
|
||||
- make time estimate accurate (beyond hack divide by 3)
|
||||
- Change api to give a not shitty poly line for Broome county buses
|
||||
- Trim poly lines down to the bit between bus stops
|
||||
- Fix the UI so console and alert aren't needed
|
||||
- refactor to work within docker and setup within docker-compose
|
||||
- make route checking more advanced with better walking heuristic
|
||||
- make route checking more advanced by allowing multiple factors with multiple weights including
|
||||
|
@ -14,6 +19,5 @@ to run you need a file called GOOGLE_API_KEY in the dir the app is run in which
|
|||
- bus travel time
|
||||
- layover time
|
||||
- ultimate arrival time
|
||||
- Test for Broome county buses (can't at night due to being too late)
|
||||
- use a DB via SeaORM to avoid spaming APIs
|
||||
- use info in db to try and predict bus schedules in future
|
||||
|
|
|
@ -59,7 +59,7 @@ struct LocIn{
|
|||
}
|
||||
fn build_route_body_pain(path:&[crate::types::Coords])->serde_json::Value{
|
||||
let inter = if path.len() >= 2 {
|
||||
&path[1..25]//path.len()-1]
|
||||
&path[1..25.min(path.len()-1)]//]
|
||||
}else {[].as_slice()};
|
||||
let inter = inter.iter().map(|v|{
|
||||
serde_json::json!({
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -21,7 +21,11 @@ async fn main() -> anyhow::Result<()> {
|
|||
app.at("/route_draw").get(bus_route_draw);
|
||||
app.at("/").get(|_|async {
|
||||
println!("get");
|
||||
Ok(tide::Response::from("OK"))
|
||||
let resp = tide::Response::builder(200)
|
||||
.body("OK")
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.build();
|
||||
Ok(resp)
|
||||
});
|
||||
app.at("/*").get(|_|async{
|
||||
Ok(tide::Response::from("???"))
|
||||
|
@ -61,7 +65,8 @@ async fn transit_path(req: tide::Request<state::State>)->tide::Result{
|
|||
route_name:route.name,
|
||||
route_id: route.id,
|
||||
enter_stop_id:enter,
|
||||
exit_stop_id:exit
|
||||
exit_stop_id:exit,
|
||||
service: route.service.into()
|
||||
}
|
||||
}).collect();
|
||||
let ret = TransitPathResult{
|
||||
|
@ -71,6 +76,7 @@ async fn transit_path(req: tide::Request<state::State>)->tide::Result{
|
|||
let resp = tide::Response::builder(200)
|
||||
.body(resp_body)
|
||||
.header("Content-Type","application/json")
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.build();
|
||||
Ok(resp)
|
||||
}
|
||||
|
@ -85,14 +91,15 @@ struct TransitPathQuery{
|
|||
}
|
||||
#[derive(serde::Serialize)]
|
||||
struct TransitPathResult{
|
||||
path:Vec<RetRoute>,
|
||||
path:Vec<RetRoute<&'static str>>,
|
||||
}
|
||||
#[derive(serde::Serialize)]
|
||||
struct RetRoute{
|
||||
struct RetRoute<S:AsRef<str>>{
|
||||
route_name:String,
|
||||
route_id: u32,
|
||||
enter_stop_id:u32,
|
||||
exit_stop_id:u32,
|
||||
service: S
|
||||
//enter_stop_coords: types::Coords
|
||||
}
|
||||
|
||||
|
@ -122,10 +129,11 @@ async fn transit_estimate(req: tide::Request<state::State>)->tide::Result{
|
|||
let Some((to_idx,_)) = route.stops.iter().enumerate().find(|(_,stop)|stop.id == query.to)
|
||||
else {return Ok(tide::Response::builder(400).body("Error: invalid id").into())};
|
||||
|
||||
let resp_body = format!("{}", path_calc::bus_travel_time(route, from_idx, to_idx).await?.num_seconds());
|
||||
let resp_body = format!("{}", path_calc::bus_travel_time(route, from_idx, to_idx).await?.num_seconds()/3);
|
||||
let resp = tide::Response::builder(200)
|
||||
.body(resp_body)
|
||||
.header("Content-Type","application/json")
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.build();
|
||||
Ok(resp)
|
||||
}
|
||||
|
@ -166,6 +174,7 @@ async fn bus_route_draw(req: tide::Request<state::State>)->tide::Result{
|
|||
let resp = tide::Response::builder(200)
|
||||
.body(resp_body)
|
||||
.header("Content-Type","application/json")
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.build();
|
||||
Ok(resp)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub async fn bus_travel_time(route:crate::route::Route, from_idx:usize, to_idx:usize)->anyhow::Result<chrono::Duration>{
|
||||
let coords:Vec<crate::types::Coords> = route.stops[from_idx..=to_idx].iter()
|
||||
// TODO: taking the min allows the bus to go backwards for travel time which is illegal
|
||||
let coords:Vec<crate::types::Coords> = route.stops[from_idx.min(to_idx)..=to_idx.max(from_idx)].iter()
|
||||
.map(|stop|crate::types::Coords{lat:stop.lat, lon:stop.lon})
|
||||
.collect();
|
||||
let travel_time = crate::google::calc_travel_path(&coords).await?;
|
||||
|
@ -62,10 +63,10 @@ pub async fn calc_route(routes:&mut [crate::route::Route], from:crate::types::Co
|
|||
let bc_route_cost = u64::MAX;
|
||||
|
||||
let min = *[direct_route_cost,bu_route_cost,bc_route_cost].iter().min().unwrap();
|
||||
if min == direct_route_cost{
|
||||
if direct_route_cost <= min{
|
||||
Ok(vec![(min_direct_route.clone(), min_direct_route.stops.iter().min_by_key(measure_distance_from).unwrap().id, min_direct_route.stops.iter().min_by_key(measure_distance_to).unwrap().id)])
|
||||
}
|
||||
else if min == bu_route_cost{
|
||||
else if min >= bu_route_cost{
|
||||
Ok(vec![(min_to_bu_route.clone(), min_to_bu_route.stops.iter().min_by_key(measure_distance_from).unwrap().id, min_to_bu_route.stops.iter().min_by_key(measure_distance_bu.clone()).unwrap().id),(min_from_bu_route.clone(), min_from_bu_route.stops.iter().min_by_key(measure_distance_bu).unwrap().id, min_from_bu_route.stops.iter().min_by_key(measure_distance_to).unwrap().id)])
|
||||
|
||||
}
|
||||
|
|
15
src/types.rs
15
src/types.rs
|
@ -5,11 +5,16 @@ pub struct Coords{
|
|||
pub lon:f64
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash)]
|
||||
pub enum Service{OCCT, BC}
|
||||
#[derive(Clone, Copy, Debug, Hash, Default)]
|
||||
pub enum Service{OCCT, #[default]BC}
|
||||
|
||||
impl Default for Service{
|
||||
fn default() -> Self {
|
||||
Service::BC
|
||||
|
||||
impl From<Service> for &'static str{
|
||||
fn from(value: Service) -> Self {
|
||||
match value {
|
||||
Service::OCCT => "OCCT",
|
||||
Service::BC => "BC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue