@rian8337/osu-droid-replay-analyzer 4.0.0-beta.90 → 4.0.0-beta.91
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/index.js +119 -121
- package/package.json +5 -5
- package/typings/index.d.ts +12 -26
package/dist/index.js
CHANGED
|
@@ -34,19 +34,19 @@ exports.MovementType = void 0;
|
|
|
34
34
|
/**
|
|
35
35
|
* The player places their finger on the screen.
|
|
36
36
|
*/
|
|
37
|
-
MovementType[MovementType["
|
|
37
|
+
MovementType[MovementType["Down"] = 0] = "Down";
|
|
38
38
|
/**
|
|
39
39
|
* The player drags their finger on the screen.
|
|
40
40
|
*/
|
|
41
|
-
MovementType[MovementType["
|
|
41
|
+
MovementType[MovementType["Move"] = 1] = "Move";
|
|
42
42
|
/**
|
|
43
43
|
* The player releases their finger from the screen.
|
|
44
44
|
*/
|
|
45
|
-
MovementType[MovementType["
|
|
45
|
+
MovementType[MovementType["Up"] = 2] = "Up";
|
|
46
46
|
})(exports.MovementType || (exports.MovementType = {}));
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* Utility to check whether relevant sliders in a beatmap are cheesed for rebalance scores
|
|
49
|
+
* Utility to check whether relevant sliders in a beatmap are cheesed for rebalance scores.
|
|
50
50
|
*/
|
|
51
51
|
class RebalanceSliderCheeseChecker {
|
|
52
52
|
/**
|
|
@@ -69,10 +69,7 @@ class RebalanceSliderCheeseChecker {
|
|
|
69
69
|
check() {
|
|
70
70
|
if (this.difficultyAttributes.difficultSliders.length === 0 ||
|
|
71
71
|
this.difficultyAttributes.sliderFactor === 1) {
|
|
72
|
-
return
|
|
73
|
-
aimPenalty: 1,
|
|
74
|
-
flashlightPenalty: 1,
|
|
75
|
-
};
|
|
72
|
+
return 1;
|
|
76
73
|
}
|
|
77
74
|
const cheesedDifficultyRatings = this.checkSliderCheesing();
|
|
78
75
|
return this.calculateSliderCheesePenalty(cheesedDifficultyRatings);
|
|
@@ -96,10 +93,16 @@ class RebalanceSliderCheeseChecker {
|
|
|
96
93
|
const object = objects[difficultSlider.index];
|
|
97
94
|
const objectData = this.data.hitObjectData[difficultSlider.index];
|
|
98
95
|
// If a miss or slider break occurs, we disregard the check for that slider.
|
|
99
|
-
if (objectData.result === osuBase.HitResult.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
if (objectData.result === osuBase.HitResult.Miss) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
let lateHitThreshold = this.hitWindow50;
|
|
100
|
+
// Before replay version 8, the slider head's hit window is capped to the duration of the slider.
|
|
101
|
+
if (this.data.replayVersion < 8) {
|
|
102
|
+
lateHitThreshold = Math.min(lateHitThreshold, object.duration);
|
|
103
|
+
}
|
|
104
|
+
if (objectData.accuracy < -this.hitWindow50 ||
|
|
105
|
+
objectData.accuracy > lateHitThreshold) {
|
|
103
106
|
continue;
|
|
104
107
|
}
|
|
105
108
|
const objectStartPosition = object.stackedPosition;
|
|
@@ -145,11 +148,11 @@ class RebalanceSliderCheeseChecker {
|
|
|
145
148
|
const currentPosition = this.getCursorPosition(cursor);
|
|
146
149
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
147
150
|
switch (cursor.id) {
|
|
148
|
-
case exports.MovementType.
|
|
151
|
+
case exports.MovementType.Up:
|
|
149
152
|
distance =
|
|
150
153
|
prevPosition.getDistance(objectStartPosition);
|
|
151
154
|
break;
|
|
152
|
-
case exports.MovementType.
|
|
155
|
+
case exports.MovementType.Move:
|
|
153
156
|
for (let mSecPassed = Math.max(prevCursor.time, minTimeLimit); mSecPassed <=
|
|
154
157
|
Math.min(cursor.time, maxTimeLimit); ++mSecPassed) {
|
|
155
158
|
const t = (mSecPassed - prevCursor.time) /
|
|
@@ -217,7 +220,7 @@ class RebalanceSliderCheeseChecker {
|
|
|
217
220
|
const currentPosition = this.getCursorPosition(cursor);
|
|
218
221
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
219
222
|
switch (cursor.id) {
|
|
220
|
-
case exports.MovementType.
|
|
223
|
+
case exports.MovementType.Move: {
|
|
221
224
|
// Interpolate cursor position during nested object time.
|
|
222
225
|
const t = (nestedObject.startTime - prevCursor.time) /
|
|
223
226
|
(cursor.time - prevCursor.time);
|
|
@@ -226,7 +229,7 @@ class RebalanceSliderCheeseChecker {
|
|
|
226
229
|
isCheesed = distance > acceptableRadius;
|
|
227
230
|
break;
|
|
228
231
|
}
|
|
229
|
-
case exports.MovementType.
|
|
232
|
+
case exports.MovementType.Up:
|
|
230
233
|
isCheesed =
|
|
231
234
|
prevPosition.getDistance(nestedPosition) >
|
|
232
235
|
acceptableRadius;
|
|
@@ -243,12 +246,9 @@ class RebalanceSliderCheeseChecker {
|
|
|
243
246
|
*/
|
|
244
247
|
calculateSliderCheesePenalty(cheesedDifficultyRatings) {
|
|
245
248
|
const summedDifficultyRating = Math.min(1, cheesedDifficultyRatings.reduce((a, v) => a + v, 0));
|
|
246
|
-
return
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
this.difficultyAttributes.sliderFactor, 2)),
|
|
250
|
-
flashlightPenalty: 1,
|
|
251
|
-
};
|
|
249
|
+
return Math.max(this.difficultyAttributes.sliderFactor, Math.pow(1 -
|
|
250
|
+
summedDifficultyRating *
|
|
251
|
+
this.difficultyAttributes.sliderFactor, 2));
|
|
252
252
|
}
|
|
253
253
|
getCursorPosition(cursor) {
|
|
254
254
|
if (this.isHardRock) {
|
|
@@ -342,7 +342,7 @@ class RebalanceThreeFingerChecker {
|
|
|
342
342
|
const objectBeforeData = objectData[beforeIndex];
|
|
343
343
|
let timeBefore = objectBefore.endTime;
|
|
344
344
|
if (objectBefore instanceof osuBase.Circle) {
|
|
345
|
-
if (objectBeforeData.result !== osuBase.HitResult.
|
|
345
|
+
if (objectBeforeData.result !== osuBase.HitResult.Miss) {
|
|
346
346
|
timeBefore += objectBeforeData.accuracy;
|
|
347
347
|
}
|
|
348
348
|
else {
|
|
@@ -354,7 +354,7 @@ class RebalanceThreeFingerChecker {
|
|
|
354
354
|
const objectAfterData = objectData[afterIndex];
|
|
355
355
|
let timeAfter = objectAfter.startTime;
|
|
356
356
|
if (objectAfter instanceof osuBase.Circle &&
|
|
357
|
-
objectAfterData.result !== osuBase.HitResult.
|
|
357
|
+
objectAfterData.result !== osuBase.HitResult.Miss) {
|
|
358
358
|
timeAfter += objectAfterData.accuracy;
|
|
359
359
|
}
|
|
360
360
|
this.breakPointAccurateTimes.push(new osuBase.BreakPoint(timeBefore, timeAfter));
|
|
@@ -376,10 +376,10 @@ class RebalanceThreeFingerChecker {
|
|
|
376
376
|
let firstObjectHitWindow = this.hitWindow.mehWindow;
|
|
377
377
|
if (firstObject instanceof osuBase.Circle) {
|
|
378
378
|
switch (firstObjectResult) {
|
|
379
|
-
case osuBase.HitResult.
|
|
379
|
+
case osuBase.HitResult.Great:
|
|
380
380
|
firstObjectHitWindow = this.hitWindow.greatWindow;
|
|
381
381
|
break;
|
|
382
|
-
case osuBase.HitResult.
|
|
382
|
+
case osuBase.HitResult.Good:
|
|
383
383
|
firstObjectHitWindow = this.hitWindow.okWindow;
|
|
384
384
|
break;
|
|
385
385
|
default:
|
|
@@ -390,10 +390,10 @@ class RebalanceThreeFingerChecker {
|
|
|
390
390
|
let lastObjectHitWindow = this.hitWindow.mehWindow;
|
|
391
391
|
if (lastObject instanceof osuBase.Circle) {
|
|
392
392
|
switch (lastObjectResult) {
|
|
393
|
-
case osuBase.HitResult.
|
|
393
|
+
case osuBase.HitResult.Great:
|
|
394
394
|
lastObjectHitWindow = this.hitWindow.greatWindow;
|
|
395
395
|
break;
|
|
396
|
-
case osuBase.HitResult.
|
|
396
|
+
case osuBase.HitResult.Good:
|
|
397
397
|
lastObjectHitWindow = this.hitWindow.okWindow;
|
|
398
398
|
break;
|
|
399
399
|
default:
|
|
@@ -462,15 +462,20 @@ class RebalanceThreeFingerChecker {
|
|
|
462
462
|
* @returns The index of the cursor, -1 if the object was missed or it's a spinner.
|
|
463
463
|
*/
|
|
464
464
|
getObjectAimIndex(object, objectData, cursorGroupIndices, cursorIndices) {
|
|
465
|
-
if (objectData.result === osuBase.HitResult.
|
|
465
|
+
if (objectData.result === osuBase.HitResult.Miss || object instanceof osuBase.Spinner) {
|
|
466
466
|
return -1;
|
|
467
467
|
}
|
|
468
468
|
// Check for sliderbreaks and treat them as misses.
|
|
469
|
-
if (object instanceof osuBase.Slider
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
469
|
+
if (object instanceof osuBase.Slider) {
|
|
470
|
+
let lateHitThreshold = this.hitWindow.mehWindow;
|
|
471
|
+
// Before replay version 8, the slider head's hit window is capped to the duration of the slider.
|
|
472
|
+
if (this.data.replayVersion < 8) {
|
|
473
|
+
lateHitThreshold = Math.min(lateHitThreshold, object.duration);
|
|
474
|
+
}
|
|
475
|
+
if (objectData.accuracy < -this.hitWindow.mehWindow ||
|
|
476
|
+
objectData.accuracy > lateHitThreshold) {
|
|
477
|
+
return -1;
|
|
478
|
+
}
|
|
474
479
|
}
|
|
475
480
|
const hitTime = object.startTime + objectData.accuracy;
|
|
476
481
|
const objectPosition = object.stackedPosition;
|
|
@@ -508,10 +513,10 @@ class RebalanceThreeFingerChecker {
|
|
|
508
513
|
const currentPosition = this.getCursorPosition(cursor);
|
|
509
514
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
510
515
|
switch (cursor.id) {
|
|
511
|
-
case exports.MovementType.
|
|
516
|
+
case exports.MovementType.Up:
|
|
512
517
|
distance = prevPosition.getDistance(objectPosition);
|
|
513
518
|
break;
|
|
514
|
-
case exports.MovementType.
|
|
519
|
+
case exports.MovementType.Move: {
|
|
515
520
|
// Interpolate movement.
|
|
516
521
|
const t = (hitTime - prevCursor.time) /
|
|
517
522
|
(cursor.time - prevCursor.time);
|
|
@@ -520,7 +525,7 @@ class RebalanceThreeFingerChecker {
|
|
|
520
525
|
objectPosition.getDistance(cursorPosition);
|
|
521
526
|
break;
|
|
522
527
|
}
|
|
523
|
-
case exports.MovementType.
|
|
528
|
+
case exports.MovementType.Down:
|
|
524
529
|
continue;
|
|
525
530
|
}
|
|
526
531
|
if (closestDistance > distance) {
|
|
@@ -550,15 +555,20 @@ class RebalanceThreeFingerChecker {
|
|
|
550
555
|
* @returns The index of the cursor, -1 if the object was missed or it's a spinner.
|
|
551
556
|
*/
|
|
552
557
|
getObjectPressIndex(object, objectData, cursorLookupIndices) {
|
|
553
|
-
if (objectData.result === osuBase.HitResult.
|
|
558
|
+
if (objectData.result === osuBase.HitResult.Miss || object instanceof osuBase.Spinner) {
|
|
554
559
|
return -1;
|
|
555
560
|
}
|
|
556
561
|
// Check for sliderbreaks and treat them as misses.
|
|
557
|
-
if (object instanceof osuBase.Slider
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
+
if (object instanceof osuBase.Slider) {
|
|
563
|
+
let lateHitThreshold = this.hitWindow.mehWindow;
|
|
564
|
+
// Before replay version 8, the slider head's hit window is capped to the duration of the slider.
|
|
565
|
+
if (this.data.replayVersion < 8) {
|
|
566
|
+
lateHitThreshold = Math.min(lateHitThreshold, object.duration);
|
|
567
|
+
}
|
|
568
|
+
if (objectData.accuracy < -this.hitWindow.mehWindow ||
|
|
569
|
+
objectData.accuracy > lateHitThreshold) {
|
|
570
|
+
return -1;
|
|
571
|
+
}
|
|
562
572
|
}
|
|
563
573
|
const hitTime = object.startTime + objectData.accuracy;
|
|
564
574
|
let nearestCursorInstanceIndex = -1;
|
|
@@ -672,12 +682,8 @@ class SliderCheeseChecker {
|
|
|
672
682
|
*/
|
|
673
683
|
check() {
|
|
674
684
|
if (this.difficultyAttributes.difficultSliders.length === 0 ||
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
return {
|
|
678
|
-
aimPenalty: 1,
|
|
679
|
-
flashlightPenalty: 1,
|
|
680
|
-
};
|
|
685
|
+
this.difficultyAttributes.sliderFactor === 1) {
|
|
686
|
+
return 1;
|
|
681
687
|
}
|
|
682
688
|
const cheesedDifficultyRatings = this.checkSliderCheesing();
|
|
683
689
|
return this.calculateSliderCheesePenalty(cheesedDifficultyRatings);
|
|
@@ -701,7 +707,7 @@ class SliderCheeseChecker {
|
|
|
701
707
|
const object = objects[difficultSlider.index];
|
|
702
708
|
const objectData = this.data.hitObjectData[difficultSlider.index];
|
|
703
709
|
// If a miss or slider break occurs, we disregard the check for that slider.
|
|
704
|
-
if (objectData.result === osuBase.HitResult.
|
|
710
|
+
if (objectData.result === osuBase.HitResult.Miss) {
|
|
705
711
|
continue;
|
|
706
712
|
}
|
|
707
713
|
let lateHitThreshold = this.hitWindow50;
|
|
@@ -756,11 +762,11 @@ class SliderCheeseChecker {
|
|
|
756
762
|
const currentPosition = this.getCursorPosition(cursor);
|
|
757
763
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
758
764
|
switch (cursor.id) {
|
|
759
|
-
case exports.MovementType.
|
|
765
|
+
case exports.MovementType.Up:
|
|
760
766
|
distance =
|
|
761
767
|
prevPosition.getDistance(objectStartPosition);
|
|
762
768
|
break;
|
|
763
|
-
case exports.MovementType.
|
|
769
|
+
case exports.MovementType.Move:
|
|
764
770
|
for (let mSecPassed = Math.max(prevCursor.time, minTimeLimit); mSecPassed <=
|
|
765
771
|
Math.min(cursor.time, maxTimeLimit); ++mSecPassed) {
|
|
766
772
|
const t = (mSecPassed - prevCursor.time) /
|
|
@@ -828,7 +834,7 @@ class SliderCheeseChecker {
|
|
|
828
834
|
const currentPosition = this.getCursorPosition(cursor);
|
|
829
835
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
830
836
|
switch (cursor.id) {
|
|
831
|
-
case exports.MovementType.
|
|
837
|
+
case exports.MovementType.Move: {
|
|
832
838
|
// Interpolate cursor position during nested object time.
|
|
833
839
|
const t = (nestedObject.startTime - prevCursor.time) /
|
|
834
840
|
(cursor.time - prevCursor.time);
|
|
@@ -837,7 +843,7 @@ class SliderCheeseChecker {
|
|
|
837
843
|
isCheesed = distance > acceptableRadius;
|
|
838
844
|
break;
|
|
839
845
|
}
|
|
840
|
-
case exports.MovementType.
|
|
846
|
+
case exports.MovementType.Up:
|
|
841
847
|
isCheesed =
|
|
842
848
|
prevPosition.getDistance(nestedPosition) >
|
|
843
849
|
acceptableRadius;
|
|
@@ -854,14 +860,9 @@ class SliderCheeseChecker {
|
|
|
854
860
|
*/
|
|
855
861
|
calculateSliderCheesePenalty(cheesedDifficultyRatings) {
|
|
856
862
|
const summedDifficultyRating = Math.min(1, cheesedDifficultyRatings.reduce((a, v) => a + v, 0));
|
|
857
|
-
return
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
this.difficultyAttributes.sliderFactor, 2)),
|
|
861
|
-
flashlightPenalty: Math.max(this.difficultyAttributes.flashlightSliderFactor, Math.pow(1 -
|
|
862
|
-
summedDifficultyRating *
|
|
863
|
-
this.difficultyAttributes.flashlightSliderFactor, 2)),
|
|
864
|
-
};
|
|
863
|
+
return Math.max(this.difficultyAttributes.sliderFactor, Math.pow(1 -
|
|
864
|
+
summedDifficultyRating *
|
|
865
|
+
this.difficultyAttributes.sliderFactor, 2));
|
|
865
866
|
}
|
|
866
867
|
getCursorPosition(cursor) {
|
|
867
868
|
if (this.isHardRock) {
|
|
@@ -955,7 +956,7 @@ class ThreeFingerChecker {
|
|
|
955
956
|
const objectBeforeData = objectData[beforeIndex];
|
|
956
957
|
let timeBefore = objectBefore.endTime;
|
|
957
958
|
if (objectBefore instanceof osuBase.Circle) {
|
|
958
|
-
if (objectBeforeData.result !== osuBase.HitResult.
|
|
959
|
+
if (objectBeforeData.result !== osuBase.HitResult.Miss) {
|
|
959
960
|
timeBefore += objectBeforeData.accuracy;
|
|
960
961
|
}
|
|
961
962
|
else {
|
|
@@ -967,7 +968,7 @@ class ThreeFingerChecker {
|
|
|
967
968
|
const objectAfterData = objectData[afterIndex];
|
|
968
969
|
let timeAfter = objectAfter.startTime;
|
|
969
970
|
if (objectAfter instanceof osuBase.Circle &&
|
|
970
|
-
objectAfterData.result !== osuBase.HitResult.
|
|
971
|
+
objectAfterData.result !== osuBase.HitResult.Miss) {
|
|
971
972
|
timeAfter += objectAfterData.accuracy;
|
|
972
973
|
}
|
|
973
974
|
this.breakPointAccurateTimes.push(new osuBase.BreakPoint(timeBefore, timeAfter));
|
|
@@ -989,10 +990,10 @@ class ThreeFingerChecker {
|
|
|
989
990
|
let firstObjectHitWindow = this.hitWindow.mehWindow;
|
|
990
991
|
if (firstObject instanceof osuBase.Circle) {
|
|
991
992
|
switch (firstObjectResult) {
|
|
992
|
-
case osuBase.HitResult.
|
|
993
|
+
case osuBase.HitResult.Great:
|
|
993
994
|
firstObjectHitWindow = this.hitWindow.greatWindow;
|
|
994
995
|
break;
|
|
995
|
-
case osuBase.HitResult.
|
|
996
|
+
case osuBase.HitResult.Good:
|
|
996
997
|
firstObjectHitWindow = this.hitWindow.okWindow;
|
|
997
998
|
break;
|
|
998
999
|
default:
|
|
@@ -1003,10 +1004,10 @@ class ThreeFingerChecker {
|
|
|
1003
1004
|
let lastObjectHitWindow = this.hitWindow.mehWindow;
|
|
1004
1005
|
if (lastObject instanceof osuBase.Circle) {
|
|
1005
1006
|
switch (lastObjectResult) {
|
|
1006
|
-
case osuBase.HitResult.
|
|
1007
|
+
case osuBase.HitResult.Great:
|
|
1007
1008
|
lastObjectHitWindow = this.hitWindow.greatWindow;
|
|
1008
1009
|
break;
|
|
1009
|
-
case osuBase.HitResult.
|
|
1010
|
+
case osuBase.HitResult.Good:
|
|
1010
1011
|
lastObjectHitWindow = this.hitWindow.okWindow;
|
|
1011
1012
|
break;
|
|
1012
1013
|
default:
|
|
@@ -1075,7 +1076,7 @@ class ThreeFingerChecker {
|
|
|
1075
1076
|
* @returns The index of the cursor, -1 if the object was missed or it's a spinner.
|
|
1076
1077
|
*/
|
|
1077
1078
|
getObjectAimIndex(object, objectData, cursorGroupIndices, cursorIndices) {
|
|
1078
|
-
if (objectData.result === osuBase.HitResult.
|
|
1079
|
+
if (objectData.result === osuBase.HitResult.Miss || object instanceof osuBase.Spinner) {
|
|
1079
1080
|
return -1;
|
|
1080
1081
|
}
|
|
1081
1082
|
// Check for sliderbreaks and treat them as misses.
|
|
@@ -1126,10 +1127,10 @@ class ThreeFingerChecker {
|
|
|
1126
1127
|
const currentPosition = this.getCursorPosition(cursor);
|
|
1127
1128
|
const prevPosition = this.getCursorPosition(prevCursor);
|
|
1128
1129
|
switch (cursor.id) {
|
|
1129
|
-
case exports.MovementType.
|
|
1130
|
+
case exports.MovementType.Up:
|
|
1130
1131
|
distance = prevPosition.getDistance(objectPosition);
|
|
1131
1132
|
break;
|
|
1132
|
-
case exports.MovementType.
|
|
1133
|
+
case exports.MovementType.Move: {
|
|
1133
1134
|
// Interpolate movement.
|
|
1134
1135
|
const t = (hitTime - prevCursor.time) /
|
|
1135
1136
|
(cursor.time - prevCursor.time);
|
|
@@ -1138,7 +1139,7 @@ class ThreeFingerChecker {
|
|
|
1138
1139
|
objectPosition.getDistance(cursorPosition);
|
|
1139
1140
|
break;
|
|
1140
1141
|
}
|
|
1141
|
-
case exports.MovementType.
|
|
1142
|
+
case exports.MovementType.Down:
|
|
1142
1143
|
continue;
|
|
1143
1144
|
}
|
|
1144
1145
|
if (closestDistance > distance) {
|
|
@@ -1168,7 +1169,7 @@ class ThreeFingerChecker {
|
|
|
1168
1169
|
* @returns The index of the cursor, -1 if the object was missed or it's a spinner.
|
|
1169
1170
|
*/
|
|
1170
1171
|
getObjectPressIndex(object, objectData, cursorLookupIndices) {
|
|
1171
|
-
if (objectData.result === osuBase.HitResult.
|
|
1172
|
+
if (objectData.result === osuBase.HitResult.Miss || object instanceof osuBase.Spinner) {
|
|
1172
1173
|
return -1;
|
|
1173
1174
|
}
|
|
1174
1175
|
// Check for sliderbreaks and treat them as misses.
|
|
@@ -1492,7 +1493,7 @@ class TwoHandChecker {
|
|
|
1492
1493
|
const prevObject = this.beatmap.hitObjects.objects[objectIndex - 1];
|
|
1493
1494
|
const prevObjectData = this.data.hitObjectData[objectIndex - 1];
|
|
1494
1495
|
if (prevObject instanceof osuBase.Spinner ||
|
|
1495
|
-
prevObjectData.result === osuBase.HitResult.
|
|
1496
|
+
prevObjectData.result === osuBase.HitResult.Miss) {
|
|
1496
1497
|
return new IndexedHitObject(object, -1, -1, -1, null, false);
|
|
1497
1498
|
}
|
|
1498
1499
|
const objectStartPosition = object.stackedPosition;
|
|
@@ -1555,7 +1556,7 @@ class TwoHandChecker {
|
|
|
1555
1556
|
if (currentPosition.equals(prevPosition)) {
|
|
1556
1557
|
continue;
|
|
1557
1558
|
}
|
|
1558
|
-
if (cursor.id === exports.MovementType.
|
|
1559
|
+
if (cursor.id === exports.MovementType.Up) {
|
|
1559
1560
|
break;
|
|
1560
1561
|
}
|
|
1561
1562
|
const currentMovement = currentPosition.subtract(prevPosition);
|
|
@@ -1647,10 +1648,10 @@ class TwoHandChecker {
|
|
|
1647
1648
|
// For sliders, set the hit window to as lenient as possible.
|
|
1648
1649
|
if (object instanceof osuBase.Circle) {
|
|
1649
1650
|
switch (data.result) {
|
|
1650
|
-
case osuBase.HitResult.
|
|
1651
|
+
case osuBase.HitResult.Great:
|
|
1651
1652
|
hitWindow = this.hitWindow.greatWindow;
|
|
1652
1653
|
break;
|
|
1653
|
-
case osuBase.HitResult.
|
|
1654
|
+
case osuBase.HitResult.Good:
|
|
1654
1655
|
hitWindow = this.hitWindow.okWindow;
|
|
1655
1656
|
break;
|
|
1656
1657
|
}
|
|
@@ -1717,7 +1718,7 @@ class TwoHandChecker {
|
|
|
1717
1718
|
break;
|
|
1718
1719
|
}
|
|
1719
1720
|
let cursorPosition;
|
|
1720
|
-
if (cursor.id === exports.MovementType.
|
|
1721
|
+
if (cursor.id === exports.MovementType.Up) {
|
|
1721
1722
|
cursorPosition = this.getCursorPosition(prevCursor);
|
|
1722
1723
|
const distance = cursorPosition.getDistance(objectPosition);
|
|
1723
1724
|
if (distance <
|
|
@@ -1828,15 +1829,15 @@ class TwoHandChecker {
|
|
|
1828
1829
|
const cursor = cursors[k];
|
|
1829
1830
|
let cursorPosition;
|
|
1830
1831
|
switch (cursor.id) {
|
|
1831
|
-
case exports.MovementType.
|
|
1832
|
+
case exports.MovementType.Down:
|
|
1832
1833
|
cursorPosition = this.getCursorPosition(cursor);
|
|
1833
1834
|
break;
|
|
1834
|
-
case exports.MovementType.
|
|
1835
|
+
case exports.MovementType.Up: {
|
|
1835
1836
|
const prevCursor = cursors[k - 1];
|
|
1836
1837
|
cursorPosition = this.getCursorPosition(prevCursor);
|
|
1837
1838
|
break;
|
|
1838
1839
|
}
|
|
1839
|
-
case exports.MovementType.
|
|
1840
|
+
case exports.MovementType.Move: {
|
|
1840
1841
|
const prevCursor = cursors[k - 1];
|
|
1841
1842
|
const t = osuBase.MathUtils.clamp((object.endTime - prevCursor.time) /
|
|
1842
1843
|
(cursor.time - prevCursor.time), 0, 1);
|
|
@@ -1850,15 +1851,15 @@ class TwoHandChecker {
|
|
|
1850
1851
|
nearestCursorIndex = i;
|
|
1851
1852
|
nearestGroupIndex = j;
|
|
1852
1853
|
switch (cursor.id) {
|
|
1853
|
-
case exports.MovementType.
|
|
1854
|
+
case exports.MovementType.Down:
|
|
1854
1855
|
nearestCursorGroupIndex = k;
|
|
1855
1856
|
nearestCursorTime = cursor.time;
|
|
1856
1857
|
break;
|
|
1857
|
-
case exports.MovementType.
|
|
1858
|
+
case exports.MovementType.Up:
|
|
1858
1859
|
nearestCursorGroupIndex = k - 1;
|
|
1859
1860
|
nearestCursorTime = cursors[k - 1].time;
|
|
1860
1861
|
break;
|
|
1861
|
-
case exports.MovementType.
|
|
1862
|
+
case exports.MovementType.Move:
|
|
1862
1863
|
nearestCursorGroupIndex = k;
|
|
1863
1864
|
nearestCursorTime = object.endTime;
|
|
1864
1865
|
break;
|
|
@@ -1896,7 +1897,7 @@ class TwoHandChecker {
|
|
|
1896
1897
|
*/
|
|
1897
1898
|
checkSliderCheesing(indexedHitObject, hitData) {
|
|
1898
1899
|
if (!(indexedHitObject.object instanceof osuBase.Slider) ||
|
|
1899
|
-
hitData.result === osuBase.HitResult.
|
|
1900
|
+
hitData.result === osuBase.HitResult.Miss ||
|
|
1900
1901
|
indexedHitObject.cursorIndex === -1) {
|
|
1901
1902
|
return false;
|
|
1902
1903
|
}
|
|
@@ -1925,17 +1926,17 @@ class CursorOccurrence {
|
|
|
1925
1926
|
toString() {
|
|
1926
1927
|
let str = `${this.time.toString()}ms `;
|
|
1927
1928
|
switch (this.id) {
|
|
1928
|
-
case exports.MovementType.
|
|
1929
|
+
case exports.MovementType.Down:
|
|
1929
1930
|
str += "Down";
|
|
1930
1931
|
break;
|
|
1931
|
-
case exports.MovementType.
|
|
1932
|
+
case exports.MovementType.Up:
|
|
1932
1933
|
str += "Up";
|
|
1933
1934
|
break;
|
|
1934
|
-
case exports.MovementType.
|
|
1935
|
+
case exports.MovementType.Move:
|
|
1935
1936
|
str += "Move";
|
|
1936
1937
|
break;
|
|
1937
1938
|
}
|
|
1938
|
-
if (this.id !== exports.MovementType.
|
|
1939
|
+
if (this.id !== exports.MovementType.Up) {
|
|
1939
1940
|
str += ` (${this.position.x.toFixed(2)}, ${this.position.y.toFixed(2)})`;
|
|
1940
1941
|
}
|
|
1941
1942
|
return str;
|
|
@@ -1957,7 +1958,7 @@ class CursorOccurrenceGroup {
|
|
|
1957
1958
|
* The cursor occurrence of movement type `movementType.DOWN`.
|
|
1958
1959
|
*/
|
|
1959
1960
|
set down(value) {
|
|
1960
|
-
if (value.id !== exports.MovementType.
|
|
1961
|
+
if (value.id !== exports.MovementType.Down) {
|
|
1961
1962
|
throw new TypeError("Attempting to set the down cursor occurrence to one with different movement type.");
|
|
1962
1963
|
}
|
|
1963
1964
|
this._down = value;
|
|
@@ -1982,7 +1983,7 @@ class CursorOccurrenceGroup {
|
|
|
1982
1983
|
* May not exist, such as when the player holds their cursor until the end of a beatmap.
|
|
1983
1984
|
*/
|
|
1984
1985
|
set up(value) {
|
|
1985
|
-
if (value && value.id !== exports.MovementType.
|
|
1986
|
+
if (value && value.id !== exports.MovementType.Up) {
|
|
1986
1987
|
throw new TypeError("Attempting to set the up cursor occurrence to one with different movement type.");
|
|
1987
1988
|
}
|
|
1988
1989
|
this._up = value;
|
|
@@ -2136,13 +2137,13 @@ class CursorData {
|
|
|
2136
2137
|
for (let i = 0; i < values.size; ++i) {
|
|
2137
2138
|
const occurrence = new CursorOccurrence(values.time[i], values.x[i], values.y[i], values.id[i]);
|
|
2138
2139
|
switch (occurrence.id) {
|
|
2139
|
-
case exports.MovementType.
|
|
2140
|
+
case exports.MovementType.Down:
|
|
2140
2141
|
downOccurrence = occurrence;
|
|
2141
2142
|
break;
|
|
2142
|
-
case exports.MovementType.
|
|
2143
|
+
case exports.MovementType.Move:
|
|
2143
2144
|
moveOccurrences.push(occurrence);
|
|
2144
2145
|
break;
|
|
2145
|
-
case exports.MovementType.
|
|
2146
|
+
case exports.MovementType.Up:
|
|
2146
2147
|
if (downOccurrence) {
|
|
2147
2148
|
this.occurrenceGroups.push(new CursorOccurrenceGroup(downOccurrence, moveOccurrences, occurrence));
|
|
2148
2149
|
downOccurrence = null;
|
|
@@ -2201,7 +2202,7 @@ class ReplayV3Data extends ReplayData {
|
|
|
2201
2202
|
if (this.replayVersion < 8) {
|
|
2202
2203
|
return this.score;
|
|
2203
2204
|
}
|
|
2204
|
-
(_a = this.scoreMultiplier) !== null && _a !== void 0 ? _a : (this.scoreMultiplier = osuBase.ModUtil.calculateScoreMultiplier(this.convertedMods.values(), osuBase.Modes.
|
|
2205
|
+
(_a = this.scoreMultiplier) !== null && _a !== void 0 ? _a : (this.scoreMultiplier = osuBase.ModUtil.calculateScoreMultiplier(this.convertedMods.values(), osuBase.Modes.Droid));
|
|
2205
2206
|
return Math.round(Math.fround(this.score * this.scoreMultiplier));
|
|
2206
2207
|
}
|
|
2207
2208
|
constructor(values) {
|
|
@@ -2279,10 +2280,7 @@ class ReplayAnalyzer {
|
|
|
2279
2280
|
/**
|
|
2280
2281
|
* Penalty values used to penalize dpp for slider cheesing.
|
|
2281
2282
|
*/
|
|
2282
|
-
this.sliderCheesePenalty =
|
|
2283
|
-
aimPenalty: 1,
|
|
2284
|
-
flashlightPenalty: 1,
|
|
2285
|
-
};
|
|
2283
|
+
this.sliderCheesePenalty = 1;
|
|
2286
2284
|
/**
|
|
2287
2285
|
* Whether this replay has been checked against 3 finger usage.
|
|
2288
2286
|
*/
|
|
@@ -2347,7 +2345,7 @@ class ReplayAnalyzer {
|
|
|
2347
2345
|
? this.data.convertedMods
|
|
2348
2346
|
: ((_b = (_a = this.difficultyAttributes) === null || _a === void 0 ? void 0 : _a.mods) !== null && _b !== void 0 ? _b : new osuBase.ModMap());
|
|
2349
2347
|
const adjustedDifficulty = new osuBase.BeatmapDifficulty(this.beatmap.difficulty);
|
|
2350
|
-
osuBase.ModUtil.applyModsToBeatmapDifficulty(adjustedDifficulty, osuBase.Modes.
|
|
2348
|
+
osuBase.ModUtil.applyModsToBeatmapDifficulty(adjustedDifficulty, osuBase.Modes.Droid, mods);
|
|
2351
2349
|
const mehWindow = mods.has(osuBase.ModPrecise)
|
|
2352
2350
|
? new osuBase.PreciseDroidHitWindow(adjustedDifficulty.od).mehWindow
|
|
2353
2351
|
: new osuBase.DroidHitWindow(adjustedDifficulty.od).mehWindow;
|
|
@@ -2355,7 +2353,7 @@ class ReplayAnalyzer {
|
|
|
2355
2353
|
for (let i = 0; i < hitObjectData.length; ++i) {
|
|
2356
2354
|
const v = hitObjectData[i];
|
|
2357
2355
|
const o = objects[i];
|
|
2358
|
-
if (o instanceof osuBase.Spinner || v.result === osuBase.HitResult.
|
|
2356
|
+
if (o instanceof osuBase.Spinner || v.result === osuBase.HitResult.Miss) {
|
|
2359
2357
|
continue;
|
|
2360
2358
|
}
|
|
2361
2359
|
const { accuracy } = v;
|
|
@@ -2405,7 +2403,7 @@ class ReplayAnalyzer {
|
|
|
2405
2403
|
for (let i = 0; i < data.hitObjectData.length; ++i) {
|
|
2406
2404
|
const object = beatmap.hitObjects.objects[i];
|
|
2407
2405
|
const objectData = data.hitObjectData[i];
|
|
2408
|
-
if (objectData.result === osuBase.HitResult.
|
|
2406
|
+
if (objectData.result === osuBase.HitResult.Miss ||
|
|
2409
2407
|
!(object instanceof osuBase.Slider)) {
|
|
2410
2408
|
continue;
|
|
2411
2409
|
}
|
|
@@ -2448,16 +2446,16 @@ class ReplayAnalyzer {
|
|
|
2448
2446
|
let { result } = objectData;
|
|
2449
2447
|
if (object instanceof osuBase.Circle) {
|
|
2450
2448
|
if (hitAccuracy <= hitWindow.greatWindow) {
|
|
2451
|
-
result = osuBase.HitResult.
|
|
2449
|
+
result = osuBase.HitResult.Great;
|
|
2452
2450
|
}
|
|
2453
2451
|
else if (hitAccuracy <= hitWindow.okWindow) {
|
|
2454
|
-
result = osuBase.HitResult.
|
|
2452
|
+
result = osuBase.HitResult.Good;
|
|
2455
2453
|
}
|
|
2456
2454
|
else if (hitAccuracy <= hitWindow.mehWindow) {
|
|
2457
|
-
result = osuBase.HitResult.
|
|
2455
|
+
result = osuBase.HitResult.Meh;
|
|
2458
2456
|
}
|
|
2459
2457
|
else {
|
|
2460
|
-
result = osuBase.HitResult.
|
|
2458
|
+
result = osuBase.HitResult.Miss;
|
|
2461
2459
|
}
|
|
2462
2460
|
}
|
|
2463
2461
|
else if (object instanceof osuBase.Slider) {
|
|
@@ -2470,34 +2468,34 @@ class ReplayAnalyzer {
|
|
|
2470
2468
|
}
|
|
2471
2469
|
}
|
|
2472
2470
|
if (ticksObtained === object.nestedHitObjects.length) {
|
|
2473
|
-
result = osuBase.HitResult.
|
|
2471
|
+
result = osuBase.HitResult.Great;
|
|
2474
2472
|
}
|
|
2475
2473
|
else if (ticksObtained >=
|
|
2476
2474
|
Math.trunc(object.nestedHitObjects.length / 2)) {
|
|
2477
|
-
result = osuBase.HitResult.
|
|
2475
|
+
result = osuBase.HitResult.Good;
|
|
2478
2476
|
}
|
|
2479
2477
|
else if (ticksObtained > 0) {
|
|
2480
|
-
result = osuBase.HitResult.
|
|
2478
|
+
result = osuBase.HitResult.Meh;
|
|
2481
2479
|
}
|
|
2482
2480
|
else {
|
|
2483
|
-
result = osuBase.HitResult.
|
|
2481
|
+
result = osuBase.HitResult.Miss;
|
|
2484
2482
|
}
|
|
2485
2483
|
}
|
|
2486
2484
|
else {
|
|
2487
|
-
result = osuBase.HitResult.
|
|
2485
|
+
result = osuBase.HitResult.Miss;
|
|
2488
2486
|
}
|
|
2489
2487
|
}
|
|
2490
2488
|
switch (result) {
|
|
2491
|
-
case osuBase.HitResult.
|
|
2489
|
+
case osuBase.HitResult.Miss:
|
|
2492
2490
|
++accuracy.nmiss;
|
|
2493
2491
|
break;
|
|
2494
|
-
case osuBase.HitResult.
|
|
2492
|
+
case osuBase.HitResult.Meh:
|
|
2495
2493
|
++accuracy.n50;
|
|
2496
2494
|
break;
|
|
2497
|
-
case osuBase.HitResult.
|
|
2495
|
+
case osuBase.HitResult.Good:
|
|
2498
2496
|
++accuracy.n100;
|
|
2499
2497
|
break;
|
|
2500
|
-
case osuBase.HitResult.
|
|
2498
|
+
case osuBase.HitResult.Great:
|
|
2501
2499
|
++accuracy.n300;
|
|
2502
2500
|
break;
|
|
2503
2501
|
}
|
|
@@ -2760,7 +2758,7 @@ class ReplayAnalyzer {
|
|
|
2760
2758
|
time[j] = this.readInt(replayDataBuffer);
|
|
2761
2759
|
id[j] = time[j] & 3;
|
|
2762
2760
|
time[j] >>= 2;
|
|
2763
|
-
if (id[j] !== exports.MovementType.
|
|
2761
|
+
if (id[j] !== exports.MovementType.Up) {
|
|
2764
2762
|
if (resultObject.replayVersion >= 5) {
|
|
2765
2763
|
x[j] = this.readFloat(replayDataBuffer);
|
|
2766
2764
|
y[j] = this.readFloat(replayDataBuffer);
|
|
@@ -2792,7 +2790,7 @@ class ReplayAnalyzer {
|
|
|
2792
2790
|
const replayObjectData = {
|
|
2793
2791
|
accuracy: 0,
|
|
2794
2792
|
tickset: [],
|
|
2795
|
-
result: osuBase.HitResult.
|
|
2793
|
+
result: osuBase.HitResult.Miss,
|
|
2796
2794
|
};
|
|
2797
2795
|
replayObjectData.accuracy = this.readShort(replayDataBuffer);
|
|
2798
2796
|
const len = this.readByte(replayDataBuffer);
|
|
@@ -2833,21 +2831,21 @@ class ReplayAnalyzer {
|
|
|
2833
2831
|
: true
|
|
2834
2832
|
: false;
|
|
2835
2833
|
switch (hitObjectData.result) {
|
|
2836
|
-
case osuBase.HitResult.
|
|
2834
|
+
case osuBase.HitResult.Miss:
|
|
2837
2835
|
++resultObject.accuracy.nmiss;
|
|
2838
2836
|
grantsGekiOrKatu = false;
|
|
2839
2837
|
break;
|
|
2840
|
-
case osuBase.HitResult.
|
|
2838
|
+
case osuBase.HitResult.Meh:
|
|
2841
2839
|
++resultObject.accuracy.n50;
|
|
2842
2840
|
grantsGekiOrKatu = false;
|
|
2843
2841
|
break;
|
|
2844
|
-
case osuBase.HitResult.
|
|
2842
|
+
case osuBase.HitResult.Good:
|
|
2845
2843
|
++resultObject.accuracy.n100;
|
|
2846
2844
|
if (grantsGekiOrKatu && isNextNewCombo) {
|
|
2847
2845
|
++resultObject.hit100k;
|
|
2848
2846
|
}
|
|
2849
2847
|
break;
|
|
2850
|
-
case osuBase.HitResult.
|
|
2848
|
+
case osuBase.HitResult.Great:
|
|
2851
2849
|
++resultObject.accuracy.n300;
|
|
2852
2850
|
if (grantsGekiOrKatu && isNextNewCombo) {
|
|
2853
2851
|
++resultObject.hit300k;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rian8337/osu-droid-replay-analyzer",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.91",
|
|
4
4
|
"description": "A replay analyzer for analyzing osu!droid replay files.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"osu",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"url": "https://github.com/Rian8337/osu-droid-module/issues"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@rian8337/osu-base": "4.0.0-beta.
|
|
38
|
-
"@rian8337/osu-difficulty-calculator": "4.0.0-beta.
|
|
39
|
-
"@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.
|
|
37
|
+
"@rian8337/osu-base": "4.0.0-beta.91",
|
|
38
|
+
"@rian8337/osu-difficulty-calculator": "4.0.0-beta.91",
|
|
39
|
+
"@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.91",
|
|
40
40
|
"java-deserialization": "^0.1.0",
|
|
41
41
|
"unzipper": "^0.10.11"
|
|
42
42
|
},
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "21fc1a8f1ddf89952521bf670a84dcfdd0495ed7"
|
|
50
50
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -11,15 +11,15 @@ declare enum MovementType {
|
|
|
11
11
|
/**
|
|
12
12
|
* The player places their finger on the screen.
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
Down = 0,
|
|
15
15
|
/**
|
|
16
16
|
* The player drags their finger on the screen.
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
Move = 1,
|
|
19
19
|
/**
|
|
20
20
|
* The player releases their finger from the screen.
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
Up = 2
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -214,10 +214,10 @@ interface ReplayObjectData {
|
|
|
214
214
|
* const rotations = Math.floor(data.accuracy / 4);
|
|
215
215
|
* ```
|
|
216
216
|
* The remainder of the division denotes the hit result of the spinner:
|
|
217
|
-
* - `HitResult.
|
|
218
|
-
* - `HitResult.
|
|
219
|
-
* - `HitResult.
|
|
220
|
-
* - `HitResult.
|
|
217
|
+
* - `HitResult.Great`: 3
|
|
218
|
+
* - `HitResult.Good`: 2
|
|
219
|
+
* - `HitResult.Meh`: 1
|
|
220
|
+
* - `HitResult.Miss`: 0
|
|
221
221
|
*/
|
|
222
222
|
accuracy: number;
|
|
223
223
|
/**
|
|
@@ -433,21 +433,7 @@ declare class ReplayData {
|
|
|
433
433
|
}
|
|
434
434
|
|
|
435
435
|
/**
|
|
436
|
-
*
|
|
437
|
-
*/
|
|
438
|
-
interface SliderCheeseInformation {
|
|
439
|
-
/**
|
|
440
|
-
* The value used to penalize the aim performance value, from 0 to 1.
|
|
441
|
-
*/
|
|
442
|
-
aimPenalty: number;
|
|
443
|
-
/**
|
|
444
|
-
* The value used to penalize the flashlight performance value, from 0 to 1.
|
|
445
|
-
*/
|
|
446
|
-
flashlightPenalty: number;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Utility to check whether relevant sliders in a beatmap are cheesed for rebalance scores..
|
|
436
|
+
* Utility to check whether relevant sliders in a beatmap are cheesed for rebalance scores.
|
|
451
437
|
*/
|
|
452
438
|
declare class RebalanceSliderCheeseChecker {
|
|
453
439
|
/**
|
|
@@ -476,7 +462,7 @@ declare class RebalanceSliderCheeseChecker {
|
|
|
476
462
|
/**
|
|
477
463
|
* Checks if relevant sliders in the given beatmap was cheesed.
|
|
478
464
|
*/
|
|
479
|
-
check():
|
|
465
|
+
check(): number;
|
|
480
466
|
/**
|
|
481
467
|
* Checks for sliders that were cheesed.
|
|
482
468
|
*/
|
|
@@ -647,7 +633,7 @@ declare class SliderCheeseChecker {
|
|
|
647
633
|
/**
|
|
648
634
|
* Checks if relevant sliders in the given beatmap was cheesed.
|
|
649
635
|
*/
|
|
650
|
-
check():
|
|
636
|
+
check(): number;
|
|
651
637
|
/**
|
|
652
638
|
* Checks for sliders that were cheesed.
|
|
653
639
|
*/
|
|
@@ -1085,7 +1071,7 @@ declare class ReplayAnalyzer {
|
|
|
1085
1071
|
/**
|
|
1086
1072
|
* Penalty values used to penalize dpp for slider cheesing.
|
|
1087
1073
|
*/
|
|
1088
|
-
sliderCheesePenalty:
|
|
1074
|
+
sliderCheesePenalty: number;
|
|
1089
1075
|
/**
|
|
1090
1076
|
* Whether this replay has been checked against 3 finger usage.
|
|
1091
1077
|
*/
|
|
@@ -1195,4 +1181,4 @@ declare class ReplayAnalyzer {
|
|
|
1195
1181
|
}
|
|
1196
1182
|
|
|
1197
1183
|
export { CursorData, CursorOccurrence, CursorOccurrenceGroup, MovementType, RebalanceSliderCheeseChecker, RebalanceThreeFingerChecker, ReplayAnalyzer, ReplayData, ReplayV3Data, SliderCheeseChecker, ThreeFingerChecker, TwoHandChecker };
|
|
1198
|
-
export type { CursorInformation, ExportedReplayJSON, ExportedReplayJSONDataV1, ExportedReplayJSONDataV2, ExportedReplayJSONDataV3, ExportedReplayJSONDataV4, ExportedReplayJSONV1, ExportedReplayJSONV2, ExportedReplayJSONV3, ExportedReplayJSONV4, HitErrorInformation, ReplayObjectData,
|
|
1184
|
+
export type { CursorInformation, ExportedReplayJSON, ExportedReplayJSONDataV1, ExportedReplayJSONDataV2, ExportedReplayJSONDataV3, ExportedReplayJSONDataV4, ExportedReplayJSONV1, ExportedReplayJSONV2, ExportedReplayJSONV3, ExportedReplayJSONV4, HitErrorInformation, ReplayObjectData, SliderHitInformation, SliderNestedHitObjectInformation, ThreeFingerInformation, TwoHandInformation };
|