actually add map files + reduce usage of unwrap
Some checks failed
Create and publish a Docker image / build-and-push-image (push) Failing after 4m52s
Some checks failed
Create and publish a Docker image / build-and-push-image (push) Failing after 4m52s
This commit is contained in:
parent
0698373151
commit
8a17159524
3 changed files with 195 additions and 70 deletions
52
web/src/controllers/map.rs
Normal file
52
web/src/controllers/map.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::{
|
||||||
|
AppState, services::trip_tracking, session_middleware::{SessionResponder, SessionResponse}, templates::{MapTemplate, TripPerspective}
|
||||||
|
};
|
||||||
|
use actix_web::{
|
||||||
|
HttpResponse, Responder, get, post, web::{self, Data}
|
||||||
|
};
|
||||||
|
use askama::Template;
|
||||||
|
use chrono::{TimeDelta, Timelike};
|
||||||
|
use chrono_tz::America::New_York;
|
||||||
|
use libseptastic::{stop::Stop, stop_schedule::{LiveTrip, SeatAvailability, Trip, TripTracking}};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_qs::actix::QsQuery;
|
||||||
|
use std::{
|
||||||
|
collections::{BTreeSet, HashSet}, default, sync::Arc
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#[get("/map")]
|
||||||
|
async fn get_map_element_html(state: Data<Arc<AppState>>, resp: SessionResponse) -> impl Responder {
|
||||||
|
|
||||||
|
let mut trips = state
|
||||||
|
.gtfs_service
|
||||||
|
.get_all_trips()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|trip| {
|
||||||
|
Some(trip.1.clone())
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
|
||||||
|
state.trip_tracking_service.annotate_trips(&mut trips).await;
|
||||||
|
|
||||||
|
let mut locations = vec![];
|
||||||
|
|
||||||
|
for other in trips {
|
||||||
|
if let libseptastic::stop_schedule::TripTracking::Tracked(td) = other.tracking_data {
|
||||||
|
if let Some(lat) = td.latitude && let Some(lng) = td.longitude {
|
||||||
|
locations.push((lat, lng, td.route_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mt: MapTemplate = MapTemplate {
|
||||||
|
locations
|
||||||
|
};
|
||||||
|
|
||||||
|
resp.respond(
|
||||||
|
"","",
|
||||||
|
mt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -243,28 +243,27 @@ impl GtfsPullService {
|
||||||
platform_id.clone(),
|
platform_id.clone(),
|
||||||
annotated_stop.id.clone()
|
annotated_stop.id.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
let platform = match state
|
let platform = match state
|
||||||
.transit_data
|
.transit_data
|
||||||
.stops
|
.stops
|
||||||
.remove(platform_id)
|
.remove(platform_id)?
|
||||||
.unwrap()
|
|
||||||
.platforms
|
.platforms
|
||||||
.clone()
|
.clone()
|
||||||
{
|
{
|
||||||
libseptastic::stop::StopType::SinglePlatform(plat) => Ok(plat),
|
libseptastic::stop::StopType::SinglePlatform(plat) => Some(plat),
|
||||||
_ => Err(anyhow!("")),
|
_ => None,
|
||||||
}
|
}?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
state
|
state
|
||||||
.transit_data
|
.transit_data
|
||||||
.stops_by_platform_id
|
.stops_by_platform_id
|
||||||
.remove(&platform.id)
|
.remove(&platform.id)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
platform
|
Some(platform)
|
||||||
})
|
})
|
||||||
.collect(),
|
.flatten()
|
||||||
|
.collect()
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -300,51 +299,64 @@ impl GtfsPullService {
|
||||||
if stop.1.latitude == None || stop.1.longitude == None {
|
if stop.1.latitude == None || stop.1.longitude == None {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let platform = Arc::new(Platform {
|
|
||||||
id: global_id.clone(),
|
|
||||||
name: stop.1.name.clone().unwrap(),
|
|
||||||
lat: stop.1.latitude.unwrap(),
|
|
||||||
lng: stop.1.longitude.unwrap(),
|
|
||||||
platform_location: libseptastic::stop::PlatformLocationType::Normal,
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(parent) = &stop.1.parent_station {
|
if let Some(lat) = stop.1.latitude &&
|
||||||
let parent_global_id = make_global_id!(prefix, parent);
|
let Some(lng) = stop.1.longitude &&
|
||||||
if !state.annotations.parent_stop_blacklist.contains(&parent_global_id) {
|
let Some(name) = stop.1.name.clone() {
|
||||||
map.entry(parent_global_id)
|
|
||||||
.or_insert(vec![]).push(global_id.clone());
|
let platform = Arc::new(Platform {
|
||||||
|
id: global_id.clone(),
|
||||||
|
name: name.clone(),
|
||||||
|
lat,
|
||||||
|
lng,
|
||||||
|
platform_location: libseptastic::stop::PlatformLocationType::Normal,
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(parent) = &stop.1.parent_station {
|
||||||
|
let parent_global_id = make_global_id!(prefix, parent);
|
||||||
|
if !state.annotations.parent_stop_blacklist.contains(&parent_global_id) {
|
||||||
|
map.entry(parent_global_id)
|
||||||
|
.or_insert(vec![]).push(global_id.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stop = Arc::new(libseptastic::stop::Stop {
|
||||||
|
id: global_id.clone(),
|
||||||
|
name: name.clone(),
|
||||||
|
platforms: libseptastic::stop::StopType::SinglePlatform(platform.clone()),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
state
|
||||||
|
.transit_data
|
||||||
|
.stops
|
||||||
|
.insert(global_id.clone(), stop.clone());
|
||||||
|
state
|
||||||
|
.transit_data
|
||||||
|
.platforms
|
||||||
|
.insert(global_id.clone(), platform.clone());
|
||||||
|
state
|
||||||
|
.transit_data
|
||||||
|
.stops_by_platform_id
|
||||||
|
.insert(global_id.clone(), stop.clone());
|
||||||
|
} else {
|
||||||
|
info!("Stop {} does not have all of latitude, longitude, and/or name", stop.1.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let stop = Arc::new(libseptastic::stop::Stop {
|
|
||||||
id: global_id.clone(),
|
|
||||||
name: stop.1.name.clone().unwrap(),
|
|
||||||
platforms: libseptastic::stop::StopType::SinglePlatform(platform.clone()),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
state
|
|
||||||
.transit_data
|
|
||||||
.stops
|
|
||||||
.insert(global_id.clone(), stop.clone());
|
|
||||||
state
|
|
||||||
.transit_data
|
|
||||||
.platforms
|
|
||||||
.insert(global_id.clone(), platform.clone());
|
|
||||||
state
|
|
||||||
.transit_data
|
|
||||||
.stops_by_platform_id
|
|
||||||
.insert(global_id.clone(), stop.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for pair in &map {
|
for pair in &map {
|
||||||
let parent_stop = state.transit_data.stops.get(pair.0).unwrap().clone();
|
let parent_stop = match state.transit_data.stops.get(pair.0) {
|
||||||
//let child_stop: Vec<libseptastic::stop::Stop> = pair.1.iter().map(|stop_id| {
|
Some(x) => x,
|
||||||
// state.transit_data.stops.get(stop_id).unwrap().clone()
|
None => continue
|
||||||
//}).collect();
|
}.clone();
|
||||||
|
|
||||||
state.annotations.multiplatform_stops.push(
|
state.annotations.multiplatform_stops.push(
|
||||||
MultiplatformStopConfig { id: parent_stop.id.clone(), name: parent_stop.name.clone(), platform_station_ids: pair.1.clone() }
|
MultiplatformStopConfig {
|
||||||
);
|
id: parent_stop.id.clone(),
|
||||||
|
name: parent_stop.name.clone(),
|
||||||
|
platform_station_ids: pair.1.clone()
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -417,15 +429,25 @@ impl GtfsPullService {
|
||||||
let global_rt_id = make_global_id!(prefix, trip.1.route_id);
|
let global_rt_id = make_global_id!(prefix, trip.1.route_id);
|
||||||
|
|
||||||
let dir = libseptastic::direction::Direction {
|
let dir = libseptastic::direction::Direction {
|
||||||
direction: match trip.1.direction_id.unwrap() {
|
direction: match trip.1.direction_id {
|
||||||
gtfs_structures::DirectionType::Outbound => {
|
Some(gtfs_structures::DirectionType::Outbound) => {
|
||||||
libseptastic::direction::CardinalDirection::Outbound
|
libseptastic::direction::CardinalDirection::Outbound
|
||||||
}
|
}
|
||||||
gtfs_structures::DirectionType::Inbound => {
|
Some(gtfs_structures::DirectionType::Inbound) => {
|
||||||
libseptastic::direction::CardinalDirection::Inbound
|
libseptastic::direction::CardinalDirection::Inbound
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
error!("Direction not found for trip {}", trip.1.id);
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
direction_destination: trip.1.trip_headsign.clone().unwrap(),
|
direction_destination: match trip.1.trip_headsign.clone() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
error!("No direction destination found for trip {}", trip.1.id);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match state.transit_data.directions.entry(global_rt_id) {
|
match state.transit_data.directions.entry(global_rt_id) {
|
||||||
|
|
@ -475,14 +497,13 @@ impl GtfsPullService {
|
||||||
let stop = state
|
let stop = state
|
||||||
.transit_data
|
.transit_data
|
||||||
.stops_by_platform_id
|
.stops_by_platform_id
|
||||||
.get(&global_stop_id)
|
.get(&global_stop_id)?
|
||||||
.unwrap()
|
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let platform = state
|
let platform = state
|
||||||
.transit_data
|
.transit_data
|
||||||
.platforms
|
.platforms
|
||||||
.get(&global_stop_id)
|
.get(&global_stop_id)?
|
||||||
.unwrap()
|
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
state
|
state
|
||||||
|
|
@ -511,13 +532,14 @@ impl GtfsPullService {
|
||||||
.or_insert(HashSet::new())
|
.or_insert(HashSet::new())
|
||||||
.insert(platform.id.clone());
|
.insert(platform.id.clone());
|
||||||
|
|
||||||
libseptastic::stop_schedule::StopSchedule {
|
Some(libseptastic::stop_schedule::StopSchedule {
|
||||||
arrival_time: i64::from(s.arrival_time.unwrap()),
|
arrival_time: i64::from(s.arrival_time?),
|
||||||
stop_sequence: i64::from(s.stop_sequence),
|
stop_sequence: i64::from(s.stop_sequence),
|
||||||
stop,
|
stop,
|
||||||
platform,
|
platform,
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(calendar_day) = state
|
if let Some(calendar_day) = state
|
||||||
|
|
@ -527,22 +549,37 @@ impl GtfsPullService {
|
||||||
{
|
{
|
||||||
let trip = libseptastic::stop_schedule::Trip {
|
let trip = libseptastic::stop_schedule::Trip {
|
||||||
trip_id: trip.1.id.clone(),
|
trip_id: trip.1.id.clone(),
|
||||||
route: state
|
route: match state
|
||||||
.transit_data
|
.transit_data
|
||||||
.routes
|
.routes
|
||||||
.get(&make_global_id!(prefix, trip.1.route_id))
|
.get(&make_global_id!(prefix, trip.1.route_id))
|
||||||
.unwrap()
|
.clone() {
|
||||||
.clone(),
|
Some(x) => x,
|
||||||
direction: libseptastic::direction::Direction {
|
None => {
|
||||||
direction: match trip.1.direction_id.unwrap() {
|
warn!("No route found for trip {} (was looking for route {})", trip.1.id, trip.1.route_id);
|
||||||
gtfs_structures::DirectionType::Outbound => {
|
continue
|
||||||
libseptastic::direction::CardinalDirection::Outbound
|
}
|
||||||
}
|
},
|
||||||
gtfs_structures::DirectionType::Inbound => {
|
direction: libseptastic::direction::Direction {
|
||||||
libseptastic::direction::CardinalDirection::Inbound
|
direction: match trip.1.direction_id {
|
||||||
|
Some(gtfs_structures::DirectionType::Outbound) => {
|
||||||
|
libseptastic::direction::CardinalDirection::Outbound
|
||||||
|
},
|
||||||
|
Some(gtfs_structures::DirectionType::Inbound) => {
|
||||||
|
libseptastic::direction::CardinalDirection::Inbound
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
warn!("No direction found for trip {}", trip.1.id);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
},
|
||||||
|
direction_destination: match trip.1.trip_headsign.clone() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
warn!("No headsign found for trip {}", trip.1.id);
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
direction_destination: trip.1.trip_headsign.clone().unwrap(),
|
|
||||||
},
|
},
|
||||||
tracking_data: libseptastic::stop_schedule::TripTracking::Untracked,
|
tracking_data: libseptastic::stop_schedule::TripTracking::Untracked,
|
||||||
schedule: sched,
|
schedule: sched,
|
||||||
|
|
|
||||||
36
web/templates/map.html
Normal file
36
web/templates/map.html
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||||
|
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||||
|
crossorigin=""/>
|
||||||
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||||||
|
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
|
||||||
|
crossorigin=""></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#map { height: 750px; width: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="map"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var map = L.map('map').setView([39.952583, -75.165222], 9);
|
||||||
|
|
||||||
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
maxZoom: 19,
|
||||||
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
{% for loc in locations %}
|
||||||
|
{
|
||||||
|
var icon = L.divIcon({
|
||||||
|
html: '<span style="background-color: #eee; padding: 2px;">{{ loc.2 }}</span>', // Your text here
|
||||||
|
className: 'text-label', // Custom CSS class
|
||||||
|
//iconSize: [100, 40], // Optional: Define size
|
||||||
|
//iconAnchor: [50, 20] // Optional: Center the text over the point
|
||||||
|
});
|
||||||
|
var marker = L.marker([{{loc.0}}, {{loc.1}}], {icon: icon}).addTo(map);
|
||||||
|
marker.bindPopup("{{ loc.2 }}")
|
||||||
|
}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</script>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue