Files
traveldrafter/web/drafting-board.js
2025-07-07 17:58:22 +02:00

238 lines
7.2 KiB
JavaScript

import { EL } from "./dom.js";
import { displayLegDetails } from "./leg-details.js";
import { fetchTrip } from './api.js';
let element_board = document.querySelector("#drafting-board-content");
export function addJourneyToDraftingBoard(journey) {
let awaiting_promises = [];
for (let leg of journey.legs.filter(item => !("walking" in item))) {
window.dataStore.legs.remember(leg.tripId, leg.origin.id, leg.destination.id);
awaiting_promises.push(fetchTrip(leg.tripId).then(result => {
window.dataStore.trips.remember(result.trip);
}));
}
Promise.all(awaiting_promises)
.then(results => {
drawDraftingBoard();
});
}
export function drawDraftingBoard() {
element_board.innerText = "";
let sorted_locations = trackedTripsLocationsSorted();
let display_locations = sorted_locations.map(item => window.dataStore.locations.data[item]);
let grid_location_indexes = {};
let location_offset = 0;
for (let sorted_location of sorted_locations) {
grid_location_indexes[sorted_location] = {
"name-start": (location_offset * 3) + 1,
"name-end": (location_offset * 3) + 4,
"column-start": (location_offset * 3) + 2,
"column-end": (location_offset * 3) + 3,
};
location_offset += 1;
}
function getStopFromTrip(trip_id, location_id) {
for (let stop of window.dataStore.trips.data[trip_id]?.stopovers || []) {
if (stop.stop.id == location_id) {
return stop;
}
}
return undefined;
}
let display_legs = window.dataStore.legs.data.map(leg => {
leg.trip = window.dataStore.trips.data[leg.trip_id];
leg.origin_location = getStopFromTrip(leg.trip_id, leg.origin_location_id);
leg.destination_location = getStopFromTrip(leg.trip_id, leg.destination_location_id);
return leg;
});
display_legs = display_legs.toSorted((leg_a, leg_b) => {
if (leg_a.origin_location_id == leg_b.origin_location_id) {
if (leg_a.origin_location.departure > leg_b.origin_location.departure) {
return 1;
} else {
return -1;
}
} else if (leg_a.destination_location_id == leg_b.destination_location_id) {
if (leg_a.destination_location.arrival > leg_b.destination_location.arrival) {
return 1;
} else {
return -1;
}
} else if (leg_a.destination_location_id == leg_b.origin_location_id) {
if (leg_a.destination_location.arrival > leg_b.origin_location.departure) {
return 1;
} else {
return -1;
}
} else if (leg_a.origin_location_id == leg_b.destination_location_id) {
if (leg_a.origin_location.departure > leg_b.destination_location.arrival) {
return 1;
} else {
return -1;
}
} else {
return 0;
}
});
let rows = display_legs.length;
element_board.style.setProperty("--drafting-board-number-locations", display_locations.length);
element_board.style.setProperty("--drafting-board-number-legs", rows);
for (let display_location of display_locations) {
let el_location_name = EL("div", {
class: [ "station-name" ],
style: {
"grid-column-start": grid_location_indexes[display_location.id]["name-start"],
"grid-column-end": grid_location_indexes[display_location.id]["name-end"],
"grid-row-start": 1,
"grid-row-end": 1,
},
});
el_location_name.innerText = display_location?.name;
element_board.appendChild(el_location_name);
let el_location_column = EL("div", {
class: [ "station-column" ],
style: {
"grid-column-start": grid_location_indexes[display_location.id]["column-start"],
"grid-column-end": grid_location_indexes[display_location.id]["column-end"],
"grid-row-start": 2,
"grid-row-end": rows + 3,
},
});
element_board.appendChild(el_location_column);
}
let leg_offset = 0;
for (let display_leg of display_legs) {
console.log(display_leg);
let el_leg_left = EL("div", {
class: [ "leg-left" ],
style: {
"grid-column-start": grid_location_indexes[display_leg.origin_location_id]["name-start"],
"grid-column-end": grid_location_indexes[display_leg.origin_location_id]["column-start"],
"grid-row-start": leg_offset + 2,
"grid-row-end": leg_offset + 2,
},
});
el_leg_left.appendChild(document.createTextNode(new Date(display_leg.origin_location.departure).toLocaleTimeString()));
el_leg_left.appendChild(EL("br", {}));
el_leg_left.appendChild(document.createTextNode("Gleis " + display_leg.origin_location.departurePlatform));
element_board.appendChild(el_leg_left);
let el_leg = EL("div", {
class: [ "leg" ],
style: {
"grid-column-start": grid_location_indexes[display_leg.origin_location_id]["column-end"],
"grid-column-end": grid_location_indexes[display_leg.destination_location_id]["column-start"],
"grid-row-start": leg_offset + 2,
"grid-row-end": leg_offset + 2,
},
});
el_leg.innerText = display_leg.trip?.line?.name;
el_leg.addEventListener("click", event => {
displayLegDetails(display_leg.trip_id, display_leg.origin_location_id, display_leg.destination_location_id);
});
element_board.appendChild(el_leg);
let el_leg_right = EL("div", {
class: [ "leg-right" ],
style: {
"grid-column-start": grid_location_indexes[display_leg.destination_location_id]["column-end"],
"grid-column-end": grid_location_indexes[display_leg.destination_location_id]["name-end"],
"grid-row-start": leg_offset + 2,
"grid-row-end": leg_offset + 2,
},
});
el_leg_right.appendChild(document.createTextNode(new Date(display_leg.destination_location.arrival).toLocaleTimeString()));
el_leg_right.appendChild(EL("br", {}));
el_leg_right.appendChild(document.createTextNode("Gleis " + display_leg.destination_location.arrivalPlatform));
element_board.appendChild(el_leg_right);
leg_offset += 1;
}
}
export function getLocationWithLeastInboundTrips(locations, legs) {
function numberOfInboundLegs(location) {
return legs.filter(leg => leg.destination_location_id == location).length;
}
let locations_sorted_by_number_of_inbound_legs = locations.toSorted((location_a, location_b) => {
let n_a = numberOfInboundLegs(location_a);
let n_b = numberOfInboundLegs(location_b);
// 1: b vor a
// -1: a vor b
if (n_a == n_b) {
return 0;
} else if (n_a > n_b) {
return 1;
} else {
return -1;
}
});
return locations_sorted_by_number_of_inbound_legs[0];
}
export function sortLocations(sorted_locations, unsorted_locations, legs) {
if (unsorted_locations.length == 0) {
return sorted_locations;
}
let selected_location_id = getLocationWithLeastInboundTrips(unsorted_locations, legs);
unsorted_locations = unsorted_locations.filter(location_id => location_id != selected_location_id);
legs = legs.filter(leg => leg.destination_location_id != selected_location_id && leg.origin_location_id != selected_location_id);
return sortLocations(sorted_locations.concat([ selected_location_id ]), unsorted_locations, legs);
}
export function trackedTripsLocationsSorted() {
let passed_locations = Array.from(new Set(
window.dataStore.legs.data.map(leg => leg.origin_location_id)
.concat(
window.dataStore.legs.data.map(leg => leg.destination_location_id)
)
));
let sorted_locations = sortLocations([], passed_locations, window.dataStore.legs.data);
console.log(sorted_locations);
console.log(sorted_locations.map(item => window.dataStore.locations.data[item]?.name));
return sorted_locations;
}