mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 16:00:56 +00:00
leg-aware capacity and wagon sharing
This commit is contained in:
@@ -559,11 +559,14 @@ export function TrainCompositionDiagram({
|
||||
// ceiling the allocation engine spends from.
|
||||
const totalTare = normalized.reduce((s, w) => s + w.tareWeightTons, 0);
|
||||
const grossWeight = totalWeight + totalTare;
|
||||
// Weakest locomotive caps the set — same rule the allocation engine applies.
|
||||
// Engine rule (combinedLocomotiveLimits): coupled locomotives pull
|
||||
// TOGETHER, so their pull limits SUM.
|
||||
const pullLimits = locos
|
||||
.map((l) => Number(l.maxPullWeightTons))
|
||||
.filter((v) => Number.isFinite(v) && v > 0);
|
||||
const pullLimit = pullLimits.length ? Math.min(...pullLimits) : null;
|
||||
const pullLimit = pullLimits.length
|
||||
? pullLimits.reduce((sum, v) => sum + v, 0)
|
||||
: null;
|
||||
return {
|
||||
total: normalized.length,
|
||||
assigned,
|
||||
|
||||
@@ -132,17 +132,24 @@ export const TrainConsistView = ({
|
||||
0,
|
||||
);
|
||||
const tareUsed = wagons.reduce((sum, w) => sum + (w.tareWeightTons ?? 0), 0);
|
||||
const weightUsed = cargoUsed + tareUsed;
|
||||
const lengthUsed = wagons.reduce((sum, w) => sum + (w.lengthMeters ?? 0), 0);
|
||||
// Prefer the server's heaviest-edge figures: on a multi-stop corridor a
|
||||
// wagon reused across legs is several slots but one physical wagon, so the
|
||||
// plain sums over-report the train against the pull/length/slot caps.
|
||||
const heaviest = trainSet?.heaviestLeg;
|
||||
const weightUsed = heaviest?.grossWeightTons ?? cargoUsed + tareUsed;
|
||||
const lengthUsed =
|
||||
heaviest?.lengthMeters ?? wagons.reduce((sum, w) => sum + (w.lengthMeters ?? 0), 0);
|
||||
const wagonsUsed = heaviest?.loadedWagonCount ?? loadedCount;
|
||||
|
||||
// Weakest locomotive caps the set — same rule the allocation engine applies.
|
||||
// Engine rule (combinedLocomotiveLimits): coupled locomotives pull TOGETHER,
|
||||
// so pull caps SUM; the track doesn't lengthen, so the length cap is the MIN.
|
||||
const locos = trainSet?.locomotives?.length
|
||||
? trainSet.locomotives
|
||||
: trainSet?.locomotive
|
||||
? [trainSet.locomotive]
|
||||
: [];
|
||||
const weightMax = locos.length
|
||||
? Math.min(...locos.map((l) => l.maxPullWeightTons))
|
||||
? locos.reduce((sum, l) => sum + l.maxPullWeightTons, 0)
|
||||
: null;
|
||||
const lengthCaps = locos
|
||||
.map((l) => l.maxTrainLengthMeters)
|
||||
@@ -156,7 +163,7 @@ export const TrainConsistView = ({
|
||||
weightMax={weightMax}
|
||||
lengthUsed={lengthUsed}
|
||||
lengthMax={lengthMax}
|
||||
wagonCount={loadedCount}
|
||||
wagonCount={wagonsUsed}
|
||||
wagonMax={maxWagons}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1103,19 +1103,31 @@ export default function TrainScheduleV2DetailPage() {
|
||||
},
|
||||
{
|
||||
label: "Wagons / load",
|
||||
// Gross: cargo load + the tare of every wagon in the consist — the
|
||||
// weight the locomotive actually hauls.
|
||||
value: `${schedule.trainSet?.wagonCount ?? displayWagonPlan.length} · ${
|
||||
Math.round(
|
||||
((schedule.trainSet?.totalWeightTons ?? 0) +
|
||||
(schedule.trainSet?.wagons ?? []).reduce(
|
||||
(sum, w) => sum + (Number(w.tareWeightTons) || 0),
|
||||
0,
|
||||
)) *
|
||||
100,
|
||||
) / 100
|
||||
}T`,
|
||||
hint: "gross · wagon tare + cargo",
|
||||
// Gross: cargo load + wagon tare — the weight the locomotives
|
||||
// actually haul. Heaviest corridor edge when the server sends it;
|
||||
// plain consist sums over-report a multi-stop train (cross-leg
|
||||
// wagon sharing counts one physical wagon as several slots).
|
||||
value: (() => {
|
||||
const heaviest = schedule.trainSet?.heaviestLeg;
|
||||
const wagonCount =
|
||||
heaviest?.loadedWagonCount ??
|
||||
schedule.trainSet?.wagonCount ??
|
||||
displayWagonPlan.length;
|
||||
const grossTons =
|
||||
heaviest?.grossWeightTons ??
|
||||
Math.round(
|
||||
((schedule.trainSet?.totalWeightTons ?? 0) +
|
||||
(schedule.trainSet?.wagons ?? []).reduce(
|
||||
(sum, w) => sum + (Number(w.tareWeightTons) || 0),
|
||||
0,
|
||||
)) *
|
||||
100,
|
||||
) / 100;
|
||||
return `${wagonCount} · ${grossTons}T`;
|
||||
})(),
|
||||
hint: schedule.trainSet?.heaviestLeg
|
||||
? "heaviest leg · wagon tare + cargo"
|
||||
: "gross · wagon tare + cargo",
|
||||
icon: Weight,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -608,6 +608,16 @@ export interface TrainScheduleDetail {
|
||||
wagonCount: number;
|
||||
totalWeightTons: number;
|
||||
totalLengthMeters: number;
|
||||
/**
|
||||
* Usage on the corridor's heaviest edge — what the locomotives actually
|
||||
* haul. Cross-leg wagon sharing makes plain slot sums over-report a
|
||||
* multi-stop train. Null without a train set.
|
||||
*/
|
||||
heaviestLeg?: {
|
||||
grossWeightTons: number;
|
||||
lengthMeters: number;
|
||||
loadedWagonCount: number;
|
||||
} | null;
|
||||
locomotive?: {
|
||||
id: string;
|
||||
code: string;
|
||||
|
||||
Reference in New Issue
Block a user