Update mode toggle, split flash visuals, and interval-ms controls
This commit is contained in:
@@ -15,14 +15,14 @@ class PresetDefaultsTest {
|
||||
|
||||
assertEquals(10 * 60, relax.defaultDurationSec)
|
||||
assertEquals(VisualPattern.PULSE, relax.visualPatternType)
|
||||
assertEquals(6f, relax.blinkFrequencyHz)
|
||||
assertEquals(167, relax.flashIntervalMs)
|
||||
|
||||
assertEquals(15 * 60, focus.defaultDurationSec)
|
||||
assertEquals(VisualPattern.FLASH, focus.visualPatternType)
|
||||
assertEquals(10f, focus.blinkFrequencyHz)
|
||||
assertEquals(100, focus.flashIntervalMs)
|
||||
|
||||
assertEquals(20 * 60, sleep.defaultDurationSec)
|
||||
assertEquals(VisualPattern.PULSE, sleep.visualPatternType)
|
||||
assertEquals(3f, sleep.blinkFrequencyHz)
|
||||
assertEquals(333, sleep.flashIntervalMs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.mindmachine.mvp
|
||||
|
||||
import com.mindmachine.mvp.domain.SessionConfig
|
||||
import com.mindmachine.mvp.domain.SessionMode
|
||||
import com.mindmachine.mvp.domain.VisualPattern
|
||||
import com.mindmachine.mvp.domain.SessionConfig
|
||||
import com.mindmachine.mvp.session.SessionValidator
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
@@ -14,7 +14,7 @@ class SessionValidatorTest {
|
||||
durationSec = 600,
|
||||
mode = SessionMode.AUDIO_VISUAL,
|
||||
visualPatternType = VisualPattern.PULSE,
|
||||
blinkFrequencyHz = 6f,
|
||||
flashIntervalMs = 167,
|
||||
intensityPercent = 50,
|
||||
carrierFrequencyHz = 200f,
|
||||
binauralDifferenceHz = 6f,
|
||||
@@ -39,7 +39,7 @@ class SessionValidatorTest {
|
||||
@Test
|
||||
fun out_of_range_values_are_blocked() {
|
||||
assertEquals("Duration must be 1 to 30 minutes.", SessionValidator.validate(valid.copy(durationSec = 59), true))
|
||||
assertEquals("Blink frequency must be 1.0 to 20.0 Hz.", SessionValidator.validate(valid.copy(blinkFrequencyHz = 21f), true))
|
||||
assertEquals("Flash interval must be 50 to 2000 ms.", SessionValidator.validate(valid.copy(flashIntervalMs = 49), true))
|
||||
assertEquals("Carrier frequency must be 80 to 400 Hz.", SessionValidator.validate(valid.copy(carrierFrequencyHz = 79f), true))
|
||||
assertEquals("Binaural difference must be 0.5 to 20 Hz.", SessionValidator.validate(valid.copy(binauralDifferenceHz = 0.1f), true))
|
||||
}
|
||||
|
||||
@@ -1,67 +1,42 @@
|
||||
package com.mindmachine.mvp
|
||||
|
||||
import com.mindmachine.mvp.domain.VisualPattern
|
||||
import com.mindmachine.mvp.session.computeVisualAlpha
|
||||
import com.mindmachine.mvp.session.FlashColor
|
||||
import com.mindmachine.mvp.session.computeSplitFlashFrame
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class VisualSignalTest {
|
||||
|
||||
@Test
|
||||
fun flashPatternAlternatesBetweenIntensityAndOff() {
|
||||
val intensity = 70
|
||||
val hz = 10f
|
||||
fun splitFlashPattern_cycles_redGreen_black_greenRed_black() {
|
||||
val intervalMs = 100
|
||||
|
||||
val on = computeVisualAlpha(
|
||||
visualPattern = VisualPattern.FLASH,
|
||||
frameTimeNanos = 0L,
|
||||
blinkFrequencyHz = hz,
|
||||
intensityPercent = intensity
|
||||
)
|
||||
val phase0 = computeSplitFlashFrame(frameTimeNanos = 0L, flashIntervalMs = intervalMs)
|
||||
val phase1 = computeSplitFlashFrame(frameTimeNanos = 100_000_000L, flashIntervalMs = intervalMs)
|
||||
val phase2 = computeSplitFlashFrame(frameTimeNanos = 200_000_000L, flashIntervalMs = intervalMs)
|
||||
val phase3 = computeSplitFlashFrame(frameTimeNanos = 300_000_000L, flashIntervalMs = intervalMs)
|
||||
|
||||
val off = computeVisualAlpha(
|
||||
visualPattern = VisualPattern.FLASH,
|
||||
frameTimeNanos = 75_000_000L,
|
||||
blinkFrequencyHz = hz,
|
||||
intensityPercent = intensity
|
||||
)
|
||||
assertEquals(FlashColor.RED, phase0.left)
|
||||
assertEquals(FlashColor.GREEN, phase0.right)
|
||||
|
||||
assertEquals(0.7f, on, 0.0001f)
|
||||
assertEquals(0f, off, 0.0001f)
|
||||
assertEquals(FlashColor.BLACK, phase1.left)
|
||||
assertEquals(FlashColor.BLACK, phase1.right)
|
||||
|
||||
assertEquals(FlashColor.GREEN, phase2.left)
|
||||
assertEquals(FlashColor.RED, phase2.right)
|
||||
|
||||
assertEquals(FlashColor.BLACK, phase3.left)
|
||||
assertEquals(FlashColor.BLACK, phase3.right)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pulsePatternStaysWithinZeroAndIntensity() {
|
||||
val intensity = 60
|
||||
fun interval_is_clamped_to_valid_range() {
|
||||
val tooFast = computeSplitFlashFrame(frameTimeNanos = 49_000_000L, flashIntervalMs = 1)
|
||||
val validAt50ms = computeSplitFlashFrame(frameTimeNanos = 49_000_000L, flashIntervalMs = 50)
|
||||
assertEquals(validAt50ms, tooFast)
|
||||
|
||||
val atStart = computeVisualAlpha(
|
||||
visualPattern = VisualPattern.PULSE,
|
||||
frameTimeNanos = 0L,
|
||||
blinkFrequencyHz = 3f,
|
||||
intensityPercent = intensity
|
||||
)
|
||||
val quarterCycle = computeVisualAlpha(
|
||||
visualPattern = VisualPattern.PULSE,
|
||||
frameTimeNanos = 83_333_333L,
|
||||
blinkFrequencyHz = 3f,
|
||||
intensityPercent = intensity
|
||||
)
|
||||
|
||||
assertTrue(atStart in 0f..0.6f)
|
||||
assertTrue(quarterCycle in 0f..0.6f)
|
||||
assertTrue(quarterCycle > atStart)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun intensityZeroAlwaysReturnsZero() {
|
||||
val alpha = computeVisualAlpha(
|
||||
visualPattern = VisualPattern.FLASH,
|
||||
frameTimeNanos = 123_000_000L,
|
||||
blinkFrequencyHz = 8f,
|
||||
intensityPercent = 0
|
||||
)
|
||||
|
||||
assertEquals(0f, alpha, 0f)
|
||||
val tooSlow = computeSplitFlashFrame(frameTimeNanos = 2_100_000_000L, flashIntervalMs = 5000)
|
||||
val validAt2000ms = computeSplitFlashFrame(frameTimeNanos = 2_100_000_000L, flashIntervalMs = 2000)
|
||||
assertEquals(validAt2000ms, tooSlow)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user