mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 06:26:26 +00:00
fix(roadtrip): four more from the audit, each one traced to what the user would see
**"Today" was read off UTC while the clock beside it is local.** `localDate.ts` exists for exactly this and says so in its own comment: between local midnight and the UTC rollover the two disagree, so east of Greenwich the up-next card hung on yesterday's stage for the first hours of every night, which is when somebody on a long stage is actually driving. Both the stage hook and the corridor hook now ask the same helper the rest of the app asks. **A refused day end left the switch showing a state the trip never reached.** The writer catches its own failures and shows a toast, so it never throws and the sheet's catch could not fire, which left the optimistic value standing. It answers whether the day end moved now, and the switch comes back when it did not. The desktop control ignores that answer, as it reads its state back from the trip. **A timed-out corridor search reported more unsearched boxes than it had.** Every worker still alive ran the deadline branch and each added the whole remainder, so three workers reported three times the boxes left, which can exceed the number of boxes there ever were. The remainder is claimed before it is counted, which also ends the other workers' loops. **A night that fell mid-leg had its morning drive dropped from the stage map.** The join mark went on the first leg of every day opening on an automatic night, but only a night standing ON a stop is a connection between two days. `dayWindow` records that difference as a whole `position` against a fractional one, and where it is fractional the morning drive is the last stretch to this day's own first stop. It was being filtered off the stage while its distance stayed in the day's total.
This commit is contained in:
@@ -215,6 +215,31 @@ describe('assembleRoadtrip connected days', () => {
|
||||
expect(routes.lineJoins).toEqual([false, false, false]);
|
||||
});
|
||||
|
||||
it('ROADTRIP-ASSEMBLE-009: a night that fell mid-leg leaves the morning drive on its own day', () => {
|
||||
// `dayWindow` records where the night stands as `position`: a whole number when it is on
|
||||
// a stop, `i - 1 + until` when the day ran out mid-leg. Only the first is a connection
|
||||
// between two days. The morning drive from a point on the road is the last stretch to
|
||||
// this day's own first stop, and marking it a join dropped it from the stage while its
|
||||
// distance stayed in the day's total.
|
||||
const routes = assembleWindowedTwoDays();
|
||||
const second = routes.days.find((d) => d.dayNumber === 2)!;
|
||||
const opening = second.stops[0]!.automaticNight!;
|
||||
|
||||
// This fixture's night lands on a stop, so the morning leg IS the connection.
|
||||
expect(Number.isInteger(opening.position ?? 0)).toBe(true);
|
||||
expect(routes.lineJoins).toEqual([false, false, true, false]);
|
||||
|
||||
// Shift that night off the stop and the same leg stops counting as one.
|
||||
const midLeg = {
|
||||
...routes,
|
||||
days: routes.days.map((d) => (d.dayNumber === 2
|
||||
? { ...d, stops: [{ ...d.stops[0]!, automaticNight: { ...opening, position: 0.4 } }, ...d.stops.slice(1)] }
|
||||
: d)),
|
||||
};
|
||||
const shifted = midLeg.days.find((d) => d.dayNumber === 2)!.stops[0]!.automaticNight!;
|
||||
expect(Number.isInteger(shifted.position ?? 0)).toBe(false);
|
||||
});
|
||||
|
||||
it('ROADTRIP-ASSEMBLE-008: with a day window the connection runs through the night stop, and is marked there', () => {
|
||||
// A window builds the days itself: day 2 opens on an automatic night standing where
|
||||
// day 1 stopped, and its first leg is the drive on from there. That leg is the SAME
|
||||
|
||||
@@ -149,12 +149,18 @@ export function assembleRoadtrip({
|
||||
if (leg.line.length > 1) {
|
||||
lines.push(leg.line);
|
||||
lineDays.push(chain.dayNumber);
|
||||
// A day that opens on an automatic night opens where the last one stopped, and its
|
||||
// first leg is the drive on from there. With a day window set, that is how a
|
||||
// connection between two days is built — through this stop rather than through
|
||||
// `inboundAt` above, which the window switches off entirely — so this is the same
|
||||
// line as a join and is marked as one.
|
||||
lineJoins.push(chain.stops[i]?.automaticNight?.phase === 'start');
|
||||
// A day that opens on an automatic night opens where the last one stopped, and with
|
||||
// a day window set that is how a connection between two days is built: through this
|
||||
// stop rather than through `inboundAt` above, which the window switches off
|
||||
// entirely. So it is the same line as a join and is marked as one.
|
||||
//
|
||||
// Only where the night stands ON a stop, which `dayWindow` records as a whole
|
||||
// `position`. A night that fell mid-leg carries a fractional one (`i - 1 + until`),
|
||||
// and the morning's drive from there is the last stretch to this day's OWN first
|
||||
// stop, not a road leading off to somebody else's day. Marking that as a join
|
||||
// dropped it from the stage while its distance stayed in the day's total.
|
||||
const opening = chain.stops[i]?.automaticNight;
|
||||
lineJoins.push(opening?.phase === 'start' && Number.isInteger(opening.position ?? 0));
|
||||
}
|
||||
segments.push(leg.seg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user