diff --git a/packages/core/cyclist.mjs b/packages/core/cyclist.mjs index a0580e713..76e808107 100644 --- a/packages/core/cyclist.mjs +++ b/packages/core/cyclist.mjs @@ -31,6 +31,7 @@ export class Cyclist { this.seconds_at_cps_change; // clock phase when cps was changed this.onToggle = onToggle; this.latency = latency; // fixed trigger time offset + this.pattern_state = {}; this.clock = createClock( getTime, // called slightly before each cycle @@ -57,9 +58,20 @@ export class Cyclist { } // query the pattern for events - const haps = this.pattern.queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' }); + let haps = this.pattern.sortHapsByPart().queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' }); + + // TODO - worth checking for stateful haps before needlessly sorting? + haps = haps.sort((a, b) => + a.part.begin + .sub(b.part.begin) + .or(a.part.end.sub(b.part.end)) + .or(a.whole.begin.sub(b.whole.begin).or(a.whole.end.sub(b.whole.end))), + ); + haps.forEach((hap) => { if (hap.hasOnset() || hap.context.processParts) { + let value; + [this.pattern_state, value] = hap.resolveState(this.pattern_state); const targetTime = (hap.part.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency; const duration = hap.duration / this.cps; @@ -68,8 +80,8 @@ export class Cyclist { const deadline = targetTime - phase; // this onTrigger has another signature onTrigger?.(hap, deadline, duration, this.cps, targetTime); - if (hap.value.cps !== undefined && this.cps != hap.value.cps) { - this.cps = hap.value.cps; + if (value.cps !== undefined && this.cps != value.cps) { + this.cps = value.cps; this.num_ticks_since_cps_change = 0; } } diff --git a/packages/core/hap.mjs b/packages/core/hap.mjs index a63bff9c7..112b511e3 100644 --- a/packages/core/hap.mjs +++ b/packages/core/hap.mjs @@ -96,14 +96,15 @@ export class Hap { return this.context.tags?.includes(tag); } + // Returns the hap value with any state transformation applied resolveState(state) { if (this.stateful && this.hasOnset()) { console.log('stateful'); const func = this.value; const [newState, newValue] = func(state); - return [newState, new Hap(this.whole, this.part, newValue, this.context, false)]; + return [newState, newValue]; } - return [state, this]; + return [state, this.value]; } spanEquals(other) { diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 1df5c8776..b2de11cb5 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -127,9 +127,9 @@ describe('Hap', () => { }; const state = { incrementme: 10 }; const ev1 = new Hap(ts(0, 1), ts(0, 1), stateful_value, {}, true); - const [state2, ev2] = ev1.resolveState(state); - const [state3, ev3] = ev1.resolveState(state2); - expect(ev3).toStrictEqual(new Hap(ts(0, 1), ts(0, 1), 11, {}, false)); + const [state2, _] = ev1.resolveState(state); + const [state3, v3] = ev1.resolveState(state2); + expect(v3).toStrictEqual(11); expect(state3).toStrictEqual({ incrementme: 12 }); }); });