Auto commit Sun Mar 22 12:01:01 AM CDT 2026
This commit is contained in:
@@ -171,7 +171,7 @@ class TimelineCurveGestureTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensureMinutePoints snaps points to minute boundaries`() {
|
||||
fun `ensureTimelinePoints snaps points to selected boundaries`() {
|
||||
val points = listOf(
|
||||
TimelinePoint(0, 0.0f),
|
||||
TimelinePoint(30, 0.5f), // 30 seconds - not a minute boundary
|
||||
@@ -179,26 +179,26 @@ class TimelineCurveGestureTest {
|
||||
)
|
||||
val curve = TimelineCurve(points)
|
||||
|
||||
val result = curve.ensureMinutePoints(180)
|
||||
val result = curve.ensureTimelinePoints(180, granularitySec = 30)
|
||||
|
||||
// Check that all points are on minute boundaries (multiples of 60)
|
||||
// Check that all points are on selected boundaries (multiples of 30)
|
||||
result.points.forEach { point ->
|
||||
assertTrue("Point at ${point.tSec} should be on minute boundary", point.tSec % 60 == 0)
|
||||
assertTrue("Point at ${point.tSec} should be on 30s boundary", point.tSec % 30 == 0)
|
||||
}
|
||||
|
||||
// Should have points at 0, 60, 120, 180 seconds
|
||||
assertEquals(4, result.points.size)
|
||||
// Should have points at 0, 30, 60, 90, 120, 150, 180 seconds
|
||||
assertEquals(7, result.points.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensureMinutePoints preserves interpolated values`() {
|
||||
fun `ensureTimelinePoints preserves interpolated values`() {
|
||||
val points = listOf(
|
||||
TimelinePoint(0, 0.0f),
|
||||
TimelinePoint(120, 1.0f),
|
||||
)
|
||||
val curve = TimelineCurve(points)
|
||||
|
||||
val result = curve.ensureMinutePoints(180)
|
||||
val result = curve.ensureTimelinePoints(180, granularitySec = 60)
|
||||
|
||||
// Value at 60 seconds should interpolate to 0.5
|
||||
val valueAt60 = result.valueAt(60f)
|
||||
@@ -209,7 +209,7 @@ class TimelineCurveGestureTest {
|
||||
fun `extendTo adds points for extended duration`() {
|
||||
val curve = TimelineCurve.constant(0.5f, 60)
|
||||
|
||||
val extended = curve.extendTo(120)
|
||||
val extended = curve.extendTo(120, granularitySec = 60)
|
||||
|
||||
// Should have points covering up to 120 seconds
|
||||
assertTrue(extended.points.any { it.tSec == 120 })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.mindmachine.mvp
|
||||
|
||||
import com.mindmachine.mvp.session.FlashColor
|
||||
import com.mindmachine.mvp.session.SplitFlashSequencer
|
||||
import com.mindmachine.mvp.session.computeSplitFlashFrame
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
@@ -39,4 +40,37 @@ class VisualSignalTest {
|
||||
val validAt2000ms = computeSplitFlashFrame(frameTimeNanos = 2_100_000_000L, flashOnMs = 2000, flashOffMs = 2000)
|
||||
assertEquals(validAt2000ms, tooSlow)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sequencer_keeps_blank_duration_constant_when_flash_duration_changes_mid_blank() {
|
||||
val sequencer = SplitFlashSequencer(startTimeNanos = 0L, flashOnMs = 100, flashOffMs = 1000)
|
||||
|
||||
assertEquals(FlashColor.BLACK, sequencer.frameAt(100_000_000L).left)
|
||||
|
||||
sequencer.updateIntervals(flashOnMs = 200, flashOffMs = 1000)
|
||||
|
||||
// Still blank before the configured 1000ms blank phase is complete.
|
||||
assertEquals(FlashColor.BLACK, sequencer.frameAt(600_000_000L).left)
|
||||
assertEquals(FlashColor.BLACK, sequencer.frameAt(1_099_000_000L).left)
|
||||
|
||||
// At 1100ms total, blank ends and next on-phase starts.
|
||||
assertEquals(FlashColor.GREEN, sequencer.frameAt(1_100_000_000L).left)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sequencer_applies_new_blank_interval_on_next_blank_boundary() {
|
||||
val sequencer = SplitFlashSequencer(startTimeNanos = 0L, flashOnMs = 100, flashOffMs = 100)
|
||||
|
||||
// Enter second on phase.
|
||||
assertEquals(FlashColor.GREEN, sequencer.frameAt(200_000_000L).left)
|
||||
|
||||
// Change blank interval during on phase; current on should finish uninterrupted.
|
||||
sequencer.updateIntervals(flashOnMs = 100, flashOffMs = 1000)
|
||||
assertEquals(FlashColor.GREEN, sequencer.frameAt(250_000_000L).left)
|
||||
|
||||
// Next phase is blank and should use new 1000ms off interval.
|
||||
assertEquals(FlashColor.BLACK, sequencer.frameAt(300_000_000L).left)
|
||||
assertEquals(FlashColor.BLACK, sequencer.frameAt(1_299_000_000L).left)
|
||||
assertEquals(FlashColor.RED, sequencer.frameAt(1_300_000_000L).left)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user