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(),
|
||||
annotated_stop.id.clone()
|
||||
);
|
||||
|
||||
let platform = match state
|
||||
.transit_data
|
||||
.stops
|
||||
.remove(platform_id)
|
||||
.unwrap()
|
||||
.remove(platform_id)?
|
||||
.platforms
|
||||
.clone()
|
||||
{
|
||||
libseptastic::stop::StopType::SinglePlatform(plat) => Ok(plat),
|
||||
_ => Err(anyhow!("")),
|
||||
}
|
||||
.unwrap();
|
||||
libseptastic::stop::StopType::SinglePlatform(plat) => Some(plat),
|
||||
_ => None,
|
||||
}?;
|
||||
|
||||
state
|
||||
.transit_data
|
||||
.stops_by_platform_id
|
||||
.remove(&platform.id)
|
||||
.unwrap();
|
||||
.remove(&platform.id)?;
|
||||
|
||||
platform
|
||||
Some(platform)
|
||||
})
|
||||
.collect(),
|
||||
.flatten()
|
||||
.collect()
|
||||
),
|
||||
});
|
||||
|
||||
|
|
@ -300,51 +299,64 @@ impl GtfsPullService {
|
|||
if stop.1.latitude == None || stop.1.longitude == None {
|
||||
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 {
|
||||
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());
|
||||
if let Some(lat) = stop.1.latitude &&
|
||||
let Some(lng) = stop.1.longitude &&
|
||||
let Some(name) = stop.1.name.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 {
|
||||
let parent_stop = state.transit_data.stops.get(pair.0).unwrap().clone();
|
||||
//let child_stop: Vec<libseptastic::stop::Stop> = pair.1.iter().map(|stop_id| {
|
||||
// state.transit_data.stops.get(stop_id).unwrap().clone()
|
||||
//}).collect();
|
||||
let parent_stop = match state.transit_data.stops.get(pair.0) {
|
||||
Some(x) => x,
|
||||
None => continue
|
||||
}.clone();
|
||||
|
||||
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(())
|
||||
|
|
@ -417,15 +429,25 @@ impl GtfsPullService {
|
|||
let global_rt_id = make_global_id!(prefix, trip.1.route_id);
|
||||
|
||||
let dir = libseptastic::direction::Direction {
|
||||
direction: match trip.1.direction_id.unwrap() {
|
||||
gtfs_structures::DirectionType::Outbound => {
|
||||
direction: match trip.1.direction_id {
|
||||
Some(gtfs_structures::DirectionType::Outbound) => {
|
||||
libseptastic::direction::CardinalDirection::Outbound
|
||||
}
|
||||
gtfs_structures::DirectionType::Inbound => {
|
||||
Some(gtfs_structures::DirectionType::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) {
|
||||
|
|
@ -475,14 +497,13 @@ impl GtfsPullService {
|
|||
let stop = state
|
||||
.transit_data
|
||||
.stops_by_platform_id
|
||||
.get(&global_stop_id)
|
||||
.unwrap()
|
||||
.get(&global_stop_id)?
|
||||
.clone();
|
||||
|
||||
let platform = state
|
||||
.transit_data
|
||||
.platforms
|
||||
.get(&global_stop_id)
|
||||
.unwrap()
|
||||
.get(&global_stop_id)?
|
||||
.clone();
|
||||
|
||||
state
|
||||
|
|
@ -511,13 +532,14 @@ impl GtfsPullService {
|
|||
.or_insert(HashSet::new())
|
||||
.insert(platform.id.clone());
|
||||
|
||||
libseptastic::stop_schedule::StopSchedule {
|
||||
arrival_time: i64::from(s.arrival_time.unwrap()),
|
||||
Some(libseptastic::stop_schedule::StopSchedule {
|
||||
arrival_time: i64::from(s.arrival_time?),
|
||||
stop_sequence: i64::from(s.stop_sequence),
|
||||
stop,
|
||||
platform,
|
||||
}
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
if let Some(calendar_day) = state
|
||||
|
|
@ -527,22 +549,37 @@ impl GtfsPullService {
|
|||
{
|
||||
let trip = libseptastic::stop_schedule::Trip {
|
||||
trip_id: trip.1.id.clone(),
|
||||
route: state
|
||||
route: match state
|
||||
.transit_data
|
||||
.routes
|
||||
.get(&make_global_id!(prefix, trip.1.route_id))
|
||||
.unwrap()
|
||||
.clone(),
|
||||
direction: libseptastic::direction::Direction {
|
||||
direction: match trip.1.direction_id.unwrap() {
|
||||
gtfs_structures::DirectionType::Outbound => {
|
||||
libseptastic::direction::CardinalDirection::Outbound
|
||||
}
|
||||
gtfs_structures::DirectionType::Inbound => {
|
||||
libseptastic::direction::CardinalDirection::Inbound
|
||||
.clone() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
warn!("No route found for trip {} (was looking for route {})", trip.1.id, trip.1.route_id);
|
||||
continue
|
||||
}
|
||||
},
|
||||
direction: libseptastic::direction::Direction {
|
||||
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,
|
||||
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