feat(core): add pattern algebra transforms on HapticPattern - #96
Conversation
… PatternElement duration through it
📝 WalkthroughWalkthroughAdds pure extension functions on ChangesPattern Algebra Transforms
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant HapticPattern
participant ThenFn as then/plus
participant SpanMs as spanMs()
Caller->>HapticPattern: repeated(times)
loop times copies
HapticPattern->>ThenFn: then(copy)
ThenFn->>SpanMs: spanMs()
SpanMs-->>ThenFn: current span
ThenFn->>ThenFn: shift copy's events by span
ThenFn-->>HapticPattern: concatenated pattern
end
HapticPattern-->>Caller: repeated pattern
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
jindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ScaleIntensityTest.kt (1)
29-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding a test for the negative-factor rejection path.
The
require(factor >= 0f)guard inscaleIntensityis an important validation but has no corresponding test verifying that negative factors throwIllegalArgumentException. Adding a simple test would close this gap.🧪 Suggested test
test("negative factor is rejected") { checkAll(patterns()) { pattern -> shouldThrow<IllegalArgumentException> { pattern.scaleIntensity(-0.5f) } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@jindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ScaleIntensityTest.kt` around lines 29 - 59, Add a test in ScaleIntensityTest to cover the negative-factor validation path in scaleIntensity. The current suite checks clamping, identity scaling, and timing preservation, but not the require(factor >= 0f) guard; add a new test that uses patterns() and asserts pattern.scaleIntensity with a negative factor throws IllegalArgumentException, using the scaleIntensity function as the anchor point.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@jindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ScaleIntensityTest.kt`:
- Around line 29-59: Add a test in ScaleIntensityTest to cover the
negative-factor validation path in scaleIntensity. The current suite checks
clamping, identity scaling, and timing preservation, but not the require(factor
>= 0f) guard; add a new test that uses patterns() and asserts
pattern.scaleIntensity with a negative factor throws IllegalArgumentException,
using the scaleIntensity function as the anchor point.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 670fae3c-1874-42ea-a6ba-21d88df50510
📒 Files selected for processing (16)
jindong-core/api/jindong-core.apijindong-core/api/jindong-core.klib.apijindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/element/PatternElement.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/executor/RawSpanMs.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/PatternSpan.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/Repeated.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/Reversed.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/ScaleIntensity.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/Then.ktjindong-core/src/commonMain/kotlin/io/github/compose/jindong/core/model/TimeStretch.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/PatternArb.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/RepeatedTest.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ReversedTest.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ScaleIntensityTest.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/ThenTest.ktjindong-core/src/commonTest/kotlin/io/github/compose/jindong/core/model/TimeStretchTest.kt
Closes #88.
Adds pure value transforms on
HapticPattern. Each returns a new pattern; no executor or platform code is involved.Decisions
scaleIntensitymaps every intensity toHapticIntensity.Custom(value * factor); theCustomconstructor already clamps to [0, 1], sofactor > 1saturates safely. Rejects negative factors.timeStretchrounds the two event edges (start and end), not start and duration independently, so touching events stay touching.iosParameters(the ADSR envelope) is carried unchanged, since envelope shape is independent of where an event sits on the timeline.reversedmirrors each event on[0, span]. Transforms may leave overlapping events; those are serialized at playback bymergeToSerial(highest intensity wins), not here. This is why the work sits on top of feat(core): serial-timeline waveform pipeline (overlap, fall-ramp, handle lifecycle) #85.repeatedfolds overthen, sorepeated(n)equalsthenapplied n times by construction.spanMs()replaces the duplicated max-end-time calculation inrawSpanMs()andPatternElement.totalDurationMs. TheSequenceElement/RepeatElementtree-sum overrides are scheduling math and stay as they are.Tests
Property laws (kotest-property): reversed involution,
timeStretch(1)identity and composition within a factor-derived tolerance, intensity range,thenassociativity and empty identity, span and count preservation. 138 tests pass on bothiosSimulatorArm64and the Android host.Base:
main.Summary by CodeRabbit
New Features
thenor+.Bug Fixes