sonolus-next-rush-engine 2.3.2 → 2.3.3-kizu
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/dist/EngineConfiguration +0 -0
- package/dist/EnginePlayData +0 -0
- package/dist/EnginePreviewData +0 -0
- package/dist/EngineRom +0 -0
- package/dist/EngineTutorialData +0 -0
- package/dist/EngineWatchData +0 -0
- package/dist/extended/convert.js +102 -74
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mmw/convert.js +2 -1
- package/dist/sus/analyze.js +34 -8
- package/dist/sus/convert.js +5 -2
- package/package.json +1 -1
package/dist/EngineConfiguration
CHANGED
|
Binary file
|
package/dist/EnginePlayData
CHANGED
|
Binary file
|
package/dist/EnginePreviewData
CHANGED
|
Binary file
|
package/dist/EngineRom
CHANGED
|
Binary file
|
package/dist/EngineTutorialData
CHANGED
|
Binary file
|
package/dist/EngineWatchData
CHANGED
|
Binary file
|
package/dist/extended/convert.js
CHANGED
|
@@ -67,6 +67,20 @@ const activeSlideStartArchetypes = new Set([
|
|
|
67
67
|
'NormalTraceSlideStartNote',
|
|
68
68
|
'CriticalTraceSlideStartNote',
|
|
69
69
|
]);
|
|
70
|
+
const slideTickArchetypes = new Set([
|
|
71
|
+
'IgnoredSlideTickNote',
|
|
72
|
+
'NormalSlideTickNote',
|
|
73
|
+
'CriticalSlideTickNote',
|
|
74
|
+
'HiddenSlideTickNote',
|
|
75
|
+
'NormalAttachedSlideTickNote',
|
|
76
|
+
'CriticalAttachedSlideTickNote',
|
|
77
|
+
]);
|
|
78
|
+
const scoredSlideTickArchetypes = new Set([
|
|
79
|
+
'NormalSlideTickNote',
|
|
80
|
+
'CriticalSlideTickNote',
|
|
81
|
+
'NormalAttachedSlideTickNote',
|
|
82
|
+
'CriticalAttachedSlideTickNote',
|
|
83
|
+
]);
|
|
70
84
|
const flickDirectionMapping = {
|
|
71
85
|
[-1]: FlickDirection.UP_LEFT,
|
|
72
86
|
0: FlickDirection.UP_OMNI,
|
|
@@ -94,6 +108,18 @@ const guideKindMapping = {
|
|
|
94
108
|
6: ConnectorKind.GUIDE_CYAN,
|
|
95
109
|
7: ConnectorKind.GUIDE_BLACK,
|
|
96
110
|
};
|
|
111
|
+
function lastIndexLeq(arr, x, key) {
|
|
112
|
+
let lo = 0;
|
|
113
|
+
let hi = arr.length;
|
|
114
|
+
while (lo < hi) {
|
|
115
|
+
const mid = (lo + hi) >> 1;
|
|
116
|
+
if (key(arr[mid]) <= x)
|
|
117
|
+
lo = mid + 1;
|
|
118
|
+
else
|
|
119
|
+
hi = mid;
|
|
120
|
+
}
|
|
121
|
+
return lo - 1;
|
|
122
|
+
}
|
|
97
123
|
class ExtData {
|
|
98
124
|
constructor(entities) {
|
|
99
125
|
this.byArch = new Map();
|
|
@@ -142,15 +168,22 @@ class EntityBuilder {
|
|
|
142
168
|
return this.values['#BEAT'] ?? -1;
|
|
143
169
|
}
|
|
144
170
|
}
|
|
171
|
+
const fieldMapCache = new WeakMap();
|
|
145
172
|
function getField(e, name) {
|
|
146
|
-
|
|
147
|
-
if (!
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
173
|
+
let fields = fieldMapCache.get(e);
|
|
174
|
+
if (!fields) {
|
|
175
|
+
fields = new Map();
|
|
176
|
+
for (const field of e.data) {
|
|
177
|
+
if (fields.has(field.name))
|
|
178
|
+
continue;
|
|
179
|
+
if (field.value !== undefined)
|
|
180
|
+
fields.set(field.name, field.value);
|
|
181
|
+
else if (field.ref !== undefined)
|
|
182
|
+
fields.set(field.name, field.ref);
|
|
183
|
+
}
|
|
184
|
+
fieldMapCache.set(e, fields);
|
|
185
|
+
}
|
|
186
|
+
return fields.get(name);
|
|
154
187
|
}
|
|
155
188
|
function getNum(e, name, def = 0) {
|
|
156
189
|
const val = getField(e, name);
|
|
@@ -236,23 +269,13 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
236
269
|
function beatToTime(beat) {
|
|
237
270
|
if (bpmChangeInfos.length === 0)
|
|
238
271
|
return (beat * 60) / 120;
|
|
239
|
-
|
|
240
|
-
for (const change of bpmChangeInfos) {
|
|
241
|
-
if (change.beat > beat)
|
|
242
|
-
break;
|
|
243
|
-
current = change;
|
|
244
|
-
}
|
|
272
|
+
const current = bpmChangeInfos[Math.max(0, lastIndexLeq(bpmChangeInfos, beat, (c) => c.beat))];
|
|
245
273
|
return current.time + ((beat - current.beat) * 60) / current.bpm;
|
|
246
274
|
}
|
|
247
275
|
function timeToBeat(time) {
|
|
248
276
|
if (bpmChangeInfos.length === 0)
|
|
249
277
|
return (time * 120) / 60;
|
|
250
|
-
|
|
251
|
-
for (const change of bpmChangeInfos) {
|
|
252
|
-
if (change.time > time)
|
|
253
|
-
break;
|
|
254
|
-
current = change;
|
|
255
|
-
}
|
|
278
|
+
const current = bpmChangeInfos[Math.max(0, lastIndexLeq(bpmChangeInfos, time, (c) => c.time))];
|
|
256
279
|
return current.beat + ((time - current.time) * current.bpm) / 60;
|
|
257
280
|
}
|
|
258
281
|
for (const { e } of ext.getByArch('#BPM_CHANGE')) {
|
|
@@ -281,6 +304,8 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
281
304
|
changeInfos.push({
|
|
282
305
|
beat: getNum(raw, '#BEAT'),
|
|
283
306
|
timeScale: getNum(raw, 'timeScale'),
|
|
307
|
+
time: 0,
|
|
308
|
+
scaledTime: 0,
|
|
284
309
|
});
|
|
285
310
|
const change = new EntityBuilder('#TIMESCALE_CHANGE');
|
|
286
311
|
change.set('#BEAT', getNum(raw, '#BEAT'));
|
|
@@ -303,6 +328,14 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
303
328
|
}
|
|
304
329
|
finalEntities.push(...changes);
|
|
305
330
|
changeInfos.sort((a, b) => a.beat - b.beat);
|
|
331
|
+
for (let i = 0; i < changeInfos.length; i++) {
|
|
332
|
+
changeInfos[i].time = beatToTime(changeInfos[i].beat);
|
|
333
|
+
changeInfos[i].scaledTime =
|
|
334
|
+
i === 0
|
|
335
|
+
? changeInfos[i].time
|
|
336
|
+
: changeInfos[i - 1].scaledTime +
|
|
337
|
+
(changeInfos[i].time - changeInfos[i - 1].time) * changeInfos[i - 1].timeScale;
|
|
338
|
+
}
|
|
306
339
|
timescaleChangesByIndex.set(idx, changeInfos);
|
|
307
340
|
if (e.name)
|
|
308
341
|
timescaleChangesByName.set(e.name, changeInfos);
|
|
@@ -324,46 +357,31 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
324
357
|
function timeToScaledTime(time, changes) {
|
|
325
358
|
if (changes.length === 0)
|
|
326
359
|
return time;
|
|
327
|
-
|
|
328
|
-
if (time < firstTime)
|
|
360
|
+
if (time < changes[0].time)
|
|
329
361
|
return time;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const start = changes[i];
|
|
333
|
-
const startTime = beatToTime(start.beat);
|
|
334
|
-
const endTime = i === changes.length - 1 ? undefined : beatToTime(changes[i + 1].beat);
|
|
335
|
-
if (endTime === undefined || time < endTime) {
|
|
336
|
-
return scaledTime + (time - startTime) * start.timeScale;
|
|
337
|
-
}
|
|
338
|
-
scaledTime += (endTime - startTime) * start.timeScale;
|
|
339
|
-
}
|
|
340
|
-
return time;
|
|
362
|
+
const current = changes[Math.max(0, lastIndexLeq(changes, time, (c) => c.time))];
|
|
363
|
+
return current.scaledTime + (time - current.time) * current.timeScale;
|
|
341
364
|
}
|
|
342
365
|
function scaledTimeToTime(scaledTime, changes) {
|
|
343
366
|
if (changes.length === 0)
|
|
344
367
|
return scaledTime;
|
|
345
|
-
|
|
346
|
-
if (scaledTime < firstTime)
|
|
368
|
+
if (scaledTime < changes[0].time)
|
|
347
369
|
return scaledTime;
|
|
348
|
-
let currentScaledTime = firstTime;
|
|
349
370
|
for (let i = 0; i < changes.length; i++) {
|
|
350
371
|
const start = changes[i];
|
|
351
|
-
|
|
352
|
-
const endTime = i === changes.length - 1 ? undefined : beatToTime(changes[i + 1].beat);
|
|
353
|
-
if (endTime === undefined) {
|
|
372
|
+
if (i === changes.length - 1) {
|
|
354
373
|
if (start.timeScale === 0)
|
|
355
374
|
return Number.POSITIVE_INFINITY;
|
|
356
|
-
return
|
|
375
|
+
return start.time + (scaledTime - start.scaledTime) / start.timeScale;
|
|
357
376
|
}
|
|
358
|
-
const
|
|
359
|
-
const minScaledTime = Math.min(
|
|
360
|
-
const maxScaledTime = Math.max(
|
|
377
|
+
const next = changes[i + 1];
|
|
378
|
+
const minScaledTime = Math.min(start.scaledTime, next.scaledTime);
|
|
379
|
+
const maxScaledTime = Math.max(start.scaledTime, next.scaledTime);
|
|
361
380
|
if (minScaledTime <= scaledTime && scaledTime <= maxScaledTime) {
|
|
362
|
-
if (Math.abs(
|
|
363
|
-
return
|
|
364
|
-
return lerp(
|
|
381
|
+
if (Math.abs(next.scaledTime - start.scaledTime) < 1e-6)
|
|
382
|
+
return start.time;
|
|
383
|
+
return lerp(start.time, next.time, unlerp(start.scaledTime, next.scaledTime, scaledTime));
|
|
365
384
|
}
|
|
366
|
-
currentScaledTime = nextScaledTime;
|
|
367
385
|
}
|
|
368
386
|
return scaledTime;
|
|
369
387
|
}
|
|
@@ -399,8 +417,16 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
399
417
|
return undefined;
|
|
400
418
|
}
|
|
401
419
|
function getTimeScaleAt(changes, beat) {
|
|
402
|
-
|
|
403
|
-
|
|
420
|
+
let lo = 0;
|
|
421
|
+
let hi = changes.length;
|
|
422
|
+
while (lo < hi) {
|
|
423
|
+
const mid = (lo + hi) >> 1;
|
|
424
|
+
if (changes[mid].beat < beat - 1e-6)
|
|
425
|
+
lo = mid + 1;
|
|
426
|
+
else
|
|
427
|
+
hi = mid;
|
|
428
|
+
}
|
|
429
|
+
return lo > 0 ? changes[lo - 1].timeScale : 1;
|
|
404
430
|
}
|
|
405
431
|
function shouldUseStartAsHead(startRef, headRef) {
|
|
406
432
|
if (startRef === headRef)
|
|
@@ -491,22 +517,10 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
491
517
|
return getNum(tailOriginal, '#BEAT') < getNum(headOriginal, '#BEAT') - 1e-6;
|
|
492
518
|
}
|
|
493
519
|
function isSlideTickRef(ref) {
|
|
494
|
-
return
|
|
495
|
-
'IgnoredSlideTickNote',
|
|
496
|
-
'NormalSlideTickNote',
|
|
497
|
-
'CriticalSlideTickNote',
|
|
498
|
-
'HiddenSlideTickNote',
|
|
499
|
-
'NormalAttachedSlideTickNote',
|
|
500
|
-
'CriticalAttachedSlideTickNote',
|
|
501
|
-
].includes(resolveOriginal(ext, ref)?.archetype ?? '');
|
|
520
|
+
return slideTickArchetypes.has(resolveOriginal(ext, ref)?.archetype ?? '');
|
|
502
521
|
}
|
|
503
522
|
function isScoredSlideTickRef(ref) {
|
|
504
|
-
return
|
|
505
|
-
'NormalSlideTickNote',
|
|
506
|
-
'CriticalSlideTickNote',
|
|
507
|
-
'NormalAttachedSlideTickNote',
|
|
508
|
-
'CriticalAttachedSlideTickNote',
|
|
509
|
-
].includes(resolveOriginal(ext, ref)?.archetype ?? '');
|
|
523
|
+
return scoredSlideTickArchetypes.has(resolveOriginal(ext, ref)?.archetype ?? '');
|
|
510
524
|
}
|
|
511
525
|
function getUltimateTailRef(archetype, startRef, tailRef) {
|
|
512
526
|
let ultimateTailRef = tailRef;
|
|
@@ -622,23 +636,37 @@ export const extendedToLevelData = (data, offset = 0) => {
|
|
|
622
636
|
return getUltimateStartRef(archetype, startRef, headRef);
|
|
623
637
|
}
|
|
624
638
|
const activeTailRefsByStart = new Map();
|
|
639
|
+
let activeTailCandidatesByStart;
|
|
640
|
+
function getActiveTailCandidates(key) {
|
|
641
|
+
if (!activeTailCandidatesByStart) {
|
|
642
|
+
activeTailCandidatesByStart = new Map();
|
|
643
|
+
for (const { e } of ext.connectors) {
|
|
644
|
+
const startRef = getField(e, 'start');
|
|
645
|
+
const headRef = getField(e, 'head');
|
|
646
|
+
if (isIgnoredSlideTickRef(headRef))
|
|
647
|
+
continue;
|
|
648
|
+
const endRef = getField(e, 'end');
|
|
649
|
+
const connectorActiveStartRef = getConnectorActiveStartRef(e.archetype, startRef, headRef, endRef);
|
|
650
|
+
const { tailRef } = resolveConnectorTailRef(e.archetype, startRef, getField(e, 'tail'));
|
|
651
|
+
const connectorKey = refKey(connectorActiveStartRef);
|
|
652
|
+
const candidate = { archetype: e.archetype, endRef, tailRef };
|
|
653
|
+
const list = activeTailCandidatesByStart.get(connectorKey);
|
|
654
|
+
if (list)
|
|
655
|
+
list.push(candidate);
|
|
656
|
+
else
|
|
657
|
+
activeTailCandidatesByStart.set(connectorKey, [candidate]);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return activeTailCandidatesByStart.get(key) ?? [];
|
|
661
|
+
}
|
|
625
662
|
function getActiveTailRef(activeStartRef) {
|
|
626
663
|
const key = refKey(activeStartRef);
|
|
627
664
|
if (activeTailRefsByStart.has(key))
|
|
628
665
|
return activeTailRefsByStart.get(key);
|
|
629
666
|
let activeTailRef;
|
|
630
667
|
let activeTailBeat = Number.NEGATIVE_INFINITY;
|
|
631
|
-
for (const {
|
|
632
|
-
const
|
|
633
|
-
const headRef = getField(e, 'head');
|
|
634
|
-
if (isIgnoredSlideTickRef(headRef))
|
|
635
|
-
continue;
|
|
636
|
-
const endRef = getField(e, 'end');
|
|
637
|
-
const connectorActiveStartRef = getConnectorActiveStartRef(e.archetype, startRef, headRef, endRef);
|
|
638
|
-
if (refKey(connectorActiveStartRef) !== key)
|
|
639
|
-
continue;
|
|
640
|
-
const { tailRef } = resolveConnectorTailRef(e.archetype, startRef, getField(e, 'tail'));
|
|
641
|
-
const candidateTailRef = endRef ?? getUltimateTailRef(e.archetype, activeStartRef, tailRef);
|
|
668
|
+
for (const { archetype, endRef, tailRef } of getActiveTailCandidates(key)) {
|
|
669
|
+
const candidateTailRef = endRef ?? getUltimateTailRef(archetype, activeStartRef, tailRef);
|
|
642
670
|
const candidateTailBeat = getRefBeat(candidateTailRef);
|
|
643
671
|
if (candidateTailBeat >= activeTailBeat) {
|
|
644
672
|
activeTailBeat = candidateTailBeat;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { USC } from './usc/index.js';
|
|
|
7
7
|
export * from './usc/index.js';
|
|
8
8
|
export { type ExtendedEntityData, type ExtendedEntityDataField, extendedToLevelData, mmwsToUSC, susToUSC, ucmmwsToLevelData, uscToLevelData, };
|
|
9
9
|
export declare const convertToLevelData: (input: string | Uint8Array | USC | LevelData, offset?: number) => LevelData;
|
|
10
|
-
export declare const version = "2.3.
|
|
10
|
+
export declare const version = "2.3.3-kizu";
|
|
11
11
|
export declare const databaseEngineItem: {
|
|
12
12
|
readonly name: "next-rush";
|
|
13
13
|
readonly version: 13;
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ export const convertToLevelData = (input, offset = 0) => {
|
|
|
65
65
|
}
|
|
66
66
|
return uscToLevelData(usc, offset, true, true);
|
|
67
67
|
};
|
|
68
|
-
export const version = '2.3.
|
|
68
|
+
export const version = '2.3.3-kizu';
|
|
69
69
|
export const databaseEngineItem = {
|
|
70
70
|
name: 'next-rush',
|
|
71
71
|
version: 13,
|
package/dist/mmw/convert.js
CHANGED
|
@@ -25,6 +25,7 @@ const mmwEaseToSonolusEase = (ease) => {
|
|
|
25
25
|
};
|
|
26
26
|
const EPSILON = 1e-6;
|
|
27
27
|
const TICKS_PER_BEAT = 480;
|
|
28
|
+
const uscColorByValue = new Map(Object.entries(USCColor).map(([name, value]) => [value, name]));
|
|
28
29
|
const laneToSonolusLane = (lane, width) => {
|
|
29
30
|
return lane - 6 + width / 2;
|
|
30
31
|
};
|
|
@@ -152,7 +153,7 @@ export const mmwsToUSC = (mmws) => {
|
|
|
152
153
|
const uscGuide = {
|
|
153
154
|
type: 'guide',
|
|
154
155
|
fade: hold.fadeType === 0 ? 'out' : hold.fadeType === 1 ? 'none' : 'in',
|
|
155
|
-
color:
|
|
156
|
+
color: uscColorByValue.get(hold.guideColor),
|
|
156
157
|
midpoints: [hold.start, ...hold.steps, hold.end].map((step) => ({
|
|
157
158
|
beat: step.tick / TICKS_PER_BEAT,
|
|
158
159
|
lane: laneToUSCLane(step),
|
package/dist/sus/analyze.js
CHANGED
|
@@ -58,10 +58,24 @@ export const analyze = (sus) => {
|
|
|
58
58
|
timeScaleChanges.push(scaledChanges);
|
|
59
59
|
return newIndex;
|
|
60
60
|
};
|
|
61
|
+
const measureChangesAsc = [...measureChanges].reverse();
|
|
62
|
+
const timeScaleGroupChangesAsc = [...timeScaleGroupChanges].reverse();
|
|
63
|
+
let measureChangeCursor = -1;
|
|
64
|
+
let timeScaleGroupChangeCursor = -1;
|
|
61
65
|
lines.forEach((line, index) => {
|
|
62
66
|
const [header, data] = line;
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
while (measureChangeCursor + 1 < measureChangesAsc.length &&
|
|
68
|
+
measureChangesAsc[measureChangeCursor + 1][0] <= index) {
|
|
69
|
+
measureChangeCursor++;
|
|
70
|
+
}
|
|
71
|
+
while (timeScaleGroupChangeCursor + 1 < timeScaleGroupChangesAsc.length &&
|
|
72
|
+
timeScaleGroupChangesAsc[timeScaleGroupChangeCursor + 1][0] <= index) {
|
|
73
|
+
timeScaleGroupChangeCursor++;
|
|
74
|
+
}
|
|
75
|
+
const measureOffset = measureChangeCursor >= 0 ? measureChangesAsc[measureChangeCursor][1] : 0;
|
|
76
|
+
const timeScaleGroupName = timeScaleGroupChangeCursor >= 0
|
|
77
|
+
? timeScaleGroupChangesAsc[timeScaleGroupChangeCursor][1]
|
|
78
|
+
: '00';
|
|
65
79
|
let timeScaleGroup = timeScaleGroups.get(timeScaleGroupName);
|
|
66
80
|
if (timeScaleGroup === undefined) {
|
|
67
81
|
timeScaleGroup = timeScaleGroups.size;
|
|
@@ -168,14 +182,18 @@ const getTicksPerBeat = (meta) => {
|
|
|
168
182
|
};
|
|
169
183
|
const getBarLengths = (lines, measureChanges) => {
|
|
170
184
|
const barLengths = [];
|
|
185
|
+
const measureChangesAsc = [...measureChanges].reverse();
|
|
186
|
+
let cursor = -1;
|
|
171
187
|
lines.forEach((line, index) => {
|
|
172
188
|
const [header, data] = line;
|
|
189
|
+
while (cursor + 1 < measureChangesAsc.length && measureChangesAsc[cursor + 1][0] <= index) {
|
|
190
|
+
cursor++;
|
|
191
|
+
}
|
|
173
192
|
if (header.length !== 5)
|
|
174
193
|
return;
|
|
175
194
|
if (!header.endsWith('02'))
|
|
176
195
|
return;
|
|
177
|
-
const measure = +header.substring(0, 3) +
|
|
178
|
-
(measureChanges.find(([changeIndex]) => changeIndex <= index)?.[1] ?? 0);
|
|
196
|
+
const measure = +header.substring(0, 3) + (cursor >= 0 ? measureChangesAsc[cursor][1] : 0);
|
|
179
197
|
if (Number.isNaN(measure))
|
|
180
198
|
return;
|
|
181
199
|
barLengths.push({ measure, length: +data });
|
|
@@ -192,12 +210,20 @@ const getToTick = (barLengths, ticksPerBeat) => {
|
|
|
192
210
|
ticks += (measure - prev.measure) * prev.length * ticksPerBeat;
|
|
193
211
|
}
|
|
194
212
|
return { measure, ticksPerMeasure: length * ticksPerBeat, ticks };
|
|
195
|
-
})
|
|
196
|
-
.reverse();
|
|
213
|
+
});
|
|
197
214
|
return (measure, p, q) => {
|
|
198
|
-
|
|
199
|
-
|
|
215
|
+
let lo = 0;
|
|
216
|
+
let hi = bars.length;
|
|
217
|
+
while (lo < hi) {
|
|
218
|
+
const mid = (lo + hi) >> 1;
|
|
219
|
+
if (bars[mid].measure <= measure)
|
|
220
|
+
lo = mid + 1;
|
|
221
|
+
else
|
|
222
|
+
hi = mid;
|
|
223
|
+
}
|
|
224
|
+
if (lo === 0)
|
|
200
225
|
throw new Error('Unexpected missing bar');
|
|
226
|
+
const bar = bars[lo - 1];
|
|
201
227
|
return (bar.ticks +
|
|
202
228
|
(measure - bar.measure) * bar.ticksPerMeasure +
|
|
203
229
|
(p * bar.ticksPerMeasure) / q);
|
package/dist/sus/convert.js
CHANGED
|
@@ -11,6 +11,7 @@ export const chsLikeToUSC = (score) => {
|
|
|
11
11
|
const preventSingles = new Set();
|
|
12
12
|
const dedupeSingles = new Set();
|
|
13
13
|
const dedupeSlides = new Map();
|
|
14
|
+
const removedSlides = new Set();
|
|
14
15
|
const requests = {
|
|
15
16
|
sideLane: false,
|
|
16
17
|
laneOffset: 0,
|
|
@@ -309,12 +310,14 @@ export const chsLikeToUSC = (score) => {
|
|
|
309
310
|
const key = getKey(startNote);
|
|
310
311
|
const dupe = dedupeSlides.get(key);
|
|
311
312
|
if (dupe)
|
|
312
|
-
|
|
313
|
+
removedSlides.add(dupe);
|
|
313
314
|
dedupeSlides.set(key, object);
|
|
314
315
|
}
|
|
315
316
|
return {
|
|
316
317
|
offset: score.offset,
|
|
317
|
-
objects
|
|
318
|
+
objects: removedSlides.size
|
|
319
|
+
? objects.filter((object) => !removedSlides.has(object))
|
|
320
|
+
: objects,
|
|
318
321
|
};
|
|
319
322
|
};
|
|
320
323
|
const getKey = (note) => `${note.lane}-${note.tick}`;
|