mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 18:48:11 +00:00
feat(train-scheduling): mid-route consist changes, audit history, safer workspace
- planned couples: loose wagons join the train at a route stop, added from the schedule yards tab; capacity credits them per corridor edge and coupling validates locomotive weight/length caps per leg - real-cut toggle: a cut wagon permanently leaves the train build at its cut yard (soft cut still sits out one trip only) - fix heaviest-leg display counting a shared slot's full cargo on every spanned edge (phantom pull-weight overload on S-2026-00045) - confirmation dialogs for workspace add/load/unload/remove actions - train-builder History and Detached-wagons tabs, backed by paginated endpoints; builder detaches now always write adjustment-log rows Migrations 3660 (planned_wagon_couples, planned_wagon_real_cuts) and 3670 (adjustment log train_schedule_id nullable) — both applied to the dev DB by hand; watch mode does not run migrations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Per-corridor-edge physical load of a train: tare + length of the wagons
|
||||
* spanning each edge, plus the cargo weight riding it. Used to validate that
|
||||
* a planned mid-route COUPLE keeps every leg within the locomotives' pull
|
||||
* weight and train length limits — a wagon cut at Mojo frees its tare/length
|
||||
* on the edges past Mojo, a wagon coupled there adds its own only from there.
|
||||
*/
|
||||
|
||||
export interface EdgeLoad {
|
||||
weightTons: number;
|
||||
lengthMeters: number;
|
||||
}
|
||||
|
||||
export interface EdgeWagonSpan {
|
||||
/** Half-open edge span [fromEdge, toEdge) the wagon physically rides. */
|
||||
fromEdge: number;
|
||||
toEdge: number;
|
||||
tareTons: number;
|
||||
lengthMeters: number;
|
||||
}
|
||||
|
||||
export interface EdgeCargoLeg {
|
||||
fromEdge: number;
|
||||
toEdge: number;
|
||||
weightTons: number;
|
||||
}
|
||||
|
||||
export function computeEdgeLoads(
|
||||
edgeCount: number,
|
||||
wagonSpans: readonly EdgeWagonSpan[],
|
||||
cargoLegs: readonly EdgeCargoLeg[],
|
||||
): EdgeLoad[] {
|
||||
const loads: EdgeLoad[] = Array.from({ length: Math.max(1, edgeCount) }, () => ({
|
||||
weightTons: 0,
|
||||
lengthMeters: 0,
|
||||
}));
|
||||
const clamp = (edge: number) => Math.min(Math.max(edge, 0), loads.length);
|
||||
for (const span of wagonSpans) {
|
||||
for (let e = clamp(span.fromEdge); e < clamp(span.toEdge); e += 1) {
|
||||
loads[e].weightTons += span.tareTons;
|
||||
loads[e].lengthMeters += span.lengthMeters;
|
||||
}
|
||||
}
|
||||
for (const cargo of cargoLegs) {
|
||||
for (let e = clamp(cargo.fromEdge); e < clamp(cargo.toEdge); e += 1) {
|
||||
loads[e].weightTons += cargo.weightTons;
|
||||
}
|
||||
}
|
||||
return loads;
|
||||
}
|
||||
Reference in New Issue
Block a user