@rian8337/osu-droid-replay-analyzer 4.0.0-beta.74 → 4.0.0-beta.76
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 +120 -5
- package/package.json +4 -4
- package/typings/index.d.ts +50 -4
package/dist/index.js
CHANGED
|
@@ -963,7 +963,7 @@ class SliderCheeseChecker {
|
|
|
963
963
|
}
|
|
964
964
|
|
|
965
965
|
/**
|
|
966
|
-
* Utility to check whether or not a beatmap is three-fingered for
|
|
966
|
+
* Utility to check whether or not a beatmap is three-fingered for live scores.
|
|
967
967
|
*/
|
|
968
968
|
class ThreeFingerChecker {
|
|
969
969
|
/**
|
|
@@ -1026,9 +1026,6 @@ class ThreeFingerChecker {
|
|
|
1026
1026
|
}
|
|
1027
1027
|
this.getAccurateBreakPoints();
|
|
1028
1028
|
this.filterCursorInstances();
|
|
1029
|
-
if (this.downCursorInstances.filter((v) => v.length > 0).length <= 3) {
|
|
1030
|
-
return { is3Finger: false, penalty: 1 };
|
|
1031
|
-
}
|
|
1032
1029
|
this.getBeatmapSections();
|
|
1033
1030
|
this.calculateNerfFactors();
|
|
1034
1031
|
const finalPenalty = this.calculateFinalPenalty();
|
|
@@ -2129,7 +2126,7 @@ class ReplayAnalyzer {
|
|
|
2129
2126
|
/**
|
|
2130
2127
|
* Gets hit error information of the replay.
|
|
2131
2128
|
*
|
|
2132
|
-
* `analyze()` must be called before calling this.
|
|
2129
|
+
* `analyze()` must be called before calling this, and `beatmap` must be defined.
|
|
2133
2130
|
*/
|
|
2134
2131
|
calculateHitError() {
|
|
2135
2132
|
var _a, _b;
|
|
@@ -2180,6 +2177,124 @@ class ReplayAnalyzer {
|
|
|
2180
2177
|
unstableRate: osuBase.MathUtils.calculateStandardDeviation(accuracies) * 10,
|
|
2181
2178
|
};
|
|
2182
2179
|
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Obtains the amount of slider ticks and ends hit in the replay.
|
|
2182
|
+
*
|
|
2183
|
+
* This requires `analyze()` to be called first and `beatmap` to be defined.
|
|
2184
|
+
*
|
|
2185
|
+
* @returns Slider hit information or `null` if the replay has not been analyzed or the beatmap is not defined.
|
|
2186
|
+
*/
|
|
2187
|
+
obtainSliderHitInformation() {
|
|
2188
|
+
const { data, beatmap } = this;
|
|
2189
|
+
if (!data || !beatmap) {
|
|
2190
|
+
return null;
|
|
2191
|
+
}
|
|
2192
|
+
const sliderInformation = {
|
|
2193
|
+
tick: { obtained: 0, total: beatmap.hitObjects.sliderTicks },
|
|
2194
|
+
end: { obtained: 0, total: beatmap.hitObjects.sliders },
|
|
2195
|
+
};
|
|
2196
|
+
for (let i = 0; i < data.hitObjectData.length; ++i) {
|
|
2197
|
+
const object = beatmap.hitObjects.objects[i];
|
|
2198
|
+
const objectData = data.hitObjectData[i];
|
|
2199
|
+
if (objectData.result === exports.HitResult.miss ||
|
|
2200
|
+
!(object instanceof osuBase.Slider)) {
|
|
2201
|
+
continue;
|
|
2202
|
+
}
|
|
2203
|
+
// Exclude the head circle.
|
|
2204
|
+
for (let j = 1; j < object.nestedHitObjects.length; ++j) {
|
|
2205
|
+
const nested = object.nestedHitObjects[j];
|
|
2206
|
+
if (!objectData.tickset[j - 1]) {
|
|
2207
|
+
continue;
|
|
2208
|
+
}
|
|
2209
|
+
if (nested instanceof osuBase.SliderTick) {
|
|
2210
|
+
++sliderInformation.tick.obtained;
|
|
2211
|
+
}
|
|
2212
|
+
else if (nested instanceof osuBase.SliderTail) {
|
|
2213
|
+
++sliderInformation.end.obtained;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
return sliderInformation;
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Simulates a hit window for the replay.
|
|
2221
|
+
*
|
|
2222
|
+
* This does not account for required spins in a spinner.
|
|
2223
|
+
*
|
|
2224
|
+
* Requires `analyze()` to be called first and `beatmap` to be defined.
|
|
2225
|
+
*
|
|
2226
|
+
* @param hitWindow The hit window to simulate.
|
|
2227
|
+
* @returns The accuracy of the replay based on the hit window, or `null` if the replay has not been analyzed or the beatmap is not defined.
|
|
2228
|
+
*/
|
|
2229
|
+
simulateHitWindow(hitWindow) {
|
|
2230
|
+
const { data, beatmap } = this;
|
|
2231
|
+
if (!data || !beatmap) {
|
|
2232
|
+
return null;
|
|
2233
|
+
}
|
|
2234
|
+
const accuracy = new osuBase.Accuracy({ n300: 0, n100: 0, n50: 0, nmiss: 0 });
|
|
2235
|
+
for (let i = 0; i < data.hitObjectData.length; ++i) {
|
|
2236
|
+
const object = beatmap.hitObjects.objects[i];
|
|
2237
|
+
const objectData = data.hitObjectData[i];
|
|
2238
|
+
const hitAccuracy = Math.abs(objectData.accuracy);
|
|
2239
|
+
let { result } = objectData;
|
|
2240
|
+
if (object instanceof osuBase.Circle) {
|
|
2241
|
+
if (hitAccuracy <= hitWindow.greatWindow) {
|
|
2242
|
+
result = exports.HitResult.great;
|
|
2243
|
+
}
|
|
2244
|
+
else if (hitAccuracy <= hitWindow.okWindow) {
|
|
2245
|
+
result = exports.HitResult.good;
|
|
2246
|
+
}
|
|
2247
|
+
else if (hitAccuracy <= hitWindow.mehWindow) {
|
|
2248
|
+
result = exports.HitResult.meh;
|
|
2249
|
+
}
|
|
2250
|
+
else {
|
|
2251
|
+
result = exports.HitResult.miss;
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
else if (object instanceof osuBase.Slider) {
|
|
2255
|
+
if (hitAccuracy <=
|
|
2256
|
+
Math.min(hitWindow.mehWindow, object.duration)) {
|
|
2257
|
+
let ticksObtained = 1;
|
|
2258
|
+
for (let j = 1; j < object.nestedHitObjects.length; ++j) {
|
|
2259
|
+
if (objectData.tickset[j - 1]) {
|
|
2260
|
+
++ticksObtained;
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
if (ticksObtained === object.nestedHitObjects.length) {
|
|
2264
|
+
result = exports.HitResult.great;
|
|
2265
|
+
}
|
|
2266
|
+
else if (ticksObtained >=
|
|
2267
|
+
Math.trunc(object.nestedHitObjects.length / 2)) {
|
|
2268
|
+
result = exports.HitResult.good;
|
|
2269
|
+
}
|
|
2270
|
+
else if (ticksObtained > 0) {
|
|
2271
|
+
result = exports.HitResult.meh;
|
|
2272
|
+
}
|
|
2273
|
+
else {
|
|
2274
|
+
result = exports.HitResult.miss;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
else {
|
|
2278
|
+
result = exports.HitResult.miss;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
switch (result) {
|
|
2282
|
+
case exports.HitResult.miss:
|
|
2283
|
+
++accuracy.nmiss;
|
|
2284
|
+
break;
|
|
2285
|
+
case exports.HitResult.meh:
|
|
2286
|
+
++accuracy.n50;
|
|
2287
|
+
break;
|
|
2288
|
+
case exports.HitResult.good:
|
|
2289
|
+
++accuracy.n100;
|
|
2290
|
+
break;
|
|
2291
|
+
case exports.HitResult.great:
|
|
2292
|
+
++accuracy.n300;
|
|
2293
|
+
break;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
return accuracy;
|
|
2297
|
+
}
|
|
2183
2298
|
/**
|
|
2184
2299
|
* Checks if a play is using 3 fingers.
|
|
2185
2300
|
*
|
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.76",
|
|
4
4
|
"description": "A replay analyzer for analyzing osu!droid replay files.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"osu",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@rian8337/osu-base": "^4.0.0-beta.74",
|
|
38
|
-
"@rian8337/osu-difficulty-calculator": "^4.0.0-beta.
|
|
39
|
-
"@rian8337/osu-rebalance-difficulty-calculator": "^4.0.0-beta.
|
|
38
|
+
"@rian8337/osu-difficulty-calculator": "^4.0.0-beta.76",
|
|
39
|
+
"@rian8337/osu-rebalance-difficulty-calculator": "^4.0.0-beta.76",
|
|
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": "d843f2cf65e2e44c87654a2be675d6ed925193ea"
|
|
50
50
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Vector2, Accuracy, ScoreRank, ModMap, DroidPlayableBeatmap, Beatmap } from '@rian8337/osu-base';
|
|
1
|
+
import { Vector2, Accuracy, ScoreRank, ModMap, DroidPlayableBeatmap, Beatmap, HitWindow } from '@rian8337/osu-base';
|
|
2
2
|
import { IExtendedDroidDifficultyAttributes as IExtendedDroidDifficultyAttributes$1 } from '@rian8337/osu-difficulty-calculator';
|
|
3
3
|
import { IExtendedDroidDifficultyAttributes } from '@rian8337/osu-rebalance-difficulty-calculator';
|
|
4
4
|
|
|
@@ -726,6 +726,33 @@ interface SliderCheeseInformation {
|
|
|
726
726
|
visualPenalty: number;
|
|
727
727
|
}
|
|
728
728
|
|
|
729
|
+
/**
|
|
730
|
+
* Represents hit information about sliders in a beatmap.
|
|
731
|
+
*/
|
|
732
|
+
interface SliderHitInformation {
|
|
733
|
+
/**
|
|
734
|
+
* Hit information of slider ticks.
|
|
735
|
+
*/
|
|
736
|
+
readonly tick: SliderNestedHitObjectInformation;
|
|
737
|
+
/**
|
|
738
|
+
* hit information of slider ends.
|
|
739
|
+
*/
|
|
740
|
+
readonly end: SliderNestedHitObjectInformation;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Hit information of a specific nested hit object.
|
|
744
|
+
*/
|
|
745
|
+
interface SliderNestedHitObjectInformation {
|
|
746
|
+
/**
|
|
747
|
+
* The amount of the nested hit objects that were obtained.
|
|
748
|
+
*/
|
|
749
|
+
obtained: number;
|
|
750
|
+
/**
|
|
751
|
+
* The amount of the nested hit objects in the beatmap.
|
|
752
|
+
*/
|
|
753
|
+
readonly total: number;
|
|
754
|
+
}
|
|
755
|
+
|
|
729
756
|
interface HitErrorInformation {
|
|
730
757
|
negativeAvg: number;
|
|
731
758
|
positiveAvg: number;
|
|
@@ -822,9 +849,28 @@ declare class ReplayAnalyzer {
|
|
|
822
849
|
/**
|
|
823
850
|
* Gets hit error information of the replay.
|
|
824
851
|
*
|
|
825
|
-
* `analyze()` must be called before calling this.
|
|
852
|
+
* `analyze()` must be called before calling this, and `beatmap` must be defined.
|
|
826
853
|
*/
|
|
827
854
|
calculateHitError(): HitErrorInformation | null;
|
|
855
|
+
/**
|
|
856
|
+
* Obtains the amount of slider ticks and ends hit in the replay.
|
|
857
|
+
*
|
|
858
|
+
* This requires `analyze()` to be called first and `beatmap` to be defined.
|
|
859
|
+
*
|
|
860
|
+
* @returns Slider hit information or `null` if the replay has not been analyzed or the beatmap is not defined.
|
|
861
|
+
*/
|
|
862
|
+
obtainSliderHitInformation(): SliderHitInformation | null;
|
|
863
|
+
/**
|
|
864
|
+
* Simulates a hit window for the replay.
|
|
865
|
+
*
|
|
866
|
+
* This does not account for required spins in a spinner.
|
|
867
|
+
*
|
|
868
|
+
* Requires `analyze()` to be called first and `beatmap` to be defined.
|
|
869
|
+
*
|
|
870
|
+
* @param hitWindow The hit window to simulate.
|
|
871
|
+
* @returns The accuracy of the replay based on the hit window, or `null` if the replay has not been analyzed or the beatmap is not defined.
|
|
872
|
+
*/
|
|
873
|
+
simulateHitWindow(hitWindow: HitWindow): Accuracy | null;
|
|
828
874
|
/**
|
|
829
875
|
* Checks if a play is using 3 fingers.
|
|
830
876
|
*
|
|
@@ -915,7 +961,7 @@ declare class SliderCheeseChecker {
|
|
|
915
961
|
}
|
|
916
962
|
|
|
917
963
|
/**
|
|
918
|
-
* Utility to check whether or not a beatmap is three-fingered for
|
|
964
|
+
* Utility to check whether or not a beatmap is three-fingered for live scores.
|
|
919
965
|
*/
|
|
920
966
|
declare class ThreeFingerChecker {
|
|
921
967
|
/**
|
|
@@ -1115,4 +1161,4 @@ declare class TwoHandChecker {
|
|
|
1115
1161
|
private getCursorPosition;
|
|
1116
1162
|
}
|
|
1117
1163
|
|
|
1118
|
-
export { CursorData, type CursorInformation, CursorOccurrence, CursorOccurrenceGroup, type ExportedReplayJSON, type ExportedReplayJSONDataV1, type ExportedReplayJSONDataV2, type ExportedReplayJSONDataV3, type ExportedReplayJSONV1, type ExportedReplayJSONV2, type ExportedReplayJSONV3, type HitErrorInformation, HitResult, MovementType, RebalanceThreeFingerChecker, ReplayAnalyzer, ReplayData, ReplayObjectData, ReplayV3Data, SliderCheeseChecker, type SliderCheeseInformation, ThreeFingerChecker, type ThreeFingerInformation, TwoHandChecker, type TwoHandInformation };
|
|
1164
|
+
export { CursorData, type CursorInformation, CursorOccurrence, CursorOccurrenceGroup, type ExportedReplayJSON, type ExportedReplayJSONDataV1, type ExportedReplayJSONDataV2, type ExportedReplayJSONDataV3, type ExportedReplayJSONV1, type ExportedReplayJSONV2, type ExportedReplayJSONV3, type HitErrorInformation, HitResult, MovementType, RebalanceThreeFingerChecker, ReplayAnalyzer, ReplayData, ReplayObjectData, ReplayV3Data, SliderCheeseChecker, type SliderCheeseInformation, type SliderHitInformation, type SliderNestedHitObjectInformation, ThreeFingerChecker, type ThreeFingerInformation, TwoHandChecker, type TwoHandInformation };
|