diff --git a/Cargo.lock b/Cargo.lock index ebd8558..7f67861 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,6 +173,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "core-foundation" version = "0.9.4" @@ -250,43 +256,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -354,8 +329,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -365,9 +342,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -484,22 +463,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots", ] [[package]] @@ -520,7 +484,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "system-configuration", "tokio", "tower-service", @@ -694,12 +658,6 @@ version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - [[package]] name = "litemap" version = "0.8.0" @@ -722,6 +680,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchit" version = "0.8.4" @@ -760,23 +724,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "object" version = "0.36.7" @@ -792,50 +739,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "parking_lot" version = "0.12.4" @@ -877,12 +780,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - [[package]] name = "potential_utf" version = "0.1.2" @@ -910,6 +807,61 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.5.10", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.40" @@ -979,21 +931,21 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -1001,6 +953,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", ] [[package]] @@ -1024,17 +977,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] -name = "rustix" -version = "1.0.8" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustls" @@ -1043,6 +989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1055,6 +1002,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] @@ -1081,44 +1029,12 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "serde" version = "1.0.219" @@ -1211,6 +1127,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.0" @@ -1285,19 +1211,6 @@ dependencies = [ "libc", ] -[[package]] -name = "tempfile" -version = "3.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "thiserror" version = "2.0.15" @@ -1328,6 +1241,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.47.1" @@ -1343,7 +1271,7 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2", + "socket2 0.6.0", "tokio-macros", "windows-sys 0.59.0", ] @@ -1359,16 +1287,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.2" @@ -1534,12 +1452,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -1651,6 +1563,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "windows-link" version = "0.1.3" diff --git a/index.html b/index.html index a6d502d..8c30b3c 100644 --- a/index.html +++ b/index.html @@ -466,8 +466,17 @@ function hideFocusDeparturePanel() { } domFocusedDeparturePanelCloseClickable.addEventListener("click", hideFocusDeparturePanel); -function goInGame() { +async function goInGame() { isInGame = true; + // make server get all eva numbers of the destination station + let testDestinationDepartures = await (await fetch("./query_departures/" + encodeURIComponent(transportModesInteger) + "/" + encodeURIComponent(stationDestination.evaNumber) + "/")).json(); + if (testDestinationDepartures[1].length < 10) { + if (!window.confirm("Warning: Low activity (" + testDestinationDepartures[1].length + ") at the specified destination. It may not be possible to win.")) { + isInGame = false; + return; + } + } + stationDestination.relatedEvaNumbers = testDestinationDepartures[0]; for (const elem of draggableElements) elem.style.cursor = "default"; draggableElements = new Array(); domWelcome.style.display = "none"; @@ -480,20 +489,23 @@ domStartGameButton.onclick = () => goInGame(); async function reloadDepartures() { domDeparturesList.replaceChildren(); hideFocusDeparturePanel(); - let currentEvaNumber = stationCurrent.evaNumber; - if (currentEvaNumber === stationDestination.evaNumber) { - // TODO: obv - alert("You won! Unfortunately, i haven't made a screen for that yet..."); - location.reload(); + if (stationDestination.evaNumber === stationCurrent.evaNumber || (stationDestination.relatedEvaNumbers && stationDestination.relatedEvaNumbers.includes(stationCurrent.evaNumber))) { + endGameWin(); return; } - let response = await fetch("./query_departures/" + encodeURIComponent(transportModesInteger) + "/" + encodeURIComponent(currentEvaNumber) + "/"); + let response = await fetch("./query_departures/" + encodeURIComponent(transportModesInteger) + "/" + encodeURIComponent(stationCurrent.evaNumber) + "/"); if (!response.ok) { let error = await response.text(); console.warn("Query Departures: Got error " + response.status + " from server: " + error); } else { - let result = await response.json(); - for (const [route, stops, routeId] of result) { + let [stationRelatedEvaNumbers, result] = await response.json(); + for (let relatedEvaNumber of stationRelatedEvaNumbers) { + if (stationDestination.evaNumber === relatedEvaNumber || (stationDestination.relatedEvaNumbers && stationDestination.relatedEvaNumbers.includes(relatedEvaNumber))) { + endGameWin(); + return; + } + } + for (const [route, stopEvaNumber, stops, routeId] of result) { if (stops.length > 0) { let departureElem = document.createElement("div"); let departureElemHead = document.createElement("div"); @@ -543,7 +555,7 @@ async function reloadDepartures() { let canceled = result[1]; let foundCurrent = true; for (const [stop, evaNumber] of result[0]) { - if (evaNumber === currentEvaNumber) foundCurrent = false; + if (evaNumber === stopEvaNumber) foundCurrent = false; } for (const [stop, evaNumber] of result[0]) { console.log(stop, ": ", evaNumber); @@ -551,7 +563,7 @@ async function reloadDepartures() { stopElem.innerText = stop; stopElem.style.wordWrap = "nowrap"; if (!foundCurrent) { - if (evaNumber === currentEvaNumber) { + if (evaNumber === stopEvaNumber) { foundCurrent = true; stopElem.classList.add("DetailedViewCurrentStop"); } else { @@ -574,6 +586,12 @@ async function reloadDepartures() { } } +function endGameWin() { + // TODO: obv + alert("You won! Unfortunately, i haven't made a screen for that yet..."); + location.reload(); +} + diff --git a/src/bahn_api/basic_types.rs b/src/bahn_api/basic_types.rs index e2cbeef..331ab91 100644 --- a/src/bahn_api/basic_types.rs +++ b/src/bahn_api/basic_types.rs @@ -7,10 +7,10 @@ pub mod station_ids { pub id: StationId, } - #[derive(Debug, PartialEq, Eq, Hash)] + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct StationEvaNumber(pub String); - #[derive(Debug, PartialEq, Eq)] + #[derive(Clone, Debug, PartialEq, Eq)] pub struct DbStopId(pub String); impl StationEvaNumber { @@ -49,7 +49,7 @@ pub mod station_ids { } } - #[derive(Debug)] + #[derive(Clone, Debug)] pub struct StationId { pub eva_number: StationEvaNumber, pub db_station_id: DbStopId, diff --git a/src/bahn_api/departures_arrivals.rs b/src/bahn_api/departures_arrivals.rs index 654bd16..7651767 100644 --- a/src/bahn_api/departures_arrivals.rs +++ b/src/bahn_api/departures_arrivals.rs @@ -6,7 +6,7 @@ use crate::bahn_api::transport_modes::TransportMode; use super::{ basic_types::{ route_ids::RouteId, - station_ids::{AsStationId, StationIdRef}, + station_ids::{AsStationId, StationEvaNumber, StationIdRef}, }, transport_modes::TransportModesSet, }; @@ -82,6 +82,7 @@ pub struct Arrivals { #[derive(Debug)] pub struct Departure { pub id: RouteId, + pub station: StationEvaNumber, pub route: String, pub category: Option, pub stops: Vec, @@ -90,6 +91,7 @@ pub struct Departure { #[derive(Debug)] pub struct Arrival { pub id: RouteId, + pub station: StationEvaNumber, pub route: String, pub category: Option, pub stops: Vec, @@ -133,7 +135,10 @@ impl GetDepartureOrArrivalError for GetArrivalsError { pub mod deserialize { use serde::Deserialize; - use crate::bahn_api::{basic_types::route_ids::RouteId, transport_modes::TransportMode}; + use crate::bahn_api::{ + basic_types::{route_ids::RouteId, station_ids::StationEvaNumber}, + transport_modes::TransportMode, + }; use super::{ Arrival, Arrivals, Departure, Departures, GetArrivalsError, GetDeparturesError, NamedStop, @@ -176,6 +181,7 @@ pub mod deserialize { .map(|dep| Departure { id: RouteId(dep.journey_id), route: dep.vehicle.route, + station: StationEvaNumber(dep.bahnhofs_id), category: dep .vehicle .category @@ -216,6 +222,7 @@ pub mod deserialize { .map(|arr| Arrival { id: RouteId(arr.journey_id), route: arr.vehicle.route, + station: StationEvaNumber(arr.bahnhofs_id), category: arr .vehicle .category @@ -233,13 +240,13 @@ pub mod deserialize { #[derive(Deserialize)] pub struct DepData { - #[serde(rename = "entries")] + #[serde(default, rename = "entries")] departures: Vec, } #[derive(Deserialize)] pub struct ArrData { - #[serde(rename = "entries")] + #[serde(default, rename = "entries")] arrivals: Vec, } @@ -249,6 +256,7 @@ pub mod deserialize { #[serde(rename = "ueber")] stops: Vec, journey_id: String, + bahnhofs_id: String, #[serde(default)] terminus: Option, #[serde(rename = "verkehrmittel")] @@ -261,6 +269,7 @@ pub mod deserialize { #[serde(rename = "ueber")] stops: Vec, journey_id: String, + bahnhofs_id: String, #[serde(default)] terminus: Option, #[serde(rename = "verkehrmittel")] diff --git a/src/server/mod.rs b/src/server/mod.rs index 2ec0c76..fb9481f 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,6 +1,6 @@ pub mod ratelimit; -use std::sync::Arc; +use std::{collections::HashSet, sync::Arc}; use axum::{Json, extract::Path, response::Html, routing::get}; use rand::seq::IndexedRandom; @@ -74,8 +74,10 @@ pub async fn main() { Station { name: station.station.name, db_station_id: station.station.id.db_station_id, + related_stations: HashSet::new(), lat_lon: station.lat_lon, transport_modes: Some(station.transport_modes), + has_been_changed: true, }, ); } @@ -98,8 +100,8 @@ pub async fn main() { return Err(StatusCode::NOT_FOUND); } let eva_number = StationEvaNumber(eva_number); - if let Some(station) = stations.lock().await.get(&eva_number) { - match departures((&eva_number, station), transport_modes).await { + if let Some(station) = stations.lock().await.get_mut(&eva_number) { + match departures((&eva_number, &station.db_station_id), transport_modes).await { Err(e) => { eprintln!( "Tried to get departures at {}, but got error: {e:?}", @@ -107,23 +109,36 @@ pub async fn main() { ); Err(StatusCode::INTERNAL_SERVER_ERROR) } - Ok(departures) => Ok(Json( - departures - .departures - .into_iter() - .map(|departure| { - ( - departure.route, - departure - .stops - .into_iter() - .map(|stop| stop.name) - .collect::>(), - departure.id.0, - ) - }) - .collect::>(), - )), + Ok(departures) => { + for departure in departures.departures.iter() { + if departure.station != eva_number && !station.related_stations.contains(&departure.station) { + station.related_stations.insert(departure.station.clone()); + } + } + Ok(Json(( + station + .related_stations + .iter() + .map(|v| v.0.clone()) + .collect::>(), + departures + .departures + .into_iter() + .map(|departure| { + ( + departure.route, + departure.station.0, + departure + .stops + .into_iter() + .map(|stop| stop.name) + .collect::>(), + departure.id.0, + ) + }) + .collect::>(), + ))) + } } } else { Err(StatusCode::GONE) @@ -163,8 +178,10 @@ pub async fn main() { Station { name: station.name, db_station_id: station.id.db_station_id, + related_stations: HashSet::new(), lat_lon: None, transport_modes: None, + has_been_changed: true, }, ); } diff --git a/src/storage/stations.rs b/src/storage/stations.rs index b3b1235..175f6a4 100644 --- a/src/storage/stations.rs +++ b/src/storage/stations.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use crate::bahn_api::{ basic_types::station_ids::{DbStopId, StationEvaNumber, StationIdRef}, @@ -12,8 +12,10 @@ pub struct Stations { pub struct Station { pub name: String, pub db_station_id: DbStopId, + pub related_stations: HashSet, pub lat_lon: Option<(f64, f64)>, pub transport_modes: Option, + pub has_been_changed: bool, } impl Stations { @@ -23,7 +25,7 @@ impl Stations { } } - pub fn insert(&mut self, eva_number: StationEvaNumber, station: Station) { + pub fn insert(&mut self, eva_number: StationEvaNumber, mut station: Station) { if let Some(prev) = self.stations.get_mut(&eva_number) { // partial update: if we had more information than the new `station` has, // keep parts of the old information, but wherever the new `station` has @@ -35,12 +37,18 @@ impl Stations { Station { name: String::new(), db_station_id: DbStopId(unreachable!()), + related_stations: HashSet::new(), lat_lon: None, transport_modes: None, + has_been_changed: true, } } + prev.has_been_changed = true; prev.name = station.name; prev.db_station_id = station.db_station_id; + for station in station.related_stations { + prev.related_stations.insert(station); + } if let Some(v) = station.lat_lon { prev.lat_lon = Some(v); } @@ -48,20 +56,29 @@ impl Stations { prev.transport_modes = Some(v); } } else { + station.has_been_changed = true; self.stations.insert(eva_number, station); } } - pub fn get(&mut self, eva_number: &StationEvaNumber) -> Option<&Station> { + pub fn get(&self, eva_number: &StationEvaNumber) -> Option<&Station> { self.stations.get(eva_number) } + pub fn get_mut(&mut self, eva_number: &StationEvaNumber) -> Option<&mut Station> { + self.stations.get_mut(eva_number) + } } impl<'a> From<(&'a StationEvaNumber, &'a Station)> for StationIdRef<'a> { fn from(value: (&'a StationEvaNumber, &'a Station)) -> Self { + (value.0, &value.1.db_station_id).into() + } +} +impl<'a> From<(&'a StationEvaNumber, &'a DbStopId)> for StationIdRef<'a> { + fn from(value: (&'a StationEvaNumber, &'a DbStopId)) -> Self { StationIdRef { eva_number: value.0, - db_station_id: &value.1.db_station_id, + db_station_id: &value.1, } } }