@rian8337/osu-droid-replay-analyzer 4.0.0-beta.18 → 4.0.0-beta.19

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.
Files changed (2) hide show
  1. package/package.json +5 -5
  2. package/typings/index.d.ts +812 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-droid-replay-analyzer",
3
- "version": "4.0.0-beta.18",
3
+ "version": "4.0.0-beta.19",
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.18",
38
- "@rian8337/osu-difficulty-calculator": "^4.0.0-beta.18",
39
- "@rian8337/osu-rebalance-difficulty-calculator": "^4.0.0-beta.18",
37
+ "@rian8337/osu-base": "^4.0.0-beta.19",
38
+ "@rian8337/osu-difficulty-calculator": "^4.0.0-beta.19",
39
+ "@rian8337/osu-rebalance-difficulty-calculator": "^4.0.0-beta.19",
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": "8c40a86996a0b1d3ca671446b2ea4120daed8a69"
49
+ "gitHead": "45f7c976ba683027dc3a4d29de8bf289aadf7707"
50
50
  }
@@ -2,118 +2,477 @@ import { Vector2, Accuracy, Mod, IModApplicableToDroid, Beatmap } from '@rian833
2
2
  import { ExtendedDroidDifficultyAttributes, DroidDifficultyCalculator as DroidDifficultyCalculator$1 } from '@rian8337/osu-rebalance-difficulty-calculator';
3
3
  import { ExtendedDroidDifficultyAttributes as ExtendedDroidDifficultyAttributes$1, DroidDifficultyCalculator } from '@rian8337/osu-difficulty-calculator';
4
4
 
5
+ /**
6
+ * Movement types of a cursor in an osu!droid replay.
7
+ *
8
+ * The cursor movement is represented as a player's action on the screen.
9
+ */
5
10
  declare enum MovementType {
11
+ /**
12
+ * The player places their finger on the screen.
13
+ */
6
14
  down = 0,
15
+ /**
16
+ * The player drags their finger on the screen.
17
+ */
7
18
  move = 1,
19
+ /**
20
+ * The player releases their finger from the screen.
21
+ */
8
22
  up = 2
9
23
  }
10
24
 
25
+ /**
26
+ * Represents a cursor's occurrence.
27
+ */
11
28
  declare class CursorOccurrence {
29
+ /**
30
+ * The time of this occurrence.
31
+ */
12
32
  readonly time: number;
33
+ /**
34
+ * The position of the occurrence.
35
+ */
13
36
  readonly position: Vector2;
37
+ /**
38
+ * The movement ID of the occurrence.
39
+ */
14
40
  readonly id: MovementType;
15
41
  constructor(time: number, x: number, y: number, id: MovementType);
16
42
  }
17
43
 
44
+ /**
45
+ * Represents a group of cursor occurrences representing a cursor instance's
46
+ * movement when a player places their finger on the screen.
47
+ */
18
48
  declare class CursorOccurrenceGroup {
49
+ /**
50
+ * The cursor occurrence of movement type `movementType.DOWN`.
51
+ */
19
52
  get down(): CursorOccurrence;
53
+ /**
54
+ * The cursor occurrence of movement type `movementType.DOWN`.
55
+ */
20
56
  set down(value: CursorOccurrence);
57
+ /**
58
+ * The cursor occurrences of movement type `movementType.MOVE`.
59
+ */
21
60
  get moves(): readonly CursorOccurrence[];
61
+ /**
62
+ * The cursor occurrence of movement type `movementType.UP`.
63
+ *
64
+ * May not exist, such as when the player holds their cursor until the end of a beatmap.
65
+ */
22
66
  get up(): CursorOccurrence | undefined;
67
+ /**
68
+ * The cursor occurrence of movement type `movementType.UP`.
69
+ *
70
+ * May not exist, such as when the player holds their cursor until the end of a beatmap.
71
+ */
23
72
  set up(value: CursorOccurrence | undefined);
73
+ /**
74
+ * The time at which this cursor occurrence group starts.
75
+ */
24
76
  get startTime(): number;
77
+ /**
78
+ * The time at which this cursor occurrence group ends.
79
+ */
25
80
  get endTime(): number;
81
+ /**
82
+ * The duration this cursor occurrence group is active for.
83
+ */
26
84
  get duration(): number;
85
+ /**
86
+ * All cursor occurrences in this group.
87
+ *
88
+ * This iterates all occurrences and as such should be used sparingly or stored locally.
89
+ */
27
90
  get allOccurrences(): CursorOccurrence[];
91
+ /**
92
+ * The cursor occurrence of movement type `movementType.DOWN`.
93
+ */
28
94
  private _down;
95
+ /**
96
+ * The cursor occurrences of movement type `movementType.MOVE`.
97
+ */
29
98
  private _moves;
99
+ /**
100
+ * The cursor occurrence of movement type `movementType.UP`.
101
+ *
102
+ * May not exist, such as when the player holds their cursor until the end of a beatmap.
103
+ */
30
104
  private _up?;
31
105
  constructor(down: CursorOccurrence, moves: CursorOccurrence[], up?: CursorOccurrence);
106
+ /**
107
+ * Determines whether this cursor occurrence group is active at the specified time.
108
+ *
109
+ * @param time The time.
110
+ * @returns Whether this cursor occurrence group is active at the specified time.
111
+ */
32
112
  isActiveAt(time: number): boolean;
113
+ /**
114
+ * Finds the cursor occurrence that is active at a given time.
115
+ *
116
+ * @param time The time.
117
+ * @returns The cursor occurrence at the given time, `null` if not found.
118
+ */
33
119
  cursorAt(time: number): CursorOccurrence | null;
34
120
  }
35
121
 
122
+ /**
123
+ * Contains information about a cursor instance.
124
+ */
36
125
  interface CursorInformation {
126
+ /**
127
+ * The movement size of the cursor instance.
128
+ */
37
129
  size: number;
130
+ /**
131
+ * The time during which this cursor instance is active in milliseconds.
132
+ */
38
133
  time: number[];
134
+ /**
135
+ * The x coordinates of this cursor instance in osu!pixels.
136
+ */
39
137
  x: number[];
138
+ /**
139
+ * The y coordinates of this cursor instance in osu!pixels.
140
+ */
40
141
  y: number[];
142
+ /**
143
+ * The hit results of this cursor instance.
144
+ */
41
145
  id: MovementType[];
42
146
  }
147
+ /**
148
+ * Represents a cursor instance in an osu!droid replay.
149
+ *
150
+ * Stores cursor movement data in the form of `CursorOccurrenceGroup`s.
151
+ *
152
+ * This is used when analyzing replays using replay analyzer.
153
+ */
43
154
  declare class CursorData {
155
+ /**
156
+ * The occurrence groups of this cursor instance.
157
+ */
44
158
  occurrenceGroups: CursorOccurrenceGroup[];
159
+ /**
160
+ * The time at which the first occurrence of this cursor instance occurs.
161
+ *
162
+ * Will return `null` if there are no occurrences.
163
+ */
45
164
  get earliestOccurrenceTime(): number | null;
165
+ /**
166
+ * The time at which the latest occurrence of this cursor instance occurs.
167
+ *
168
+ * Will return `null` if there are no occurrences.
169
+ */
46
170
  get latestOccurrenceTime(): number | null;
171
+ /**
172
+ * The amount of cursor occurrences of this cursor instance.
173
+ */
47
174
  get totalOccurrences(): number;
175
+ /**
176
+ * All cursor occurrences of this cursor instnace.
177
+ *
178
+ * This iterates all occurrence groups and as such should be used sparingly or stored locally.
179
+ */
48
180
  get allOccurrences(): CursorOccurrence[];
49
181
  constructor(values: CursorInformation);
50
182
  }
51
183
 
184
+ /**
185
+ * Represents an exported replay's JSON structure.
186
+ */
52
187
  interface ExportedReplayJSON {
188
+ /**
189
+ * The version of the exported replay.
190
+ */
53
191
  version: number;
192
+ /**
193
+ * Data of the exported replay.
194
+ */
54
195
  replaydata: {
196
+ /**
197
+ * The path towards the beatmap's `.osu` file from the song directory of the game.
198
+ */
55
199
  filename: string;
200
+ /**
201
+ * The name of the player.
202
+ */
56
203
  playername: string;
204
+ /**
205
+ * The name of the replay file.
206
+ */
57
207
  replayfile: string;
208
+ /**
209
+ * Droid modifications that are used in the replay.
210
+ */
58
211
  mod: string;
212
+ /**
213
+ * The amount of total score achieved.
214
+ */
59
215
  score: number;
216
+ /**
217
+ * The maximum combo achieved.
218
+ */
60
219
  combo: number;
220
+ /**
221
+ * The rank achieved in the replay.
222
+ */
61
223
  mark: string;
224
+ /**
225
+ * The amount of geki hits in the replay.
226
+ */
62
227
  h300k: number;
228
+ /**
229
+ * The amount of great hits in the replay.
230
+ */
63
231
  h300: number;
232
+ /**
233
+ * The amount of katu hits in the replay.
234
+ */
64
235
  h100k: number;
236
+ /**
237
+ * The amount of good hits in the replay.
238
+ */
65
239
  h100: number;
240
+ /**
241
+ * The amount of meh hits in the replay.
242
+ */
66
243
  h50: number;
244
+ /**
245
+ * The amount of misses in the replay.
246
+ */
67
247
  misses: number;
248
+ /**
249
+ * Accuracy gained in the replay.
250
+ */
68
251
  accuracy: number;
252
+ /**
253
+ * The epoch date at which the score was set, in milliseconds.
254
+ */
69
255
  time: number;
256
+ /**
257
+ * Whether the score is a full combo (1 is `true`, 0 is `false`).
258
+ */
70
259
  perfect: number;
71
260
  };
72
261
  }
73
262
 
263
+ /**
264
+ * The result of a hit in an osu!droid replay.
265
+ */
74
266
  declare enum HitResult {
267
+ /**
268
+ * Miss (0).
269
+ */
75
270
  miss = 1,
271
+ /**
272
+ * Meh (50).
273
+ */
76
274
  meh = 2,
275
+ /**
276
+ * Good (100).
277
+ */
77
278
  good = 3,
279
+ /**
280
+ * Great (300).
281
+ */
78
282
  great = 4
79
283
  }
80
284
 
285
+ /**
286
+ * Represents a hitobject in an osu!droid replay.
287
+ *
288
+ * Stores information about hitobjects in an osu!droid replay such as hit offset, tickset, and hit result.
289
+ *
290
+ * This is used when analyzing replays using replay analyzer.
291
+ */
81
292
  declare class ReplayObjectData {
293
+ /**
294
+ * For circles, this is the offset at which the circle was hit. If the hit accuracy is 10000, it means the circle was tapped too late ([game source code](https://github.com/osudroid/osu-droid/blob/6306c68e3ffaf671eac794bf45cc95c0f3313a82/src/ru/nsu/ccfit/zuev/osu/game/HitCircle.java#L298-L306)).
295
+ *
296
+ * For sliders, this is the offset at which the slider head was hit. For
297
+ * sliderbreaks, the accuracy would be `Math.floor(<hit window 50>ms) + 13ms` ([game source code](https://github.com/osudroid/osu-droid/blob/6306c68e3ffaf671eac794bf45cc95c0f3313a82/src/ru/nsu/ccfit/zuev/osu/game/Slider.java#L821)).
298
+ *
299
+ * For spinners, this is the total amount at which the spinner was spinned:
300
+ * ```js
301
+ * const rotations = Math.floor(data.accuracy / 4);
302
+ * ```
303
+ * The remainder of the division denotes the hit result of the spinner:
304
+ * - `HitResult.great`: 3
305
+ * - `HitResult.good`: 2
306
+ * - `HitResult.meh`: 1
307
+ * - `HitResult.miss`: 0
308
+ */
82
309
  accuracy: number;
310
+ /**
311
+ * The tickset of the hitobject.
312
+ *
313
+ * This is used to determine whether or not a slider event (tick, repeat, and end) is hit based on the order they appear.
314
+ */
83
315
  tickset: boolean[];
316
+ /**
317
+ * The bitwise hit result of the hitobject.
318
+ */
84
319
  result: HitResult;
85
320
  constructor(values: {
321
+ /**
322
+ * The offset of which the hitobject was hit in milliseconds.
323
+ */
86
324
  accuracy: number;
325
+ /**
326
+ * The tickset of the hitobject.
327
+ *
328
+ * This is used to determine whether or not a slider event (tick/repeat/end) is hit based on the order they appear.
329
+ */
87
330
  tickset: boolean[];
331
+ /**
332
+ * The bitwise hit result of the hitobject.
333
+ */
88
334
  result: HitResult;
89
335
  });
90
336
  }
91
337
 
338
+ /**
339
+ * Contains information about a replay.
340
+ */
92
341
  interface ReplayInformation {
342
+ /**
343
+ * The version of the replay.
344
+ */
93
345
  replayVersion: number;
346
+ /**
347
+ * The folder name containing the beatmap played.
348
+ */
94
349
  folderName: string;
350
+ /**
351
+ * The file name of the beatmap played.
352
+ */
95
353
  fileName: string;
354
+ /**
355
+ * The MD5 hash of the beatmap played.
356
+ */
96
357
  hash: string;
358
+ /**
359
+ * The date of which the play was set.
360
+ *
361
+ * Only available in replay v3 or later.
362
+ */
97
363
  time?: Date;
364
+ /**
365
+ * The amount of geki and 300 katu achieved in the play. See {@link https://osu.ppy.sh/help/wiki/Score this} osu! wiki page for more information.
366
+ *
367
+ * Only available in replay v3 or later.
368
+ *
369
+ * If `beatmap` is defined in analyzer (either in `Beatmap` or `DroidDifficultyCalculator` instance), this will be analyzed using beatmap hitobject information and replay hitobject data for replay v1 and v2.
370
+ */
98
371
  hit300k?: number;
372
+ /**
373
+ * The amount of 100 katu achieved in the play. See {@link https://osu.ppy.sh/help/wiki/Score this} osu! wiki page for more information.
374
+ *
375
+ * Only available in replay v3 or later.
376
+ *
377
+ * If `beatmap` is defined in analyzer (either in `Beatmap` or `DroidDifficultyCalculator` instance), this will be analyzed using beatmap hitobject information and replay hitobject data for replay v1 and v2.
378
+ */
99
379
  hit100k?: number;
380
+ /**
381
+ * The total score achieved in the play.
382
+ *
383
+ * Only available in replay v3 or later.
384
+ */
100
385
  score?: number;
386
+ /**
387
+ * The maximum combo achieved in the play.
388
+ *
389
+ * Only available in replay v3 or later.
390
+ */
101
391
  maxCombo?: number;
392
+ /**
393
+ * The accuracy achieved in the play.
394
+ */
102
395
  accuracy: Accuracy;
396
+ /**
397
+ * Whether or not the play achieved the beatmap's maximum combo.
398
+ *
399
+ * Only available in replay v3 or later.
400
+ */
103
401
  isFullCombo?: boolean;
402
+ /**
403
+ * The name of the player in the replay.
404
+ *
405
+ * Only available in replay v3 or later.
406
+ */
104
407
  playerName?: string;
408
+ /**
409
+ * Enabled modifications during the play in raw Java object format.
410
+ *
411
+ * Only available in replay v3 or later.
412
+ */
105
413
  rawMods?: string;
414
+ /**
415
+ * The achieved rank in the play.
416
+ */
106
417
  rank: string;
418
+ /**
419
+ * Enabled modifications during the play in osu!standard format.
420
+ *
421
+ * Only available in replay v3 or later.
422
+ */
107
423
  convertedMods?: (Mod & IModApplicableToDroid)[];
424
+ /**
425
+ * The speed multiplier of the replay.
426
+ *
427
+ * Only available in replay v4 or later. By default this is 1.
428
+ */
108
429
  speedMultiplier?: number;
430
+ /**
431
+ * The force CS of the replay.
432
+ *
433
+ * Only available in replay v5 or later.
434
+ */
109
435
  forceCS?: number;
436
+ /**
437
+ * The force AR of the replay.
438
+ *
439
+ * Only available in replay v4 or later.
440
+ */
110
441
  forceAR?: number;
442
+ /**
443
+ * The force OD of the replay.
444
+ *
445
+ * Only available in replay v5 or later.
446
+ */
111
447
  forceOD?: number;
448
+ /**
449
+ * The force HP of the replay.
450
+ *
451
+ * Only available in replay v5 or later.
452
+ */
112
453
  forceHP?: number;
454
+ /**
455
+ * The follow delay set for the FL mod, in seconds.
456
+ *
457
+ * Only available in replay v5 orlater. By default this is 0.12.
458
+ */
113
459
  flashlightFollowDelay?: number;
460
+ /**
461
+ * The cursor movement data of the replay.
462
+ */
114
463
  cursorMovement: CursorData[];
464
+ /**
465
+ * The hit object data of the replay.
466
+ */
115
467
  hitObjectData: ReplayObjectData[];
116
468
  }
469
+ /**
470
+ * Represents a replay data in an osu!droid replay.
471
+ *
472
+ * Stores generic information about an osu!droid replay such as player name, MD5 hash, time set, etc.
473
+ *
474
+ * This is used when analyzing replays using replay analyzer.
475
+ */
117
476
  declare class ReplayData implements ReplayInformation {
118
477
  readonly replayVersion: number;
119
478
  readonly folderName: string;
@@ -141,38 +500,162 @@ declare class ReplayData implements ReplayInformation {
141
500
  constructor(values: ReplayInformation);
142
501
  }
143
502
 
503
+ /**
504
+ * Information about the result of a three-finger check.
505
+ */
144
506
  interface ThreeFingerInformation {
507
+ /**
508
+ * Whether the beatmap is three-fingered.
509
+ */
145
510
  readonly is3Finger: boolean;
511
+ /**
512
+ * The final penalty. By default this is 1.
513
+ */
146
514
  readonly penalty: number;
147
515
  }
148
516
 
517
+ /**
518
+ * Utility to check whether or not a beatmap is three-fingered for rebalance scores.
519
+ */
149
520
  declare class RebalanceThreeFingerChecker {
521
+ /**
522
+ * The beatmap that is being analyzed.
523
+ */
150
524
  readonly beatmap: Beatmap;
525
+ /**
526
+ * The data of the replay.
527
+ */
151
528
  readonly data: ReplayData;
529
+ /**
530
+ * The difficulty attributes of the beatmap.
531
+ */
152
532
  readonly difficultyAttributes: ExtendedDroidDifficultyAttributes;
533
+ /**
534
+ * The hitobjects to be analyzed.
535
+ *
536
+ * This is being maintained separately due to possible change in object scale.
537
+ */
153
538
  private readonly hitObjects;
539
+ /**
540
+ * The ratio threshold between non-3 finger cursors and 3-finger cursors.
541
+ *
542
+ * Increasing this number will increase detection accuracy, however
543
+ * it also increases the chance of falsely flagged plays.
544
+ */
154
545
  private readonly threeFingerRatioThreshold;
546
+ /**
547
+ * Extended sections of the beatmap for drag detection.
548
+ */
155
549
  private readonly beatmapSections;
550
+ /**
551
+ * The hit window of this beatmap. Keep in mind that speed-changing mods do not change hit window length in game logic.
552
+ */
156
553
  private readonly hitWindow;
554
+ /**
555
+ * A reprocessed break points to match right on object time.
556
+ *
557
+ * This is used to increase detection accuracy since break points do not start right at the
558
+ * start of the hitobject before it and do not end right at the first hitobject after it.
559
+ */
157
560
  private readonly breakPointAccurateTimes;
561
+ /**
562
+ * A cursor occurrence nested array that only contains `movementType.DOWN` movement ID occurrences.
563
+ *
564
+ * Each index represents the cursor index.
565
+ */
158
566
  private readonly downCursorInstances;
567
+ /**
568
+ * Nerf factors from all sections that were three-fingered.
569
+ */
159
570
  private readonly nerfFactors;
571
+ /**
572
+ * Whether this score uses the Precise mod.
573
+ */
160
574
  private readonly isPrecise;
575
+ /**
576
+ * @param beatmap The beatmap to analyze.
577
+ * @param data The data of the replay.
578
+ * @param difficultyAttributes The difficulty attributes of the beatmap.
579
+ */
161
580
  constructor(beatmap: Beatmap, data: ReplayData, difficultyAttributes: ExtendedDroidDifficultyAttributes);
581
+ /**
582
+ * Checks whether a beatmap is eligible to be detected for 3-finger.
583
+ *
584
+ * @param difficultyAttributes The difficulty attributes of the beatmap.
585
+ */
162
586
  static isEligibleToDetect(difficultyAttributes: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes): boolean;
587
+ /**
588
+ * Checks if the given beatmap is 3-fingered and also returns the final penalty.
589
+ *
590
+ * The beatmap will be separated into sections and each section will be determined
591
+ * whether or not it is dragged.
592
+ *
593
+ * After that, each section will be assigned a nerf factor based on whether or not
594
+ * the section is 3-fingered. These nerf factors will be summed up into a final
595
+ * nerf factor, taking beatmap difficulty into account.
596
+ */
163
597
  check(): ThreeFingerInformation;
598
+ /**
599
+ * Generates a new set of "accurate break points".
600
+ *
601
+ * This is done to increase detection accuracy since break points do not start right at the
602
+ * end of the hitobject before it and do not end right at the first hitobject after it.
603
+ */
164
604
  private getAccurateBreakPoints;
605
+ /**
606
+ * Filters the original cursor instances, returning only those with `movementType.DOWN` movement ID.
607
+ *
608
+ * This also filters cursors that are in break period or happen before start/after end of the beatmap.
609
+ */
165
610
  private filterCursorInstances;
611
+ /**
612
+ * Divides the beatmap into sections, which will be used to
613
+ * detect dragged sections and improve detection speed.
614
+ */
166
615
  private getBeatmapSections;
616
+ /**
617
+ * Obtains the index of the nearest cursor of which an object was pressed in terms of time.
618
+ *
619
+ * @param object The object to obtain the index for.
620
+ * @param objectData The hit data of the object.
621
+ * @param cursorLookupIndices The cursor indices to start looking for the cursor from, to save computation time.
622
+ * @param excludedIndices The cursor indices that should not be checked.
623
+ * @returns The index of the cursor, -1 if the object was missed or it's a spinner.
624
+ */
167
625
  private getObjectPressIndex;
626
+ /**
627
+ * Checks if a section is dragged and returns the index of the drag finger.
628
+ *
629
+ * If the section is not dragged, -1 will be returned.
630
+ *
631
+ * @param section The section to check.
632
+ */
168
633
  private findDragIndex;
634
+ /**
635
+ * Creates nerf factors by scanning through objects.
636
+ */
169
637
  private calculateNerfFactors;
638
+ /**
639
+ * Calculates the final penalty.
640
+ */
170
641
  private calculateFinalPenalty;
171
642
  }
172
643
 
644
+ /**
645
+ * Information about the result of a slider cheese check.
646
+ */
173
647
  interface SliderCheeseInformation {
648
+ /**
649
+ * The value used to penalize the aim performance value, from 0 to 1.
650
+ */
174
651
  aimPenalty: number;
652
+ /**
653
+ * The value used to penalize the flashlight performance value, from 0 to 1.
654
+ */
175
655
  flashlightPenalty: number;
656
+ /**
657
+ * The value used to penalize the visual performance value, from 0 to 1.
658
+ */
176
659
  visualPenalty: number;
177
660
  }
178
661
 
@@ -181,21 +664,73 @@ interface HitErrorInformation {
181
664
  positiveAvg: number;
182
665
  unstableRate: number;
183
666
  }
667
+ /**
668
+ * A replay analyzer that analyzes a replay from osu!droid.
669
+ *
670
+ * Created by reverse engineering the replay parser from the game itself, which can be found {@link https://github.com/osudroid/osu-droid/blob/master/src/ru/nsu/ccfit/zuev/osu/scoring/Replay.java here}.
671
+ *
672
+ * Once analyzed, the result can be accessed via the `data` property.
673
+ */
184
674
  declare class ReplayAnalyzer {
675
+ /**
676
+ * The score ID of the replay.
677
+ */
185
678
  scoreID: number;
679
+ /**
680
+ * The original odr file of the replay.
681
+ */
186
682
  originalODR: Buffer | null;
683
+ /**
684
+ * The fixed odr file of the replay.
685
+ */
187
686
  fixedODR: Buffer | null;
687
+ /**
688
+ * Whether or not the play is considered using >=3 finger abuse.
689
+ */
188
690
  is3Finger?: boolean;
691
+ /**
692
+ * Whether or not the play is considered 2-handed.
693
+ */
189
694
  is2Hand?: boolean;
695
+ /**
696
+ * The beatmap that is being analyzed. `DroidDifficultyCalculator` or `RebalanceDroidDifficultyCalculator` is required for three finger or two hand analyzing.
697
+ */
190
698
  beatmap?: Beatmap | DroidDifficultyCalculator | DroidDifficultyCalculator$1;
699
+ /**
700
+ * The difficulty attributes of the beatmap.
701
+ */
191
702
  difficultyAttributes?: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes;
703
+ /**
704
+ * The results of the analyzer. `null` when initialized.
705
+ */
192
706
  data: ReplayData | null;
707
+ /**
708
+ * Penalty value used to penalize dpp for 2-hand.
709
+ */
193
710
  aimPenalty: number;
711
+ /**
712
+ * Penalty value used to penalize dpp for 3 finger abuse.
713
+ */
194
714
  tapPenalty: number;
715
+ /**
716
+ * Penalty values used to penalize dpp for slider cheesing.
717
+ */
195
718
  sliderCheesePenalty: SliderCheeseInformation;
719
+ /**
720
+ * Whether this replay has been checked against 3 finger usage.
721
+ */
196
722
  hasBeenCheckedFor3Finger: boolean;
723
+ /**
724
+ * Whether this replay has been checked against 2 hand usage.
725
+ */
197
726
  hasBeenCheckedFor2Hand: boolean;
727
+ /**
728
+ * Whether this replay has been checked against slider cheesing.
729
+ */
198
730
  hasBeenCheckedForSliderCheesing: boolean;
731
+ /**
732
+ * The amount of two-handed objects.
733
+ */
199
734
  twoHandedNoteCount: number;
200
735
  private convertedBeatmap?;
201
736
  private readonly BYTE_LENGTH;
@@ -204,78 +739,355 @@ declare class ReplayAnalyzer {
204
739
  private readonly FLOAT_LENGTH;
205
740
  private readonly LONG_LENGTH;
206
741
  constructor(values: {
742
+ /**
743
+ * The ID of the score.
744
+ */
207
745
  scoreID: number;
746
+ /**
747
+ * The beatmap to analyze.
748
+ *
749
+ * `DroidDifficultyCalculator` or `RebalanceDroidDifficultyCalculator` is required for two hand and slider cheese analyzing.
750
+ */
208
751
  map?: Beatmap | DroidDifficultyCalculator | DroidDifficultyCalculator$1;
752
+ /**
753
+ * The difficulty attributes.
754
+ *
755
+ * If `map` is defined as `DroidDifficultyCalculator` or `RebalanceDroidDifficultyCalculator`, the difficulty attributes will be obtained from it instead.
756
+ */
209
757
  difficultyAttributes?: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes;
210
758
  });
759
+ /**
760
+ * Analyzes a replay.
761
+ */
211
762
  analyze(): Promise<ReplayAnalyzer>;
763
+ /**
764
+ * Downloads the given score ID's replay.
765
+ */
212
766
  private downloadReplay;
767
+ /**
768
+ * Decompresses a replay.
769
+ *
770
+ * The decompressed replay is in a form of Java object. This will be converted to a buffer and deserialized to read data from the replay.
771
+ */
213
772
  private decompress;
773
+ /**
774
+ * Parses a replay after being downloaded and converted to a buffer.
775
+ */
214
776
  private parseReplay;
777
+ /**
778
+ * Gets hit error information of the replay.
779
+ *
780
+ * `analyze()` must be called before calling this.
781
+ */
215
782
  calculateHitError(): HitErrorInformation | null;
783
+ /**
784
+ * Converts replay mods to droid mod string.
785
+ */
216
786
  private convertDroidMods;
787
+ /**
788
+ * Checks if a play is using 3 fingers.
789
+ *
790
+ * Requires `analyze()` to be called first and `map` and `difficultyAttributes` to be defined.
791
+ */
217
792
  checkFor3Finger(): void;
793
+ /**
794
+ * Checks if a play is using 2 hands.
795
+ *
796
+ * Requires `analyze()` to be called first and `map` to be defined as `DroidDifficultyCalculator`.
797
+ */
218
798
  checkFor2Hand(): void;
799
+ /**
800
+ * Checks if a play has cheesed sliders.
801
+ *
802
+ * Requires `analyze()` to be called first and `map` and `difficultyAttributes` to be defined.
803
+ */
219
804
  checkForSliderCheesing(): void;
220
805
  }
221
806
 
807
+ /**
808
+ * Utility to check whether relevant sliders in a beatmap are cheesed.
809
+ */
222
810
  declare class SliderCheeseChecker {
811
+ /**
812
+ * The beatmap that is being analyzed.
813
+ */
223
814
  readonly beatmap: Beatmap;
815
+ /**
816
+ * The data of the replay.
817
+ */
224
818
  readonly data: ReplayData;
819
+ /**
820
+ * The difficulty attributes of the beatmap.
821
+ */
225
822
  readonly difficultyAttributes: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes;
823
+ /**
824
+ * The 50 osu!droid hit window of the analyzed beatmap.
825
+ */
226
826
  private readonly hitWindow50;
827
+ /**
828
+ * @param beatmap The beatmap to analyze.
829
+ * @param data The data of the replay.
830
+ * @param difficultyAttributes The difficulty attributes of the beatmap.
831
+ */
227
832
  constructor(beatmap: Beatmap, data: ReplayData, difficultyAttributes: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes);
833
+ /**
834
+ * Checks if relevant sliders in the given beatmap was cheesed.
835
+ */
228
836
  check(): SliderCheeseInformation;
837
+ /**
838
+ * Checks for sliders that were cheesed.
839
+ */
229
840
  private checkSliderCheesing;
841
+ /**
842
+ * Calculates the slider cheese penalty.
843
+ */
230
844
  private calculateSliderCheesePenalty;
231
845
  }
232
846
 
847
+ /**
848
+ * Utility to check whether or not a beatmap is three-fingered.
849
+ */
233
850
  declare class ThreeFingerChecker {
851
+ /**
852
+ * The beatmap that is being analyzed.
853
+ */
234
854
  readonly beatmap: Beatmap;
855
+ /**
856
+ * The data of the replay.
857
+ */
235
858
  readonly data: ReplayData;
859
+ /**
860
+ * The difficulty attributes of the beatmap.
861
+ */
236
862
  readonly difficultyAttributes: ExtendedDroidDifficultyAttributes$1;
863
+ /**
864
+ * The distance threshold between cursors to assume that two cursors are
865
+ * actually pressed with 1 finger in osu!pixels.
866
+ *
867
+ * This is used to prevent cases where a player would lift their finger
868
+ * too fast to the point where the 4th cursor instance or beyond is recorded
869
+ * as 1st, 2nd, or 3rd cursor instance.
870
+ */
237
871
  private readonly cursorDistancingDistanceThreshold;
872
+ /**
873
+ * The threshold for the amount of cursors that are assumed to be pressed
874
+ * by a single finger.
875
+ */
238
876
  private readonly cursorDistancingCountThreshold;
877
+ /**
878
+ * The threshold for the time difference of cursors that are assumed to be pressed
879
+ * by a single finger, in milliseconds.
880
+ */
239
881
  private readonly cursorDistancingTimeThreshold;
882
+ /**
883
+ * The amount of notes that has a tap strain exceeding `strainThreshold`.
884
+ */
240
885
  private readonly strainNoteCount;
886
+ /**
887
+ * The ratio threshold between non-3 finger cursors and 3-finger cursors.
888
+ *
889
+ * Increasing this number will increase detection accuracy, however
890
+ * it also increases the chance of falsely flagged plays.
891
+ */
241
892
  private readonly threeFingerRatioThreshold;
893
+ /**
894
+ * Extended sections of the beatmap for drag detection.
895
+ */
242
896
  private readonly beatmapSections;
897
+ /**
898
+ * This threshold is used to filter out accidental taps.
899
+ *
900
+ * Increasing this number makes the filtration more sensitive, however it
901
+ * will also increase the chance of 3-fingered plays getting out from
902
+ * being flagged.
903
+ */
243
904
  private readonly accidentalTapThreshold;
905
+ /**
906
+ * The hit window of this beatmap. Keep in mind that speed-changing mods do not change hit window length in game logic.
907
+ */
244
908
  private readonly hitWindow;
909
+ /**
910
+ * A reprocessed break points to match right on object time.
911
+ *
912
+ * This is used to increase detection accuracy since break points do not start right at the
913
+ * start of the hitobject before it and do not end right at the first hitobject after it.
914
+ */
245
915
  private readonly breakPointAccurateTimes;
916
+ /**
917
+ * A cursor occurrence nested array that only contains `movementType.DOWN` movement ID occurrences.
918
+ *
919
+ * Each index represents the cursor index.
920
+ */
246
921
  private readonly downCursorInstances;
922
+ /**
923
+ * Nerf factors from all sections that were three-fingered.
924
+ */
247
925
  private readonly nerfFactors;
926
+ /**
927
+ * Whether this score uses the Precise mod.
928
+ */
248
929
  private readonly isPrecise;
930
+ /**
931
+ * @param beatmap The beatmap to analyze.
932
+ * @param data The data of the replay.
933
+ * @param difficultyAttributes The difficulty attributes of the beatmap.
934
+ */
249
935
  constructor(beatmap: Beatmap, data: ReplayData, difficultyAttributes: ExtendedDroidDifficultyAttributes$1);
936
+ /**
937
+ * Checks whether a beatmap is eligible to be detected for 3-finger.
938
+ *
939
+ * @param difficultyAttributes The difficulty attributes of the beatmap.
940
+ */
250
941
  static isEligibleToDetect(difficultyAttributes: ExtendedDroidDifficultyAttributes$1 | ExtendedDroidDifficultyAttributes): boolean;
942
+ /**
943
+ * Checks if the given beatmap is 3-fingered and also returns the final penalty.
944
+ *
945
+ * The beatmap will be separated into sections and each section will be determined
946
+ * whether or not it is dragged.
947
+ *
948
+ * After that, each section will be assigned a nerf factor based on whether or not
949
+ * the section is 3-fingered. These nerf factors will be summed up into a final
950
+ * nerf factor, taking beatmap difficulty into account.
951
+ */
251
952
  check(): ThreeFingerInformation;
953
+ /**
954
+ * Generates a new set of "accurate break points".
955
+ *
956
+ * This is done to increase detection accuracy since break points do not start right at the
957
+ * start of the hitobject before it and do not end right at the first hitobject after it.
958
+ */
252
959
  private getAccurateBreakPoints;
960
+ /**
961
+ * Filters the original cursor instances, returning only those with `movementType.DOWN` movement ID.
962
+ *
963
+ * This also filters cursors that are in break period or happen before start/after end of the beatmap.
964
+ */
253
965
  private filterCursorInstances;
966
+ /**
967
+ * Divides the beatmap into sections, which will be used to
968
+ * detect dragged sections and improve detection speed.
969
+ */
254
970
  private getBeatmapSections;
971
+ /**
972
+ * Checks whether or not each beatmap sections is dragged.
973
+ */
255
974
  private detectDragPlay;
975
+ /**
976
+ * Checks if a section is dragged and returns the index of the drag finger.
977
+ *
978
+ * If the section is not dragged, -1 will be returned.
979
+ *
980
+ * @param section The section to check.
981
+ */
256
982
  private checkDrag;
983
+ /**
984
+ * Finds the drag index of the section.
985
+ *
986
+ * @param sectionObjects The objects in the section.
987
+ * @param sectionReplayObjectData The hitobject data of all objects in the section.
988
+ * @param cursorIndexes The indexes of the cursor instance that has at least an occurrence in the section.
989
+ */
257
990
  private findDragIndex;
991
+ /**
992
+ * Attempts to prevent accidental taps from being flagged.
993
+ *
994
+ * This detection will filter cursors that don't hit
995
+ * any object in beatmap sections, thus eliminating any
996
+ * unnecessary taps.
997
+ */
258
998
  private preventAccidentalTaps;
999
+ /**
1000
+ * Creates nerf factors by scanning through objects.
1001
+ *
1002
+ * This check will ignore all objects with speed strain below `strainThreshold`.
1003
+ */
259
1004
  private calculateNerfFactors;
1005
+ /**
1006
+ * Calculates the final penalty.
1007
+ */
260
1008
  private calculateFinalPenalty;
261
1009
  }
262
1010
 
1011
+ /**
1012
+ * Information about the result of a check.
1013
+ */
263
1014
  interface TwoHandInformation {
1015
+ /**
1016
+ * Whether or not the beatmap is 2-handed.
1017
+ */
264
1018
  readonly is2Hand: boolean;
1019
+ /**
1020
+ * The amount of two-handed objects.
1021
+ */
265
1022
  readonly twoHandedNoteCount: number;
266
1023
  }
1024
+ /**
1025
+ * Utility to check whether or not a beatmap is two-handed.
1026
+ */
267
1027
  declare class TwoHandChecker {
1028
+ /**
1029
+ * The difficulty calculator that is being analyzed.
1030
+ */
268
1031
  readonly calculator: DroidDifficultyCalculator | DroidDifficultyCalculator$1;
1032
+ /**
1033
+ * The data of the replay.
1034
+ */
269
1035
  readonly data: ReplayData;
1036
+ /**
1037
+ * The hitobjects of the beatmap that have been assigned with their respective cursor index.
1038
+ */
270
1039
  private readonly indexedHitObjects;
1040
+ /**
1041
+ * The osu!droid hitwindow of the analyzed beatmap.
1042
+ */
271
1043
  private readonly hitWindow;
1044
+ /**
1045
+ * The 50 osu!droid hit window of the analyzed beatmap.
1046
+ */
272
1047
  private readonly hitWindow50;
1048
+ /**
1049
+ * @param calculator The difficulty calculator to analyze.
1050
+ * @param data The data of the replay.
1051
+ */
273
1052
  constructor(calculator: DroidDifficultyCalculator | DroidDifficultyCalculator$1, data: ReplayData);
1053
+ /**
1054
+ * Checks if a beatmap is two-handed.
1055
+ */
274
1056
  check(): TwoHandInformation;
1057
+ /**
1058
+ * Converts hitobjects into indexed hit objects.
1059
+ */
275
1060
  private indexHitObjects;
1061
+ /**
1062
+ * Gets the cursor index that hits the given object.
1063
+ *
1064
+ * @param objectIndex The index of the object to check.
1065
+ * @returns The cursor index that hits the given object, -1 if the index is not found, the object is a spinner, or the object was missed.
1066
+ */
276
1067
  private getIndexedHitObject;
1068
+ /**
1069
+ * Gets the position of the cursor that presses an object.
1070
+ *
1071
+ * @param objectIndex THe index of the object.
1072
+ * @returns The position of the cursor that presses the object.
1073
+ */
277
1074
  private getCursorPositionForObjectStart;
1075
+ /**
1076
+ * Gets the position of the cursor that at an object's end position.
1077
+ *
1078
+ * @param objectIndex THe index of the object.
1079
+ * @returns The position of the cursor at the object's end position.
1080
+ */
278
1081
  private getCursorPositionForObjectEnd;
1082
+ /**
1083
+ * Checks whether a slider was cheesed.
1084
+ *
1085
+ * This is done by checking if a cursor follows a slider all the way to its end position.
1086
+ *
1087
+ * @param indexedHitObject The indexed slider.
1088
+ * @param hitData The hit data of the slider.
1089
+ * @returns Whether the slider was cheesed.
1090
+ */
279
1091
  private checkSliderCheesing;
280
1092
  }
281
1093