Skip to content

Commit a633166

Browse files
committed
front: sort tracks in track occupancy diagram
1 parent 7e3db86 commit a633166

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

front/src/modules/simulationResult/components/SpaceTimeChartWrapper/useTrackOccupancy.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,40 @@ type DeployedWaypoint = {
4343
loading?: boolean;
4444
};
4545

46-
const NO_TRACK_SPECIFIED_ID = '__no_track_specified__';
4746
const NO_TRACK_SPECIFIED_SYMBOL = '[ ]';
4847

48+
// Extracts the first integer (including negative) from a string, or null if none is found
49+
function extractFirstNumber(s: string): number | null {
50+
const match = s.match(/-?\d+/);
51+
return match ? parseInt(match[0], 10) : null;
52+
}
53+
54+
//Sorts tracks for display in the track occupancy diagram.
55+
function sortTracks(infraTracks: Track[], virtualTracks: Track[]): Track[] {
56+
const ncTrack = virtualTracks.find((t) => t.id === NO_TRACK_SPECIFIED_SYMBOL);
57+
const otherVirtual = virtualTracks.filter((t) => t.id !== NO_TRACK_SPECIFIED_SYMBOL);
58+
59+
// First pass: alphabetical sort as the stable base (tracks without a name sort last)
60+
otherVirtual.sort((a, b) => {
61+
if (!a.name && !b.name) return 0;
62+
if (!a.name) return 1;
63+
if (!b.name) return -1;
64+
return a.name.localeCompare(b.name);
65+
});
66+
67+
const withNumbers: Track[] = [];
68+
const withoutNumbers: Track[] = [];
69+
for (const track of otherVirtual) {
70+
if (track.name && extractFirstNumber(track.name) !== null) withNumbers.push(track);
71+
else withoutNumbers.push(track);
72+
}
73+
74+
// Numeric sort (Array.sort is stable, so alphabetical order is preserved for equal values)
75+
withNumbers.sort((a, b) => extractFirstNumber(a.name!)! - extractFirstNumber(b.name!)!);
76+
77+
return [...infraTracks, ...withNumbers, ...withoutNumbers, ...(ncTrack ? [ncTrack] : [])];
78+
}
79+
4980
type StationLabel = { type?: 'label'; label: string } | { type: 'requestedPoint' };
5081
function extractStationLabel(
5182
stationLabel: StationLabel | undefined,
@@ -210,7 +241,7 @@ const useTrackOccupancy = ({
210241
const { local_track_name: localTrackName, trains } = trackItem;
211242
let trackId: string;
212243
if (!localTrackName) {
213-
trackId = NO_TRACK_SPECIFIED_ID;
244+
trackId = NO_TRACK_SPECIFIED_SYMBOL;
214245
} else {
215246
const mappedTrackId = waypointId
216247
? localTrackNameToTrackIdRef.current.get(waypointId)?.get(localTrackName)
@@ -329,7 +360,7 @@ const useTrackOccupancy = ({
329360
}
330361
const virtualTracks: Track[] = [...virtualTrackIds].map((id) => ({
331362
id,
332-
name: id === NO_TRACK_SPECIFIED_ID ? NO_TRACK_SPECIFIED_SYMBOL : id,
363+
name: id === NO_TRACK_SPECIFIED_SYMBOL ? NO_TRACK_SPECIFIED_SYMBOL : id,
333364
}));
334365

335366
res.push({
@@ -346,7 +377,7 @@ const useTrackOccupancy = ({
346377
};
347378
}),
348379
loading: opState.zones.type === 'loading',
349-
tracks: [...infraTracks, ...virtualTracks],
380+
tracks: sortTracks(infraTracks, virtualTracks),
350381
});
351382
}
352383
});

0 commit comments

Comments
 (0)