diff --git a/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/manifest.sha256 b/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/manifest.sha256 index 2e9ae71..16ed633 100644 --- a/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/manifest.sha256 +++ b/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/manifest.sha256 @@ -1,5 +1,5 @@ ce2887fae1259726a10d3341752f469270131f84131469cfded451c70584b50d invariant-results.json -b723ca025912805ae1616db6498f64292c0a5398704299befb230b749fa53c77 readable-report.xlsx +93699864fdb9bfad5cd7f3238341907a8e2552fb6df76c0c7857b85dc306c037 readable-report.xlsx e0be7cc804c2376617baeaa83554d0980bacad6af59866f7f651883dd5546007 summary.json 4f619b1eaeba4eda13ebbb0fd86577ccfb7308aa7a9d5cb78bb57bdc3ab0c608 task-results.csv 30694b474a3a4af2bf269903a21a817dafce860b445def1429595d5ee975dbb2 tick-events.csv diff --git a/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/readable-report.xlsx b/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/readable-report.xlsx index 80e6306..6120155 100644 Binary files a/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/readable-report.xlsx and b/javaTest/outputs/wcs-history-driven-center-dispatch-20260731/readable-report.xlsx differ diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java index 79ff624..5ce1205 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java @@ -100,7 +100,8 @@ public final class HistoricalDispatchSimulator { events, traversedEdges); verifyLedger(ledger, invariants); - boolean awaitingFutureArrival = active.isEmpty() && clearanceMoves.isEmpty() + boolean awaitingFutureArrival = queue.size() > 0 + && active.isEmpty() && clearanceMoves.isEmpty() && queue.readyAt(now).isEmpty(); if (watchdog.observe(terminal.size(), businessProgress || clearanceProgress.moved || awaitingFutureArrival, @@ -461,7 +462,7 @@ public final class HistoricalDispatchSimulator { ResourceKey edge = ResourceKey.edge(from, to); List resources = Arrays.asList( ResourceKey.node(from), edge, ResourceKey.node(to)); - Instant decisionTime = Instant.EPOCH.plusMillis(now + tick); + Instant decisionTime = Instant.EPOCH.plusMillis(now); TrafficVehicleSnapshot frozen = new TrafficVehicleSnapshot(vehicleId, Long.toString(vehicle.getBootId()), tick + 1, tick + 1, decisionTime, from, to, diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java index 0f063d4..7f45d64 100644 --- a/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java +++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationClock.java @@ -27,15 +27,10 @@ public final class SimulationClock { Collections.sort(ordered); LinkedHashMap converted = new LinkedHashMap(); - long simulationMillis = 0L; - LocalDateTime previous = null; + LocalDateTime first = ordered.get(0); for (LocalDateTime arrival : ordered) { - if (previous != null) { - long sourceGap = Duration.between(previous, arrival).toMillis(); - simulationMillis += sourceGap / acceleration; - } + long simulationMillis = Duration.between(first, arrival).toMillis() / acceleration; converted.put(arrival, simulationMillis); - previous = arrival; } this.arrivals = Collections.unmodifiableMap(converted); } diff --git a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java index 401728b..c4b1cfd 100644 --- a/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java +++ b/javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationClockTest.java @@ -31,4 +31,17 @@ class SimulationClockTest { assertThrows(IllegalArgumentException.class, () -> new SimulationClock(Arrays.asList(base), 25)); } + + @Test + void scalesFromTheFirstArrivalWithoutAccumulatingRoundingLoss() { + LocalDateTime base = LocalDateTime.of(2026, 3, 1, 10, 0); + LocalDateTime firstGap = base.plusNanos(99_000_000L); + LocalDateTime secondGap = base.plusNanos(198_000_000L); + + SimulationClock clock = new SimulationClock( + Arrays.asList(base, firstGap, secondGap), 100); + + assertEquals(0L, clock.toSimulationMillis(firstGap)); + assertEquals(1L, clock.toSimulationMillis(secondGap)); + } }