@msb235/blits 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +198 -0
- package/README.md +3 -3
- package/dist/ahead.d.ts +26 -0
- package/dist/ahead.js +264 -0
- package/dist/around.d.ts +11 -0
- package/dist/around.js +32 -0
- package/dist/bare.js +37 -14
- package/dist/blank.d.ts +10 -0
- package/dist/blank.js +26 -0
- package/dist/blend.d.ts +2 -1
- package/dist/blend.js +1 -6
- package/dist/bound.d.ts +70 -0
- package/dist/bound.js +351 -0
- package/dist/chain.d.ts +2 -1
- package/dist/chain.js +7 -5
- package/dist/changes.d.ts +24 -0
- package/dist/changes.js +189 -0
- package/dist/channels.d.ts +39 -13
- package/dist/channels.js +14 -5
- package/dist/color.d.ts +12 -10
- package/dist/color.js +25 -25
- package/dist/columns.d.ts +2 -1
- package/dist/columns.js +62 -38
- package/dist/contribution.d.ts +30 -0
- package/dist/contribution.js +374 -0
- package/dist/copyout.d.ts +10 -0
- package/dist/copyout.js +69 -24
- package/dist/crowd.d.ts +16 -6
- package/dist/crowd.js +20 -11
- package/dist/cue.d.ts +8 -1
- package/dist/cue.js +39 -13
- package/dist/cut.d.ts +8 -0
- package/dist/cut.js +4 -0
- package/dist/delay.d.ts +3 -0
- package/dist/delay.js +7 -0
- package/dist/drop.d.ts +9 -0
- package/dist/drop.js +84 -0
- package/dist/due.d.ts +24 -5
- package/dist/due.js +114 -34
- package/dist/easing.d.ts +6 -4
- package/dist/easing.js +7 -3
- package/dist/everyone.d.ts +8 -2
- package/dist/everyone.js +33 -3
- package/dist/fade.d.ts +2 -1
- package/dist/fade.js +2 -1
- package/dist/fill.d.ts +3 -2
- package/dist/fill.js +52 -20
- package/dist/fit.d.ts +44 -26
- package/dist/fit.js +10 -9
- package/dist/fold.d.ts +4 -37
- package/dist/fold.js +5 -513
- package/dist/gather.d.ts +12 -7
- package/dist/gather.js +179 -44
- package/dist/gone.js +2 -2
- package/dist/grid.d.ts +47 -0
- package/dist/grid.js +247 -0
- package/dist/handle.d.ts +2 -0
- package/dist/handle.js +14 -8
- package/dist/held.d.ts +2 -1
- package/dist/held.js +2 -1
- package/dist/history.d.ts +6 -5
- package/dist/history.js +7 -9
- package/dist/hosts.js +9 -15
- package/dist/index.d.ts +5 -4
- package/dist/keyfill.d.ts +1 -1
- package/dist/keyfill.js +5 -3
- package/dist/keyrows.d.ts +12 -0
- package/dist/keyrows.js +99 -12
- package/dist/lane.d.ts +38 -11
- package/dist/lane.js +46 -11
- package/dist/lanes.d.ts +30 -12
- package/dist/lanes.js +56 -36
- package/dist/leavings.d.ts +2 -2
- package/dist/leavings.js +1 -1
- package/dist/lives.d.ts +47 -0
- package/dist/lives.js +180 -0
- package/dist/meet.d.ts +2 -2
- package/dist/meet.js +95 -7
- package/dist/mixer.d.ts +56 -37
- package/dist/mixer.js +57 -171
- package/dist/motion.d.ts +14 -118
- package/dist/motion.js +16 -8
- package/dist/motions.d.ts +62 -155
- package/dist/motions.js +56 -370
- package/dist/moved.d.ts +1 -1
- package/dist/moved.js +16 -7
- package/dist/named.d.ts +6 -2
- package/dist/named.js +49 -3
- package/dist/numbers.d.ts +7 -0
- package/dist/numbers.js +33 -0
- package/dist/owed.d.ts +2 -0
- package/dist/owed.js +4 -0
- package/dist/pack.d.ts +2 -1
- package/dist/pack.js +2 -3
- package/dist/patch.d.ts +7 -3
- package/dist/patch.js +6 -2
- package/dist/places.d.ts +53 -0
- package/dist/places.js +171 -0
- package/dist/plot.d.ts +12 -0
- package/dist/plot.js +52 -0
- package/dist/project.d.ts +4 -4
- package/dist/project.js +9 -212
- package/dist/pull.js +22 -9
- package/dist/qualify.js +93 -31
- package/dist/reading.d.ts +6 -0
- package/dist/reading.js +5 -0
- package/dist/record.d.ts +5 -1
- package/dist/record.js +3 -2
- package/dist/relink.d.ts +1 -1
- package/dist/renumber.d.ts +10 -0
- package/dist/renumber.js +75 -0
- package/dist/restored.d.ts +2 -2
- package/dist/restored.js +1 -1
- package/dist/rests.d.ts +9 -0
- package/dist/rests.js +76 -0
- package/dist/revive.d.ts +3 -2
- package/dist/revive.js +2 -2
- package/dist/{locus.d.ts → role.d.ts} +10 -9
- package/dist/{locus.js → role.js} +3 -3
- package/dist/roles.d.ts +10 -0
- package/dist/roles.js +158 -0
- package/dist/roster.js +3 -3
- package/dist/rotation.d.ts +1 -1
- package/dist/rotation.js +1 -1
- package/dist/rows.js +28 -20
- package/dist/sample.d.ts +2 -2
- package/dist/sample.js +33 -7
- package/dist/seat.d.ts +17 -0
- package/dist/seat.js +25 -0
- package/dist/seek.js +5 -5
- package/dist/setting.d.ts +27 -0
- package/dist/setting.js +55 -0
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/dist/signals.d.ts +64 -32
- package/dist/signals.js +20 -18
- package/dist/stack.d.ts +5 -5
- package/dist/stack.js +5 -5
- package/dist/standing.d.ts +2 -1
- package/dist/standing.js +3 -2
- package/dist/store.d.ts +9 -0
- package/dist/store.js +24 -0
- package/dist/strays.d.ts +2 -1
- package/dist/strays.js +23 -15
- package/dist/stretch.d.ts +112 -0
- package/dist/stretch.js +9 -0
- package/dist/subject.d.ts +142 -0
- package/dist/subject.js +1 -0
- package/dist/tape.d.ts +9 -5
- package/dist/tape.js +5 -1
- package/dist/then.d.ts +9 -0
- package/dist/then.js +57 -0
- package/dist/ticker.d.ts +4 -4
- package/dist/trace.d.ts +4 -0
- package/dist/trace.js +255 -0
- package/dist/transport.d.ts +0 -8
- package/dist/transport.js +0 -4
- package/dist/turns.d.ts +4 -3
- package/dist/turns.js +4 -3
- package/dist/types/arc.d.ts +12 -11
- package/dist/types/channel.d.ts +12 -8
- package/dist/types/history.d.ts +35 -19
- package/dist/types/mix.d.ts +237 -163
- package/dist/types/motion.d.ts +151 -0
- package/dist/types/motion.js +1 -0
- package/dist/types/patch.d.ts +67 -34
- package/dist/types/place.d.ts +51 -36
- package/dist/types/trace.d.ts +51 -0
- package/dist/types/trace.js +1 -0
- package/dist/types/transport.d.ts +20 -18
- package/dist/types/voice.d.ts +144 -73
- package/dist/types/watch.d.ts +88 -40
- package/dist/types.d.ts +2 -0
- package/dist/unreached.d.ts +2 -0
- package/dist/unreached.js +7 -0
- package/dist/voice.d.ts +10 -143
- package/dist/voice.js +37 -82
- package/dist/warn.d.ts +2 -0
- package/dist/warn.js +1 -1
- package/dist/watch.d.ts +2 -2
- package/dist/watch.js +5 -3
- package/dist/wave.d.ts +4 -3
- package/dist/wave.js +3 -2
- package/dist/weigh.d.ts +7 -1
- package/dist/weigh.js +27 -0
- package/docs/schema.html +223 -34
- package/package.json +2 -2
package/dist/lane.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { unbareLane } from './bare.js';
|
|
2
|
-
import { frozenTime } from './clock.js';
|
|
3
2
|
import { motionOf } from './motion.js';
|
|
3
|
+
/**
|
|
4
|
+
* Keeps the weight a probe read from the last fill as `Row.PROBED`, for `weightOf`, before a fill
|
|
5
|
+
* writes the position's new weight; reads `per` only where the copy could change a bit.
|
|
6
|
+
*/
|
|
7
|
+
export function keepProbed(data, o, per, q, fills) {
|
|
8
|
+
const w = data[o + 2 /* Row.WEIGHT */];
|
|
9
|
+
if ((w !== data[o + 3 /* Row.PROBED */] || w === 0) && per[q + 5 /* Per.LANE_FILL */] === fills - 1)
|
|
10
|
+
data[o + 3 /* Row.PROBED */] = w;
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* Below what share of its subjects probed last frame a lane stops filling, and above what share it
|
|
6
14
|
* fills again; between the two it keeps doing what it did, so a host near the line does not flip
|
|
@@ -70,6 +78,8 @@ export class Lane {
|
|
|
70
78
|
fade = 1;
|
|
71
79
|
/** Whether the voice has no fade in or out this fill, so its envelope is 1 for every subject. */
|
|
72
80
|
flat = false;
|
|
81
|
+
/** The fill that last ran it, so what it remembers within one fill is that fill's. */
|
|
82
|
+
ran = -1;
|
|
73
83
|
/** The voice's clock at this fill, set before `one` runs its subjects. */
|
|
74
84
|
elapsedNow = 0;
|
|
75
85
|
/** A motion patch's state, which the lane samples in place of calling the patch. */
|
|
@@ -80,8 +90,12 @@ export class Lane {
|
|
|
80
90
|
bareFill = -1;
|
|
81
91
|
bareElapsed = Number.NaN;
|
|
82
92
|
bareSeeks = Number.NaN;
|
|
83
|
-
/** The
|
|
93
|
+
/** The role its voice shares, gathered before the voices are folded in order. */
|
|
84
94
|
group = null;
|
|
95
|
+
/** The `Arg.MARK` it was last placed under, for a role run a subject at a time to put back. */
|
|
96
|
+
mark = Number.NaN;
|
|
97
|
+
/** Whether it took every subject when it opened, so a fill makes each one's first call. */
|
|
98
|
+
every = false;
|
|
85
99
|
voiceAt() {
|
|
86
100
|
return this.voice;
|
|
87
101
|
}
|
|
@@ -128,6 +142,22 @@ export class Lane {
|
|
|
128
142
|
positionOf(slot) {
|
|
129
143
|
return slot < this.at.length ? this.at[slot] - 1 : -1;
|
|
130
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Room for `n` positions and subject numbers below `cap`, for a voice that reaches every subject:
|
|
147
|
+
* grown as it met them, a voice replaced every frame regrew both from nothing each frame.
|
|
148
|
+
*/
|
|
149
|
+
reserve(n, cap) {
|
|
150
|
+
if (n * 8 /* Row.STRIDE */ > this.data.length) {
|
|
151
|
+
const data = new Float64Array(n * 8 /* Row.STRIDE */);
|
|
152
|
+
data.set(this.data);
|
|
153
|
+
this.data = data;
|
|
154
|
+
}
|
|
155
|
+
if (cap > this.at.length) {
|
|
156
|
+
const at = new Int32Array(cap);
|
|
157
|
+
at.set(this.at);
|
|
158
|
+
this.at = at;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
131
161
|
/** Gives a subject the voice reaches a position, from what its record fixed on first sight. */
|
|
132
162
|
add(slot, held) {
|
|
133
163
|
const p = this.list.length;
|
|
@@ -154,6 +184,20 @@ export class Lane {
|
|
|
154
184
|
this.records[p] = held;
|
|
155
185
|
this.deltas[p] = null;
|
|
156
186
|
}
|
|
187
|
+
/** The subject numbered `from` is numbered `to` now, a number no position holds: same position. */
|
|
188
|
+
renumber(from, to) {
|
|
189
|
+
const p = this.positionOf(from);
|
|
190
|
+
if (p < 0)
|
|
191
|
+
return;
|
|
192
|
+
if (to >= this.at.length) {
|
|
193
|
+
const at = new Int32Array(Math.max(to + 1, this.at.length * 2, 64));
|
|
194
|
+
at.set(this.at);
|
|
195
|
+
this.at = at;
|
|
196
|
+
}
|
|
197
|
+
this.list[p] = to;
|
|
198
|
+
this.at[to] = p + 1;
|
|
199
|
+
this.at[from] = 0;
|
|
200
|
+
}
|
|
157
201
|
/** A subject lost its number: the last position moves into its place. */
|
|
158
202
|
remove(slot) {
|
|
159
203
|
const p = this.positionOf(slot);
|
|
@@ -183,12 +227,3 @@ export class Lane {
|
|
|
183
227
|
this.deltas[last] = null;
|
|
184
228
|
}
|
|
185
229
|
}
|
|
186
|
-
/**
|
|
187
|
-
* A subject's voice time once its voice's freezes apply: frozen at 0 before it starts and at the end
|
|
188
|
-
* of its passes after, and NaN where it shows nothing, as past its end running back.
|
|
189
|
-
*/
|
|
190
|
-
export function frozenAt(voice, elapsed) {
|
|
191
|
-
if (elapsed > voice.span && voice.hidesPast)
|
|
192
|
-
return Number.NaN;
|
|
193
|
-
return frozenTime(elapsed, voice.freezesBefore, voice.freezesAfter, voice.span);
|
|
194
|
-
}
|
package/dist/lanes.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { Column } from './columns.js';
|
|
2
|
-
import { copy } from './copyout.js';
|
|
2
|
+
import { type Copier, copy } from './copyout.js';
|
|
3
3
|
import { type Crowd, row } from './crowd.js';
|
|
4
4
|
import { call, foldKeys, one, parting, readKeyed, reset, run, runEveryone, signalled, subjectAt } from './fill.js';
|
|
5
5
|
import { fold, foldDelta, foldInto, foldRun, gate, gather, unplain } from './gather.js';
|
|
6
|
-
import { type Lane, type Laned, type
|
|
7
|
-
import type { Watcher } from './motions.js';
|
|
6
|
+
import { type Lane, type Laned, type Role } from './lane.js';
|
|
8
7
|
import { absent, Numbers } from './numbers.js';
|
|
9
8
|
import { Owed } from './owed.js';
|
|
10
9
|
import { Placed } from './placed.js';
|
|
10
|
+
import { type Seat } from './seat.js';
|
|
11
|
+
import type { Watcher } from './stretch.js';
|
|
12
|
+
import type { Subject } from './subject.js';
|
|
11
13
|
import type { Channel } from './types.js';
|
|
12
|
-
import type {
|
|
14
|
+
import type { Voice } from './voice.js';
|
|
13
15
|
/** What a lane fill asks of the mix it belongs to. */
|
|
14
16
|
export interface LaneHost<I, O> {
|
|
15
17
|
readonly voices: readonly Voice<I, O>[];
|
|
@@ -69,7 +71,7 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
69
71
|
readonly byId: Map<number, Lane<I, O>>;
|
|
70
72
|
/** The crowds of single-subject voices, one per list of channels, and which holds each voice. */
|
|
71
73
|
crowds: Crowd<I, O>[];
|
|
72
|
-
readonly
|
|
74
|
+
readonly seats: Map<number, Seat<I, O>>;
|
|
73
75
|
/** Which crowd voices' rows are placed on each subject. */
|
|
74
76
|
readonly placed: Placed;
|
|
75
77
|
/**
|
|
@@ -79,15 +81,20 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
79
81
|
unlinked: Float64Array<ArrayBuffer>;
|
|
80
82
|
/** Whether two crowds share a channel, so their rows must interleave in voice order. */
|
|
81
83
|
overlap: boolean;
|
|
82
|
-
/** The
|
|
83
|
-
|
|
84
|
+
/** The roles whose voices are on lanes, every member of each on one. */
|
|
85
|
+
roles: Role<I, O>[];
|
|
84
86
|
/** The lane and record `one` is folding, whose band state a rest-less channel reads. */
|
|
85
87
|
folding: Lane<I, O> | null;
|
|
88
|
+
/** Whether a probe meeting lanes has `one` make their first call for its subject: see `meet`. */
|
|
89
|
+
meeting: boolean;
|
|
90
|
+
/** The lanes the last subject met and `foldNow` folded at its probe, and the fill it did so in. */
|
|
91
|
+
folds: number[];
|
|
92
|
+
foldsFill: number;
|
|
86
93
|
rec: Subject<unknown> | null;
|
|
87
94
|
/** The numbers a fill's methods hand each other: see `Arg`. */
|
|
88
95
|
readonly arg: Float64Array<ArrayBuffer>;
|
|
89
|
-
/** While a fill gathers a
|
|
90
|
-
into:
|
|
96
|
+
/** While a fill gathers a role: that role and the member gathering, where folds go instead. */
|
|
97
|
+
into: Role<I, O> | null;
|
|
91
98
|
intoId: number;
|
|
92
99
|
readonly lawsByKey: Map<string, Float64Array<ArrayBufferLike>>;
|
|
93
100
|
lastLaw: Float64Array | null;
|
|
@@ -102,6 +109,8 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
102
109
|
/** By subject number, the laned voices its probes fold on the general path this fill. */
|
|
103
110
|
readonly owed: Owed;
|
|
104
111
|
laned: Laned[];
|
|
112
|
+
/** Writes `laned`'s values for a subject into a pose; made at the first copy after they change. */
|
|
113
|
+
copier: Copier | null;
|
|
105
114
|
/** By kit slot, the laned channel there. */
|
|
106
115
|
bySlot: (Laned | undefined)[];
|
|
107
116
|
/** By kit slot, whether a fill leaves the channel's values for probes to copy. */
|
|
@@ -138,6 +147,13 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
138
147
|
subjects: (I | typeof absent | undefined)[];
|
|
139
148
|
/** Whether a probe has held a subject since the last fill let them go. */
|
|
140
149
|
holding: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Whether probes hold their subjects for the next fill: while the last fill looked one up. A
|
|
152
|
+
* fill of bare tweens never does, and holding cost a store a subject and a clear a frame.
|
|
153
|
+
*/
|
|
154
|
+
holds: boolean;
|
|
155
|
+
/** How many times a fill or a probe has looked a subject up by number, for `holds`. */
|
|
156
|
+
lookups: number;
|
|
141
157
|
/** While a fill runs, so a probe a patch makes from inside it takes the general path. */
|
|
142
158
|
filling: boolean;
|
|
143
159
|
/**
|
|
@@ -146,14 +162,16 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
146
162
|
*/
|
|
147
163
|
readonly late: number[];
|
|
148
164
|
/**
|
|
149
|
-
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs: each
|
|
150
|
-
*
|
|
165
|
+
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs of rows: each
|
|
166
|
+
* run's first row and how many follow, and its first lane slot where its slots follow one apart
|
|
167
|
+
* too, else -1, when each row's slot is read from `queueFrom` by row.
|
|
151
168
|
*/
|
|
152
169
|
queueSlots: Int32Array<ArrayBuffer>;
|
|
153
170
|
queueRows: Int32Array<ArrayBuffer>;
|
|
154
171
|
queueCounts: Int32Array<ArrayBuffer>;
|
|
155
172
|
queued: number;
|
|
156
173
|
queuedFor: readonly Column[] | null;
|
|
174
|
+
queueFrom: Int32Array | null;
|
|
157
175
|
keeps: boolean;
|
|
158
176
|
now: number;
|
|
159
177
|
filledAt: number;
|
|
@@ -270,7 +288,7 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
270
288
|
/** A voice's clock moved the `shown` of records it had already placed: copies them again. */
|
|
271
289
|
reshown(id: number): void;
|
|
272
290
|
/** Something on a voice changed: a crowd copies it again at the next fill. */
|
|
273
|
-
voiceChanged(
|
|
291
|
+
voiceChanged(voice: Voice<I, O>): void;
|
|
274
292
|
}
|
|
275
293
|
declare const methods: {
|
|
276
294
|
copy: typeof copy;
|
package/dist/lanes.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { lit } from './bound.js';
|
|
1
2
|
import { copy } from './copyout.js';
|
|
2
3
|
import { row } from './crowd.js';
|
|
3
4
|
import { call, fillAll, foldKeys, one, parting, readKeyed, reset, run, runEveryone, signalled, subjectAt, } from './fill.js';
|
|
@@ -9,6 +10,7 @@ import { Placed } from './placed.js';
|
|
|
9
10
|
import { requalify, retouch } from './qualify.js';
|
|
10
11
|
import { reading } from './reading.js';
|
|
11
12
|
import { reportedRow, unplace } from './rows.js';
|
|
13
|
+
import { seatOf } from './seat.js';
|
|
12
14
|
/**
|
|
13
15
|
* The lanes of one mix: subject numbers, which channels and voices run on lanes, and the values a
|
|
14
16
|
* frame's fill leaves for probes to copy.
|
|
@@ -23,7 +25,7 @@ export class Lanes {
|
|
|
23
25
|
byId = new Map();
|
|
24
26
|
/** The crowds of single-subject voices, one per list of channels, and which holds each voice. */
|
|
25
27
|
crowds = [];
|
|
26
|
-
|
|
28
|
+
seats = new Map();
|
|
27
29
|
/** Which crowd voices' rows are placed on each subject. */
|
|
28
30
|
placed = new Placed();
|
|
29
31
|
/**
|
|
@@ -33,14 +35,19 @@ export class Lanes {
|
|
|
33
35
|
unlinked = new Float64Array(0);
|
|
34
36
|
/** Whether two crowds share a channel, so their rows must interleave in voice order. */
|
|
35
37
|
overlap = false;
|
|
36
|
-
/** The
|
|
37
|
-
|
|
38
|
+
/** The roles whose voices are on lanes, every member of each on one. */
|
|
39
|
+
roles = [];
|
|
38
40
|
/** The lane and record `one` is folding, whose band state a rest-less channel reads. */
|
|
39
41
|
folding = null;
|
|
42
|
+
/** Whether a probe meeting lanes has `one` make their first call for its subject: see `meet`. */
|
|
43
|
+
meeting = false;
|
|
44
|
+
/** The lanes the last subject met and `foldNow` folded at its probe, and the fill it did so in. */
|
|
45
|
+
folds = [];
|
|
46
|
+
foldsFill = -1;
|
|
40
47
|
rec = null;
|
|
41
48
|
/** The numbers a fill's methods hand each other: see `Arg`. */
|
|
42
|
-
arg = new Float64Array(
|
|
43
|
-
/** While a fill gathers a
|
|
49
|
+
arg = new Float64Array(8 /* Arg.SIZE */);
|
|
50
|
+
/** While a fill gathers a role: that role and the member gathering, where folds go instead. */
|
|
44
51
|
into = null;
|
|
45
52
|
intoId = 0;
|
|
46
53
|
lawsByKey = new Map();
|
|
@@ -56,6 +63,8 @@ export class Lanes {
|
|
|
56
63
|
/** By subject number, the laned voices its probes fold on the general path this fill. */
|
|
57
64
|
owed = new Owed();
|
|
58
65
|
laned = [];
|
|
66
|
+
/** Writes `laned`'s values for a subject into a pose; made at the first copy after they change. */
|
|
67
|
+
copier = null;
|
|
59
68
|
/** By kit slot, the laned channel there. */
|
|
60
69
|
bySlot = [];
|
|
61
70
|
/** By kit slot, whether a fill leaves the channel's values for probes to copy. */
|
|
@@ -92,6 +101,13 @@ export class Lanes {
|
|
|
92
101
|
subjects = [];
|
|
93
102
|
/** Whether a probe has held a subject since the last fill let them go. */
|
|
94
103
|
holding = false;
|
|
104
|
+
/**
|
|
105
|
+
* Whether probes hold their subjects for the next fill: while the last fill looked one up. A
|
|
106
|
+
* fill of bare tweens never does, and holding cost a store a subject and a clear a frame.
|
|
107
|
+
*/
|
|
108
|
+
holds = true;
|
|
109
|
+
/** How many times a fill or a probe has looked a subject up by number, for `holds`. */
|
|
110
|
+
lookups = 0;
|
|
95
111
|
/** While a fill runs, so a probe a patch makes from inside it takes the general path. */
|
|
96
112
|
filling = false;
|
|
97
113
|
/**
|
|
@@ -100,14 +116,16 @@ export class Lanes {
|
|
|
100
116
|
*/
|
|
101
117
|
late = [];
|
|
102
118
|
/**
|
|
103
|
-
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs: each
|
|
104
|
-
*
|
|
119
|
+
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs of rows: each
|
|
120
|
+
* run's first row and how many follow, and its first lane slot where its slots follow one apart
|
|
121
|
+
* too, else -1, when each row's slot is read from `queueFrom` by row.
|
|
105
122
|
*/
|
|
106
123
|
queueSlots = new Int32Array(0);
|
|
107
124
|
queueRows = new Int32Array(0);
|
|
108
125
|
queueCounts = new Int32Array(0);
|
|
109
126
|
queued = 0;
|
|
110
127
|
queuedFor = null;
|
|
128
|
+
queueFrom = null;
|
|
111
129
|
keeps = false;
|
|
112
130
|
now = Number.NaN;
|
|
113
131
|
filledAt = Number.NaN;
|
|
@@ -218,10 +236,9 @@ export class Lanes {
|
|
|
218
236
|
lane.remove(slot);
|
|
219
237
|
return;
|
|
220
238
|
}
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
unplace(this, c, p);
|
|
239
|
+
const s = this.seats.get(id);
|
|
240
|
+
if (s !== undefined && s.crowd.list[s.row] === slot)
|
|
241
|
+
unplace(this, s.crowd, s.row);
|
|
225
242
|
}
|
|
226
243
|
/** A voice brought a subject back: its next probe meets every lane again, as it met them first. */
|
|
227
244
|
rejoin(slot) {
|
|
@@ -239,9 +256,8 @@ export class Lanes {
|
|
|
239
256
|
const lane = this.byId.get(id);
|
|
240
257
|
if (lane !== undefined)
|
|
241
258
|
return this.reported(lane, slot);
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
return c === undefined || p === undefined ? undefined : reportedRow(this, c, p, slot);
|
|
259
|
+
const s = this.seats.get(id);
|
|
260
|
+
return s === undefined ? undefined : reportedRow(this, s.crowd, s.row, slot);
|
|
245
261
|
}
|
|
246
262
|
reported(lane, slot) {
|
|
247
263
|
const o = slot * 6 /* Per.SLOT */;
|
|
@@ -275,8 +291,10 @@ export class Lanes {
|
|
|
275
291
|
if (lane) {
|
|
276
292
|
per[o + 3 /* Per.LANE_PROBE */] = probe;
|
|
277
293
|
per[o + 5 /* Per.LANE_FILL */] = this.fills;
|
|
278
|
-
this.
|
|
279
|
-
|
|
294
|
+
if (this.holds) {
|
|
295
|
+
this.subjects[slot] = subject;
|
|
296
|
+
this.holding = true;
|
|
297
|
+
}
|
|
280
298
|
}
|
|
281
299
|
else
|
|
282
300
|
per[o + 4 /* Per.GENERAL_PROBE */] = probe;
|
|
@@ -381,8 +399,12 @@ export class Lanes {
|
|
|
381
399
|
paid(id, slot, w) {
|
|
382
400
|
const lane = this.byId.get(id);
|
|
383
401
|
const p = lane === undefined ? -1 : lane.positionOf(slot);
|
|
384
|
-
if (p
|
|
385
|
-
|
|
402
|
+
if (p < 0)
|
|
403
|
+
return;
|
|
404
|
+
lane.data[p * 8 /* Row.STRIDE */ + 2 /* Row.WEIGHT */] = w;
|
|
405
|
+
const b = lane.voice.bound;
|
|
406
|
+
if (b !== null && w !== 0)
|
|
407
|
+
lit(b, slot, this.fills);
|
|
386
408
|
}
|
|
387
409
|
/**
|
|
388
410
|
* Whether a subject's laned values are at their channels' rest, as `atRest` reads the pose `copy`
|
|
@@ -418,10 +440,9 @@ export class Lanes {
|
|
|
418
440
|
lane.remove(slot);
|
|
419
441
|
const placed = this.placed;
|
|
420
442
|
for (let id = placed.any(slot); id !== 0; id = placed.any(slot)) {
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
unplace(this, c, p);
|
|
443
|
+
const s = this.seats.get(id);
|
|
444
|
+
if (s !== undefined && s.crowd.list[s.row] === slot)
|
|
445
|
+
unplace(this, s.crowd, s.row);
|
|
425
446
|
else
|
|
426
447
|
placed.remove(slot, id);
|
|
427
448
|
}
|
|
@@ -453,10 +474,10 @@ export class Lanes {
|
|
|
453
474
|
* next fill, and a lane keeps the sample the old one gave.
|
|
454
475
|
*/
|
|
455
476
|
stretchChanged(id, s) {
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
c.restale(
|
|
477
|
+
const seat = this.seats.get(id);
|
|
478
|
+
if (seat !== undefined) {
|
|
479
|
+
const c = seat.crowd;
|
|
480
|
+
c.restale(seat.row, c.hot[seat.row * c.stride + 0 /* Hot.FLAGS */]);
|
|
460
481
|
return;
|
|
461
482
|
}
|
|
462
483
|
const lane = this.byId.get(id);
|
|
@@ -481,12 +502,11 @@ export class Lanes {
|
|
|
481
502
|
}
|
|
482
503
|
/** A voice's clock moved the `shown` of records it had already placed: copies them again. */
|
|
483
504
|
reshown(id) {
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
const held = c.records[p];
|
|
505
|
+
const s = this.seats.get(id);
|
|
506
|
+
if (s !== undefined) {
|
|
507
|
+
const held = s.crowd.records[s.row];
|
|
488
508
|
if (held !== undefined)
|
|
489
|
-
|
|
509
|
+
s.crowd.data[s.row * 8 /* Row.STRIDE */ + 1 /* Row.SINCE */] = held.shown;
|
|
490
510
|
}
|
|
491
511
|
const lane = this.byId.get(id);
|
|
492
512
|
if (lane === undefined)
|
|
@@ -498,12 +518,12 @@ export class Lanes {
|
|
|
498
518
|
}
|
|
499
519
|
}
|
|
500
520
|
/** Something on a voice changed: a crowd copies it again at the next fill. */
|
|
501
|
-
voiceChanged(
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
if (c === undefined || p === undefined)
|
|
521
|
+
voiceChanged(voice) {
|
|
522
|
+
const s = seatOf(this, voice);
|
|
523
|
+
if (s === null)
|
|
505
524
|
return;
|
|
506
|
-
const
|
|
525
|
+
const c = s.crowd;
|
|
526
|
+
const f = s.row * c.stride + 0 /* Hot.FLAGS */;
|
|
507
527
|
c.hot[f] = c.hot[f] | 64 /* Flag.VOICE */;
|
|
508
528
|
}
|
|
509
529
|
}
|
package/dist/leavings.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Cut } from './
|
|
2
|
-
import type { Left, Subject } from './
|
|
1
|
+
import { type Cut } from './cut.js';
|
|
2
|
+
import type { Left, Subject } from './subject.js';
|
|
3
3
|
/**
|
|
4
4
|
* Under history, the records subjects left a voice with, while a seek or a read back may reach
|
|
5
5
|
* them: in the order they left, the oldest let go of from the front, and each subject's found
|
package/dist/leavings.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { within } from './cut.js';
|
|
1
2
|
import { Store } from './store.js';
|
|
2
|
-
import { within } from './transport.js';
|
|
3
3
|
/**
|
|
4
4
|
* Under history, the records subjects left a voice with, while a seek or a read back may reach
|
|
5
5
|
* them: in the order they left, the oldest let go of from the front, and each subject's found
|
package/dist/lives.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Cut } from './cut.js';
|
|
2
|
+
import type { Motions } from './motions.js';
|
|
3
|
+
import { type Change, type Paging, type Run } from './stretch.js';
|
|
4
|
+
/** A run a release kept, with when: `early` where the release came before anything read its frame. */
|
|
5
|
+
export type Released<I> = {
|
|
6
|
+
subject: I;
|
|
7
|
+
at: number;
|
|
8
|
+
seq: number;
|
|
9
|
+
early: boolean;
|
|
10
|
+
} & Run;
|
|
11
|
+
/**
|
|
12
|
+
* Forgets a subject, so a later ask starts it afresh from `from`. Given the mix time `at` and frame
|
|
13
|
+
* `seq`, under history, its run is kept for a rewind before then, until `reach` passes it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function release<I>(this: Motions<I>, subject: I, at?: number, reach?: number, seq?: number, early?: boolean): void;
|
|
16
|
+
/** Puts back each subject released after frame `seq`, as it stood when released. */
|
|
17
|
+
export declare function unrelease<I>(this: Motions<I>, seq: number): void;
|
|
18
|
+
/** Subject `s`'s run as it stands. */
|
|
19
|
+
export declare function runAt<I>(this: Motions<I>, s: number): Run;
|
|
20
|
+
/** A subject's run as plain data, for a voice leaving memory; undefined where it has none. */
|
|
21
|
+
export declare function pack<I>(this: Motions<I>, subject: I): Run | undefined;
|
|
22
|
+
/** Puts a subject's run back as `pack` or a release left it, replacing any it has now. */
|
|
23
|
+
export declare function unpack<I>(this: Motions<I>, subject: I, run: Run): void;
|
|
24
|
+
/** A released run a history store gave back, for a rewind to before its release. */
|
|
25
|
+
export declare function reclaim<I>(this: Motions<I>, subject: I, at: number, seq: number, run: Run & {
|
|
26
|
+
early?: boolean;
|
|
27
|
+
}): void;
|
|
28
|
+
/**
|
|
29
|
+
* The run `subject` had in frame `cut`: the one a release after the cut kept, else the one it has
|
|
30
|
+
* now; undefined where it has neither. Its changes after the cut are still on it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runThen<I>(this: Motions<I>, subject: I, cut: Cut): Run | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Stretches a history store gave back, each by the frame it was in force by: each life of the
|
|
35
|
+
* subject, ended by a release, takes those from its own, ahead of the earliest it still keeps.
|
|
36
|
+
*/
|
|
37
|
+
export declare function restretch<I>(this: Motions<I>, subject: I, back: readonly Paging[]): void;
|
|
38
|
+
/**
|
|
39
|
+
* The mix time and frame a stretch was in force by, which a store keys it under: when the change
|
|
40
|
+
* that ended it was made, which falls in the same life of the subject.
|
|
41
|
+
*/
|
|
42
|
+
export declare function made<I>(this: Motions<I>, c: Change | undefined): {
|
|
43
|
+
at: number;
|
|
44
|
+
seq: number;
|
|
45
|
+
};
|
|
46
|
+
/** Lets go of stretches older than the one in force at `reading.horizon`. */
|
|
47
|
+
export declare function prune<I>(this: Motions<I>, s: number): void;
|
package/dist/lives.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { within } from './cut.js';
|
|
2
|
+
import { absent } from './numbers.js';
|
|
3
|
+
import { reading } from './reading.js';
|
|
4
|
+
const PENDING = 2 /* RunFlag.PENDING */;
|
|
5
|
+
const OLDER = 4 /* RunFlag.OLDER */;
|
|
6
|
+
/** A run that shares nothing with the patch's own. */
|
|
7
|
+
const runOf = (r) => ({
|
|
8
|
+
flags: r.flags,
|
|
9
|
+
stretches: r.stretches.map((seg) => ({ ...seg })),
|
|
10
|
+
pending: r.pending?.map((c) => ({ ...c })),
|
|
11
|
+
});
|
|
12
|
+
/** `segs`, in time order, ahead of `list`: those older than its first, one per time. */
|
|
13
|
+
function ahead(segs, list) {
|
|
14
|
+
const first = list[0].at;
|
|
15
|
+
const out = [];
|
|
16
|
+
for (const seg of [...segs].sort((x, y) => x.at - y.at))
|
|
17
|
+
if (seg.at < first && out[out.length - 1]?.at !== seg.at)
|
|
18
|
+
out.push(seg);
|
|
19
|
+
return out.length === 0 ? list : [...out, ...list];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Forgets a subject, so a later ask starts it afresh from `from`. Given the mix time `at` and frame
|
|
23
|
+
* `seq`, under history, its run is kept for a rewind before then, until `reach` passes it.
|
|
24
|
+
*/
|
|
25
|
+
export function release(subject, at, reach = Number.NEGATIVE_INFINITY, seq = Number.NaN, early = false) {
|
|
26
|
+
const s = this.known(subject);
|
|
27
|
+
if (s === undefined)
|
|
28
|
+
return;
|
|
29
|
+
if (at !== undefined) {
|
|
30
|
+
const kept = [];
|
|
31
|
+
for (const e of this.released)
|
|
32
|
+
if (e.at >= reach)
|
|
33
|
+
kept.push(e);
|
|
34
|
+
else
|
|
35
|
+
this.owner?.page(this.ownerId, 'released', e.subject, [
|
|
36
|
+
{ at: e.at, seq: e.seq, data: { ...runOf(e), early: e.early } },
|
|
37
|
+
]);
|
|
38
|
+
this.released = kept;
|
|
39
|
+
this.released.push({ subject, at, seq, early, ...this.runAt(s) });
|
|
40
|
+
}
|
|
41
|
+
this.slots.delete(subject);
|
|
42
|
+
this.numbers.release(s);
|
|
43
|
+
}
|
|
44
|
+
/** Puts back each subject released after frame `seq`, as it stood when released. */
|
|
45
|
+
export function unrelease(seq) {
|
|
46
|
+
const back = this.released.filter((e) => e.seq > seq).sort((a, b) => a.seq - b.seq);
|
|
47
|
+
if (back.length === 0)
|
|
48
|
+
return;
|
|
49
|
+
this.released = this.released.filter((e) => e.seq <= seq);
|
|
50
|
+
const done = new Set();
|
|
51
|
+
for (const e of back) {
|
|
52
|
+
if (done.has(e.subject))
|
|
53
|
+
continue;
|
|
54
|
+
done.add(e.subject);
|
|
55
|
+
this.unpack(e.subject, e);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Subject `s`'s run as it stands. */
|
|
59
|
+
export function runAt(s) {
|
|
60
|
+
const older = this.older?.[s];
|
|
61
|
+
const pending = this.pending?.[s];
|
|
62
|
+
return {
|
|
63
|
+
flags: this.runs[this.base(s) + 1],
|
|
64
|
+
stretches: older === undefined ? [this.latest(s)] : [...older, this.latest(s)],
|
|
65
|
+
pending: pending === undefined ? undefined : [...pending],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** A subject's run as plain data, for a voice leaving memory; undefined where it has none. */
|
|
69
|
+
export function pack(subject) {
|
|
70
|
+
const s = this.known(subject);
|
|
71
|
+
return s === undefined ? undefined : runOf(this.runAt(s));
|
|
72
|
+
}
|
|
73
|
+
/** Puts a subject's run back as `pack` or a release left it, replacing any it has now. */
|
|
74
|
+
export function unpack(subject, run) {
|
|
75
|
+
const now = this.known(subject);
|
|
76
|
+
if (now !== undefined) {
|
|
77
|
+
this.slots.delete(subject);
|
|
78
|
+
this.numbers.release(now);
|
|
79
|
+
}
|
|
80
|
+
if (this.n < 0)
|
|
81
|
+
this.size(run.stretches[0].x0.length);
|
|
82
|
+
const s = this.take(subject);
|
|
83
|
+
this.runs[this.base(s) + 1] = run.flags & ~(OLDER | PENDING);
|
|
84
|
+
const latest = run.stretches[run.stretches.length - 1];
|
|
85
|
+
this.write(s, latest);
|
|
86
|
+
if (run.stretches.length > 1) {
|
|
87
|
+
if (this.older === null)
|
|
88
|
+
this.older = [undefined];
|
|
89
|
+
this.older[s] = run.stretches.slice(0, -1);
|
|
90
|
+
this.flag(s, OLDER, true);
|
|
91
|
+
}
|
|
92
|
+
if (run.pending !== undefined) {
|
|
93
|
+
if (this.pending === null)
|
|
94
|
+
this.pending = [undefined];
|
|
95
|
+
this.pending[s] = run.pending;
|
|
96
|
+
this.flag(s, PENDING, true);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** A released run a history store gave back, for a rewind to before its release. */
|
|
100
|
+
export function reclaim(subject, at, seq, run) {
|
|
101
|
+
if (this.released.some((e) => e.seq === seq && Object.is(e.subject, subject)))
|
|
102
|
+
return;
|
|
103
|
+
this.released.push({ subject, at, seq, ...run, early: run.early === true });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The run `subject` had in frame `cut`: the one a release after the cut kept, else the one it has
|
|
107
|
+
* now; undefined where it has neither. Its changes after the cut are still on it.
|
|
108
|
+
*/
|
|
109
|
+
export function runThen(subject, cut) {
|
|
110
|
+
let life;
|
|
111
|
+
for (const e of this.released)
|
|
112
|
+
if (Object.is(e.subject, subject) &&
|
|
113
|
+
!within(cut, e.seq, e.early) &&
|
|
114
|
+
(life === undefined || e.seq < life.seq))
|
|
115
|
+
life = e;
|
|
116
|
+
if (life !== undefined)
|
|
117
|
+
return life;
|
|
118
|
+
const s = this.known(subject);
|
|
119
|
+
return s === undefined ? undefined : this.runAt(s);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Stretches a history store gave back, each by the frame it was in force by: each life of the
|
|
123
|
+
* subject, ended by a release, takes those from its own, ahead of the earliest it still keeps.
|
|
124
|
+
*/
|
|
125
|
+
export function restretch(subject, back) {
|
|
126
|
+
const lives = this.released
|
|
127
|
+
.filter((e) => Object.is(e.subject, subject))
|
|
128
|
+
.sort((x, y) => x.seq - y.seq);
|
|
129
|
+
let from = Number.NEGATIVE_INFINITY;
|
|
130
|
+
const within = (to) => back.filter((r) => r.seq > from && r.seq <= to).map((r) => r.data);
|
|
131
|
+
for (const e of lives) {
|
|
132
|
+
e.stretches = ahead(within(e.seq), e.stretches);
|
|
133
|
+
from = e.seq;
|
|
134
|
+
}
|
|
135
|
+
const s = this.known(subject);
|
|
136
|
+
if (s === undefined)
|
|
137
|
+
return;
|
|
138
|
+
const older = this.older?.[s] ?? [];
|
|
139
|
+
const list = ahead(within(Number.POSITIVE_INFINITY), [...older, this.latest(s)]);
|
|
140
|
+
if (list.length === older.length + 1)
|
|
141
|
+
return;
|
|
142
|
+
if (this.older === null)
|
|
143
|
+
this.older = [undefined];
|
|
144
|
+
this.older[s] = list.slice(0, -1);
|
|
145
|
+
this.flag(s, OLDER, true);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The mix time and frame a stretch was in force by, which a store keys it under: when the change
|
|
149
|
+
* that ended it was made, which falls in the same life of the subject.
|
|
150
|
+
*/
|
|
151
|
+
export function made(c) {
|
|
152
|
+
const made = c?.made;
|
|
153
|
+
if (made === undefined || Number.isNaN(made))
|
|
154
|
+
return { at: this.owner?.now() ?? Number.NaN, seq: this.owner?.seq() ?? Number.NaN };
|
|
155
|
+
return { at: made, seq: c?.seq ?? Number.NaN };
|
|
156
|
+
}
|
|
157
|
+
/** Lets go of stretches older than the one in force at `reading.horizon`. */
|
|
158
|
+
export function prune(s) {
|
|
159
|
+
const list = this.older?.[s];
|
|
160
|
+
if (list === undefined)
|
|
161
|
+
return;
|
|
162
|
+
let n = 0;
|
|
163
|
+
while (n < list.length &&
|
|
164
|
+
(n + 1 < list.length ? list[n + 1].at : this.runs[this.base(s)]) <=
|
|
165
|
+
reading.horizon)
|
|
166
|
+
n++;
|
|
167
|
+
if (n === 0)
|
|
168
|
+
return;
|
|
169
|
+
const out = list.splice(0, n);
|
|
170
|
+
const subject = this.numbers.subject(s);
|
|
171
|
+
if (this.owner !== null && subject !== absent)
|
|
172
|
+
this.owner.page(this.ownerId, 'stretch', subject, out.map((seg, i) => {
|
|
173
|
+
const next = out[i + 1] ?? list[0];
|
|
174
|
+
return { ...this.made(next === undefined ? this.causes?.[s] : next.change), data: seg };
|
|
175
|
+
}));
|
|
176
|
+
if (list.length === 0) {
|
|
177
|
+
this.older[s] = undefined;
|
|
178
|
+
this.flag(s, OLDER, false);
|
|
179
|
+
}
|
|
180
|
+
}
|
package/dist/meet.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Lanes } from './lanes.js';
|
|
2
|
-
import type { Subject } from './
|
|
2
|
+
import type { Subject } from './subject.js';
|
|
3
3
|
/**
|
|
4
4
|
* Whether the lanes a probe of the subject at `slot` just met (`met`) can be folded on the general
|
|
5
|
-
* path after the lanes' values: none is in a
|
|
5
|
+
* path after the lanes' values: none is in a role or a crowd, the subject owes none already this
|
|
6
6
|
* fill, and each comes after every other laned voice in voice order, so folding it last folds in
|
|
7
7
|
* the general path's order.
|
|
8
8
|
*/
|