From 8112e30691acc8b9b47137bb134efc4f78a1140e Mon Sep 17 00:00:00 2001 From: zgw <13623675548@163.com> Date: Fri, 31 Jul 2026 15:28:40 +0800 Subject: [PATCH] fix(javaTest): align simulation time semantics --- .../manifest.sha256 | 2 +- .../readable-report.xlsx | Bin 195491 -> 195496 bytes .../HistoricalDispatchSimulator.java | 5 +++-- .../history/simulation/SimulationClock.java | 9 ++------- .../simulation/SimulationClockTest.java | 13 +++++++++++++ 5 files changed, 19 insertions(+), 10 deletions(-) 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 80e6306a4a2a6a90c1812b6918d7c62fafd9ef48..6120155752222601f14ccdff01a30d927af930b5 100644 GIT binary patch delta 3884 zcmZ`+2|QG58=pDGzGmN*Mk3o-B1=uE%#|e<&7h1Jk!6TUiaQ9CEoR8MF+#aoaEWk9 zR4$P$$u2v|o+T!V?+o|$)&1@_zu)|xbI$Xg=Y9VF=l{IteebSu-(TY$!l?qc&5RB4ySszV$32Yud}s8{o9X@tDy2_R{0#LzVeVzuZQ-n)ov zH|nFnaM`%8U2oE7^2os(l5aN;)f?UVD!g<__5=2ni=!Pb@xvbCD7_z^lQ$_s1tiI!Q*uVpOCuP)qyDJzH!_+EokLmuLebW)eTDh4OaIF6#G z$aDE;PTqfEP=&SdAI=C=>=6+LcGHV)%IXooI8W0SF#_1^}?3+IVz&OjK zVd5~5$N(g-G3XQq9bV3$175m^dgsb~5H2frJQEJP8V5QP;bIjHKH+zW=*ASEjxwH@ zqst7|Gsw2#^v~KRvuDJmwb=N@V@~At27>esKuIg%zWCccPM7bV`=CM{FBEU+qK-@7 zjoD4L1+I0ARQ`dCiABl0h|*P#ZV|+6#)f;#V7x#^2cRnU`l^MXh^u}iH!(lG4JY4N z;|uia)5<`@PC%3VYP8Mx7}l|W`a`}dr=L7$k1}mIKNSh{!GyI>=3F}K??LeQ$d=D9 zXhsL7nsEuU<7dp4MA>06IoAH@zRr0EoOGYs?gw$0X=8%SXZ<@>op7`>?q%lBhEBMd z_qb%vJ9fnpoiVnlSo84W8-bpEzlWG_g!;-+nwJ*abehQY)tQOkjby=@Tq!=2?uG6{ z4NRDI$ZQa{S{Uho}4y+;5#@J0-u8xMZQW7VAp);RF12`wdl zgo@NU9_RU@&%^k9Ob)spR(1nPtcN9;*=Vv+wY_wc-o1){b1toDRRhAWl!OW^*xQ(n zf+1;-$zP4UF*7)R=YrSbs=1tAZIuvv;qh>Yy}@|+ZtCM0!;sQt&Ep5Q<4ZpNy~NaJ zw=2x?1Wnf!W`>N?WNWM5-Ln&&tzbrlD%>Fc4601CI7|>jHL{>ynk&gLxP{U`Db$rk z$|zNUTO#3(#{}t}G(?svr?o~|lvewzuBkNSw=oJdK!T-5pH?Nof|kb&e5tKW4%@W7 z;&tC=-mU%vDA^6{CEuwPbm4XAhQJj00nD+@09syYpnCQ+ts_dPJi70_r6`5(K!lFR z873kA+l2Tt2@$gtH}RqR<|fAb4q=M*0L|nvHZk>(OK+ zVI=YdO@&X!9`P3~qcA2dqp;m%YK{thH!Wp!n2L-up@=-+Atpc%2LXV2@ z7Qy)0n+t}Ok&)=B0GqVa(olMw5XxG|A5n6NuxEwNsqMUemrnXoxN7b5VXJl@q0C>z z;u9`*K`efkTF2b+W&_W`(>i~}eueu->`*%vvd55O2}YC>2_c`zha~YG@(2A1X+iB( zI(+}fAJwG?n{!l6aq~BWxL11qBlqq5iXAvSyDOhS+4Zp@eOzhhSQL{A_r7wJfd#6? zMP=UQUNn46cDLAfJreg^axt&uPY1VQMEhHt_s!)8iP0lPGpUIdgKEq3Ju2m2AK?y$ z*7!8FO^~K)0@vSFHr~=ThUo?1ysM4;fGySeUes;lMLMCbAz`TGRo`v6;#L&kSf@$v zEau4y)dGG}*fVz}qpA3un~G4^{_`1-GDWtPNfv>mskHKmKPz-Wyd+;-qA5~mho`!2 zrPV=7kRPq0L*AANBNTVs1dQ;Qo z6Z+=2iMQv~_9FvR3FfqXah#HnJ-;ope%meW$ZY8pBeNJJ!8`W^X|05g4Drd*-XgNic6?&v2!eH&RZvxjua(;5m7q)6{lY~B3# zLsf*(d6@%rGoUOMsh6j~iFOpcU7|osx-@_}CQ6AAd7dWtPnAfKex>!{3U~Z_9P5q} ze(2L_`9h4@lfeNIoHUnxq_+q=lY=@qv(@Y1=>76a#|8(W;#evd>j~#`^eXcy|JcHs zQW0iQe}L$IK#VM`%!l6SJ43C@#vg02_qYC0@LkkP?2ij0#I|QT_m7$6m9(V*kDC-y zLx4UkL)dUch{!3ZmxaSxM9gN|)TCtB!P3swjizOd_@RwQnZt>jo{W+sN1j$W&!44? zF^W8@eMN&N!F!X=WLYb@OtNy^ldqoAR>Ybcw<(+cdR8Yq{euiM>WA3#raD|}$TFML ztz#4Oe(Q^e537(jiLy0YoAV)CON=6hLFvY7k2b}pq<`|0wP?_hp|eBkYm=0^WxZeC z721Qf%OAU(t8X8UUdtpFzI^++Ku+D+YVuy^)a8&vJVRC#Ib!X`AJb{>Pxbi=zcMaf zsWGexaXL&+@BCD_9L!jl`qDailQDMWzdMYutL2ODfB-lEUAPYdZ&{fa2IIi+_7j=+ zK>zl|`Xqn{m@cPjz=f5AxuGC*1*n$SEdWw*0UZ~;gIcb-Zs%Ne+_h0C0{HPGAj`=d z)Zxr%xCe?Y0*Yjd3j-Pg>>u;Q=e$B4ue|s7oS}PoDcD&?98t0WA|oX}ArN85dvmo{02f$v+A3gMG0rn~~Zq0-JS-e1u>#cA#tvt#y z8xg}ZXvKG!Eyw}iT!NNRJS|^A}oq4g7m;Y&qpo({n4qxn%$eN-P7sWM2R!95qsaEpK(= zcL8GSO_HNUAHiP+7`cvs-q&9D?Z*l_W|?s%?e}O^4{fhF^ZVCa{U*zlV$QSZen0%U zop?efLON~}TkHNI$c=z{KH2-{>xU(Wxqmf}8M=;Z9(VIKMmlG7?m2|JDAXQ#>ftpy zhZvpgaz%T%*KH#p$2{oItkP2}LLG0Y>gsrvrEbBZrzeF(;MlpL73aQOeQs|9uAa~v zGQ`t1izHpOCsAzCCW%(g6oVg8wbxaaZlgkd52#f@z;rA-8xz+P_R^^p%TVawU2>2s zHAOWiOx{ds8_?&9fejy0>Y4onp{lU5k!KBge%ikX`l+qE^7dyBCEu(=WS$q&%4=Cy z!K*3!vd3K~Ik|$98bY$CjJq{jmB9A+UUxmjI(n(< zThFlL9-KW#b7Nv*`Ku@+^KRSo;h}P@vtn~S7g{>gi1n=^s^KGTV@=&7V&4NQA6@}y zaL#XsH}L8zpbhQ*!AGlrG&~+`feiC@mT5a!lNVV!e10b!QE&yXNL0}4t6 zRT#itx&J+U{2dYo%L#uD`Z54TXk`IG27qSTUIt*wv~r(!Ea5Mk_m^FS?6(C7G+GBx z->o!3>%fui+a28sY(QIru_XZ9T7m?;u@3NTJ9o;z?HpX*c1nWA8xR_3T89llnx%II U02fyPVK89>5Mc9K1)!Aw14%2?*#H0l delta 3960 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 G9QY4Uug5b0 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)); + } }