@rian8337/osu-droid-replay-analyzer 4.0.0-beta.97 → 4.0.0-beta.99

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 CHANGED
@@ -2338,7 +2338,6 @@ class ReplayAnalyzer {
2338
2338
  * `analyze()` must be called before calling this, and `beatmap` must be defined.
2339
2339
  */
2340
2340
  calculateHitError() {
2341
- var _a, _b;
2342
2341
  if (!this.data || !this.beatmap) {
2343
2342
  return null;
2344
2343
  }
@@ -2348,14 +2347,7 @@ class ReplayAnalyzer {
2348
2347
  let positiveTotal = 0;
2349
2348
  let negativeTotal = 0;
2350
2349
  const { objects } = this.beatmap.hitObjects;
2351
- const mods = this.data.isReplayV3()
2352
- ? this.data.convertedMods
2353
- : ((_b = (_a = this.difficultyAttributes) === null || _a === void 0 ? void 0 : _a.mods) !== null && _b !== void 0 ? _b : new osuBase.ModMap());
2354
- const adjustedDifficulty = new osuBase.BeatmapDifficulty(this.beatmap.difficulty);
2355
- osuBase.ModUtil.applyModsToBeatmapDifficulty(adjustedDifficulty, osuBase.Modes.Droid, mods);
2356
- const mehWindow = mods.has(osuBase.ModPrecise)
2357
- ? new osuBase.PreciseDroidHitWindow(adjustedDifficulty.od).mehWindow
2358
- : new osuBase.DroidHitWindow(adjustedDifficulty.od).mehWindow;
2350
+ const { mehWindow } = this.getBeatmapHitWindow();
2359
2351
  const accuracies = [];
2360
2352
  for (let i = 0; i < hitObjectData.length; ++i) {
2361
2353
  const v = hitObjectData[i];
@@ -2392,7 +2384,7 @@ class ReplayAnalyzer {
2392
2384
  };
2393
2385
  }
2394
2386
  /**
2395
- * Obtains the amount of slider ticks and ends hit in the replay.
2387
+ * Obtains the amount of slider nested objects hit in the replay.
2396
2388
  *
2397
2389
  * This requires `analyze()` to be called first and `beatmap` to be defined.
2398
2390
  *
@@ -2404,27 +2396,46 @@ class ReplayAnalyzer {
2404
2396
  return null;
2405
2397
  }
2406
2398
  const sliderInformation = {
2407
- tick: { obtained: 0, total: beatmap.hitObjects.sliderTicks },
2408
- end: { obtained: 0, total: beatmap.hitObjects.sliders },
2399
+ head: { obtained: 0, total: beatmap.hitObjects.sliders },
2400
+ tick: { obtained: 0, total: 0 },
2401
+ repeat: { obtained: 0, total: 0 },
2402
+ end: { obtained: 0, total: 0 },
2409
2403
  };
2404
+ const hitWindow = this.getBeatmapHitWindow();
2410
2405
  for (let i = 0; i < data.hitObjectData.length; ++i) {
2411
2406
  const object = beatmap.hitObjects.objects[i];
2412
2407
  const objectData = data.hitObjectData[i];
2413
- if (objectData.result === osuBase.HitResult.Miss ||
2414
- !(object instanceof osuBase.Slider)) {
2408
+ if (!(object instanceof osuBase.Slider)) {
2415
2409
  continue;
2416
2410
  }
2417
- // Exclude the head circle.
2411
+ let lateHitThreshold = hitWindow.mehWindow;
2412
+ // Before replay version 8, the slider head's hit window is capped to the duration of the slider.
2413
+ if (data.replayVersion < 8) {
2414
+ lateHitThreshold = Math.min(lateHitThreshold, object.duration);
2415
+ }
2416
+ if (-hitWindow.mehWindow <= objectData.accuracy &&
2417
+ objectData.accuracy <= lateHitThreshold) {
2418
+ ++sliderInformation.head.obtained;
2419
+ }
2418
2420
  for (let j = 1; j < object.nestedHitObjects.length; ++j) {
2419
2421
  const nested = object.nestedHitObjects[j];
2420
- if (!objectData.tickset[j - 1]) {
2421
- continue;
2422
- }
2423
- if (nested instanceof osuBase.SliderTick) {
2424
- ++sliderInformation.tick.obtained;
2422
+ let tickInformation;
2423
+ switch (true) {
2424
+ case nested instanceof osuBase.SliderTick:
2425
+ tickInformation = sliderInformation.tick;
2426
+ break;
2427
+ case nested instanceof osuBase.SliderRepeat:
2428
+ tickInformation = sliderInformation.repeat;
2429
+ break;
2430
+ case nested instanceof osuBase.SliderTail:
2431
+ tickInformation = sliderInformation.end;
2432
+ break;
2433
+ default:
2434
+ continue;
2425
2435
  }
2426
- else if (nested instanceof osuBase.SliderTail) {
2427
- ++sliderInformation.end.obtained;
2436
+ ++tickInformation.total;
2437
+ if (objectData.tickset[j - 1]) {
2438
+ ++tickInformation.obtained;
2428
2439
  }
2429
2440
  }
2430
2441
  }
@@ -2574,8 +2585,16 @@ class ReplayAnalyzer {
2574
2585
  .setRequireAPIkey(false)
2575
2586
  .setEndpoint("upload")
2576
2587
  .addParameter("", `${this.scoreID.toString()}.odr`);
2577
- const result = yield apiRequestBuilder.sendRequest();
2588
+ let result;
2589
+ try {
2590
+ result = yield apiRequestBuilder.sendRequest();
2591
+ }
2592
+ catch (e) {
2593
+ console.error(`Error retrieving replay for score ID ${this.scoreID.toString()}: ${e.message}`);
2594
+ return null;
2595
+ }
2578
2596
  if (result.statusCode !== 200) {
2597
+ console.error(`Error retrieving replay for score ID ${this.scoreID.toString()}: ${result.describeFailure()}`);
2579
2598
  return null;
2580
2599
  }
2581
2600
  return result.data;
@@ -2913,6 +2932,20 @@ class ReplayAnalyzer {
2913
2932
  : (_a = this.difficultyAttributes) === null || _a === void 0 ? void 0 : _a.mods;
2914
2933
  return this.beatmap.createDroidPlayableBeatmap(mods);
2915
2934
  }
2935
+ getBeatmapHitWindow() {
2936
+ var _a, _b;
2937
+ if (!this.data || !this.beatmap) {
2938
+ return null;
2939
+ }
2940
+ const mods = this.data.isReplayV3()
2941
+ ? this.data.convertedMods
2942
+ : ((_b = (_a = this.difficultyAttributes) === null || _a === void 0 ? void 0 : _a.mods) !== null && _b !== void 0 ? _b : new osuBase.ModMap());
2943
+ const adjustedDifficulty = new osuBase.BeatmapDifficulty(this.beatmap.difficulty);
2944
+ osuBase.ModUtil.applyModsToBeatmapDifficulty(adjustedDifficulty, osuBase.Modes.Droid, mods);
2945
+ return mods.has(osuBase.ModPrecise)
2946
+ ? new osuBase.PreciseDroidHitWindow(adjustedDifficulty.od)
2947
+ : new osuBase.DroidHitWindow(adjustedDifficulty.od);
2948
+ }
2916
2949
  readByte(buffer) {
2917
2950
  const num = buffer.readInt8(this.bufferOffset);
2918
2951
  this.bufferOffset += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-droid-replay-analyzer",
3
- "version": "4.0.0-beta.97",
3
+ "version": "4.0.0-beta.99",
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.97",
38
- "@rian8337/osu-difficulty-calculator": "4.0.0-beta.97",
39
- "@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.97",
37
+ "@rian8337/osu-base": "4.0.0-beta.98",
38
+ "@rian8337/osu-difficulty-calculator": "4.0.0-beta.99",
39
+ "@rian8337/osu-rebalance-difficulty-calculator": "4.0.0-beta.99",
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": "0d77ee41c1b0eca8e46c118e942417483c4a9452"
49
+ "gitHead": "8db713bd3e23b065f26d65f4d312e3d55c384a1c"
50
50
  }
@@ -1003,10 +1003,18 @@ type ExportedReplayJSONV4 = ExportedReplayJSON<4, ExportedReplayJSONDataV4>;
1003
1003
  * Represents hit information about sliders in a beatmap.
1004
1004
  */
1005
1005
  interface SliderHitInformation {
1006
+ /**
1007
+ * Hit information of slider heads.
1008
+ */
1009
+ readonly head: SliderNestedHitObjectInformation;
1006
1010
  /**
1007
1011
  * Hit information of slider ticks.
1008
1012
  */
1009
1013
  readonly tick: SliderNestedHitObjectInformation;
1014
+ /**
1015
+ * Hit information of slider repeats.
1016
+ */
1017
+ readonly repeat: SliderNestedHitObjectInformation;
1010
1018
  /**
1011
1019
  * hit information of slider ends.
1012
1020
  */
@@ -1023,7 +1031,7 @@ interface SliderNestedHitObjectInformation {
1023
1031
  /**
1024
1032
  * The amount of the nested hit objects in the beatmap.
1025
1033
  */
1026
- readonly total: number;
1034
+ total: number;
1027
1035
  }
1028
1036
 
1029
1037
  interface HitErrorInformation {
@@ -1126,7 +1134,7 @@ declare class ReplayAnalyzer {
1126
1134
  */
1127
1135
  calculateHitError(): HitErrorInformation | null;
1128
1136
  /**
1129
- * Obtains the amount of slider ticks and ends hit in the replay.
1137
+ * Obtains the amount of slider nested objects hit in the replay.
1130
1138
  *
1131
1139
  * This requires `analyze()` to be called first and `beatmap` to be defined.
1132
1140
  *
@@ -1185,6 +1193,7 @@ declare class ReplayAnalyzer {
1185
1193
  private parseOldReplayInformation;
1186
1194
  private calculateRank;
1187
1195
  private constructPlayableBeatmap;
1196
+ private getBeatmapHitWindow;
1188
1197
  private readByte;
1189
1198
  private readShort;
1190
1199
  private readInt;