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/zugportal.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/onboard/zugportal.rs (limited to 'src/onboard/zugportal.rs') diff --git a/src/onboard/zugportal.rs b/src/onboard/zugportal.rs new file mode 100644 index 0000000..0ad6cfd --- /dev/null +++ b/src/onboard/zugportal.rs @@ -0,0 +1,109 @@ +/// implementation of traits to query zugportal.de +/// (available at least in the Munich S-Bahn, maybe other trains) +use chrono::{DateTime, Utc}; +use serde::Deserialize; + +use crate::onboard; +use crate::onboard::{OnBoardAPI, OnBoardInfo}; +use crate::{traits::*, travelynx::TrainRef}; + +pub struct Zugportal {} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Journey { + name: String, // the line's name, e.g. S 8 + no: i64, + stops: Vec +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Stop { + station: Station, + status: String, // one of "Normal", ...? + track: Track, + messages: Vec, + arrival_time: Option, + departure_time: Option +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Station { + eva_no: String, + name: String +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Track { + target: String, + prediction: String +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct DepartureTime { + target: DateTime, + predicted: DateTime, + time_type: String, // one of REAL, PREVIEW, ..? + diff: i64 // diff in minutes? + // NOTE: also sends predictedTimeInMs and targetTimeInMs; these might be unix times +} + +impl IsStation for Stop { + fn name(&self) -> &str { + &self.station.name + } + + fn scheduled_arrival(&self) -> Option<&chrono::DateTime> { + self.arrival_time.as_ref().map(|t| &t.target) + } + + fn real_arrival(&self) -> Option<&chrono::DateTime> { + self.arrival_time.as_ref().map(|t| &t.predicted) + } + + fn ds100(&self) -> &str { + "??" + } +} + +impl std::fmt::Display for Stop { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.station.name) + } +} + +impl OnBoardInfo for Journey { + fn guess_last_station(&self) -> Option<&dyn IsStation> { + todo!() + } + + fn get_train_ref(&self) -> TrainRef { + TrainRef { + _type: self.name.clone(), + no: self.no.to_string().clone() + } + } + + fn stops<'a>( + &'a self + ) -> Box + 'a> { + Box::new(self.stops.iter().map(|s| s as &dyn IsStation)) + } +} + +impl OnBoardAPI for Zugportal { + fn apiurl(&self) -> &'static str { + "https://zugportal.de/prd/zupo-travel-information/api/public/ri/journey" + } + + fn request( + &self, + debug: bool + ) -> Result, serde_json::Error> { + onboard::request::<_, Journey>(self, debug) + } +} -- cgit v1.2.3