From eca6c610586ab5281af2ad44e7034741a6180363 Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 6 Jul 2026 18:20:48 +0800 Subject: [PATCH] test(shift): cover non-zero cycleOffset and multiple phase breaks; add kindAt KDoc --- .../kotlin/plus/rua/project/ShiftPattern.kt | 4 +++ .../plus/rua/project/ShiftPatternTest.kt | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/core/src/main/kotlin/plus/rua/project/ShiftPattern.kt b/core/src/main/kotlin/plus/rua/project/ShiftPattern.kt index 7cacda9..37a8c61 100644 --- a/core/src/main/kotlin/plus/rua/project/ShiftPattern.kt +++ b/core/src/main/kotlin/plus/rua/project/ShiftPattern.kt @@ -39,6 +39,10 @@ data class ShiftPattern( val phaseBreaks: List = emptyList(), val name: String = "默认" ) { + /** + * 返回 [date] 当天的班次。优先级:overrides → 活跃锚点的 cycle 索引。 + * cycle 为空时返回 null。 + */ fun kindAt(date: LocalDate): ShiftKind? { if (cycle.isEmpty()) return null // 1. 单日翻转优先 diff --git a/core/src/test/kotlin/plus/rua/project/ShiftPatternTest.kt b/core/src/test/kotlin/plus/rua/project/ShiftPatternTest.kt index 8f60227..9ebb401 100644 --- a/core/src/test/kotlin/plus/rua/project/ShiftPatternTest.kt +++ b/core/src/test/kotlin/plus/rua/project/ShiftPatternTest.kt @@ -217,6 +217,41 @@ class ShiftPatternTest { assertEquals(ShiftKind.OFF, pattern.kindAt(LocalDate(2026, 5, 18))) } + @Test + fun kindAt_phaseBreakWithOffset_shiftsPhase() { + // 断点 5/19,cycleOffset=2:5/19 对应 cycle[2]=OFF(而非 cycle[0]=WORK) + val pattern = twoOnTwoOff.copy( + phaseBreaks = listOf(PhaseBreak(LocalDate(2026, 5, 19), 2)) + ) + // 5/19 = cycle[(0+2)%4] = cycle[2] = OFF + assertEquals(ShiftKind.OFF, pattern.kindAt(LocalDate(2026, 5, 19))) + // 5/20 = cycle[(1+2)%4] = cycle[3] = OFF + assertEquals(ShiftKind.OFF, pattern.kindAt(LocalDate(2026, 5, 20))) + // 5/21 = cycle[(2+2)%4] = cycle[0] = WORK + assertEquals(ShiftKind.WORK, pattern.kindAt(LocalDate(2026, 5, 21))) + } + + @Test + fun kindAt_multiplePhaseBreaks_usesLatestApplicable() { + // 两个断点:5/19(offset 0) 和 5/25(offset 1) + val pattern = twoOnTwoOff.copy( + phaseBreaks = listOf( + PhaseBreak(LocalDate(2026, 5, 19), 0), + PhaseBreak(LocalDate(2026, 5, 25), 1) + ) + ) + // 5/19-5/24 受第一个断点支配(offset 0) + // 5/19 = cycle[0] = WORK + assertEquals(ShiftKind.WORK, pattern.kindAt(LocalDate(2026, 5, 19))) + // 5/24 = cycle[(5)%4] = cycle[1] = WORK + assertEquals(ShiftKind.WORK, pattern.kindAt(LocalDate(2026, 5, 24))) + // 5/25 起受第二个断点支配(offset 1) + // 5/25 = cycle[(0+1)%4] = cycle[1] = WORK + assertEquals(ShiftKind.WORK, pattern.kindAt(LocalDate(2026, 5, 25))) + // 5/26 = cycle[(1+1)%4] = cycle[2] = OFF + assertEquals(ShiftKind.OFF, pattern.kindAt(LocalDate(2026, 5, 26))) + } + // ---- kindAt: override + phaseBreak 组合(用户原始例子)---- @Test