239 lines
6.3 KiB
JavaScript
239 lines
6.3 KiB
JavaScript
const MAX_DISPLAYED_VIAS = 4
|
|
|
|
function searchStation(query) {
|
|
return fetch(`https://displays.api.sbb.ch/internal/api/v1/betriebspunkt?query=${query}`, {
|
|
headers: {
|
|
"X-API-Key": API_KEY
|
|
}
|
|
}).then(res => {
|
|
return res.json()
|
|
})
|
|
}
|
|
|
|
function fetchInfo(bpuic) {
|
|
return fetch(`https://displays.api.sbb.ch/internal/api/v1/data/${bpuic}`, {
|
|
headers: {
|
|
"X-API-Key": API_KEY
|
|
}
|
|
}).then(res => {
|
|
return res.json()
|
|
/*
|
|
}).then(res => {
|
|
const trains = res.contents[0].verkehrsmittels
|
|
console.log(`${trains.length} trains`)
|
|
let platforms = trains.map(t => t.gleisAbIst)
|
|
platforms = [... new Set(platforms)]
|
|
console.log(`Platforms: ${platforms.sort()}`)
|
|
return res*/
|
|
})
|
|
}
|
|
|
|
const example = {
|
|
config: {
|
|
stationName: ""
|
|
},
|
|
contents: [
|
|
{
|
|
type: "GA",
|
|
verkehrsmittels: [
|
|
{
|
|
vmArt: "IR",
|
|
liniennummer: 90,
|
|
dsVmArt: {
|
|
vmArt: "IR",
|
|
ttsTexte: {
|
|
FR: "InterRegio"
|
|
}
|
|
},
|
|
zeitAbKb: "2024-04-08T18:32:00", // heure de départ prévue
|
|
zeitAbErw: "2024-04-08T18:33:00", // heure de départ réelle
|
|
gleisAbKb: 1, // voie prévue
|
|
gleisAbIst: 1, // voie réelle
|
|
verspaetungsminutenAb: 0, // au moins n minutes de retard
|
|
verspaetungsminutenAn: 0, // au plus n minutes de retard
|
|
ziele: [
|
|
{
|
|
betriebspunkt: {
|
|
bpuic: 8501609,
|
|
bezeichnungOffiziell: "Brig"
|
|
}
|
|
}
|
|
],
|
|
vias: [
|
|
{
|
|
betriebspunkt: {
|
|
bpuic: 8501500,
|
|
bezeichnungOffiziell: "Martigny"
|
|
},
|
|
prio: 601,
|
|
trennung: false // séparation
|
|
}
|
|
],
|
|
formation: {
|
|
richtung: "RECHTS",
|
|
waggons: [
|
|
{
|
|
sektor: "A",
|
|
form: "MITTE", // icône (MITTE, START_LINKS, END_RECHT)
|
|
typ: "FIKTIV", // classe (FIKTIV = rien, ERSTE, ZWEITE, ERSTE_ZWEITE, RESTAURANT_ERSTE, FAMILIENWAGEN, TRIEBFAHRZEUG = loco)
|
|
angebote: [], // services (vélos, resto, etc.)
|
|
statusList: [], // status (GESCHLOSSEN)
|
|
nummer: null,
|
|
zielIndex: null // terminus (utile si séparation)
|
|
},
|
|
{
|
|
sektor: "A",
|
|
form: "MITTE",
|
|
typ: "ZWEITE",
|
|
angebote: [
|
|
"VELOHAKEN" // NIEDERFLUREINSTIEG, ROLLSTUHLSTELLPLAETZE, KINDERWAGEN, RESERVATIONSPFLICHTIGE
|
|
],
|
|
nummer: null,
|
|
zielIndex: 0
|
|
},
|
|
{
|
|
sektor: "A",
|
|
form: "MITTE",
|
|
typ: "ZWEITE",
|
|
angebote: [
|
|
"VELOHAKEN"
|
|
],
|
|
nummer: null,
|
|
zielIndex: 0
|
|
}
|
|
],
|
|
ziele: [
|
|
{
|
|
zielIndex: 0,
|
|
betriebspunkt: {
|
|
bpuic: 8501609,
|
|
bezeichnungOffiziell: "Brig"
|
|
},
|
|
fromPos: 1, // premier wagon concerné
|
|
toPos: 10 // dernier wagon concerné
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
function getTimeFromTS(timestamp) {
|
|
const date = new Date(timestamp)
|
|
const hours = date.getHours().toString().padStart(2, "0")
|
|
const minutes = date.getMinutes().toString().padStart(2, "0")
|
|
return `${hours}:${minutes}`
|
|
}
|
|
|
|
function selectVias(vias) {
|
|
if (vias.length <= MAX_DISPLAYED_VIAS) return vias
|
|
|
|
let priorities = vias.map((via, index) => [via.prio, index])
|
|
priorities = priorities.sort((a, b) => a[0] - b[0])
|
|
|
|
let selectedVias = []
|
|
let selectedPrio = priorities.slice(0, MAX_DISPLAYED_VIAS).sort((a, b) => a[1] - b[1])
|
|
selectedPrio.forEach(([prio, index]) => {
|
|
selectedVias.push(vias[index])
|
|
})
|
|
return selectedVias
|
|
}
|
|
|
|
function buildComposition(formation) {
|
|
const template = document.getElementById("waggon-template").cloneNode(true)
|
|
template.removeAttribute("id")
|
|
template.classList.remove("template")
|
|
|
|
const composition = document.getElementById("composition")
|
|
const sectors = document.getElementById("sectors")
|
|
sectors.innerHTML = ""
|
|
|
|
const carriages = document.getElementById("carriages")
|
|
carriages.innerHTML = ""
|
|
carriages.dataset.direction = formation.richtung === "RECHTS" ? "right" : "left"
|
|
|
|
const weights = {}
|
|
let first = true
|
|
for (let i = 0; i < formation.waggons.length; i++) {
|
|
const waggon = formation.waggons[i]
|
|
|
|
if (!(waggon.sektor in weights)) {
|
|
weights[waggon.sektor] = 0
|
|
}
|
|
weights[waggon.sektor]++
|
|
|
|
if (waggon.typ === "FIKTIV") {
|
|
continue
|
|
}
|
|
|
|
const elmt = template.cloneNode(true)
|
|
if (first) {
|
|
first = false
|
|
carriages.style.setProperty("--offset", i.toString())
|
|
}
|
|
elmt.classList.add("form-" + waggon.form.toLowerCase())
|
|
const cls = {
|
|
ERSTE: ["1", "first"],
|
|
ZWEITE: ["2", "second"],
|
|
ERSTE_ZWEITE: ["1|2", "first-second"],
|
|
RESTAURANT_ERSTE: ["1", "first"],
|
|
RESTAURANT_ZWEITE: ["1", "first"],
|
|
FAMILIENWAGEN: ["", "familie"],
|
|
TRIEBFAHRZEUG: ["", "loc"]
|
|
}[waggon.typ]
|
|
elmt.querySelector(".class").innerText = cls[0]
|
|
elmt.classList.add("class-" + cls[1])
|
|
if (waggon.nummer !== null) {
|
|
elmt.querySelector(".number").innerText = waggon.nummer
|
|
}
|
|
|
|
carriages.appendChild(elmt)
|
|
}
|
|
|
|
composition.style.setProperty("--n-waggons", formation.waggons.length.toString())
|
|
const sectorLetters = Object.keys(weights).sort()
|
|
sectorLetters.forEach(letter => {
|
|
const sector = document.createElement("div")
|
|
sector.classList.add("sector")
|
|
sector.style.setProperty("--weight", weights[letter].toString())
|
|
sector.innerText = letter
|
|
sectors.appendChild(sector)
|
|
})
|
|
console.log(weights)
|
|
}
|
|
|
|
function updateDisplay(result, idx=0, platform=null) {
|
|
document.getElementById("station").innerText = result.config.stationName
|
|
|
|
let trains = result.contents[0].verkehrsmittels
|
|
if (platform !== null) {
|
|
trains = trains.filter(t => t.gleisAbIst === platform)
|
|
}
|
|
const train = trains[idx]
|
|
|
|
let icon = train.vmArt
|
|
let iconTxt = train.dsVmArt.ttsTexte.FR
|
|
if (train.liniennummer !== null) {
|
|
icon += "-" + train.liniennummer
|
|
iconTxt += " " + train.liniennummer
|
|
}
|
|
icon = "icons/" + icon.toLowerCase() + "-negative.svg"
|
|
document.getElementById("train-type").src = icon
|
|
document.getElementById("train-type").alt = iconTxt
|
|
document.getElementById("departure").innerText = getTimeFromTS(train.zeitAbKb)
|
|
|
|
document.getElementById("destination").innerText = train.ziele[0].betriebspunkt.bezeichnungOffiziell
|
|
const stopsList = document.getElementById("stops")
|
|
stopsList.innerHTML = ""
|
|
const vias = selectVias(train.vias)
|
|
vias.forEach(via => {
|
|
const stop = document.createElement("div")
|
|
stop.classList.add("stop")
|
|
stop.innerText = via.betriebspunkt.bezeichnungOffiziell
|
|
stopsList.appendChild(stop)
|
|
})
|
|
|
|
buildComposition(train.formation)
|
|
} |