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

This commit is contained in:
Nicholas Orlowsky 2026-04-19 22:54:49 -04:00
parent 0698373151
commit 8a17159524
No known key found for this signature in database
GPG key ID: A9F3BA4C0AA7A70B
3 changed files with 195 additions and 70 deletions

View 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
)
}

View file

@ -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
View 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: '&copy; <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>