(int) strtotime($dt); $orders = [$t('2026-05-03 10:00:00'), $t('2026-06-12 10:00:00'), $t('2026-08-20 10:00:00')]; // ---------- slotBefore 基本 ---------- expect(S::slotBefore($orders, 0, $t('2026-09-10 10:00:00')) === 3, '三笔订单之后继承 → k=3'); expect(S::slotBefore($orders, 0, $t('2026-07-01 00:00:00')) === 2, '两笔之后 → k=2'); expect(S::slotBefore($orders, 0, $t('2026-05-03 09:59:59')) === 0, '首单之前 → k=0'); expect(S::slotBefore([], 0, $t('2026-09-10 10:00:00')) === 0, '无订单 → k=0'); expect(S::slotBefore([], 1, $t('2026-09-10 10:00:00')) === 1, '无订单有偏移 → k=offset'); // ---------- 严格小于:同一秒 ---------- expect(S::slotBefore($orders, 0, $t('2026-08-20 10:00:00')) === 2, '同一秒订单视为「指派之后」,不计入 k'); expect(S::slotBefore($orders, 0, $t('2026-08-20 10:00:01')) === 3, '晚一秒即计入'); // 对偶:持有人规则 t <= ct 归新持有人(RevisitRateLogic.php 指针 while tl[ptr].t <= ct) $assignTs = $t('2026-08-20 10:00:00'); $orderCt = $t('2026-08-20 10:00:00'); expect(($assignTs <= $orderCt) && S::slotBefore([$orderCt], 0, $assignTs) === 0, '同一秒:订单归新持有人且不计入 k(对偶成立)'); // ---------- 偏移 ---------- expect(S::slotBefore($orders, 2, $t('2026-09-10 10:00:00')) === 5, '偏移叠加'); expect(S::slotBefore($orders, -3, $t('2026-09-10 10:00:00')) === 3, '负偏移钳到 0'); expect(S::slotBefore($orders, 99, $t('2026-09-10 10:00:00')) === 23, '偏移上限 20'); expect(S::slotBefore(['1778000000', 1779000000], 0, 1778500000) === 1, '字符串时间戳可用'); // ---------- resolveRevisitSlotStartOffset ---------- $map = [1 => 0, 2 => 1, 3 => -5, 4 => 25, 5 => '2']; expect(S::resolveRevisitSlotStartOffset(1, $map) === 0, 'offset 0'); expect(S::resolveRevisitSlotStartOffset(2, $map) === 1, 'offset 1'); expect(S::resolveRevisitSlotStartOffset(3, $map) === 0, '负值钳 0'); expect(S::resolveRevisitSlotStartOffset(4, $map) === S::MAX_OFFSET, '超限钳 20'); expect(S::resolveRevisitSlotStartOffset(5, $map) === 2, '字符串转 int'); expect(S::resolveRevisitSlotStartOffset(999, $map) === 0, '缺键默认 0'); // ---------- current_slot / next_slot 口径(与 batchCurrentSlot 组装一致) ---------- $validCount = \count($orders); $offset = S::resolveRevisitSlotStartOffset(2, $map); $currentSlot = $validCount + $offset; expect($currentSlot === 4 && $currentSlot + 1 === 5, 'current_slot = |E(D)| + off(D),next_slot = current_slot + 1'); expect(S::slotBefore($orders, $offset, PHP_INT_MAX) === $currentSlot, '未来时刻的 slot_at 等于 current_slot'); echo "RevisitVisitSlotServiceTest OK ({$checks} checks)\n";