From cd13c85c69cf761b2da84ad91af64d23a3568aa5 Mon Sep 17 00:00:00 2001 From: stuebinm Date: Wed, 9 Feb 2022 02:51:59 +0100 Subject: existential types in rust are weird … lots and lots of traits … --- src/onboard/iceportal.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/onboard/iceportal.rs (limited to 'src/onboard/iceportal.rs') diff --git a/src/onboard/iceportal.rs b/src/onboard/iceportal.rs new file mode 100644 index 0000000..04ec291 --- /dev/null +++ b/src/onboard/iceportal.rs @@ -0,0 +1,126 @@ +/// implementation of traits to query the iceportal.de +/// (available in high speed trains in DE) +use chrono::{DateTime, Utc}; +use serde::Deserialize; +use serde_json::Value; + +use crate::onboard; +use crate::onboard::{OnBoardAPI, OnBoardInfo}; +use crate::{serde::*, traits::*, travelynx::TrainRef}; + +pub struct Iceportal {} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TripInfo { + trip: Trip, + connection: Option, + selected_route: Option, + active: Option +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Trip { + train_type: String, + vzn: String, // train number + // some position info here + actual_position: u64, // distance along track, presumably + stops: Vec +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Stop { + info: StopInfo, + station: Station, + timetable: Timetable +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StopInfo { + distance_from_start: u64, + position_status: String // one of "departed", "future", ... ? +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Station { + eva_nr: String, + name: String +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Timetable { + #[serde(deserialize_with = "option_naive_read_unixtime_db")] + scheduled_arrival_time: Option>, + #[serde(deserialize_with = "option_naive_read_unixtime_db")] + actual_arrival_time: Option> +} + +impl IsStation for Stop { + fn name(&self) -> &str { + &self.station.name + } + + fn scheduled_arrival(&self) -> Option<&chrono::DateTime> { + self.timetable.scheduled_arrival_time.as_ref() + } + + fn real_arrival(&self) -> Option<&chrono::DateTime> { + self.timetable.scheduled_arrival_time.as_ref() + } + + fn ds100(&self) -> &str { + "??" + } +} + +impl OnBoardInfo for TripInfo { + fn guess_last_station(&self) -> Option<&dyn IsStation> { + let current_pos = self.trip.actual_position; + self + .trip + .stops + .iter() + .rev() + .map(|stop| (stop.info.distance_from_start, stop)) + .filter(|(dist, _)| dist <= ¤t_pos) + .next() + .map(|(_, stop)| stop as &dyn IsStation) + } + + fn get_train_ref(&self) -> TrainRef { + TrainRef { + _type: self.trip.train_type.clone(), + no: self.trip.vzn.clone() + } + } + + fn stops<'a>( + &'a self + ) -> Box + 'a> { + Box::new(self.trip.stops.iter().map(|s| s as &dyn IsStation)) + } +} + +impl std::fmt::Display for Stop { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.station.name) + } +} + +impl OnBoardAPI for Iceportal { + fn apiurl(&self) -> &'static str { + "https://iceportal.de/api1/rs/tripInfo/trip" + } + + fn request( + &self, + debug: bool + ) -> Result, serde_json::Error> { + onboard::request::<_, TripInfo>(self, debug) + } +} -- cgit v1.2.3