intercity fix

This commit is contained in:
Marshal
2026-07-31 10:50:16 +00:00
parent 74b7ee81fc
commit a64af98205
17 changed files with 1174 additions and 182 deletions

View File

@@ -87,22 +87,46 @@ function phaseCountdown(
}
}
/** GROSS weight already on this train (each booking's cargo + wagon tare) —
* compared against the locomotive pull limit, which is a gross ceiling. */
/**
* GROSS weight the locomotives actually haul: the HEAVIEST LEG, never the
* whole-route sum — disjoint legs (Mojo→Dire + Dire→Doraleh) are pulled one
* at a time, so summing every booking over-reports a multi-stop train.
* Prefers the API's consist-derived heaviestLeg; before allocation it falls
* back to a per-leg max over the bookings (same span math as the header strip).
*/
function usedWeight(schedule: TrainScheduleDetail): number {
return (schedule.bookings ?? []).reduce(
(sum, b) => sum + (Number(b.weightTons) || 0),
0,
);
const consist = schedule.trainSet?.heaviestLeg?.grossWeightTons;
if (consist != null) return Number(consist) || 0;
const bookings = schedule.bookings ?? [];
const stops = schedule.stops ?? [];
if (stops.length <= 2) {
return bookings.reduce((sum, b) => sum + (Number(b.weightTons) || 0), 0);
}
const indexOf = new Map(stops.map((s, i) => [s.yardId, i]));
const lastIdx = stops.length - 1;
let heaviest = 0;
for (let edge = 0; edge < lastIdx; edge += 1) {
let legTons = 0;
for (const b of bookings) {
const from = (b.originYardId ? indexOf.get(b.originYardId) : undefined) ?? 0;
const toRaw = b.destinationYardId ? indexOf.get(b.destinationYardId) : lastIdx;
const to = toRaw != null && toRaw > from ? toRaw : lastIdx;
if (from <= edge && edge < to) legTons += Number(b.weightTons) || 0;
}
heaviest = Math.max(heaviest, legTons);
}
return heaviest;
}
/**
* Pull capacity of the set = the WEAKEST locomotive's max pull weight (0 when
* unknown). The API caps at the weakest loco, not the sum of all locos — a
* consist can only pull as hard as its weakest engine. Both sides of this meter
* are gross: `usedWeight` sums per-booking gross (cargo + wagon tare).
* Pull capacity of the set. Locomotive pull weights ADD UP (they haul
* together), so prefer the API's maxGrossWeightTons — the combined set limit
* incl. overage tolerance, the same ceiling the validator holds each leg to —
* and fall back to summing the locos' own limits.
*/
function pullCapacity(schedule: TrainScheduleDetail): number {
if (schedule.maxGrossWeightTons != null) return Number(schedule.maxGrossWeightTons) || 0;
const set = schedule.trainSet;
if (!set) return 0;
const locos =
@@ -111,8 +135,7 @@ function pullCapacity(schedule: TrainScheduleDetail): number {
: set.locomotive
? [set.locomotive]
: [];
if (locos.length === 0) return 0;
return Math.min(...locos.map((l) => Number(l.maxPullWeightTons) || 0));
return locos.reduce((sum, l) => sum + (Number(l.maxPullWeightTons) || 0), 0);
}
export function ScheduleWorkspacePanel({
@@ -371,6 +394,7 @@ export function ScheduleWorkspacePanel({
<Text size="xs" fw={600} c={over ? "red" : "dimmed"}>
Load {used.toFixed(1)}T
{capacity > 0 ? ` / ${capacity.toFixed(0)}T pull` : ""}
{(schedule.stops?.length ?? 0) > 2 ? " · heaviest leg" : ""}
</Text>
</Group>
{over ? (