@rian8337/osu-difficulty-calculator 4.0.0-beta.90 → 4.0.0-beta.92

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 (3) hide show
  1. package/dist/index.js +3502 -2693
  2. package/package.json +3 -3
  3. package/typings/index.d.ts +1056 -846
@@ -1,115 +1,4 @@
1
- import { ModMap, SerializedMod, PlaceableHitObject, Vector2, Modes, PlayableBeatmap, Mod, Beatmap, DroidPlayableBeatmap, Accuracy, OsuPlayableBeatmap } from '@rian8337/osu-base';
2
-
3
- /**
4
- * Holds data that can be used to calculate performance points.
5
- */
6
- interface IDifficultyAttributes {
7
- /**
8
- * The mods which were applied to the beatmap.
9
- */
10
- mods: ModMap;
11
- /**
12
- * The combined star rating of all skills.
13
- */
14
- starRating: number;
15
- /**
16
- * The maximum achievable combo.
17
- */
18
- maxCombo: number;
19
- /**
20
- * The difficulty corresponding to the aim skill.
21
- */
22
- aimDifficulty: number;
23
- /**
24
- * The difficulty corresponding to the flashlight skill.
25
- */
26
- flashlightDifficulty: number;
27
- /**
28
- * The number of clickable objects weighted by difficulty.
29
- *
30
- * Related to speed/tap difficulty.
31
- */
32
- speedNoteCount: number;
33
- /**
34
- * Describes how much of aim difficulty is contributed to by hitcircles or sliders.
35
- *
36
- * A value closer to 1 indicates most of aim difficulty is contributed by hitcircles.
37
- *
38
- * A value closer to 0 indicates most of aim difficulty is contributed by sliders.
39
- */
40
- sliderFactor: number;
41
- /**
42
- * The overall clock rate that was applied to the beatmap.
43
- */
44
- clockRate: number;
45
- /**
46
- * The perceived overall difficulty **exclusive** of rate-adjusting mods (DT/HT/etc).
47
- *
48
- * Rate-adjusting mods don't directly affect the overall difficulty value, but have a perceived effect as a result of adjusting audio timing.
49
- */
50
- overallDifficulty: number;
51
- /**
52
- * The number of hitcircles in the beatmap.
53
- */
54
- hitCircleCount: number;
55
- /**
56
- * The number of sliders in the beatmap.
57
- */
58
- sliderCount: number;
59
- /**
60
- * The number of spinners in the beatmap.
61
- */
62
- spinnerCount: number;
63
- /**
64
- * The number of sliders weighted by difficulty.
65
- */
66
- aimDifficultSliderCount: number;
67
- /**
68
- * The amount of strains that are considered difficult with respect to the aim skill.
69
- */
70
- aimDifficultStrainCount: number;
71
- }
72
-
73
- /**
74
- * Represents difficulty attributes that can be cached.
75
- */
76
- type CacheableDifficultyAttributes<T extends IDifficultyAttributes> = Omit<T, "mods" | "toCacheableAttributes"> & {
77
- /**
78
- * The mods which were applied to the beatmap.
79
- */
80
- mods: SerializedMod[];
81
- };
82
-
83
- /**
84
- * Holds data that can be used to calculate performance points.
85
- */
86
- declare abstract class DifficultyAttributes implements IDifficultyAttributes {
87
- mods: ModMap;
88
- starRating: number;
89
- maxCombo: number;
90
- aimDifficulty: number;
91
- flashlightDifficulty: number;
92
- speedNoteCount: number;
93
- sliderFactor: number;
94
- clockRate: number;
95
- overallDifficulty: number;
96
- hitCircleCount: number;
97
- sliderCount: number;
98
- spinnerCount: number;
99
- aimDifficultSliderCount: number;
100
- aimDifficultStrainCount: number;
101
- constructor(cacheableAttributes?: CacheableDifficultyAttributes<IDifficultyAttributes>);
102
- /**
103
- * Converts this `DifficultyAttributes` instance to an attribute structure that can be cached.
104
- *
105
- * @returns The cacheable attributes.
106
- */
107
- toCacheableAttributes(): CacheableDifficultyAttributes<this>;
108
- /**
109
- * Returns a string representation of the difficulty attributes.
110
- */
111
- toString(): string;
112
- }
1
+ import { PlaceableHitObject, Vector2, Modes, ModMap, HitResult, HitWindow, SerializedMod, PlayableBeatmap, Mod, Beatmap, Accuracy, DroidPlayableBeatmap, OsuPlayableBeatmap } from '@rian8337/osu-base';
113
2
 
114
3
  /**
115
4
  * Represents a hit object with difficulty calculation values.
@@ -133,10 +22,18 @@ declare abstract class DifficultyHitObject {
133
22
  * The aim strain generated by the hitobject if sliders are not considered.
134
23
  */
135
24
  aimStrainWithoutSliders: number;
25
+ /**
26
+ * The flashlight strain generated by the hitobject.
27
+ */
28
+ flashlightStrain: number;
136
29
  /**
137
30
  * The rhythm multiplier generated by the hitobject. This is used to alter tap strain.
138
31
  */
139
32
  rhythmMultiplier: number;
33
+ /**
34
+ * The normalized distance from the start position of the previous hitobject to the start position of this hitobject.
35
+ */
36
+ jumpDistance: number;
140
37
  /**
141
38
  * The normalized distance from the "lazy" end position of the previous hitobject to the start position of this hitobject.
142
39
  *
@@ -188,7 +85,18 @@ declare abstract class DifficultyHitObject {
188
85
  *
189
86
  * Calculated as the angle between the circles (current-2, current-1, current).
190
87
  */
191
- angle: number | null;
88
+ angleSigned: number | null;
89
+ /**
90
+ * Unsigned angle the player has to take to hit this hitobject.
91
+ *
92
+ * Calculated as the angle between the circles (current-2, current-1, current).
93
+ */
94
+ get angle(): number | null;
95
+ /**
96
+ * Angle of the vector created between current and current-1 normalized to consider
97
+ * symmetrical vectors in any axis to be the same angle.
98
+ */
99
+ normalizedVectorAngle: number | null;
192
100
  /**
193
101
  * The amount of milliseconds elapsed between this hitobject and the last hitobject.
194
102
  */
@@ -197,6 +105,11 @@ declare abstract class DifficultyHitObject {
197
105
  * The amount of milliseconds elapsed since the start time of the previous hitobject, with a minimum of 25ms.
198
106
  */
199
107
  readonly strainTime: number;
108
+ /**
109
+ * The amount of milliseconds elapsed between the last {@link DifficultyHitObject}'s {@link endTime} and
110
+ * this {@link DifficultyHitObject}'s {@link startTime} capped to a minimum of {@link minDeltaTime}ms.
111
+ */
112
+ readonly lastObjectEndDeltaTime: number;
200
113
  /**
201
114
  * Adjusted start time of the hitobject, taking speed multiplier into account.
202
115
  */
@@ -206,13 +119,21 @@ declare abstract class DifficultyHitObject {
206
119
  */
207
120
  readonly endTime: number;
208
121
  /**
209
- * The full great window of the hitobject.
122
+ * Adjusted preempt time of the hitobject, taking speed multiplier into account.
123
+ */
124
+ readonly timePreempt: number;
125
+ /**
126
+ * The beatmap clock rate.
210
127
  */
211
- readonly fullGreatWindow: number;
128
+ readonly clockRate: number;
212
129
  /**
213
130
  * Selective bonus for beatmaps with higher circle size.
214
131
  */
215
132
  abstract get smallCircleBonus(): number;
133
+ /**
134
+ * This {@link DifficultyHitObject}'s immediate overall difficulty value calculated from the raw hitwindow.
135
+ */
136
+ get overallDifficulty(): number;
216
137
  /**
217
138
  * Other hitobjects in the beatmap, including this hitobject.
218
139
  */
@@ -220,14 +141,14 @@ declare abstract class DifficultyHitObject {
220
141
  /**
221
142
  * The normalized radius of the hitobject.
222
143
  */
223
- static readonly normalizedRadius: number;
144
+ abstract readonly normalizedRadius: number;
224
145
  /**
225
146
  * The normalized diameter of the hitobject.
226
147
  */
227
- static get normalizedDiameter(): number;
148
+ get normalizedDiameter(): number;
228
149
  protected abstract readonly mode: Modes;
229
- protected readonly maximumSliderRadius: number;
230
- protected readonly assumedSliderRadius: number;
150
+ protected get maximumSliderRadius(): number;
151
+ protected get assumedSliderRadius(): number;
231
152
  /**
232
153
  * The lowest possible delta time value.
233
154
  */
@@ -278,10 +199,10 @@ declare abstract class DifficultyHitObject {
278
199
  * Calculates the opacity of the hitobject at a given time.
279
200
  *
280
201
  * @param time The time to calculate the hitobject's opacity at.
281
- * @param mods The mods used.
202
+ * @param mods The mods used. Defaults to No Mod.
282
203
  * @returns The opacity of the hitobject at the given time.
283
204
  */
284
- opacityAt(time: number, mods: ModMap): number;
205
+ opacityAt(time: number, mods?: ModMap): number;
285
206
  /**
286
207
  * How possible is it to doubletap this object together with the next one and get perfect
287
208
  * judgement in range from 0 to 1.
@@ -289,154 +210,210 @@ declare abstract class DifficultyHitObject {
289
210
  * A value closer to 1 indicates a higher possibility.
290
211
  */
291
212
  getDoubletapness(nextObj: this | null): number;
292
- protected setDistances(clockRate: number): void;
293
- private calculateSliderCursorPosition;
294
- private getEndCursorPosition;
295
- }
296
-
297
- /**
298
- * A bare minimal abstract skill for fully custom skill implementations.
299
- *
300
- * This class should be considered a "processing" class and not persisted.
301
- */
302
- declare abstract class Skill {
303
- /**
304
- * The mods that this skill processes.
305
- */
306
- protected readonly mods: ModMap;
307
- constructor(mods: ModMap);
308
213
  /**
309
- * Processes a hitobject.
310
- *
311
- * @param current The hitobject to process.
214
+ * Retrieves the full rate-adjusted hit window for a {@link HitResult}.
312
215
  */
313
- abstract process(current: DifficultyHitObject): void;
216
+ hitWindowFor(result: HitResult): number;
314
217
  /**
315
- * Returns the calculated difficulty value representing all hitobjects that have been processed up to this point.
218
+ * The {@link HitWindow} for this {@link DifficultyHitObject}.
316
219
  */
317
- abstract difficultyValue(): number;
220
+ protected get rawHitWindow(): HitWindow;
221
+ private setDistances;
222
+ private calculateAngle;
223
+ private calculateSliderAngle;
224
+ private calculateSliderCursorPosition;
225
+ private getEndCursorPosition;
318
226
  }
319
227
 
320
228
  /**
321
- * Represents the strain peaks of various calculated difficulties.
229
+ * Holds data that can be used to calculate performance points.
322
230
  */
323
- interface StrainPeaks {
324
- /**
325
- * The strain peaks of aim difficulty if sliders are considered.
326
- */
327
- aimWithSliders: readonly number[];
328
- /**
329
- * The strain peaks of aim difficulty if sliders are not considered.
330
- */
331
- aimWithoutSliders: readonly number[];
231
+ interface IDifficultyAttributes {
332
232
  /**
333
- * The strain peaks of speed difficulty.
233
+ * The mods which were applied to the beatmap.
334
234
  */
335
- speed: readonly number[];
235
+ mods: ModMap;
336
236
  /**
337
- * The strain peaks of flashlight difficulty.
237
+ * The combined star rating of all skills.
338
238
  */
339
- flashlight: readonly number[];
340
- }
341
-
342
- /**
343
- * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
344
- * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
345
- */
346
- declare abstract class StrainSkill extends Skill {
239
+ starRating: number;
347
240
  /**
348
- * Strain peaks are stored here.
241
+ * The maximum achievable combo.
349
242
  */
350
- readonly strainPeaks: number[];
243
+ maxCombo: number;
351
244
  /**
352
- * The number of sections with the highest strains, which the peak strain reductions will apply to.
353
- * This is done in order to decrease their impact on the overall difficulty of the map for this skill.
245
+ * The difficulty corresponding to the aim skill.
354
246
  */
355
- protected abstract readonly reducedSectionCount: number;
247
+ aimDifficulty: number;
356
248
  /**
357
- * The baseline multiplier applied to the section with the biggest strain.
249
+ * The difficulty corresponding to the flashlight skill.
358
250
  */
359
- protected abstract readonly reducedSectionBaseline: number;
251
+ flashlightDifficulty: number;
360
252
  /**
361
- * Determines how quickly strain decays for the given skill.
253
+ * The number of clickable objects weighted by difficulty.
362
254
  *
363
- * For example, a value of 0.15 indicates that strain decays to 15% of its original value in one second.
364
- */
365
- protected abstract readonly strainDecayBase: number;
366
- protected readonly _objectStrains: number[];
367
- protected difficulty: number;
368
- /**
369
- * The strains of hitobjects.
255
+ * Related to speed/tap difficulty.
370
256
  */
371
- get objectStrains(): readonly number[];
372
- private readonly sectionLength;
373
- private currentStrain;
374
- private currentSectionPeak;
375
- private currentSectionEnd;
257
+ speedNoteCount: number;
376
258
  /**
377
- * Converts a difficulty value to a performance value.
259
+ * Describes how much of aim difficulty is contributed to by hitcircles or sliders.
378
260
  *
379
- * @param difficulty The difficulty value to convert.
380
- * @returns The performance value.
381
- */
382
- static difficultyToPerformance(difficulty: number): number;
383
- process(current: DifficultyHitObject): void;
384
- /**
385
- * Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
261
+ * A value closer to 1 indicates most of aim difficulty is contributed by hitcircles.
262
+ *
263
+ * A value closer to 0 indicates most of aim difficulty is contributed by sliders.
386
264
  */
387
- saveCurrentPeak(): void;
265
+ sliderFactor: number;
388
266
  /**
389
- * Returns the number of strains weighed against the top strain.
390
- *
391
- * The result is scaled by clock rate as it affects the total number of strains.
267
+ * The overall clock rate that was applied to the beatmap.
392
268
  */
393
- countTopWeightedStrains(): number;
269
+ clockRate: number;
394
270
  /**
395
- * Calculates strain decay for a specified time frame.
271
+ * The perceived overall difficulty **exclusive** of rate-adjusting mods (DT/HT/etc).
396
272
  *
397
- * @param ms The time frame to calculate.
273
+ * Rate-adjusting mods don't directly affect the overall difficulty value, but have a perceived effect as a result of adjusting audio timing.
398
274
  */
399
- protected strainDecay(ms: number): number;
275
+ overallDifficulty: number;
400
276
  /**
401
- * Calculates the starting time of a strain section at an object.
402
- *
403
- * @param current The object at which the strain section starts.
404
- * @returns The start time of the strain section.
277
+ * The number of hitcircles in the beatmap.
405
278
  */
406
- protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
279
+ hitCircleCount: number;
407
280
  /**
408
- * Calculates the strain value at a hitobject.
409
- *
410
- * @param current The hitobject to calculate.
281
+ * The number of sliders in the beatmap.
411
282
  */
412
- protected abstract strainValueAt(current: DifficultyHitObject): number;
283
+ sliderCount: number;
413
284
  /**
414
- * Saves the current strain to a hitobject.
285
+ * The number of spinners in the beatmap.
415
286
  */
416
- protected abstract saveToHitObject(current: DifficultyHitObject): void;
287
+ spinnerCount: number;
417
288
  /**
418
- * Retrieves the peak strain at a point in time.
419
- *
420
- * @param time The time to retrieve the peak strain at.
421
- * @param current The current hit object.
422
- * @returns The peak strain.
289
+ * The number of sliders weighted by difficulty.
423
290
  */
424
- protected abstract calculateInitialStrain(time: number, current: DifficultyHitObject): number;
291
+ aimDifficultSliderCount: number;
425
292
  /**
426
- * Sets the initial strain level for a new section.
427
- *
428
- * @param time The beginning of the new section in milliseconds.
429
- * @param current The current hitobject.
293
+ * The amount of strains that are considered difficult with respect to the aim skill.
430
294
  */
431
- private startNewSectionFrom;
295
+ aimDifficultStrainCount: number;
432
296
  }
433
297
 
434
298
  /**
435
- * The base of a difficulty calculator.
299
+ * Represents difficulty attributes that can be cached.
436
300
  */
437
- declare abstract class DifficultyCalculator<TBeatmap extends PlayableBeatmap, THitObject extends DifficultyHitObject, TAttributes extends DifficultyAttributes> {
301
+ type CacheableDifficultyAttributes<T extends IDifficultyAttributes> = Omit<T, "mods" | "toCacheableAttributes"> & {
438
302
  /**
439
- * `Mod`s that adjust the difficulty of a beatmap.
303
+ * The mods which were applied to the beatmap.
304
+ */
305
+ mods: SerializedMod[];
306
+ };
307
+
308
+ /**
309
+ * Holds data that can be used to calculate performance points.
310
+ */
311
+ declare abstract class DifficultyAttributes implements IDifficultyAttributes {
312
+ mods: ModMap;
313
+ starRating: number;
314
+ maxCombo: number;
315
+ aimDifficulty: number;
316
+ flashlightDifficulty: number;
317
+ speedNoteCount: number;
318
+ sliderFactor: number;
319
+ clockRate: number;
320
+ overallDifficulty: number;
321
+ hitCircleCount: number;
322
+ sliderCount: number;
323
+ spinnerCount: number;
324
+ aimDifficultSliderCount: number;
325
+ aimDifficultStrainCount: number;
326
+ constructor(cacheableAttributes?: CacheableDifficultyAttributes<IDifficultyAttributes>);
327
+ /**
328
+ * Converts this `DifficultyAttributes` instance to an attribute structure that can be cached.
329
+ *
330
+ * @returns The cacheable attributes.
331
+ */
332
+ toCacheableAttributes(): CacheableDifficultyAttributes<this>;
333
+ /**
334
+ * Returns a string representation of the difficulty attributes.
335
+ */
336
+ toString(): string;
337
+ }
338
+
339
+ /**
340
+ * Represents the strain peaks of various calculated difficulties.
341
+ */
342
+ interface StrainPeaks {
343
+ /**
344
+ * The strain peaks of aim difficulty if sliders are considered.
345
+ */
346
+ aimWithSliders: readonly number[];
347
+ /**
348
+ * The strain peaks of aim difficulty if sliders are not considered.
349
+ */
350
+ aimWithoutSliders: readonly number[];
351
+ /**
352
+ * The strain peaks of speed difficulty.
353
+ */
354
+ speed: readonly number[];
355
+ /**
356
+ * The strain peaks of flashlight difficulty.
357
+ */
358
+ flashlight: readonly number[];
359
+ }
360
+
361
+ /**
362
+ * An interface for `Skill`s that have peak difficulties.
363
+ */
364
+ interface IHasPeakDifficulty {
365
+ /**
366
+ * The peak difficulties calculated by this `Skill`.
367
+ */
368
+ get peaks(): readonly number[];
369
+ }
370
+
371
+ /**
372
+ * A bare minimal abstract skill for fully custom skill implementations.
373
+ */
374
+ declare abstract class Skill {
375
+ /**
376
+ * The mods that this skill processes.
377
+ */
378
+ protected readonly mods: ModMap;
379
+ private _objectDifficulties;
380
+ /**
381
+ * The difficulties of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
382
+ */
383
+ protected get objectDifficulties(): readonly number[];
384
+ constructor(mods: ModMap);
385
+ /**
386
+ * Calculates the strain value of a hitobject and stores the value in it.
387
+ * This value is affected by previously processed objects.
388
+ *
389
+ * @param current The hitobject to process.
390
+ */
391
+ process(current: DifficultyHitObject): void;
392
+ /**
393
+ * Returns the calculated difficulty value representing all hitobjects that have been processed up to this point.
394
+ */
395
+ abstract difficultyValue(): number;
396
+ /**
397
+ * Saves the calculated difficulty to a {@link DifficultyHitObject}.
398
+ *
399
+ * @param current The {@link DifficultyHitObject} to save the difficulty to.
400
+ * @param difficulty The difficulty to save.
401
+ */
402
+ protected saveToHitObject(current: DifficultyHitObject, difficulty: number): void;
403
+ /**
404
+ * Calculates the difficulty value of a hitobject and stores the value in it.
405
+ *
406
+ * @param current The hitobject to process.
407
+ */
408
+ protected abstract processInternal(current: DifficultyHitObject): number;
409
+ }
410
+
411
+ /**
412
+ * The base of a difficulty calculator.
413
+ */
414
+ declare abstract class DifficultyCalculator<TBeatmap extends PlayableBeatmap, THitObject extends DifficultyHitObject, TAttributes extends DifficultyAttributes> {
415
+ /**
416
+ * `Mod`s that adjust the difficulty of a beatmap.
440
417
  */
441
418
  protected readonly difficultyAdjustmentMods: (typeof Mod)[];
442
419
  /**
@@ -473,15 +450,16 @@ declare abstract class DifficultyCalculator<TBeatmap extends PlayableBeatmap, TH
473
450
  * Creates the `Skill`s to calculate the difficulty of a `PlayableBeatmap`.
474
451
  *
475
452
  * @param beatmap The `PlayableBeatmap` whose difficulty will be calculated.
476
- * @return The `Skill`s.
453
+ * @returns The `Skill`s.
477
454
  */
478
455
  protected abstract createSkills(beatmap: TBeatmap): Skill[];
479
456
  /**
480
457
  * Creates the `Skill`s to obtain the strain peaks of a `PlayableBeatmap`.
481
458
  *
482
- * @param beatmap
459
+ * @param beatmap The `PlayableBeatmap` whose strain peaks will be calculated.
460
+ * @returns The `Skill`s.
483
461
  */
484
- protected abstract createStrainPeakSkills(beatmap: TBeatmap): StrainSkill[];
462
+ protected abstract createStrainPeakSkills(beatmap: TBeatmap): (Skill & IHasPeakDifficulty)[];
485
463
  /**
486
464
  * Creates difficulty hitobjects for this calculator.
487
465
  *
@@ -492,12 +470,13 @@ declare abstract class DifficultyCalculator<TBeatmap extends PlayableBeatmap, TH
492
470
  /**
493
471
  * Creates a `DifficultyAttributes` object to describe a `PlayableBeatmap`'s difficulty.
494
472
  *
495
- * @param beatmap The `PlayableBeatmap` whose difficulty was calculated.
473
+ * @param beatmap The `Beatmap` whose difficulty was calculated.
474
+ * @param playableBeatmap The `PlayableBeatmap` whose difficulty was calculated.
496
475
  * @param skills The `Skill`s which processed the `PlayableBeatmap`.
497
476
  * @param objects The `DifficultyHitObject`s which were processed.
498
477
  * @returns The `DifficultyAttributes` object.
499
478
  */
500
- protected abstract createDifficultyAttributes(beatmap: TBeatmap, skills: Skill[], objects: THitObject[]): TAttributes;
479
+ protected abstract createDifficultyAttributes(beatmap: Beatmap, playableBeatmap: TBeatmap, skills: Skill[], objects: THitObject[]): TAttributes;
501
480
  /**
502
481
  * Constructs a `PlayableBeatmap` from a `Beatmap` with specific `Mod`s.
503
482
  *
@@ -509,83 +488,159 @@ declare abstract class DifficultyCalculator<TBeatmap extends PlayableBeatmap, TH
509
488
  }
510
489
 
511
490
  /**
512
- * Represents a slider that is considered difficult.
513
- *
514
- * This structure is a part of difficulty attributes and can be cached.
491
+ * Represents options for performance calculation.
515
492
  */
516
- interface DifficultSlider {
493
+ interface PerformanceCalculationOptions {
517
494
  /**
518
- * The index of the slider in the beatmap.
495
+ * The maximum combo achieved in the score.
519
496
  */
520
- readonly index: number;
497
+ combo?: number;
521
498
  /**
522
- * The difficulty rating of this slider compared to other sliders, based on the velocity of the slider.
523
- *
524
- * A value closer to 1 indicates that this slider is more difficult compared to most sliders.
499
+ * The accuracy achieved in the score.
500
+ */
501
+ accPercent?: Accuracy | number;
502
+ /**
503
+ * The amount of misses achieved in the score.
525
504
  *
526
- * A value closer to 0 indicates that this slider is easier compared to most sliders.
505
+ * If {@link accPercent} is provided as an {@link Accuracy} object, this value will be ignored.
527
506
  */
528
- readonly difficultyRating: number;
507
+ miss?: number;
508
+ /**
509
+ * The amount of slider ends dropped in the score.
510
+ */
511
+ sliderEndsDropped?: number;
512
+ /**
513
+ * The amount of slider ticks missed in the score.
514
+ */
515
+ sliderTicksMissed?: number;
516
+ /**
517
+ * The tap penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
518
+ */
519
+ tapPenalty?: number;
520
+ /**
521
+ * The aim slider cheese penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
522
+ */
523
+ sliderCheesePenalty?: number;
524
+ /**
525
+ * The total score achieved in the score.
526
+ */
527
+ totalScore?: number;
529
528
  }
530
529
 
531
530
  /**
532
- * Represents an osu!droid hit object with difficulty calculation values.
531
+ * The base class of performance calculators.
533
532
  */
534
- declare class DroidDifficultyHitObject extends DifficultyHitObject {
533
+ declare abstract class PerformanceCalculator<T extends IDifficultyAttributes> {
535
534
  /**
536
- * The tap strain generated by the hitobject.
535
+ * The overall performance value.
537
536
  */
538
- tapStrain: number;
537
+ total: number;
539
538
  /**
540
- * The tap strain generated by the hitobject if `strainTime` isn't modified by
541
- * OD. This is used in three-finger detection.
539
+ * The calculated accuracy.
542
540
  */
543
- originalTapStrain: number;
541
+ computedAccuracy: Accuracy;
544
542
  /**
545
- * The rhythm strain generated by the hitobject.
543
+ * The calculated maximum combo.
546
544
  */
547
- rhythmStrain: number;
545
+ combo: number;
548
546
  /**
549
- * The flashlight strain generated by the hitobject if sliders are considered.
547
+ * The difficulty attributes that is being calculated.
550
548
  */
551
- flashlightStrainWithSliders: number;
549
+ readonly difficultyAttributes: T | CacheableDifficultyAttributes<T>;
552
550
  /**
553
- * The flashlight strain generated by the hitobject if sliders are not considered.
551
+ * The mods that were used.
554
552
  */
555
- flashlightStrainWithoutSliders: number;
553
+ protected readonly mods: ModMap;
554
+ private _sliderEndsDropped;
556
555
  /**
557
- * The reading difficulty generated by the hitobject.
556
+ * The amount of slider ends dropped in the score.
558
557
  */
559
- readingDifficulty: number;
558
+ protected get sliderEndsDropped(): number;
559
+ private _sliderTicksMissed;
560
+ /**
561
+ * The amount of slider ticks missed in the score.
562
+ *
563
+ * This is used to calculate the slider accuracy.
564
+ */
565
+ protected get sliderTicksMissed(): number;
566
+ private _usingClassicSliderAccuracy;
567
+ /**
568
+ * Whether this score uses classic slider accuracy.
569
+ */
570
+ protected get usingClassicSliderAccuracy(): boolean;
560
571
  /**
561
- * The note density of the hitobject.
572
+ * @param difficultyAttributes The difficulty attributes to calculate.
562
573
  */
563
- noteDensity: number;
574
+ constructor(difficultyAttributes: T | CacheableDifficultyAttributes<T>);
564
575
  /**
565
- * The overlapping factor of the hitobject.
576
+ * Calculates the performance points of the beatmap.
566
577
  *
567
- * This is used to scale visual skill.
578
+ * @param options Options for performance calculation.
579
+ * @returns The current instance.
568
580
  */
569
- overlappingFactor: number;
581
+ calculate(options?: PerformanceCalculationOptions): this;
570
582
  /**
571
- * Adjusted preempt time of the hitobject, taking speed multiplier into account.
583
+ * Returns a string representative of the class.
572
584
  */
573
- readonly timePreempt: number;
574
- private readonly radiusBuffThreshold;
575
- protected readonly mode = Modes.droid;
576
- protected readonly maximumSliderRadius: number;
577
- get smallCircleBonus(): number;
585
+ abstract toString(): string;
578
586
  /**
579
- * Note: You **must** call `computeProperties` at some point due to how TypeScript handles
580
- * overridden properties (see [this](https://github.com/microsoft/TypeScript/issues/1617) GitHub issue).
587
+ * Calculates all values that will be used for calculating the total
588
+ * performance value of the beatmap and stores them in this instance.
589
+ */
590
+ protected abstract calculateValues(): void;
591
+ /**
592
+ * The total hits that can be done in the beatmap.
593
+ */
594
+ protected get totalHits(): number;
595
+ /**
596
+ * The total hits that were successfully done.
597
+ */
598
+ protected get totalSuccessfulHits(): number;
599
+ /**
600
+ * The total of imperfect hits (100s, 50s, misses).
601
+ */
602
+ protected get totalImperfectHits(): number;
603
+ /**
604
+ * Processes given options for usage in performance calculation.
581
605
  *
582
- * @param object The underlying hitobject.
583
- * @param lastObject The hitobject before this hitobject.
584
- * @param difficultyHitObjects All difficulty hitobjects in the processed beatmap.
585
- * @param clockRate The clock rate of the beatmap.
606
+ * @param options Options for performance calculation.
586
607
  */
587
- constructor(object: PlaceableHitObject, lastObject: PlaceableHitObject | null, difficultyHitObjects: readonly DifficultyHitObject[], clockRate: number, index: number);
588
- opacityAt(time: number, mods: ModMap): number;
608
+ protected handleOptions(options?: PerformanceCalculationOptions): void;
609
+ /**
610
+ * Determines whether an attribute is a cacheable attribute.
611
+ *
612
+ * @param attributes The attributes to check.
613
+ * @returns Whether the attributes are cacheable.
614
+ */
615
+ private isCacheableAttribute;
616
+ }
617
+
618
+ /**
619
+ * Represents an osu!droid hit object with difficulty calculation values.
620
+ */
621
+ declare class DroidDifficultyHitObject extends DifficultyHitObject {
622
+ /**
623
+ * The tap difficulty generated by the hitobject.
624
+ */
625
+ tapDifficulty: number;
626
+ /**
627
+ * The tap difficulty generated by the hitobject if `strainTime` isn't modified by
628
+ * OD. This is used in three-finger detection.
629
+ */
630
+ originalTapDifficulty: number;
631
+ /**
632
+ * The rhythm difficulty generated by the hitobject.
633
+ */
634
+ rhythmDifficulty: number;
635
+ /**
636
+ * The reading difficulty generated by the hitobject.
637
+ */
638
+ readingDifficulty: number;
639
+ readonly normalizedRadius = 50;
640
+ protected readonly mode = Modes.Droid;
641
+ protected get maximumSliderRadius(): number;
642
+ get smallCircleBonus(): number;
643
+ opacityAt(time: number, mods?: ModMap): number;
589
644
  previous(backwardsIndex: number): this | null;
590
645
  next(forwardsIndex: number): this | null;
591
646
  /**
@@ -604,87 +659,23 @@ declare class DroidDifficultyHitObject extends DifficultyHitObject {
604
659
  }
605
660
 
606
661
  /**
607
- * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
608
- * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
662
+ * Represents a slider that is considered difficult.
663
+ *
664
+ * This structure is a part of difficulty attributes and can be cached.
609
665
  */
610
- declare abstract class DroidSkill extends StrainSkill {
666
+ interface DifficultSlider {
611
667
  /**
612
- * The bonus multiplier that is given for a sequence of notes of equal difficulty.
668
+ * The index of the slider in the beatmap.
613
669
  */
614
- protected abstract readonly starsPerDouble: number;
615
- process(current: DifficultyHitObject): void;
616
- difficultyValue(): number;
670
+ readonly index: number;
617
671
  /**
618
- * Gets the strain of a hitobject.
672
+ * The difficulty rating of this slider compared to other sliders, based on the velocity of the slider.
619
673
  *
620
- * @param current The hitobject to get the strain from.
621
- * @returns The strain of the hitobject.
674
+ * A value closer to 1 indicates that this slider is more difficult compared to most sliders.
675
+ *
676
+ * A value closer to 0 indicates that this slider is easier compared to most sliders.
622
677
  */
623
- protected abstract getObjectStrain(current: DifficultyHitObject): number;
624
- protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
625
- }
626
-
627
- /**
628
- * Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
629
- */
630
- declare class DroidAim extends DroidSkill {
631
- protected readonly strainDecayBase = 0.15;
632
- protected readonly reducedSectionCount = 10;
633
- protected readonly reducedSectionBaseline = 0.75;
634
- protected readonly starsPerDouble = 1.05;
635
- private readonly skillMultiplier;
636
- private currentAimStrain;
637
- private readonly sliderStrains;
638
- private maxSliderStrain;
639
- readonly withSliders: boolean;
640
- constructor(mods: ModMap, withSliders: boolean);
641
- static difficultyToPerformance(difficulty: number): number;
642
- /**
643
- * Obtains the amount of sliders that are considered difficult in terms of relative strain.
644
- */
645
- countDifficultSliders(): number;
646
- protected strainValueAt(current: DroidDifficultyHitObject): number;
647
- protected calculateInitialStrain(time: number, current: DroidDifficultyHitObject): number;
648
- protected getObjectStrain(): number;
649
- /**
650
- * @param current The hitobject to save to.
651
- */
652
- protected saveToHitObject(current: DroidDifficultyHitObject): void;
653
- }
654
-
655
- /**
656
- * An evaluator for calculating osu!droid Aim skill.
657
- */
658
- declare abstract class DroidAimEvaluator {
659
- private static readonly wideAngleMultiplier;
660
- private static readonly acuteAngleMultiplier;
661
- private static readonly sliderMultiplier;
662
- private static readonly velocityChangeMultiplier;
663
- private static readonly wiggleMultiplier;
664
- private static readonly singleSpacingThreshold;
665
- private static readonly minSpeedBonus;
666
- /**
667
- * Evaluates the difficulty of aiming the current object, based on:
668
- *
669
- * - cursor velocity to the current object,
670
- * - angle difficulty,
671
- * - sharp velocity increases,
672
- * - and slider difficulty.
673
- *
674
- * @param current The current object.
675
- * @param withSliders Whether to take slider difficulty into account.
676
- */
677
- static evaluateDifficultyOf(current: DroidDifficultyHitObject, withSliders: boolean): number;
678
- /**
679
- * Calculates the snap aim strain of a hitobject.
680
- */
681
- private static snapAimStrainOf;
682
- /**
683
- * Calculates the flow aim strain of a hitobject.
684
- */
685
- private static flowAimStrainOf;
686
- private static calculateWideAngleBonus;
687
- private static calculateAcuteAngleBonus;
678
+ readonly difficultyRating: number;
688
679
  }
689
680
 
690
681
  /**
@@ -707,26 +698,30 @@ interface IDroidDifficultyAttributes extends IDifficultyAttributes {
707
698
  * The amount of strains that are considered difficult with respect to the tap skill.
708
699
  */
709
700
  tapDifficultStrainCount: number;
710
- /**
711
- * The amount of strains that are considered difficult with respect to the flashlight skill.
712
- */
713
- flashlightDifficultStrainCount: number;
714
701
  /**
715
702
  * The amount of notes that are considered difficult with respect to the reading skill.
716
703
  */
717
704
  readingDifficultNoteCount: number;
718
705
  /**
719
- * The average delta time of speed objects.
706
+ * Describes how much of {@link aimDifficultStrainCount} is contributed to by circles or sliders.
707
+ *
708
+ * A value closer to 0 indicates most of {@link aimDifficultStrainCount} is contributed by circles.
709
+ *
710
+ * A value closer to infinity indicates most of {@link aimDifficultStrainCount} is contributed by sliders.
720
711
  */
721
- averageSpeedDeltaTime: number;
712
+ aimTopWeightedSliderFactor: number;
722
713
  /**
723
- * Describes how much of tap difficulty is contributed by notes that are "vibroable".
714
+ * Describes how much of {@link tapDifficultStrainCount} is contributed to by circles or sliders.
724
715
  *
725
- * A value closer to 1 indicates most of tap difficulty is contributed by notes that are not "vibroable".
716
+ * A value closer to 0 indicates most of {@link tapDifficultStrainCount} is contributed by circles.
726
717
  *
727
- * A value closer to 0 indicates most of tap difficulty is contributed by notes that are "vibroable".
718
+ * A value closer to infinity indicates most of {@link tapDifficultStrainCount} is contributed by sliders.
719
+ */
720
+ tapTopWeightedSliderFactor: number;
721
+ /**
722
+ * The maximum score obtainable on the beatmap.
728
723
  */
729
- vibroFactor: number;
724
+ maximumScore: number;
730
725
  }
731
726
 
732
727
  /**
@@ -734,13 +729,13 @@ interface IDroidDifficultyAttributes extends IDifficultyAttributes {
734
729
  */
735
730
  declare class DroidDifficultyAttributes extends DifficultyAttributes implements IDroidDifficultyAttributes {
736
731
  tapDifficulty: number;
737
- rhythmDifficulty: number;
738
732
  readingDifficulty: number;
739
- tapDifficultStrainCount: number;
740
- flashlightDifficultStrainCount: number;
733
+ aimTopWeightedSliderFactor: number;
734
+ tapTopWeightedSliderFactor: number;
741
735
  readingDifficultNoteCount: number;
742
- averageSpeedDeltaTime: number;
743
- vibroFactor: number;
736
+ rhythmDifficulty: number;
737
+ tapDifficultStrainCount: number;
738
+ maximumScore: number;
744
739
  constructor(cacheableAttributes?: CacheableDifficultyAttributes<IDroidDifficultyAttributes>);
745
740
  toString(): string;
746
741
  }
@@ -780,14 +775,6 @@ interface IExtendedDroidDifficultyAttributes extends IDroidDifficultyAttributes
780
775
  * Sliders that are considered difficult.
781
776
  */
782
777
  difficultSliders: DifficultSlider[];
783
- /**
784
- * Describes how much of flashlight difficulty is contributed to by hitcircles or sliders.
785
- *
786
- * A value closer to 1 indicates most of flashlight difficulty is contributed by hitcircles.
787
- *
788
- * A value closer to 0 indicates most of flashlight difficulty is contributed by sliders.
789
- */
790
- flashlightSliderFactor: number;
791
778
  }
792
779
 
793
780
  /**
@@ -798,7 +785,6 @@ declare class ExtendedDroidDifficultyAttributes extends DroidDifficultyAttribute
798
785
  mode: "live";
799
786
  possibleThreeFingeredSections: HighStrainSection[];
800
787
  difficultSliders: DifficultSlider[];
801
- flashlightSliderFactor: number;
802
788
  constructor(cacheableAttributes?: CacheableDifficultyAttributes<IExtendedDroidDifficultyAttributes>);
803
789
  }
804
790
 
@@ -806,209 +792,21 @@ declare class ExtendedDroidDifficultyAttributes extends DroidDifficultyAttribute
806
792
  * A difficulty calculator for osu!droid gamemode.
807
793
  */
808
794
  declare class DroidDifficultyCalculator extends DifficultyCalculator<DroidPlayableBeatmap, DroidDifficultyHitObject, ExtendedDroidDifficultyAttributes> {
809
- /**
810
- * The strain threshold to start detecting for possible three-fingered section.
811
- *
812
- * Increasing this number will result in less sections being flagged.
813
- */
814
- static readonly threeFingerStrainThreshold = 175;
815
- private readonly difficultyMultiplier;
816
795
  constructor();
817
796
  retainDifficultyAdjustmentMods(mods: Mod[]): Mod[];
818
- protected createDifficultyAttributes(beatmap: DroidPlayableBeatmap, skills: Skill[], objects: DroidDifficultyHitObject[]): ExtendedDroidDifficultyAttributes;
797
+ protected createDifficultyAttributes(beatmap: Beatmap, playableBeatmap: DroidPlayableBeatmap, skills: Skill[], objects: DroidDifficultyHitObject[]): ExtendedDroidDifficultyAttributes;
819
798
  protected createPlayableBeatmap(beatmap: Beatmap, mods?: ModMap): DroidPlayableBeatmap;
820
799
  protected createDifficultyHitObjects(beatmap: DroidPlayableBeatmap): DroidDifficultyHitObject[];
821
800
  protected createSkills(beatmap: DroidPlayableBeatmap): Skill[];
822
- protected createStrainPeakSkills(beatmap: DroidPlayableBeatmap): StrainSkill[];
801
+ protected createStrainPeakSkills(beatmap: DroidPlayableBeatmap): (Skill & IHasPeakDifficulty)[];
823
802
  private populateAimAttributes;
824
803
  private populateTapAttributes;
825
804
  private populateRhythmAttributes;
826
805
  private populateFlashlightAttributes;
827
806
  private populateReadingAttributes;
828
- /**
829
- * Calculates the base rating of a `Skill`.
830
- *
831
- * @param skill The `Skill` to calculate the rating of.
832
- * @returns The rating of the `Skill`.
833
- */
834
- private calculateRating;
835
- }
836
-
837
- /**
838
- * Represents the skill required to memorize and hit every object in a beatmap with the Flashlight mod enabled.
839
- */
840
- declare class DroidFlashlight extends DroidSkill {
841
- protected readonly strainDecayBase = 0.15;
842
- protected readonly reducedSectionCount = 0;
843
- protected readonly reducedSectionBaseline = 1;
844
- protected readonly starsPerDouble = 1.06;
845
- private readonly skillMultiplier;
846
- private currentFlashlightStrain;
847
- readonly withSliders: boolean;
848
- constructor(mods: ModMap, withSliders: boolean);
849
- static difficultyToPerformance(difficulty: number): number;
850
- protected strainValueAt(current: DroidDifficultyHitObject): number;
851
- protected calculateInitialStrain(time: number, current: DifficultyHitObject): number;
852
- protected getObjectStrain(): number;
853
- protected saveToHitObject(current: DroidDifficultyHitObject): void;
854
- difficultyValue(): number;
855
- }
856
-
857
- /**
858
- * An evaluator for calculating osu!droid Flashlight skill.
859
- */
860
- declare abstract class DroidFlashlightEvaluator {
861
- private static readonly maxOpacityBonus;
862
- private static readonly hiddenBonus;
863
- private static readonly traceableCircleBonus;
864
- private static readonly traceableObjectBonus;
865
- private static readonly minVelocity;
866
- private static readonly sliderMultiplier;
867
- private static readonly minAngleMultiplier;
868
- /**
869
- * Evaluates the difficulty of memorizing and hitting the current object, based on:
870
- *
871
- * - distance between a number of previous objects and the current object,
872
- * - the visual opacity of the current object,
873
- * - the angle made by the current object,
874
- * - length and speed of the current object (for sliders),
875
- * - and whether Hidden mod is enabled.
876
- *
877
- * @param current The current object.
878
- * @param mods The mods used.
879
- * @param withSliders Whether to take slider difficulty into account.
880
- */
881
- static evaluateDifficultyOf(current: DroidDifficultyHitObject, mods: ModMap, withSliders: boolean): number;
882
- }
883
-
884
- /**
885
- * Represents options for performance calculation.
886
- */
887
- interface PerformanceCalculationOptions {
888
- /**
889
- * The maximum combo achieved in the score.
890
- */
891
- combo?: number;
892
- /**
893
- * The accuracy achieved in the score.
894
- */
895
- accPercent?: Accuracy | number;
896
- /**
897
- * The amount of misses achieved in the score.
898
- */
899
- miss?: number;
900
- /**
901
- * The amount of slider ends dropped in the score.
902
- */
903
- sliderEndsDropped?: number;
904
- /**
905
- * The amount of slider ticks missed in the score.
906
- */
907
- sliderTicksMissed?: number;
908
- /**
909
- * The tap penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
910
- */
911
- tapPenalty?: number;
912
- /**
913
- * The aim slider cheese penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
914
- */
915
- aimSliderCheesePenalty?: number;
916
- /**
917
- * The flashlight slider cheese penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
918
- */
919
- flashlightSliderCheesePenalty?: number;
920
- /**
921
- * The visual slider cheese penalty to apply for penalized scores. Only used when using `DroidPerformanceCalculator`.
922
- */
923
- visualSliderCheesePenalty?: number;
924
- }
925
-
926
- /**
927
- * The base class of performance calculators.
928
- */
929
- declare abstract class PerformanceCalculator<T extends IDifficultyAttributes> {
930
- /**
931
- * The overall performance value.
932
- */
933
- total: number;
934
- /**
935
- * The calculated accuracy.
936
- */
937
- computedAccuracy: Accuracy;
938
- /**
939
- * The calculated maximum combo.
940
- */
941
- combo: number;
942
- /**
943
- * The difficulty attributes that is being calculated.
944
- */
945
- readonly difficultyAttributes: T | CacheableDifficultyAttributes<T>;
946
- /**
947
- * The mods that were used.
948
- */
949
- protected readonly mods: ModMap;
950
- private _sliderEndsDropped;
951
- /**
952
- * The amount of slider ends dropped in the score.
953
- */
954
- protected get sliderEndsDropped(): number;
955
- private _sliderTicksMissed;
956
- /**
957
- * The amount of slider ticks missed in the score.
958
- *
959
- * This is used to calculate the slider accuracy.
960
- */
961
- protected get sliderTicksMissed(): number;
962
- private _usingClassicSliderAccuracy;
963
- /**
964
- * Whether this score uses classic slider accuracy.
965
- */
966
- protected get usingClassicSliderAccuracy(): boolean;
967
- /**
968
- * @param difficultyAttributes The difficulty attributes to calculate.
969
- */
970
- constructor(difficultyAttributes: T | CacheableDifficultyAttributes<T>);
971
- /**
972
- * Calculates the performance points of the beatmap.
973
- *
974
- * @param options Options for performance calculation.
975
- * @returns The current instance.
976
- */
977
- calculate(options?: PerformanceCalculationOptions): this;
978
- /**
979
- * Returns a string representative of the class.
980
- */
981
- abstract toString(): string;
982
- /**
983
- * Calculates all values that will be used for calculating the total
984
- * performance value of the beatmap and stores them in this instance.
985
- */
986
- protected abstract calculateValues(): void;
987
- /**
988
- * The total hits that can be done in the beatmap.
989
- */
990
- protected get totalHits(): number;
991
- /**
992
- * The total hits that were successfully done.
993
- */
994
- protected get totalSuccessfulHits(): number;
995
- /**
996
- * The total of imperfect hits (100s, 50s, misses).
997
- */
998
- protected get totalImperfectHits(): number;
999
- /**
1000
- * Processes given options for usage in performance calculation.
1001
- *
1002
- * @param options Options for performance calculation.
1003
- */
1004
- protected handleOptions(options?: PerformanceCalculationOptions): void;
1005
- /**
1006
- * Determines whether an attribute is a cacheable attribute.
1007
- *
1008
- * @param attributes The attributes to check.
1009
- * @returns Whether the attributes are cacheable.
1010
- */
1011
- private isCacheableAttribute;
807
+ private calculateAimDifficultyRating;
808
+ private calculateDifficultyRating;
809
+ static sumCognitionDifficulty(reading: number, flashlight: number): number;
1012
810
  }
1013
811
 
1014
812
  /**
@@ -1054,24 +852,23 @@ declare class DroidPerformanceCalculator extends PerformanceCalculator<IDroidDif
1054
852
  *
1055
853
  * Can be properly obtained by analyzing the replay associated with the score.
1056
854
  */
1057
- get aimSliderCheesePenalty(): number;
855
+ get sliderCheesePenalty(): number;
1058
856
  /**
1059
- * The penalty used to penalize the flashlight performance value.
1060
- *
1061
- * Can be properly obtained by analyzing the replay associated with the score.
857
+ * The total score achieved in the score.
1062
858
  */
1063
- get flashlightSliderCheesePenalty(): number;
859
+ get totalScore(): number | null;
1064
860
  /**
1065
861
  * The amount of misses, including slider breaks.
1066
862
  */
1067
863
  get effectiveMissCount(): number;
1068
864
  static readonly finalMultiplier = 1.24;
1069
- private _aimSliderCheesePenalty;
1070
- private _flashlightSliderCheesePenalty;
865
+ static readonly normExponent = 1.1;
866
+ private _sliderCheesePenalty;
1071
867
  private _tapPenalty;
1072
868
  private _effectiveMissCount;
1073
869
  private _deviation;
1074
870
  private _tapDeviation;
871
+ private _totalScore;
1075
872
  protected calculateValues(): void;
1076
873
  protected handleOptions(options?: PerformanceCalculationOptions): void;
1077
874
  /**
@@ -1129,111 +926,154 @@ declare class DroidPerformanceCalculator extends PerformanceCalculator<IDroidDif
1129
926
  *
1130
927
  * Inaccuracies are capped to the number of circles in the map.
1131
928
  */
1132
- private calculateDeviation;
929
+ private calculateAimDeviation;
1133
930
  /**
1134
- * Does the same as {@link calculateDeviation}, but only for notes and inaccuracies that are relevant to tap difficulty.
931
+ * Does the same as {@link calculateAimDeviation}, but only for notes and inaccuracies that are relevant to tap difficulty.
1135
932
  *
1136
- * Treats all difficult speed notes as circles, so this method can sometimes return a lower deviation than {@link calculateDeviation}.
933
+ * Treats all difficult speed notes as circles, so this method can sometimes return a lower deviation than {@link calculateAimDeviation}.
1137
934
  * This is fine though, since this method is only used to scale tap pp.
1138
935
  */
1139
936
  private calculateTapDeviation;
1140
937
  /**
1141
- * Calculates a multiplier for tap to account for improper tapping based on the deviation and tap difficulty.
938
+ * Estimates the player's tap deviation based on the OD, given number of greats, oks, mehs and misses,
939
+ * assuming the player's mean hit error is 0. The estimation is consistent in that two SS scores on the
940
+ * same map with the same settings will always return the same deviation.
1142
941
  *
1143
- * [Graph](https://www.desmos.com/calculator/z5l9ebrwpi)
942
+ * Misses are ignored because they are usually due to misaiming.
943
+ *
944
+ * Greats and oks are assumed to follow a normal distribution, whereas mehs are assumed to follow a uniform distribution.
945
+ */
946
+ private calculateDeviation;
947
+ /**
948
+ * Calculates a multiplier for tap to account for improper tapping based on the deviation and tap difficulty.
949
+ *
950
+ * [Graph](https://www.desmos.com/calculator/z5l9ebrwpi)
1144
951
  */
1145
952
  private calculateTapHighDeviationNerf;
1146
953
  private getHitWindow;
954
+ private calculateEstimatedSliderBreaks;
955
+ private calculateMaximumComboBasedMissCount;
956
+ /**
957
+ * Calculates the amount of misses + sliderbreaks from combo.
958
+ */
959
+ private calculateComboBasedEstimatedMissCount;
1147
960
  toString(): string;
1148
961
  }
1149
962
 
1150
963
  /**
1151
- * Represents the skill required to read every object in the map.
964
+ * An evaluator for calculating osu!droid agility aim difficulty.
1152
965
  */
1153
- declare class DroidReading extends Skill {
1154
- private readonly clockRate;
1155
- private readonly hitObjects;
1156
- private readonly noteDifficulties;
1157
- private readonly strainDecayBase;
1158
- private readonly skillMultiplier;
1159
- private currentNoteDifficulty;
1160
- private difficulty;
1161
- private noteWeightSum;
1162
- constructor(mods: ModMap, clockRate: number, hitObjects: readonly PlaceableHitObject[]);
966
+ declare abstract class DroidAgilityEvaluator {
1163
967
  /**
1164
- * Converts a difficulty value to a performance value.
968
+ * Evaluates the difficulty of fast aiming the current object.
1165
969
  *
1166
- * @param difficulty The difficulty value to convert.
1167
- * @returns The performance value.
970
+ * @param current The current object.
1168
971
  */
1169
- static difficultyToPerformance(difficulty: number): number;
1170
- process(current: DroidDifficultyHitObject): void;
1171
- difficultyValue(): number;
972
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject): number;
973
+ private static highBpmBonus;
974
+ }
975
+
976
+ /**
977
+ * An evaluator for calculating osu!droid Flashlight skill.
978
+ */
979
+ declare abstract class DroidFlashlightEvaluator {
980
+ private static readonly maxOpacityBonus;
981
+ private static readonly hiddenBonus;
982
+ private static readonly traceableCircleBonus;
983
+ private static readonly traceableObjectBonus;
984
+ private static readonly minVelocity;
985
+ private static readonly sliderMultiplier;
986
+ private static readonly minAngleMultiplier;
1172
987
  /**
1173
- * Returns the number of relevant objects weighted against the top note.
988
+ * Evaluates the difficulty of memorizing and hitting the current object, based on:
989
+ *
990
+ * - distance between a number of previous objects and the current object,
991
+ * - the visual opacity of the current object,
992
+ * - the angle made by the current object,
993
+ * - length and speed of the current object (for sliders),
994
+ * - and whether Hidden mod is enabled.
995
+ *
996
+ * @param current The current object.
997
+ * @param mods The mods used.
1174
998
  */
1175
- countTopWeightedNotes(): number;
1176
- private strainDecay;
999
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject, mods: ModMap): number;
1000
+ }
1001
+
1002
+ /**
1003
+ * An evaluator for calculating osu!droid flow aim difficulty.
1004
+ */
1005
+ declare abstract class DroidFlowAimEvaluator {
1006
+ private static readonly velocityChangeMultiplier;
1007
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject, withSliders: boolean): number;
1008
+ private static calculateOverlapFactor;
1177
1009
  }
1178
1010
 
1179
1011
  /**
1180
- * An evaluator for calculating osu!droid reading skill.
1012
+ * Evaluator for reading difficulty in osu!droid.
1181
1013
  */
1182
1014
  declare abstract class DroidReadingEvaluator {
1183
- private static readonly emptyModMap;
1184
1015
  private static readonly readingWindowSize;
1185
- private static readonly distanceInfluenceThreshold;
1186
1016
  private static readonly hiddenMultiplier;
1017
+ private static readonly traceableMultiplier;
1187
1018
  private static readonly densityMultiplier;
1188
1019
  private static readonly densityDifficultyBase;
1189
1020
  private static readonly preemptBalancingFactor;
1190
1021
  private static readonly preemptStartingPoint;
1191
- static evaluateDifficultyOf(current: DroidDifficultyHitObject, clockRate: number, mods: ModMap): number;
1022
+ private static readonly minimumAngleRelevancyTime;
1023
+ private static readonly maximumAngleRelevancyTime;
1192
1024
  /**
1193
- * Retrieves a list of objects that are visible at the point in time the current object needs to be hit.
1194
- *
1195
- * @param current The current object.
1025
+ * Evaluates the difficulty of reading the object.
1196
1026
  */
1197
- private static retrievePastVisibleObjects;
1027
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject, mods: ModMap): number;
1198
1028
  /**
1199
- * Calculates the density of objects visible at the point in time the current object needs to be hit.
1029
+ * Calculates the density difficulty of the current object and how hard it is to aim it because of it based on:
1200
1030
  *
1201
- * @param current The current object.
1031
+ * - cursor velocity to the current object,
1032
+ * - how many times the current object's angle was repeated,
1033
+ * - density of objects visible when the current object appears, and
1034
+ * - density of objects visible when the current object needs to be clicked.
1202
1035
  */
1203
- private static calculateCurrentVisibleObjectsDensity;
1036
+ private static calculateDensityDifficulty;
1204
1037
  /**
1205
- * Returns the time an object spends invisible with the Hidden mod at the current approach rate.
1038
+ * Calculates the difficulty of aiming the current object when the approach rate is very high based on:
1206
1039
  *
1207
- * @param current The current object.
1040
+ * - cursor velocity to the current object,
1041
+ * - how many times the current object's angle was repeated, and
1042
+ * - how many milliseconds elapse between the approach circle appearing and touching the inner circle.
1208
1043
  */
1209
- private static getDurationSpentInvisible;
1044
+ private static calculatePreemptDifficulty;
1210
1045
  /**
1211
- * Calculates a factor of how often the current object's angle has been repeated in a certain time frame.
1212
- * It does this by checking the difference in angle between current and past objects and sums them up
1213
- * based on a range of similarity.
1046
+ * Calculates the difficulty of aiming the current object when the Hidden mod is active based on:
1214
1047
  *
1215
- * @param current The current object.
1048
+ * - cursor velocity to the current object,
1049
+ * - time the current object spends invisible,
1050
+ * - density of objects visible when the current object appears,
1051
+ * - density of objects visible when the current object needs to be clicked,
1052
+ * - how many times the current object's angle was repeated, and
1053
+ * - if the current object is perfectly stacked to the previous one.
1054
+ */
1055
+ private static calculateHiddenDifficulty;
1056
+ private static calculateTraceableDifficulty;
1057
+ private static getPastObjectDifficultyInfluence;
1058
+ /**
1059
+ * Returns a list of objects that are visible on screen at the point in time the current object becomes visible.
1060
+ */
1061
+ private static retrievePastVisibleObjects;
1062
+ /**
1063
+ * Returns the density of objects visible at the point in time the current object needs to be clicked capped by the reading window.
1064
+ */
1065
+ private static retrieveCurrentVisibleObjectDensity;
1066
+ /**
1067
+ * Returns a factor of how often the current object's angle has been repeated in a certain time frame.
1068
+ * It does this by checking the difference in angle between current and past objects and sums them based on a range of similarity.
1069
+ * https://www.desmos.com/calculator/eb057a4822
1216
1070
  */
1217
1071
  private static getConstantAngleNerfFactor;
1072
+ /**
1073
+ * Returns a nerfing factor for when objects are very distant in time, affecting reading less.
1074
+ */
1218
1075
  private static getTimeNerfFactor;
1219
- }
1220
-
1221
- /**
1222
- * Represents the skill required to properly follow a beatmap's rhythm.
1223
- */
1224
- declare class DroidRhythm extends DroidSkill {
1225
- protected readonly reducedSectionCount = 5;
1226
- protected readonly reducedSectionBaseline = 0.75;
1227
- protected readonly strainDecayBase = 0.3;
1228
- protected readonly starsPerDouble = 1.75;
1229
- private readonly useSliderAccuracy;
1230
- private currentRhythmStrain;
1231
- private currentRhythmMultiplier;
1232
- constructor(mods: ModMap);
1233
- protected strainValueAt(current: DroidDifficultyHitObject): number;
1234
- protected calculateInitialStrain(time: number, current: DroidDifficultyHitObject): number;
1235
- protected getObjectStrain(): number;
1236
- protected saveToHitObject(current: DroidDifficultyHitObject): void;
1076
+ private static highBpmBonus;
1237
1077
  }
1238
1078
 
1239
1079
  /**
@@ -1252,43 +1092,37 @@ declare abstract class DroidRhythmEvaluator {
1252
1092
  * @param useSliderAccuracy Whether to use slider accuracy.
1253
1093
  */
1254
1094
  static evaluateDifficultyOf(current: DroidDifficultyHitObject, useSliderAccuracy: boolean): number;
1095
+ private static getEffectiveRatio;
1255
1096
  }
1256
1097
 
1257
1098
  /**
1258
- * Represents the skill required to press keys or tap with regards to keeping up with the speed at which objects need to be hit.
1099
+ * An evaluator for calculating osu!droid snap aim difficulty.
1259
1100
  */
1260
- declare class DroidTap extends DroidSkill {
1261
- protected readonly reducedSectionCount = 10;
1262
- protected readonly reducedSectionBaseline = 0.75;
1263
- protected readonly strainDecayBase = 0.3;
1264
- protected readonly starsPerDouble = 1.1;
1265
- private currentTapStrain;
1266
- private currentRhythmMultiplier;
1267
- private readonly skillMultiplier;
1268
- private readonly _objectDeltaTimes;
1269
- private maxStrain;
1270
- /**
1271
- * The delta time of hitobjects.
1272
- */
1273
- get objectDeltaTimes(): readonly number[];
1274
- readonly considerCheesability: boolean;
1275
- readonly strainTimeCap?: number;
1276
- constructor(mods: ModMap, considerCheesability: boolean, strainTimeCap?: number);
1277
- /**
1278
- * The amount of notes that are relevant to the difficulty.
1279
- */
1280
- relevantNoteCount(): number;
1281
- /**
1282
- * The delta time relevant to the difficulty.
1283
- */
1284
- relevantDeltaTime(): number;
1285
- protected strainValueAt(current: DroidDifficultyHitObject): number;
1286
- protected calculateInitialStrain(time: number, current: DroidDifficultyHitObject): number;
1287
- protected getObjectStrain(): number;
1101
+ declare abstract class DroidSnapAimEvaluator {
1102
+ private static readonly wideAngleMultiplier;
1103
+ private static readonly acuteAngleMultiplier;
1104
+ private static readonly sliderMultiplier;
1105
+ private static readonly velocityChangeMultiplier;
1106
+ private static readonly wiggleMultiplier;
1107
+ private static readonly angleRepetitionNoteLimit;
1108
+ private static readonly maximumRepetitionNerf;
1109
+ private static readonly maximumVectorInfluence;
1288
1110
  /**
1289
- * @param current The hitobject to save to.
1111
+ * Evaluates the difficulty of aiming the current object, based on:
1112
+ *
1113
+ * - cursor velocity to the current object,
1114
+ * - angle difficulty,
1115
+ * - sharp velocity increases,
1116
+ * - and slider difficulty.
1117
+ *
1118
+ * @param current The current object.
1119
+ * @param withSliders Whether to take slider difficulty into account.
1290
1120
  */
1291
- protected saveToHitObject(current: DroidDifficultyHitObject): void;
1121
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject, withSliders: boolean): number;
1122
+ private static calculateWideAngleAcuteness;
1123
+ static calculateAcuteAngleAcuteness(angle: number): number;
1124
+ private static highBpmBonus;
1125
+ private static calculateVectorAngleRepetition;
1292
1126
  }
1293
1127
 
1294
1128
  /**
@@ -1306,49 +1140,9 @@ declare abstract class DroidTapEvaluator {
1306
1140
  *
1307
1141
  * @param current The current object.
1308
1142
  * @param considerCheesability Whether to consider cheesability.
1309
- * @param strainTimeCap The strain time to cap the object's strain time to.
1310
- */
1311
- static evaluateDifficultyOf(current: DroidDifficultyHitObject, considerCheesability: boolean, strainTimeCap?: number): number;
1312
- }
1313
-
1314
- /**
1315
- * Holds data that can be used to calculate osu!standard performance points.
1316
- */
1317
- interface IOsuDifficultyAttributes extends IDifficultyAttributes {
1318
- /**
1319
- * The perceived approach rate **exclusive** of rate-adjusting mods (DT/HT/etc).
1320
- *
1321
- * Rate-adjusting mods don't directly affect the approach rate difficulty value, but have a perceived effect as a result of adjusting audio timing.
1322
- */
1323
- approachRate: number;
1324
- /**
1325
- * The health drain rate of the beatmap.
1326
- */
1327
- drainRate: number;
1328
- /**
1329
- * The difficulty corresponding to the speed skill.
1330
- */
1331
- speedDifficulty: number;
1332
- /**
1333
- * The amount of strains that are considered difficult with respect to the speed skill.
1334
- */
1335
- speedDifficultStrainCount: number;
1336
- /**
1337
- * Describes how much of {@link aimDifficultStrainCount} is contributed to by circles or sliders.
1338
- *
1339
- * A value closer to 0 indicates most of {@link aimDifficultStrainCount} is contributed by circles.
1340
- *
1341
- * A value closer to infinity indicates most of {@link aimDifficultStrainCount} is contributed by sliders.
1342
- */
1343
- aimTopWeightedSliderFactor: number;
1344
- /**
1345
- * Describes how much of {@link speedDifficultStrainCount} is contributed to by circles or sliders.
1346
- *
1347
- * A value closer to 0 indicates most of {@link speedDifficultStrainCount} is contributed by circles.
1348
- *
1349
- * A value closer to infinity indicates most of {@link speedDifficultStrainCount} is contributed by sliders.
1350
1143
  */
1351
- speedTopWeightedSliderFactor: number;
1144
+ static evaluateDifficultyOf(current: DroidDifficultyHitObject, considerCheesability: boolean): number;
1145
+ private static highBpmBonus;
1352
1146
  }
1353
1147
 
1354
1148
  /**
@@ -1359,53 +1153,9 @@ declare class OsuDifficultyHitObject extends DifficultyHitObject {
1359
1153
  * The speed strain generated by the hitobject.
1360
1154
  */
1361
1155
  speedStrain: number;
1362
- /**
1363
- * The flashlight strain generated by this hitobject.
1364
- */
1365
- flashlightStrain: number;
1156
+ readonly normalizedRadius = 50;
1366
1157
  get smallCircleBonus(): number;
1367
- protected readonly mode = Modes.osu;
1368
- }
1369
-
1370
- /**
1371
- * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1372
- * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1373
- */
1374
- declare abstract class OsuSkill extends StrainSkill {
1375
- /**
1376
- * The weight by which each strain value decays.
1377
- */
1378
- protected abstract readonly decayWeight: number;
1379
- difficultyValue(): number;
1380
- }
1381
-
1382
- /**
1383
- * Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
1384
- */
1385
- declare class OsuAim extends OsuSkill {
1386
- protected readonly strainDecayBase = 0.15;
1387
- protected readonly reducedSectionCount = 10;
1388
- protected readonly reducedSectionBaseline = 0.75;
1389
- protected readonly decayWeight = 0.9;
1390
- private currentAimStrain;
1391
- private readonly skillMultiplier;
1392
- private readonly sliderStrains;
1393
- readonly withSliders: boolean;
1394
- constructor(mods: ModMap, withSliders: boolean);
1395
- /**
1396
- * Obtains the amount of sliders that are considered difficult in terms of relative strain.
1397
- */
1398
- countDifficultSliders(): number;
1399
- /**
1400
- * Obtains the amount of sliders that are considered difficult in terms of relative strain, weighted by consistency.
1401
- */
1402
- countTopWeightedSliders(): number;
1403
- protected strainValueAt(current: OsuDifficultyHitObject): number;
1404
- protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1405
- /**
1406
- * @param current The hitobject to save to.
1407
- */
1408
- protected saveToHitObject(current: OsuDifficultyHitObject): void;
1158
+ protected readonly mode = Modes.Osu;
1409
1159
  }
1410
1160
 
1411
1161
  /**
@@ -1433,55 +1183,6 @@ declare abstract class OsuAimEvaluator {
1433
1183
  private static calculateAcuteAngleBonus;
1434
1184
  }
1435
1185
 
1436
- /**
1437
- * Holds data that can be used to calculate osu!standard performance points.
1438
- */
1439
- declare class OsuDifficultyAttributes extends DifficultyAttributes implements IOsuDifficultyAttributes {
1440
- approachRate: number;
1441
- drainRate: number;
1442
- speedDifficulty: number;
1443
- speedDifficultStrainCount: number;
1444
- aimTopWeightedSliderFactor: number;
1445
- speedTopWeightedSliderFactor: number;
1446
- constructor(cacheableAttributes?: CacheableDifficultyAttributes<IOsuDifficultyAttributes>);
1447
- toString(): string;
1448
- }
1449
-
1450
- /**
1451
- * A difficulty calculator for osu!standard gamemode.
1452
- */
1453
- declare class OsuDifficultyCalculator extends DifficultyCalculator<OsuPlayableBeatmap, OsuDifficultyHitObject, OsuDifficultyAttributes> {
1454
- private readonly starRatingMultiplier;
1455
- constructor();
1456
- retainDifficultyAdjustmentMods(mods: Mod[]): Mod[];
1457
- protected createDifficultyAttributes(beatmap: OsuPlayableBeatmap, skills: Skill[]): OsuDifficultyAttributes;
1458
- protected createPlayableBeatmap(beatmap: Beatmap, mods?: ModMap): OsuPlayableBeatmap;
1459
- protected createDifficultyHitObjects(beatmap: OsuPlayableBeatmap): OsuDifficultyHitObject[];
1460
- protected createSkills(beatmap: OsuPlayableBeatmap): OsuSkill[];
1461
- protected createStrainPeakSkills(beatmap: OsuPlayableBeatmap): StrainSkill[];
1462
- private calculateMechanicalDifficultyRating;
1463
- private calculateStarRating;
1464
- static calculateRateAdjustedApproachRate(approachRate: number, clockRate: number): number;
1465
- static calculateRateAdjustedOverallDifficulty(overallDifficulty: number, clockRate: number): number;
1466
- }
1467
-
1468
- /**
1469
- * Represents the skill required to memorize and hit every object in a beatmap with the Flashlight mod enabled.
1470
- */
1471
- declare class OsuFlashlight extends OsuSkill {
1472
- protected readonly strainDecayBase = 0.15;
1473
- protected readonly reducedSectionCount = 0;
1474
- protected readonly reducedSectionBaseline = 1;
1475
- protected readonly decayWeight = 1;
1476
- private currentFlashlightStrain;
1477
- private readonly skillMultiplier;
1478
- static difficultyToPerformance(difficulty: number): number;
1479
- difficultyValue(): number;
1480
- protected strainValueAt(current: OsuDifficultyHitObject): number;
1481
- protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1482
- protected saveToHitObject(current: OsuDifficultyHitObject): void;
1483
- }
1484
-
1485
1186
  /**
1486
1187
  * An evaluator for calculating osu!standard Flashlight skill.
1487
1188
  */
@@ -1507,12 +1208,212 @@ declare abstract class OsuFlashlightEvaluator {
1507
1208
  }
1508
1209
 
1509
1210
  /**
1510
- * A performance points calculator that calculates performance points for osu!standard gamemode.
1211
+ * An evaluator for calculating osu!standard Rhythm skill.
1511
1212
  */
1512
- declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficultyAttributes> {
1513
- /**
1514
- * The aim performance value.
1515
- */
1213
+ declare abstract class OsuRhythmEvaluator {
1214
+ private static readonly historyTimeMax;
1215
+ private static readonly historyObjectsMax;
1216
+ private static readonly rhythmOverallMultiplier;
1217
+ private static readonly rhythmRatioMultiplier;
1218
+ /**
1219
+ * Calculates a rhythm multiplier for the difficulty of the tap associated
1220
+ * with historic data of the current object.
1221
+ *
1222
+ * @param current The current object.
1223
+ */
1224
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1225
+ }
1226
+
1227
+ /**
1228
+ * An evaluator for calculating osu!standard speed skill.
1229
+ */
1230
+ declare abstract class OsuSpeedEvaluator {
1231
+ private static readonly minSpeedBonus;
1232
+ private static readonly DISTANCE_MULTIPLIER;
1233
+ /**
1234
+ * Evaluates the difficulty of tapping the current object, based on:
1235
+ *
1236
+ * - time between pressing the previous and current object,
1237
+ * - distance between those objects,
1238
+ * - and how easily they can be cheesed.
1239
+ *
1240
+ * @param current The current object.
1241
+ * @param mods The mods applied.
1242
+ */
1243
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject, mods: ModMap): number;
1244
+ }
1245
+
1246
+ /**
1247
+ * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1248
+ * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1249
+ */
1250
+ declare abstract class StrainSkill extends Skill implements IHasPeakDifficulty {
1251
+ /**
1252
+ * The number of sections with the highest strains, which the peak strain reductions will apply to.
1253
+ * This is done in order to decrease their impact on the overall difficulty of the map for this skill.
1254
+ */
1255
+ protected readonly reducedSectionCount: number;
1256
+ /**
1257
+ * The baseline multiplier applied to the section with the biggest strain.
1258
+ */
1259
+ protected readonly reducedSectionBaseline: number;
1260
+ protected readonly _objectStrains: number[];
1261
+ /**
1262
+ * The strains of hitobjects.
1263
+ */
1264
+ get objectStrains(): readonly number[];
1265
+ protected readonly strainPeaks: number[];
1266
+ get peaks(): readonly number[];
1267
+ private readonly sectionLength;
1268
+ private currentStrain;
1269
+ private currentSectionPeak;
1270
+ private currentSectionEnd;
1271
+ /**
1272
+ * Converts a difficulty value to a performance value.
1273
+ *
1274
+ * @param difficulty The difficulty value to convert.
1275
+ * @returns The performance value.
1276
+ */
1277
+ static difficultyToPerformance(difficulty: number): number;
1278
+ /**
1279
+ * Obtains the live strain peaks for each {@link sectionLength} of the beatmap, including the peak of the current section.
1280
+ */
1281
+ get currentStrainPeaks(): number[];
1282
+ /**
1283
+ * Returns the number of strains weighed against the top strain.
1284
+ *
1285
+ * The result is scaled by clock rate as it affects the total number of strains.
1286
+ *
1287
+ * @param difficultyValue The final difficulty value.
1288
+ */
1289
+ countTopWeightedStrains(difficultyValue: number): number;
1290
+ protected processInternal(current: DifficultyHitObject): number;
1291
+ /**
1292
+ * Calculates the starting time of a strain section at an object.
1293
+ *
1294
+ * @param current The object at which the strain section starts.
1295
+ * @returns The start time of the strain section.
1296
+ */
1297
+ protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
1298
+ /**
1299
+ * Calculates the strain value at a hitobject.
1300
+ *
1301
+ * @param current The hitobject to calculate.
1302
+ */
1303
+ protected abstract strainValueAt(current: DifficultyHitObject): number;
1304
+ /**
1305
+ * Retrieves the peak strain at a point in time.
1306
+ *
1307
+ * @param time The time to retrieve the peak strain at.
1308
+ * @param current The current hit object.
1309
+ * @returns The peak strain.
1310
+ */
1311
+ protected abstract calculateInitialStrain(time: number, current: DifficultyHitObject): number;
1312
+ /**
1313
+ * Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
1314
+ */
1315
+ private saveCurrentPeak;
1316
+ /**
1317
+ * Sets the initial strain level for a new section.
1318
+ *
1319
+ * @param time The beginning of the new section in milliseconds.
1320
+ * @param current The current hitobject.
1321
+ */
1322
+ private startNewSectionFrom;
1323
+ }
1324
+
1325
+ /**
1326
+ * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1327
+ * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1328
+ */
1329
+ declare abstract class OsuSkill extends StrainSkill {
1330
+ /**
1331
+ * The weight by which each strain value decays.
1332
+ */
1333
+ protected abstract readonly decayWeight: number;
1334
+ protected difficulty: number;
1335
+ difficultyValue(): number;
1336
+ }
1337
+
1338
+ /**
1339
+ * Holds data that can be used to calculate osu!standard performance points.
1340
+ */
1341
+ interface IOsuDifficultyAttributes extends IDifficultyAttributes {
1342
+ /**
1343
+ * The perceived approach rate **exclusive** of rate-adjusting mods (DT/HT/etc).
1344
+ *
1345
+ * Rate-adjusting mods don't directly affect the approach rate difficulty value, but have a perceived effect as a result of adjusting audio timing.
1346
+ */
1347
+ approachRate: number;
1348
+ /**
1349
+ * The health drain rate of the beatmap.
1350
+ */
1351
+ drainRate: number;
1352
+ /**
1353
+ * The difficulty corresponding to the speed skill.
1354
+ */
1355
+ speedDifficulty: number;
1356
+ /**
1357
+ * The amount of strains that are considered difficult with respect to the speed skill.
1358
+ */
1359
+ speedDifficultStrainCount: number;
1360
+ /**
1361
+ * Describes how much of {@link aimDifficultStrainCount} is contributed to by circles or sliders.
1362
+ *
1363
+ * A value closer to 0 indicates most of {@link aimDifficultStrainCount} is contributed by circles.
1364
+ *
1365
+ * A value closer to infinity indicates most of {@link aimDifficultStrainCount} is contributed by sliders.
1366
+ */
1367
+ aimTopWeightedSliderFactor: number;
1368
+ /**
1369
+ * Describes how much of {@link speedDifficultStrainCount} is contributed to by circles or sliders.
1370
+ *
1371
+ * A value closer to 0 indicates most of {@link speedDifficultStrainCount} is contributed by circles.
1372
+ *
1373
+ * A value closer to infinity indicates most of {@link speedDifficultStrainCount} is contributed by sliders.
1374
+ */
1375
+ speedTopWeightedSliderFactor: number;
1376
+ }
1377
+
1378
+ /**
1379
+ * Holds data that can be used to calculate osu!standard performance points.
1380
+ */
1381
+ declare class OsuDifficultyAttributes extends DifficultyAttributes implements IOsuDifficultyAttributes {
1382
+ approachRate: number;
1383
+ drainRate: number;
1384
+ speedDifficulty: number;
1385
+ speedDifficultStrainCount: number;
1386
+ aimTopWeightedSliderFactor: number;
1387
+ speedTopWeightedSliderFactor: number;
1388
+ constructor(cacheableAttributes?: CacheableDifficultyAttributes<IOsuDifficultyAttributes>);
1389
+ toString(): string;
1390
+ }
1391
+
1392
+ /**
1393
+ * A difficulty calculator for osu!standard gamemode.
1394
+ */
1395
+ declare class OsuDifficultyCalculator extends DifficultyCalculator<OsuPlayableBeatmap, OsuDifficultyHitObject, OsuDifficultyAttributes> {
1396
+ private readonly starRatingMultiplier;
1397
+ constructor();
1398
+ retainDifficultyAdjustmentMods(mods: Mod[]): Mod[];
1399
+ protected createDifficultyAttributes(_beatmap: Beatmap, playableBeatmap: OsuPlayableBeatmap, skills: Skill[]): OsuDifficultyAttributes;
1400
+ protected createPlayableBeatmap(beatmap: Beatmap, mods?: ModMap): OsuPlayableBeatmap;
1401
+ protected createDifficultyHitObjects(beatmap: OsuPlayableBeatmap): OsuDifficultyHitObject[];
1402
+ protected createSkills(beatmap: OsuPlayableBeatmap): OsuSkill[];
1403
+ protected createStrainPeakSkills(beatmap: OsuPlayableBeatmap): StrainSkill[];
1404
+ private calculateMechanicalDifficultyRating;
1405
+ private calculateStarRating;
1406
+ static calculateRateAdjustedApproachRate(approachRate: number, clockRate: number): number;
1407
+ static calculateRateAdjustedOverallDifficulty(overallDifficulty: number, clockRate: number): number;
1408
+ }
1409
+
1410
+ /**
1411
+ * A performance points calculator that calculates performance points for osu!standard gamemode.
1412
+ */
1413
+ declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficultyAttributes> {
1414
+ /**
1415
+ * The aim performance value.
1416
+ */
1516
1417
  aim: number;
1517
1418
  /**
1518
1419
  * The speed performance value.
@@ -1594,27 +1495,360 @@ declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficu
1594
1495
  }
1595
1496
 
1596
1497
  /**
1597
- * An evaluator for calculating osu!standard Rhythm skill.
1498
+ * Data class for variable length strain.
1598
1499
  */
1599
- declare abstract class OsuRhythmEvaluator {
1600
- private static readonly historyTimeMax;
1601
- private static readonly historyObjectsMax;
1602
- private static readonly rhythmOverallMultiplier;
1603
- private static readonly rhythmRatioMultiplier;
1500
+ declare class StrainPeak {
1501
+ readonly value: number;
1502
+ readonly sectionLength: number;
1503
+ constructor(value: number, sectionLength: number);
1504
+ compareTo(other: StrainPeak): number;
1505
+ }
1506
+
1507
+ /**
1508
+ * A skill that evaluates strain over a variable length of time. A new strain peak is created for every
1509
+ * {@link DifficultyHitObject}.
1510
+ */
1511
+ declare abstract class VariableLengthStrainSkill extends Skill implements IHasPeakDifficulty {
1604
1512
  /**
1605
- * Calculates a rhythm multiplier for the difficulty of the tap associated
1606
- * with historic data of the current object.
1513
+ * The weight by which each strain value decays.
1514
+ */
1515
+ protected readonly decayWeight: number;
1516
+ /**
1517
+ * The maximum length of a strain section, in milliseconds.
1518
+ */
1519
+ protected readonly maxSectionLength: number;
1520
+ /**
1521
+ * The number of {@link maxSectionLength} sections calculated such that enough of the difficulty value is preserved.
1607
1522
  *
1608
- * @param current The current object.
1523
+ * This should be overridden if strains are ever used outside of {@link difficultyValue}, or if {@link difficultyValue}
1524
+ * is overridden to not use the default geometric sum.
1525
+ *
1526
+ * This should be removed in the future when a better memory-saving technique is implemented.
1609
1527
  */
1610
- static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1528
+ protected get maxStoredSections(): number;
1529
+ private currentSectionPeak;
1530
+ private currentSectionBegin;
1531
+ private currentSectionEnd;
1532
+ private totalLength;
1533
+ private readonly strainPeaks;
1534
+ get peaks(): readonly number[];
1535
+ /**
1536
+ * Stores previous strains so that, if a difficult {@link DifficultyHitObject} is followed by an easier
1537
+ * {@link DifficultyHitObject}, the difficult one gets a full strain instead of being cut short.
1538
+ */
1539
+ private readonly queuedStrains;
1540
+ static difficultyToPerformance(difficulty: number): number;
1541
+ /**
1542
+ * Obtains the live strain peaks for each {@link maxSectionLength} of the beatmap, including the
1543
+ * peak of the current section.
1544
+ */
1545
+ get currentStrainPeaks(): StrainPeak[];
1546
+ difficultyValue(): number;
1547
+ /**
1548
+ * Returns the number of strains weighed against the top strain.
1549
+ *
1550
+ * The result is scaled by clock rate as it affects the total number of strains.
1551
+ */
1552
+ countTopWeightedStrains(difficultyValue: number): number;
1553
+ protected processInternal(current: DifficultyHitObject): number;
1554
+ /**
1555
+ * Calculates the strain value at the {@link DifficultyHitObject}. This value is calculated with or without respect to
1556
+ * previous {@link DifficultyHitObject}s.
1557
+ *
1558
+ * @param current The {@link DifficultyHitObject} for which the strain value should be calculated.
1559
+ */
1560
+ protected abstract strainValueAt(current: DifficultyHitObject): number;
1561
+ /**
1562
+ * Retrieves the peak strain at a point in time.
1563
+ *
1564
+ * @param time The time to retrieve the peak strain at.
1565
+ * @param current The current hit object.
1566
+ * @returns The peak strain.
1567
+ */
1568
+ protected abstract calculateInitialStrain(time: number, current: DifficultyHitObject): number;
1569
+ /**
1570
+ * Fills the space between the end of the current section and the current {@link DifficultyHitObject}, if any.
1571
+ *
1572
+ * @param current The current {@link DifficultyHitObject}.
1573
+ */
1574
+ private backfillPeaks;
1575
+ /**
1576
+ * Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
1577
+ */
1578
+ private saveCurrentPeak;
1579
+ private startNewSectionFrom;
1580
+ private addStrainPeakInPlace;
1581
+ }
1582
+
1583
+ /**
1584
+ * Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
1585
+ */
1586
+ declare class DroidAim extends VariableLengthStrainSkill {
1587
+ private currentStrain;
1588
+ private readonly skillMultiplierSnap;
1589
+ private readonly skillMultiplierAgility;
1590
+ private readonly skillMultiplierFlow;
1591
+ private readonly skillMultiplierTotal;
1592
+ private readonly combinedSnapNormExponent;
1593
+ /**
1594
+ * The number of sections with the highest strains, which the peak strain reductions will apply to.
1595
+ * This is done in order to decrease their impact on the overall difficulty of the beatmap.
1596
+ */
1597
+ private readonly reducedSectionTime;
1598
+ /**
1599
+ * The baseline multiplier applied to the section with the biggest strain.
1600
+ */
1601
+ private readonly reducedStrainBaseline;
1602
+ private readonly sliderStrains;
1603
+ private maxSliderStrain;
1604
+ readonly withSliders: boolean;
1605
+ constructor(mods: ModMap, withSliders: boolean);
1606
+ /**
1607
+ * Obtains the amount of sliders that are considered difficult in terms of relative strain.
1608
+ */
1609
+ countDifficultSliders(): number;
1610
+ /**
1611
+ * Obtains the amount of sliders that are considered difficult in terms of relative strain, weighted by consistency.
1612
+ *
1613
+ * @param difficultyValue The final difficulty value.
1614
+ */
1615
+ countTopWeightedSliders(difficultyValue: number): number;
1616
+ protected strainValueAt(current: DroidDifficultyHitObject): number;
1617
+ protected calculateInitialStrain(time: number, current: DroidDifficultyHitObject): number;
1618
+ protected saveToHitObject(current: DroidDifficultyHitObject, difficulty: number): void;
1619
+ private calculateAdjustedDifficulty;
1620
+ private calculateTotalValue;
1621
+ /**
1622
+ * Converts the ratio of snap to flow into the probability of snapping or flowing.
1623
+ *
1624
+ * Constraints:
1625
+ * - `P(snap) + P(flow) = 1` (the object is always either snapped or flowed)
1626
+ * - `P(snap) = f(snap / flow)` and `P(flow) = f(flow/snap)` (i.e., snap and flow are symmetric and
1627
+ * reversible). This means `f(x) + f(1/x) = 1`
1628
+ * - `0 <= f(x) <= 1` (cannot have negative or greater than 100% probability of snapping or flowing)
1629
+ *
1630
+ * This logistic function is a solution, which fits nicely with the general idea of interpolation and
1631
+ * provides a tuneable constant.
1632
+ *
1633
+ * @param ratio The ratio.
1634
+ * @returns The probability.
1635
+ */
1636
+ private calculateSnapFlowProbability;
1637
+ difficultyValue(): number;
1638
+ private getReducedStrainPeaks;
1639
+ private strainDecay;
1640
+ }
1641
+
1642
+ /**
1643
+ * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1644
+ * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1645
+ */
1646
+ declare abstract class DroidSkill extends StrainSkill {
1647
+ /**
1648
+ * The bonus multiplier that is given for a sequence of notes of equal difficulty.
1649
+ */
1650
+ protected abstract readonly starsPerDouble: number;
1651
+ protected difficulty: number;
1652
+ process(current: DifficultyHitObject): void;
1653
+ difficultyValue(): number;
1654
+ /**
1655
+ * Gets the strain of a hitobject.
1656
+ *
1657
+ * @param current The hitobject to get the strain from.
1658
+ * @returns The strain of the hitobject.
1659
+ */
1660
+ protected abstract getObjectStrain(current: DifficultyHitObject): number;
1661
+ protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
1662
+ }
1663
+
1664
+ /**
1665
+ * Represents the skill required to memorize and hit every object in a beatmap with the Flashlight mod enabled.
1666
+ */
1667
+ declare class DroidFlashlight extends DroidSkill {
1668
+ private readonly totalObjects;
1669
+ protected readonly reducedSectionCount = 0;
1670
+ protected readonly reducedSectionBaseline = 1;
1671
+ protected readonly starsPerDouble = 1.06;
1672
+ private readonly skillMultiplier;
1673
+ private currentFlashlightStrain;
1674
+ static difficultyToPerformance(difficulty: number): number;
1675
+ constructor(mods: ModMap, totalObjects: number);
1676
+ protected strainValueAt(current: DroidDifficultyHitObject): number;
1677
+ protected calculateInitialStrain(time: number, current: DifficultyHitObject): number;
1678
+ protected getObjectStrain(): number;
1679
+ protected saveToHitObject(current: DroidDifficultyHitObject): void;
1680
+ difficultyValue(): number;
1681
+ private calculateAdjustedDifficulty;
1682
+ private strainDecay;
1683
+ }
1684
+
1685
+ /**
1686
+ * A skill that calculates the difficulty of {@link DifficultyHitObject}s using harmonic summation.
1687
+ */
1688
+ declare abstract class HarmonicSkill extends Skill implements IHasPeakDifficulty {
1689
+ private _noteWeightSum;
1690
+ /**
1691
+ * The sum of note weights, calculated during summation.
1692
+ *
1693
+ * Required for any calculations that normalizes the difficulty value.
1694
+ */
1695
+ protected get noteWeightSum(): number;
1696
+ /**
1697
+ * Scaling factor applied as `x / (i + 1)`, where `x` is the skill's {@link harmonicScale} and `i`
1698
+ * is the index of the {@link DifficultyHitObject} being processed.
1699
+ *
1700
+ * A higher value increases the influence of the hardest {@link DifficultyHitObject}s during summation.
1701
+ */
1702
+ protected readonly harmonicScale: number;
1703
+ /**
1704
+ * An exponent that controls the rate of which decay increases as the index increases.
1705
+ *
1706
+ * Values closer to 1 decay faster, whilst lower values give more weight to easier {@link DifficultyHitObject}s.
1707
+ */
1708
+ protected readonly decayExponent: number;
1709
+ get peaks(): readonly number[];
1710
+ static difficultyToPerformance(difficulty: number): number;
1711
+ difficultyValue(): number;
1712
+ /**
1713
+ * Calculates the amount of object difficulties weighed against the top object difficulty.
1714
+ *
1715
+ * @param difficultyValue The final difficulty value.
1716
+ */
1717
+ countTopWeightedObjectDifficulties(difficultyValue: number): number;
1718
+ /**
1719
+ * Transforms the difficulties of {@link DifficultyHitObject}s before they are summed together.
1720
+ *
1721
+ * This can be used to decrease weight of certain {@link DifficultyHitObject}s based on a skill-specific criteria.
1722
+ *
1723
+ * @param difficulties The difficulties of {@link DifficultyHitObject}s to transform.
1724
+ */
1725
+ protected applyDifficultyTransformation(difficulties: number[]): void;
1726
+ protected processInternal(current: DifficultyHitObject): number;
1727
+ /**
1728
+ * Calculates the difficulty value of a {@link DifficultyHitObject}. This value is calculated with or without respect to previous objects.
1729
+ *
1730
+ * @param current The {@link DifficultyHitObject} for which the difficulty value should be calculated.
1731
+ */
1732
+ protected abstract objectDifficultyOf(current: DifficultyHitObject): number;
1733
+ }
1734
+
1735
+ /**
1736
+ * Represents the skill required to read every object in the beatmap.
1737
+ */
1738
+ declare class DroidReading extends HarmonicSkill {
1739
+ private readonly clockRate;
1740
+ private readonly hitObjects;
1741
+ private currentDifficulty;
1742
+ private readonly skillMultiplier;
1743
+ private readonly difficultyDecayBase;
1744
+ constructor(mods: ModMap, clockRate: number, hitObjects: readonly PlaceableHitObject[]);
1745
+ countTopWeightedObjectDifficulties(difficultyValue: number): number;
1746
+ protected objectDifficultyOf(current: DroidDifficultyHitObject): number;
1747
+ protected applyDifficultyTransformation(difficulties: number[]): void;
1748
+ protected saveToHitObject(current: DroidDifficultyHitObject, difficulty: number): void;
1749
+ private calculateAdjustedDifficulty;
1750
+ private calculateReducedNoteCount;
1751
+ private difficultyDecay;
1752
+ }
1753
+
1754
+ /**
1755
+ * Represents the skill required to properly follow a beatmap's rhythm.
1756
+ */
1757
+ declare class DroidRhythm extends HarmonicSkill {
1758
+ protected readonly harmonicScale = 25;
1759
+ protected readonly decayExponent = 0.8;
1760
+ private readonly skillMultiplier;
1761
+ private readonly strainDecayBase;
1762
+ private currentRhythmDifficulty;
1763
+ private currentRhythmMultiplier;
1764
+ private readonly useSliderAccuracy;
1765
+ constructor(mods: ModMap);
1766
+ protected objectDifficultyOf(current: DroidDifficultyHitObject): number;
1767
+ protected saveToHitObject(current: DroidDifficultyHitObject): void;
1768
+ private strainDecay;
1769
+ }
1770
+
1771
+ /**
1772
+ * Represents the skill required to press keys or tap with regards to keeping up with the speed at which objects need to be hit.
1773
+ */
1774
+ declare class DroidTap extends HarmonicSkill {
1775
+ protected readonly harmonicScale = 20;
1776
+ private readonly skillMultiplier;
1777
+ private readonly strainDecayBase;
1778
+ private currentTapDifficulty;
1779
+ private currentRhythmMultiplier;
1780
+ private readonly sliderDifficulties;
1781
+ private maxDifficulty;
1782
+ readonly considerCheesability: boolean;
1783
+ constructor(mods: ModMap, considerCheesability: boolean);
1784
+ /**
1785
+ * The amount of notes that are relevant to the difficulty.
1786
+ */
1787
+ relevantNoteCount(): number;
1788
+ /**
1789
+ * Obtains the amount of sliders that are considered difficult in terms of relative difficulty, weighted by consistency.
1790
+ *
1791
+ * @param difficultyValue The final difficulty value.
1792
+ */
1793
+ countTopWeightedSliders(difficultyValue: number): number;
1794
+ protected objectDifficultyOf(current: DroidDifficultyHitObject): number;
1795
+ protected saveToHitObject(current: DroidDifficultyHitObject): void;
1796
+ private strainDecay;
1797
+ }
1798
+
1799
+ /**
1800
+ * Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
1801
+ */
1802
+ declare class OsuAim extends OsuSkill {
1803
+ private readonly strainDecayBase;
1804
+ protected readonly reducedSectionCount = 10;
1805
+ protected readonly reducedSectionBaseline = 0.75;
1806
+ protected readonly decayWeight = 0.9;
1807
+ private currentAimStrain;
1808
+ private readonly skillMultiplier;
1809
+ private readonly sliderStrains;
1810
+ readonly withSliders: boolean;
1811
+ constructor(mods: ModMap, withSliders: boolean);
1812
+ /**
1813
+ * Obtains the amount of sliders that are considered difficult in terms of relative strain.
1814
+ */
1815
+ countDifficultSliders(): number;
1816
+ /**
1817
+ * Obtains the amount of sliders that are considered difficult in terms of relative strain, weighted by consistency.
1818
+ */
1819
+ countTopWeightedSliders(): number;
1820
+ protected strainValueAt(current: OsuDifficultyHitObject): number;
1821
+ protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1822
+ /**
1823
+ * @param current The hitobject to save to.
1824
+ */
1825
+ protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
1826
+ private strainDecay;
1827
+ }
1828
+
1829
+ /**
1830
+ * Represents the skill required to memorize and hit every object in a beatmap with the Flashlight mod enabled.
1831
+ */
1832
+ declare class OsuFlashlight extends OsuSkill {
1833
+ private readonly strainDecayBase;
1834
+ protected readonly reducedSectionCount = 0;
1835
+ protected readonly reducedSectionBaseline = 1;
1836
+ protected readonly decayWeight = 1;
1837
+ private currentFlashlightStrain;
1838
+ private readonly skillMultiplier;
1839
+ static difficultyToPerformance(difficulty: number): number;
1840
+ difficultyValue(): number;
1841
+ protected strainValueAt(current: OsuDifficultyHitObject): number;
1842
+ protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1843
+ protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
1844
+ private strainDecay;
1611
1845
  }
1612
1846
 
1613
1847
  /**
1614
1848
  * Represents the skill required to press keys or tap with regards to keeping up with the speed at which objects need to be hit.
1615
1849
  */
1616
1850
  declare class OsuSpeed extends OsuSkill {
1617
- protected readonly strainDecayBase = 0.3;
1851
+ private readonly strainDecayBase;
1618
1852
  protected readonly reducedSectionCount = 5;
1619
1853
  protected readonly reducedSectionBaseline = 0.75;
1620
1854
  protected readonly decayWeight = 0.9;
@@ -1639,33 +1873,9 @@ declare class OsuSpeed extends OsuSkill {
1639
1873
  /**
1640
1874
  * @param current The hitobject to save to.
1641
1875
  */
1642
- protected saveToHitObject(current: OsuDifficultyHitObject): void;
1643
- }
1644
-
1645
- /**
1646
- * An evaluator for calculating osu!standard speed skill.
1647
- */
1648
- declare abstract class OsuSpeedEvaluator {
1649
- /**
1650
- * Spacing threshold for a single hitobject spacing.
1651
- *
1652
- * About 1.25 circles distance between hitobject centers.
1653
- */
1654
- private static readonly SINGLE_SPACING_THRESHOLD;
1655
- private static readonly minSpeedBonus;
1656
- private static readonly DISTANCE_MULTIPLIER;
1657
- /**
1658
- * Evaluates the difficulty of tapping the current object, based on:
1659
- *
1660
- * - time between pressing the previous and current object,
1661
- * - distance between those objects,
1662
- * - and how easily they can be cheesed.
1663
- *
1664
- * @param current The current object.
1665
- * @param mods The mods applied.
1666
- */
1667
- static evaluateDifficultyOf(current: OsuDifficultyHitObject, mods: ModMap): number;
1876
+ protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
1877
+ private strainDecay;
1668
1878
  }
1669
1879
 
1670
- export { DifficultyAttributes, DifficultyCalculator, DifficultyHitObject, DroidAim, DroidAimEvaluator, DroidDifficultyAttributes, DroidDifficultyCalculator, DroidDifficultyHitObject, DroidFlashlight, DroidFlashlightEvaluator, DroidPerformanceCalculator, DroidReading, DroidReadingEvaluator, DroidRhythm, DroidRhythmEvaluator, DroidTap, DroidTapEvaluator, ExtendedDroidDifficultyAttributes, OsuAim, OsuAimEvaluator, OsuDifficultyAttributes, OsuDifficultyCalculator, OsuDifficultyHitObject, OsuFlashlight, OsuFlashlightEvaluator, OsuPerformanceCalculator, OsuRhythmEvaluator, OsuSpeed, OsuSpeedEvaluator, PerformanceCalculator };
1880
+ export { DifficultyAttributes, DifficultyCalculator, DifficultyHitObject, DroidAgilityEvaluator, DroidAim, DroidDifficultyAttributes, DroidDifficultyCalculator, DroidDifficultyHitObject, DroidFlashlight, DroidFlashlightEvaluator, DroidFlowAimEvaluator, DroidPerformanceCalculator, DroidReading, DroidReadingEvaluator, DroidRhythm, DroidRhythmEvaluator, DroidSnapAimEvaluator, DroidTap, DroidTapEvaluator, ExtendedDroidDifficultyAttributes, OsuAim, OsuAimEvaluator, OsuDifficultyAttributes, OsuDifficultyCalculator, OsuDifficultyHitObject, OsuFlashlight, OsuFlashlightEvaluator, OsuPerformanceCalculator, OsuRhythmEvaluator, OsuSpeed, OsuSpeedEvaluator, PerformanceCalculator };
1671
1881
  export type { CacheableDifficultyAttributes, DifficultSlider, HighStrainSection, IDifficultyAttributes, IDroidDifficultyAttributes, IExtendedDroidDifficultyAttributes, IOsuDifficultyAttributes, PerformanceCalculationOptions, StrainPeaks };