From 67e8e03f52af5dfde5e6b291a3adbae66cb97593 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Thu, 3 Oct 2024 22:43:16 +0200 Subject: [PATCH 01/11] Yeetus deletus, rip out the arrivals table (it has become unnecessary to the new goal of creating a switching table --- TODO.md | 2 +- index.html | 15 ++++++--------- locations.txt | 5 +++++ main.js | 30 ++++++------------------------ 4 files changed, 18 insertions(+), 34 deletions(-) create mode 100644 locations.txt diff --git a/TODO.md b/TODO.md index 1f8e729..36d9ef6 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ # TODO: -- Add Departure from Wasserstraße to Arrivals so you +- Add the departures/arrivals from `locations.txt` so you can actually get the time you will have to leave for the bus - CSS all the things diff --git a/index.html b/index.html index 7e41ab4..de799b5 100644 --- a/index.html +++ b/index.html @@ -6,14 +6,11 @@ -

Departures

- - -
-

Arrivals

- - -
- +
+ + +
+
+ \ No newline at end of file diff --git a/locations.txt b/locations.txt new file mode 100644 index 0000000..20ba298 --- /dev/null +++ b/locations.txt @@ -0,0 +1,5 @@ +Ozeanum +Wasserstraße +Bahnhof +Bahnhof Rügendamm + diff --git a/main.js b/main.js index ab63b07..8df1a87 100644 --- a/main.js +++ b/main.js @@ -1,18 +1,13 @@ -function format(infos){ +function formatInfos(infos){ let output = [] for (let i = 0; i < infos.length; i++) { const info = infos[i]; - // console.log('=====') - // console.log(info.direction || info.provenance); - // console.log(info.line.name); - // const time = new Date(info.plannedWhen) - // console.log(time.getHours() + ':' + time.getMinutes()); - output.push(formatInfo(info)); + output.push(formatBody(info)); } return output; } -function formatInfo(info){ +function formatBody(info){ const container = document.createElement("tr") const lineName = document.createElement("td") const destination = document.createElement("td") @@ -37,10 +32,6 @@ async function getDepartures(id, params) { return (await queryStops("departures", id, params)).departures } -async function getArrivals(id, params) { - return (await queryStops("arrivals", id, params)).arrivals -} - async function queryStops(type, id, params) { const urlSearchParams = new URLSearchParams(params); const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); @@ -54,8 +45,7 @@ async function queryStops(type, id, params) { } (async () => { - const departBody = document.querySelector("#departTable") - const arriveBody = document.querySelector("#arriveTable") + const body = document.querySelector("#departTable"); const id = 8010338; const params = { duration: 600, @@ -63,15 +53,7 @@ async function queryStops(type, id, params) { linesOfStops: false, remarks: true, }; - const addParams = structuredClone(params); - addParams.direction = "325719"; - let departures = format(await getDepartures(id, params)); - // let departSep = document.createElement("h2") - // departSep.innerText = "Departures" - let arrivals = format(await getArrivals(id, addParams)) - // let arrivalSep = document.createElement("h2") - // arrivalSep.innerText = "Arrivals" - departBody.replaceChildren(...departures) - arriveBody.replaceChildren(...arrivals) + let departures = formatInfos(await getDepartures(id, params)); + body.replaceChildren(...departures) })(); From 2386c0482417e1d5cdc06d378680508132314b68 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Mon, 16 Dec 2024 21:15:57 +0100 Subject: [PATCH 02/11] **All the changes** --- .gitignore | 0 README.md | 0 TODO.md | 0 .../DepartureMono-Regular.otf | Bin .../DepartureMono-Regular.woff | Bin .../DepartureMono-Regular.woff2 | Bin fonts/DepartureMono-1.346/LICENSE | 0 fonts/DepartureMono-1.346/README.md | 0 index.html | 11 +- locations.txt | 0 main.css | 66 +++++++++- main.js | 32 ++--- main2.mjs | 11 ++ transchamp/api.mjs | 69 ++++++++++ transchamp/data.mjs | 73 +++++++++++ transchamp/display.mjs | 121 ++++++++++++++++++ transchamp/index.mjs | 0 17 files changed, 356 insertions(+), 27 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 README.md mode change 100644 => 100755 TODO.md mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.otf mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.woff mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 mode change 100644 => 100755 fonts/DepartureMono-1.346/LICENSE mode change 100644 => 100755 fonts/DepartureMono-1.346/README.md mode change 100644 => 100755 index.html mode change 100644 => 100755 locations.txt mode change 100644 => 100755 main.css mode change 100644 => 100755 main.js create mode 100644 main2.mjs create mode 100644 transchamp/api.mjs create mode 100644 transchamp/data.mjs create mode 100644 transchamp/display.mjs create mode 100644 transchamp/index.mjs diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/TODO.md b/TODO.md old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.otf b/fonts/DepartureMono-1.346/DepartureMono-Regular.otf old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.woff b/fonts/DepartureMono-1.346/DepartureMono-Regular.woff old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 b/fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/LICENSE b/fonts/DepartureMono-1.346/LICENSE old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/README.md b/fonts/DepartureMono-1.346/README.md old mode 100644 new mode 100755 diff --git a/index.html b/index.html old mode 100644 new mode 100755 index de799b5..dd30e0e --- a/index.html +++ b/index.html @@ -6,11 +6,10 @@ -
- - -
-
- + + +
+ + \ No newline at end of file diff --git a/locations.txt b/locations.txt old mode 100644 new mode 100755 diff --git a/main.css b/main.css old mode 100644 new mode 100755 index 662e15d..04bdb3e --- a/main.css +++ b/main.css @@ -9,21 +9,77 @@ } :root { - font-family: "Departure Mono"; + font-family: "Departure Mono", serif; + + --foreground-color: black; + --background-color: #5e7b6f; + --font-size: 12pt; + + color: var(--foreground-color); + background-color: var(--background-color); + font-size: var(--font-size); +} + +table { + border-collapse: collapse; } .information { width: 100%; + text-align: left; + + tr td, tr th { + vertical-align: top; + line-height: 1.5; + padding: .5em; + } + tr td { + height: calc(2 * 1.5 * 1em); + } } .time { - text-align: right; + text-align: left; + width: 1em; + + .actual { + font-weight: bold; + } + .planned, .delay { + font-size: 75%; + } + .delay { + color: red; + font-weight: bold; + background-color: var(--foreground-color); + padding: .5ex; + } + .delay::before { + content: "+" + } +} + +td.time { + background-color: var(--foreground-color); + color: var(--background-color); } .line { - width: 10em; + width: 10ex; + text-align: left; +} + +.direction { + width: auto; + text-align: left; +} + +.platform { + width: 3em; + text-align: right; } -.container { - height: 3em; +.cancelled .line, .cancelled .direction { + text-decoration: line-through; + color: red; } \ No newline at end of file diff --git a/main.js b/main.js old mode 100644 new mode 100755 index 8df1a87..c7e2b98 --- a/main.js +++ b/main.js @@ -27,22 +27,22 @@ function formatBody(info){ return container } - -async function getDepartures(id, params) { - return (await queryStops("departures", id, params)).departures -} - -async function queryStops(type, id, params) { - const urlSearchParams = new URLSearchParams(params); - const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); - // duration=600&results=20&linesOfStops=false&remarks=true" - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Error: ${response.status}`); - } - - return await response.json(); -} +// +// async function getDepartures(id, params) { +// return (await queryStops("departures", id, params)).departures +// } +// +// async function queryStops(type, id, params) { +// const urlSearchParams = new URLSearchParams(params); +// const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); +// duration=600&results=20&linesOfStops=false&remarks=true" +// const response = await fetch(url); +// if (!response.ok) { +// throw new Error(`Error: ${response.status}`); +// } +// +// return await response.json(); +// } (async () => { const body = document.querySelector("#departTable"); diff --git a/main2.mjs b/main2.mjs new file mode 100644 index 0000000..5349c4a --- /dev/null +++ b/main2.mjs @@ -0,0 +1,11 @@ +import {formatConnections} from "./transchamp/display.mjs"; +import {getDepartingConnections} from "./transchamp/api.mjs"; + +document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( + // 8010338, { + 8010139, { + duration: 600, + results: 10, + linesOfStops: false, + remarks: true, +}))); \ No newline at end of file diff --git a/transchamp/api.mjs b/transchamp/api.mjs new file mode 100644 index 0000000..8286367 --- /dev/null +++ b/transchamp/api.mjs @@ -0,0 +1,69 @@ +import {Connection} from "./data.mjs"; + +/** + * @typedef StopsParameters + * @type {object} + * @property {number} duration + * @property {number} results + * @property {boolean} linesOfStops + * @property {boolean} remarks + */ + + + +/** + * Returns the departing connections of a station. + * + * @param {number} stationId Bahnhofs-/Haltestellenummer + * @param {StopsParameters} params API parameters to pass to the stations API + * @return {Promise} + */ +export async function getDepartingConnections(stationId, params) { + const response = await getDepartures(stationId, params); + return response.map((departure) => { + return new Connection( + departure.line.name, + departure.line.productName, + departure.direction || departure.provenance || departure.destination.name, + new Date(departure.when), // Reales-when + new Date(departure.plannedWhen), // Fahrplan-when + departure.delay, + departure.platform, + departure.plannedPlatform, + departure.remarks, + ) + }) +} + +// The following fluff might need major refactoring + +/** + * + * @param {number} stationId + * @param {StopsParameters} params + * @returns {Promise} + */ +async function getDepartures(stationId, params) { + return (await queryStops("departures", stationId, params)).departures +} + +/** + * + * @param {string} type + * @param {number} stationId + * @param {StopsParameters} params + * @returns {Promise} + */ +async function queryStops(type, stationId, params) { + const urlSearchParams = new URLSearchParams( + Object.entries(params).map((e) => {return [e[0].toString(), e[1].toString()]}) + ) + const url = `https://v6.db.transport.rest/stops/${stationId}/${type}?` + urlSearchParams.toString(); + // duration=600&results=20&linesOfStops=false&remarks=true" + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Error: ${response.status}`); + } + + return await response.json(); +} diff --git a/transchamp/data.mjs b/transchamp/data.mjs new file mode 100644 index 0000000..b50ee82 --- /dev/null +++ b/transchamp/data.mjs @@ -0,0 +1,73 @@ + + +/** + * + * @enum {string} + */ +export const Transport = { + RE: "RE", + BUS: "Bus", + ICE: "ICE", + IC: "IC", + RUF: "RUF" +} + +export class Connection { + /** + * + * @param {string} line + * @param {Transport} transportation + * @param {string} direction + * @param {Date} departure + * @param {Date} plannedDeparture + * @param {number} delay + * @param {string|null} platform + * @param {string|null} plannedPlatform + * @param {Remark[]} remarks + */ + constructor(line, transportation, direction, departure, plannedDeparture, delay, platform, plannedPlatform, remarks = []) { + this.line = line; + this.transport = transportation; + this.direction = direction; + this.departure = departure; + this.plannedDeparture = plannedDeparture; + this.delay = delay; + this.platform = platform; + this.plannedPlatform = plannedPlatform; + this.remarks = remarks; + } +} + +/** + * @enum {string} + */ +export const RemarkCode = { + Cancelled: "journey-cancelled", + Alternative: "alternative-trip", +} + +export class Remark { + /** + * @param {string} type + * @param {RemarkCode|null} code + * @param {string} text + * @param {string|null} summary + */ + constructor(type, code, text, summary = null) { + this.type = type; + this.code = code; + this.text = text; + this.summary = summary; + } + + static hasCancelled(remarks) { + return remarks.some((remark) => remark.code === RemarkCode.Cancelled) + } +} + +// arrival +// departure +// delay +// richtung (ort) +// linie -> departures.Object.line.name +// verkehrsmittel -> departures.Object.line.productName \ No newline at end of file diff --git a/transchamp/display.mjs b/transchamp/display.mjs new file mode 100644 index 0000000..3e7cbff --- /dev/null +++ b/transchamp/display.mjs @@ -0,0 +1,121 @@ + +import {Connection, Remark} from "./data.mjs"; + +/** + * + * @param {string} element + * @param {string} text + * @param {string} className + * @returns {HTMLElement} + */ +function elementWithText(element, text, className = "") { + const htmlElement = document.createElement(element); + htmlElement.innerText = text; + htmlElement.className = className; + return htmlElement; +} + + +/** + * + * @param {string} element + * @param {HTMLElement[]} children + * @param {string} className + * @returns {HTMLElement} + */ +function elementWithChildren(element, children, className = "") { + const htmlElement = document.createElement(element); + htmlElement.append(...children) + htmlElement.className = className; + return htmlElement; +} + + +/** + * Return the heading of the departure table. + * @returns {HTMLTableSectionElement} + */ +function headingConnections() { + const thead = document.createElement("thead") + const row = document.createElement("tr"); + row.appendChild(elementWithText("th", "Abfahrt", "time")); + row.appendChild(elementWithText("th", "Linie", "line")); + row.appendChild(elementWithText("th", "Richtung", "direction")); + row.appendChild(elementWithText("th", "Gleis", "platform")); + thead.appendChild(row); + return thead +} + +function formatDate(date) { + return date.toLocaleTimeString("de-DE", {hour: "2-digit", minute: "2-digit"}) +} + +/** + * + * @param {Date} actual + * @param {Date} planned + * @param {number} delay + * @return {HTMLElement[]} + */ +function formatDeparture(actual, planned, delay) { + const departureElements = []; + departureElements.push(elementWithText("span", formatDate(actual), "actual")); + departureElements.push(document.createElement("br")); + departureElements.push(elementWithText("span", formatDate(planned), "planned")); + if (delay && delay >= 60) { + departureElements.push(elementWithText("span", (delay / 60).toFixed(0), "delay")); + } + return departureElements; +} + + +/** + * + * @param {Remark[]}remarks + */ +function formatRemarks(remarks) { + if (!remarks.length) { + return [] + } + const text = " +++ " + remarks.map((remark) => { + return remark.text + }).join(" +++ ") + " +++ " + return elementWithText("marquee", text, ""); +} + +/** + * Format a single connection into an HTML table row. + * + * @param {Connection} connection + * @returns {HTMLTableRowElement} + */ +function formatConnectionAsRow(connection){ + const connectionRow = document.createElement("tr") + connectionRow.appendChild(elementWithChildren("td", formatDeparture(connection.departure, connection.plannedDeparture, connection.delay), "time")) + connectionRow.appendChild(elementWithText("td", connection.line, "line")) + connectionRow.appendChild(elementWithChildren("td", [ + document.createTextNode(connection.direction), + document.createElement("br"), + formatRemarks(connection.remarks) + ], "direction")) + connectionRow.appendChild(elementWithText("td", connection.platform || "", "platform")) + if (Remark.hasCancelled(connection.remarks)) { + connectionRow.classList.add("cancelled") + } + return connectionRow +} + +/** + * @param {Connection[]} connections + * @return {HTMLTableElement} + */ +export function formatConnections(connections) { + const tbl = document.createElement("table") + tbl.className = "information" + const tbody = document.createElement("tbody") + tbody.append(...connections.map(formatConnectionAsRow)) + + tbl.appendChild(headingConnections()) + tbl.appendChild(tbody) + return tbl +} \ No newline at end of file diff --git a/transchamp/index.mjs b/transchamp/index.mjs new file mode 100644 index 0000000..e69de29 From b43f449742b1da85e6245f8fad8ef95b961e35fe Mon Sep 17 00:00:00 2001 From: Souliboi Date: Tue, 17 Dec 2024 15:18:34 +0100 Subject: [PATCH 03/11] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2ca9b09..c62c5b4 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # TransportChamp ---------------- -Repo for a very rudimentary website to display current -information about local transport for the hackerspace Port39 +Repo for website to display current +information about local transport for the Hackerspace Port39 -Using Apache2 for the server itself, planned to run on a -Raspberry Pi +Currently supported methods of transport supported are: +1. RE +2. ICE +3. IC +4. BUS +5. RUF + +Major thanks to [Varbin](https://github.com/Varbin) who co-authored a lot of this \ No newline at end of file From 17a4cf4a4bc03b50fbedf3c3072be472d1cacc45 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Wed, 18 Dec 2024 12:57:14 +0100 Subject: [PATCH 04/11] Replace the old main.js and replace it with main2.mjs --- index.html | 3 +-- main.js | 59 ------------------------------------------------------ main.mjs | 21 +++++++++++++++++++ main2.mjs | 11 ---------- 4 files changed, 22 insertions(+), 72 deletions(-) delete mode 100755 main.js create mode 100644 main.mjs delete mode 100644 main2.mjs diff --git a/index.html b/index.html index dd30e0e..2f8e088 100755 --- a/index.html +++ b/index.html @@ -9,7 +9,6 @@
- - + \ No newline at end of file diff --git a/main.js b/main.js deleted file mode 100755 index c7e2b98..0000000 --- a/main.js +++ /dev/null @@ -1,59 +0,0 @@ -function formatInfos(infos){ - let output = [] - for (let i = 0; i < infos.length; i++) { - const info = infos[i]; - output.push(formatBody(info)); - } - return output; -} - -function formatBody(info){ - const container = document.createElement("tr") - const lineName = document.createElement("td") - const destination = document.createElement("td") - const time = document.createElement("td") - const realTime = new Date(info.plannedWhen) - destination.innerText = info.direction || info.provenance; - lineName.innerText = info.line.name; - time.innerText = realTime.toLocaleTimeString("de-DE", {hour: "2-digit", minute: "2-digit"}); - - container.className = "container" - container.appendChild(lineName) - lineName.className = "line" - destination.className = "destination" - container.appendChild(destination) - time.className = "time" - container.appendChild(time) - return container -} - -// -// async function getDepartures(id, params) { -// return (await queryStops("departures", id, params)).departures -// } -// -// async function queryStops(type, id, params) { -// const urlSearchParams = new URLSearchParams(params); -// const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); -// duration=600&results=20&linesOfStops=false&remarks=true" -// const response = await fetch(url); -// if (!response.ok) { -// throw new Error(`Error: ${response.status}`); -// } -// -// return await response.json(); -// } - -(async () => { - const body = document.querySelector("#departTable"); - const id = 8010338; - const params = { - duration: 600, - results: 10, - linesOfStops: false, - remarks: true, - }; - let departures = formatInfos(await getDepartures(id, params)); - body.replaceChildren(...departures) -})(); - diff --git a/main.mjs b/main.mjs new file mode 100644 index 0000000..c5f9d90 --- /dev/null +++ b/main.mjs @@ -0,0 +1,21 @@ +import {formatConnections} from "./transchamp/display.mjs"; +import {getDepartingConnections} from "./transchamp/api.mjs"; +import {Stations} from "./transchamp/data.mjs"; + +/** + * Return all departing connections from a single given station + * + * @param {Stations} station + * @return {HTMLElement} + */ +async function getDepartingConnectionsFromStation(station) { + document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( + station, { + duration: 600, + results: 10, + linesOfStops: false, + remarks: true, + }))); +} + +getDepartingConnectionsFromStation(Stations.Stralsund) \ No newline at end of file diff --git a/main2.mjs b/main2.mjs deleted file mode 100644 index 5349c4a..0000000 --- a/main2.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import {formatConnections} from "./transchamp/display.mjs"; -import {getDepartingConnections} from "./transchamp/api.mjs"; - -document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( - // 8010338, { - 8010139, { - duration: 600, - results: 10, - linesOfStops: false, - remarks: true, -}))); \ No newline at end of file From 7fa8e8c50df7e7253a5591adfce19d474e7cdef6 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Wed, 18 Dec 2024 12:58:01 +0100 Subject: [PATCH 05/11] Some cleanup, add some stations --- transchamp/data.mjs | 22 +++++++++++++--------- transchamp/display.mjs | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/transchamp/data.mjs b/transchamp/data.mjs index b50ee82..328d8f0 100644 --- a/transchamp/data.mjs +++ b/transchamp/data.mjs @@ -1,6 +1,15 @@ - +/** + * A list of all our known stations + * + * @enum {number} + */ +export const Stations = { + Greifswald: 8010139, + Stralsund: 8010338 +} /** + * All known methods of transport available from departing connections * * @enum {string} */ @@ -39,6 +48,8 @@ export class Connection { } /** + * All known remark strings that aren't null + * * @enum {string} */ export const RemarkCode = { @@ -63,11 +74,4 @@ export class Remark { static hasCancelled(remarks) { return remarks.some((remark) => remark.code === RemarkCode.Cancelled) } -} - -// arrival -// departure -// delay -// richtung (ort) -// linie -> departures.Object.line.name -// verkehrsmittel -> departures.Object.line.productName \ No newline at end of file +} \ No newline at end of file diff --git a/transchamp/display.mjs b/transchamp/display.mjs index 3e7cbff..dcbc60e 100644 --- a/transchamp/display.mjs +++ b/transchamp/display.mjs @@ -1,4 +1,3 @@ - import {Connection, Remark} from "./data.mjs"; /** @@ -71,7 +70,7 @@ function formatDeparture(actual, planned, delay) { /** * - * @param {Remark[]}remarks + * @param {Remark[]} remarks */ function formatRemarks(remarks) { if (!remarks.length) { @@ -106,6 +105,7 @@ function formatConnectionAsRow(connection){ } /** + * * @param {Connection[]} connections * @return {HTMLTableElement} */ From a446edca11f29c362822ea712299aea9c43cda85 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Thu, 3 Oct 2024 22:43:16 +0200 Subject: [PATCH 06/11] Yeetus deletus, rip out the arrivals table (it has become unnecessary to the new goal of creating a switching table --- TODO.md | 2 +- index.html | 15 ++++++--------- locations.txt | 5 +++++ main.js | 30 ++++++------------------------ 4 files changed, 18 insertions(+), 34 deletions(-) create mode 100644 locations.txt diff --git a/TODO.md b/TODO.md index 1f8e729..36d9ef6 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ # TODO: -- Add Departure from Wasserstraße to Arrivals so you +- Add the departures/arrivals from `locations.txt` so you can actually get the time you will have to leave for the bus - CSS all the things diff --git a/index.html b/index.html index 7e41ab4..de799b5 100644 --- a/index.html +++ b/index.html @@ -6,14 +6,11 @@ -

Departures

- - -
-

Arrivals

- - -
- +
+ + +
+
+ \ No newline at end of file diff --git a/locations.txt b/locations.txt new file mode 100644 index 0000000..20ba298 --- /dev/null +++ b/locations.txt @@ -0,0 +1,5 @@ +Ozeanum +Wasserstraße +Bahnhof +Bahnhof Rügendamm + diff --git a/main.js b/main.js index ab63b07..8df1a87 100644 --- a/main.js +++ b/main.js @@ -1,18 +1,13 @@ -function format(infos){ +function formatInfos(infos){ let output = [] for (let i = 0; i < infos.length; i++) { const info = infos[i]; - // console.log('=====') - // console.log(info.direction || info.provenance); - // console.log(info.line.name); - // const time = new Date(info.plannedWhen) - // console.log(time.getHours() + ':' + time.getMinutes()); - output.push(formatInfo(info)); + output.push(formatBody(info)); } return output; } -function formatInfo(info){ +function formatBody(info){ const container = document.createElement("tr") const lineName = document.createElement("td") const destination = document.createElement("td") @@ -37,10 +32,6 @@ async function getDepartures(id, params) { return (await queryStops("departures", id, params)).departures } -async function getArrivals(id, params) { - return (await queryStops("arrivals", id, params)).arrivals -} - async function queryStops(type, id, params) { const urlSearchParams = new URLSearchParams(params); const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); @@ -54,8 +45,7 @@ async function queryStops(type, id, params) { } (async () => { - const departBody = document.querySelector("#departTable") - const arriveBody = document.querySelector("#arriveTable") + const body = document.querySelector("#departTable"); const id = 8010338; const params = { duration: 600, @@ -63,15 +53,7 @@ async function queryStops(type, id, params) { linesOfStops: false, remarks: true, }; - const addParams = structuredClone(params); - addParams.direction = "325719"; - let departures = format(await getDepartures(id, params)); - // let departSep = document.createElement("h2") - // departSep.innerText = "Departures" - let arrivals = format(await getArrivals(id, addParams)) - // let arrivalSep = document.createElement("h2") - // arrivalSep.innerText = "Arrivals" - departBody.replaceChildren(...departures) - arriveBody.replaceChildren(...arrivals) + let departures = formatInfos(await getDepartures(id, params)); + body.replaceChildren(...departures) })(); From 07f9dcfa9df16751b8074235742b3bb6b5bc319c Mon Sep 17 00:00:00 2001 From: Souliboi Date: Mon, 16 Dec 2024 21:15:57 +0100 Subject: [PATCH 07/11] **All the changes** --- .gitignore | 0 README.md | 0 TODO.md | 0 .../DepartureMono-Regular.otf | Bin .../DepartureMono-Regular.woff | Bin .../DepartureMono-Regular.woff2 | Bin fonts/DepartureMono-1.346/LICENSE | 0 fonts/DepartureMono-1.346/README.md | 0 index.html | 11 +- locations.txt | 0 main.css | 70 ++++++++-- main.js | 32 ++--- main2.mjs | 11 ++ transchamp/api.mjs | 69 ++++++++++ transchamp/data.mjs | 73 +++++++++++ transchamp/display.mjs | 121 ++++++++++++++++++ transchamp/index.mjs | 0 17 files changed, 356 insertions(+), 31 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 README.md mode change 100644 => 100755 TODO.md mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.otf mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.woff mode change 100644 => 100755 fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 mode change 100644 => 100755 fonts/DepartureMono-1.346/LICENSE mode change 100644 => 100755 fonts/DepartureMono-1.346/README.md mode change 100644 => 100755 index.html mode change 100644 => 100755 locations.txt mode change 100644 => 100755 main.css mode change 100644 => 100755 main.js create mode 100644 main2.mjs create mode 100644 transchamp/api.mjs create mode 100644 transchamp/data.mjs create mode 100644 transchamp/display.mjs create mode 100644 transchamp/index.mjs diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/TODO.md b/TODO.md old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.otf b/fonts/DepartureMono-1.346/DepartureMono-Regular.otf old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.woff b/fonts/DepartureMono-1.346/DepartureMono-Regular.woff old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 b/fonts/DepartureMono-1.346/DepartureMono-Regular.woff2 old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/LICENSE b/fonts/DepartureMono-1.346/LICENSE old mode 100644 new mode 100755 diff --git a/fonts/DepartureMono-1.346/README.md b/fonts/DepartureMono-1.346/README.md old mode 100644 new mode 100755 diff --git a/index.html b/index.html old mode 100644 new mode 100755 index de799b5..dd30e0e --- a/index.html +++ b/index.html @@ -6,11 +6,10 @@ -
- - -
-
- + + +
+ + \ No newline at end of file diff --git a/locations.txt b/locations.txt old mode 100644 new mode 100755 diff --git a/main.css b/main.css old mode 100644 new mode 100755 index 4ceaac8..04bdb3e --- a/main.css +++ b/main.css @@ -9,25 +9,77 @@ } :root { - font-family: "Departure Mono"; - --lavender-web: #d8d8f6ff; - --rose-quartz: #978897ff; - --davys-gray: #494850ff; - --raisin-black: #2c2c34ff; + font-family: "Departure Mono", serif; + + --foreground-color: black; + --background-color: #5e7b6f; + --font-size: 12pt; + + color: var(--foreground-color); + background-color: var(--background-color); + font-size: var(--font-size); +} + +table { + border-collapse: collapse; } .information { width: 100%; + text-align: left; + + tr td, tr th { + vertical-align: top; + line-height: 1.5; + padding: .5em; + } + tr td { + height: calc(2 * 1.5 * 1em); + } } .time { - text-align: right; + text-align: left; + width: 1em; + + .actual { + font-weight: bold; + } + .planned, .delay { + font-size: 75%; + } + .delay { + color: red; + font-weight: bold; + background-color: var(--foreground-color); + padding: .5ex; + } + .delay::before { + content: "+" + } +} + +td.time { + background-color: var(--foreground-color); + color: var(--background-color); } .line { - width: 10em; + width: 10ex; + text-align: left; +} + +.direction { + width: auto; + text-align: left; +} + +.platform { + width: 3em; + text-align: right; } -.container { - height: 3em; +.cancelled .line, .cancelled .direction { + text-decoration: line-through; + color: red; } \ No newline at end of file diff --git a/main.js b/main.js old mode 100644 new mode 100755 index 8df1a87..c7e2b98 --- a/main.js +++ b/main.js @@ -27,22 +27,22 @@ function formatBody(info){ return container } - -async function getDepartures(id, params) { - return (await queryStops("departures", id, params)).departures -} - -async function queryStops(type, id, params) { - const urlSearchParams = new URLSearchParams(params); - const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); - // duration=600&results=20&linesOfStops=false&remarks=true" - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Error: ${response.status}`); - } - - return await response.json(); -} +// +// async function getDepartures(id, params) { +// return (await queryStops("departures", id, params)).departures +// } +// +// async function queryStops(type, id, params) { +// const urlSearchParams = new URLSearchParams(params); +// const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); +// duration=600&results=20&linesOfStops=false&remarks=true" +// const response = await fetch(url); +// if (!response.ok) { +// throw new Error(`Error: ${response.status}`); +// } +// +// return await response.json(); +// } (async () => { const body = document.querySelector("#departTable"); diff --git a/main2.mjs b/main2.mjs new file mode 100644 index 0000000..5349c4a --- /dev/null +++ b/main2.mjs @@ -0,0 +1,11 @@ +import {formatConnections} from "./transchamp/display.mjs"; +import {getDepartingConnections} from "./transchamp/api.mjs"; + +document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( + // 8010338, { + 8010139, { + duration: 600, + results: 10, + linesOfStops: false, + remarks: true, +}))); \ No newline at end of file diff --git a/transchamp/api.mjs b/transchamp/api.mjs new file mode 100644 index 0000000..8286367 --- /dev/null +++ b/transchamp/api.mjs @@ -0,0 +1,69 @@ +import {Connection} from "./data.mjs"; + +/** + * @typedef StopsParameters + * @type {object} + * @property {number} duration + * @property {number} results + * @property {boolean} linesOfStops + * @property {boolean} remarks + */ + + + +/** + * Returns the departing connections of a station. + * + * @param {number} stationId Bahnhofs-/Haltestellenummer + * @param {StopsParameters} params API parameters to pass to the stations API + * @return {Promise} + */ +export async function getDepartingConnections(stationId, params) { + const response = await getDepartures(stationId, params); + return response.map((departure) => { + return new Connection( + departure.line.name, + departure.line.productName, + departure.direction || departure.provenance || departure.destination.name, + new Date(departure.when), // Reales-when + new Date(departure.plannedWhen), // Fahrplan-when + departure.delay, + departure.platform, + departure.plannedPlatform, + departure.remarks, + ) + }) +} + +// The following fluff might need major refactoring + +/** + * + * @param {number} stationId + * @param {StopsParameters} params + * @returns {Promise} + */ +async function getDepartures(stationId, params) { + return (await queryStops("departures", stationId, params)).departures +} + +/** + * + * @param {string} type + * @param {number} stationId + * @param {StopsParameters} params + * @returns {Promise} + */ +async function queryStops(type, stationId, params) { + const urlSearchParams = new URLSearchParams( + Object.entries(params).map((e) => {return [e[0].toString(), e[1].toString()]}) + ) + const url = `https://v6.db.transport.rest/stops/${stationId}/${type}?` + urlSearchParams.toString(); + // duration=600&results=20&linesOfStops=false&remarks=true" + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Error: ${response.status}`); + } + + return await response.json(); +} diff --git a/transchamp/data.mjs b/transchamp/data.mjs new file mode 100644 index 0000000..b50ee82 --- /dev/null +++ b/transchamp/data.mjs @@ -0,0 +1,73 @@ + + +/** + * + * @enum {string} + */ +export const Transport = { + RE: "RE", + BUS: "Bus", + ICE: "ICE", + IC: "IC", + RUF: "RUF" +} + +export class Connection { + /** + * + * @param {string} line + * @param {Transport} transportation + * @param {string} direction + * @param {Date} departure + * @param {Date} plannedDeparture + * @param {number} delay + * @param {string|null} platform + * @param {string|null} plannedPlatform + * @param {Remark[]} remarks + */ + constructor(line, transportation, direction, departure, plannedDeparture, delay, platform, plannedPlatform, remarks = []) { + this.line = line; + this.transport = transportation; + this.direction = direction; + this.departure = departure; + this.plannedDeparture = plannedDeparture; + this.delay = delay; + this.platform = platform; + this.plannedPlatform = plannedPlatform; + this.remarks = remarks; + } +} + +/** + * @enum {string} + */ +export const RemarkCode = { + Cancelled: "journey-cancelled", + Alternative: "alternative-trip", +} + +export class Remark { + /** + * @param {string} type + * @param {RemarkCode|null} code + * @param {string} text + * @param {string|null} summary + */ + constructor(type, code, text, summary = null) { + this.type = type; + this.code = code; + this.text = text; + this.summary = summary; + } + + static hasCancelled(remarks) { + return remarks.some((remark) => remark.code === RemarkCode.Cancelled) + } +} + +// arrival +// departure +// delay +// richtung (ort) +// linie -> departures.Object.line.name +// verkehrsmittel -> departures.Object.line.productName \ No newline at end of file diff --git a/transchamp/display.mjs b/transchamp/display.mjs new file mode 100644 index 0000000..3e7cbff --- /dev/null +++ b/transchamp/display.mjs @@ -0,0 +1,121 @@ + +import {Connection, Remark} from "./data.mjs"; + +/** + * + * @param {string} element + * @param {string} text + * @param {string} className + * @returns {HTMLElement} + */ +function elementWithText(element, text, className = "") { + const htmlElement = document.createElement(element); + htmlElement.innerText = text; + htmlElement.className = className; + return htmlElement; +} + + +/** + * + * @param {string} element + * @param {HTMLElement[]} children + * @param {string} className + * @returns {HTMLElement} + */ +function elementWithChildren(element, children, className = "") { + const htmlElement = document.createElement(element); + htmlElement.append(...children) + htmlElement.className = className; + return htmlElement; +} + + +/** + * Return the heading of the departure table. + * @returns {HTMLTableSectionElement} + */ +function headingConnections() { + const thead = document.createElement("thead") + const row = document.createElement("tr"); + row.appendChild(elementWithText("th", "Abfahrt", "time")); + row.appendChild(elementWithText("th", "Linie", "line")); + row.appendChild(elementWithText("th", "Richtung", "direction")); + row.appendChild(elementWithText("th", "Gleis", "platform")); + thead.appendChild(row); + return thead +} + +function formatDate(date) { + return date.toLocaleTimeString("de-DE", {hour: "2-digit", minute: "2-digit"}) +} + +/** + * + * @param {Date} actual + * @param {Date} planned + * @param {number} delay + * @return {HTMLElement[]} + */ +function formatDeparture(actual, planned, delay) { + const departureElements = []; + departureElements.push(elementWithText("span", formatDate(actual), "actual")); + departureElements.push(document.createElement("br")); + departureElements.push(elementWithText("span", formatDate(planned), "planned")); + if (delay && delay >= 60) { + departureElements.push(elementWithText("span", (delay / 60).toFixed(0), "delay")); + } + return departureElements; +} + + +/** + * + * @param {Remark[]}remarks + */ +function formatRemarks(remarks) { + if (!remarks.length) { + return [] + } + const text = " +++ " + remarks.map((remark) => { + return remark.text + }).join(" +++ ") + " +++ " + return elementWithText("marquee", text, ""); +} + +/** + * Format a single connection into an HTML table row. + * + * @param {Connection} connection + * @returns {HTMLTableRowElement} + */ +function formatConnectionAsRow(connection){ + const connectionRow = document.createElement("tr") + connectionRow.appendChild(elementWithChildren("td", formatDeparture(connection.departure, connection.plannedDeparture, connection.delay), "time")) + connectionRow.appendChild(elementWithText("td", connection.line, "line")) + connectionRow.appendChild(elementWithChildren("td", [ + document.createTextNode(connection.direction), + document.createElement("br"), + formatRemarks(connection.remarks) + ], "direction")) + connectionRow.appendChild(elementWithText("td", connection.platform || "", "platform")) + if (Remark.hasCancelled(connection.remarks)) { + connectionRow.classList.add("cancelled") + } + return connectionRow +} + +/** + * @param {Connection[]} connections + * @return {HTMLTableElement} + */ +export function formatConnections(connections) { + const tbl = document.createElement("table") + tbl.className = "information" + const tbody = document.createElement("tbody") + tbody.append(...connections.map(formatConnectionAsRow)) + + tbl.appendChild(headingConnections()) + tbl.appendChild(tbody) + return tbl +} \ No newline at end of file diff --git a/transchamp/index.mjs b/transchamp/index.mjs new file mode 100644 index 0000000..e69de29 From af9ab0704a46a2d9fad41049b751eaccec8b733d Mon Sep 17 00:00:00 2001 From: Souliboi Date: Tue, 17 Dec 2024 15:18:34 +0100 Subject: [PATCH 08/11] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2ca9b09..c62c5b4 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # TransportChamp ---------------- -Repo for a very rudimentary website to display current -information about local transport for the hackerspace Port39 +Repo for website to display current +information about local transport for the Hackerspace Port39 -Using Apache2 for the server itself, planned to run on a -Raspberry Pi +Currently supported methods of transport supported are: +1. RE +2. ICE +3. IC +4. BUS +5. RUF + +Major thanks to [Varbin](https://github.com/Varbin) who co-authored a lot of this \ No newline at end of file From 03fc8050c393df73ee054829e37fa6b5f1878171 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Wed, 18 Dec 2024 12:57:14 +0100 Subject: [PATCH 09/11] Replace the old main.js and replace it with main2.mjs --- index.html | 3 +-- main.js | 59 ------------------------------------------------------ main.mjs | 21 +++++++++++++++++++ main2.mjs | 11 ---------- 4 files changed, 22 insertions(+), 72 deletions(-) delete mode 100755 main.js create mode 100644 main.mjs delete mode 100644 main2.mjs diff --git a/index.html b/index.html index dd30e0e..2f8e088 100755 --- a/index.html +++ b/index.html @@ -9,7 +9,6 @@
- - + \ No newline at end of file diff --git a/main.js b/main.js deleted file mode 100755 index c7e2b98..0000000 --- a/main.js +++ /dev/null @@ -1,59 +0,0 @@ -function formatInfos(infos){ - let output = [] - for (let i = 0; i < infos.length; i++) { - const info = infos[i]; - output.push(formatBody(info)); - } - return output; -} - -function formatBody(info){ - const container = document.createElement("tr") - const lineName = document.createElement("td") - const destination = document.createElement("td") - const time = document.createElement("td") - const realTime = new Date(info.plannedWhen) - destination.innerText = info.direction || info.provenance; - lineName.innerText = info.line.name; - time.innerText = realTime.toLocaleTimeString("de-DE", {hour: "2-digit", minute: "2-digit"}); - - container.className = "container" - container.appendChild(lineName) - lineName.className = "line" - destination.className = "destination" - container.appendChild(destination) - time.className = "time" - container.appendChild(time) - return container -} - -// -// async function getDepartures(id, params) { -// return (await queryStops("departures", id, params)).departures -// } -// -// async function queryStops(type, id, params) { -// const urlSearchParams = new URLSearchParams(params); -// const url = `https://v6.db.transport.rest/stops/${id}/${type}?` + urlSearchParams.toString(); -// duration=600&results=20&linesOfStops=false&remarks=true" -// const response = await fetch(url); -// if (!response.ok) { -// throw new Error(`Error: ${response.status}`); -// } -// -// return await response.json(); -// } - -(async () => { - const body = document.querySelector("#departTable"); - const id = 8010338; - const params = { - duration: 600, - results: 10, - linesOfStops: false, - remarks: true, - }; - let departures = formatInfos(await getDepartures(id, params)); - body.replaceChildren(...departures) -})(); - diff --git a/main.mjs b/main.mjs new file mode 100644 index 0000000..c5f9d90 --- /dev/null +++ b/main.mjs @@ -0,0 +1,21 @@ +import {formatConnections} from "./transchamp/display.mjs"; +import {getDepartingConnections} from "./transchamp/api.mjs"; +import {Stations} from "./transchamp/data.mjs"; + +/** + * Return all departing connections from a single given station + * + * @param {Stations} station + * @return {HTMLElement} + */ +async function getDepartingConnectionsFromStation(station) { + document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( + station, { + duration: 600, + results: 10, + linesOfStops: false, + remarks: true, + }))); +} + +getDepartingConnectionsFromStation(Stations.Stralsund) \ No newline at end of file diff --git a/main2.mjs b/main2.mjs deleted file mode 100644 index 5349c4a..0000000 --- a/main2.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import {formatConnections} from "./transchamp/display.mjs"; -import {getDepartingConnections} from "./transchamp/api.mjs"; - -document.querySelector("body").replaceChildren(formatConnections(await getDepartingConnections( - // 8010338, { - 8010139, { - duration: 600, - results: 10, - linesOfStops: false, - remarks: true, -}))); \ No newline at end of file From 38bb590aa247a78d1a33752797315d68d1e59748 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Wed, 18 Dec 2024 12:58:01 +0100 Subject: [PATCH 10/11] Some cleanup, add some stations --- transchamp/data.mjs | 22 +++++++++++++--------- transchamp/display.mjs | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/transchamp/data.mjs b/transchamp/data.mjs index b50ee82..328d8f0 100644 --- a/transchamp/data.mjs +++ b/transchamp/data.mjs @@ -1,6 +1,15 @@ - +/** + * A list of all our known stations + * + * @enum {number} + */ +export const Stations = { + Greifswald: 8010139, + Stralsund: 8010338 +} /** + * All known methods of transport available from departing connections * * @enum {string} */ @@ -39,6 +48,8 @@ export class Connection { } /** + * All known remark strings that aren't null + * * @enum {string} */ export const RemarkCode = { @@ -63,11 +74,4 @@ export class Remark { static hasCancelled(remarks) { return remarks.some((remark) => remark.code === RemarkCode.Cancelled) } -} - -// arrival -// departure -// delay -// richtung (ort) -// linie -> departures.Object.line.name -// verkehrsmittel -> departures.Object.line.productName \ No newline at end of file +} \ No newline at end of file diff --git a/transchamp/display.mjs b/transchamp/display.mjs index 3e7cbff..dcbc60e 100644 --- a/transchamp/display.mjs +++ b/transchamp/display.mjs @@ -1,4 +1,3 @@ - import {Connection, Remark} from "./data.mjs"; /** @@ -71,7 +70,7 @@ function formatDeparture(actual, planned, delay) { /** * - * @param {Remark[]}remarks + * @param {Remark[]} remarks */ function formatRemarks(remarks) { if (!remarks.length) { @@ -106,6 +105,7 @@ function formatConnectionAsRow(connection){ } /** + * * @param {Connection[]} connections * @return {HTMLTableElement} */ From 937deacb370b69e4758ef3a7bf39c008dd74b3d6 Mon Sep 17 00:00:00 2001 From: Souliboi Date: Wed, 18 Dec 2024 14:33:29 +0100 Subject: [PATCH 11/11] Add more stations --- transchamp/data.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/transchamp/data.mjs b/transchamp/data.mjs index 328d8f0..dd1c45f 100644 --- a/transchamp/data.mjs +++ b/transchamp/data.mjs @@ -5,7 +5,10 @@ */ export const Stations = { Greifswald: 8010139, - Stralsund: 8010338 + Stralsund: 8010338, + Ruegendamm: 8013062, + Ozeaneum: 325666, + Wasserstrasse: 325719 } /**