@rian8337/osu-difficulty-calculator 4.0.0-beta.94 → 4.0.0-beta.95

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 +1290 -802
  2. package/package.json +3 -3
  3. package/typings/index.d.ts +326 -179
@@ -26,6 +26,10 @@ declare abstract class DifficultyHitObject {
26
26
  * The flashlight strain generated by the hitobject.
27
27
  */
28
28
  flashlightStrain: number;
29
+ /**
30
+ * The reading difficulty generated by the hitobject.
31
+ */
32
+ readingDifficulty: number;
29
33
  /**
30
34
  * The rhythm multiplier generated by the hitobject. This is used to alter tap strain.
31
35
  */
@@ -249,6 +253,10 @@ interface IDifficultyAttributes {
249
253
  * The difficulty corresponding to the flashlight skill.
250
254
  */
251
255
  flashlightDifficulty: number;
256
+ /**
257
+ * The difficulty corresponding to the reading skill.
258
+ */
259
+ readingDifficulty: number;
252
260
  /**
253
261
  * The number of clickable objects weighted by difficulty.
254
262
  *
@@ -293,6 +301,18 @@ interface IDifficultyAttributes {
293
301
  * The amount of strains that are considered difficult with respect to the aim skill.
294
302
  */
295
303
  aimDifficultStrainCount: number;
304
+ /**
305
+ * Describes how much of {@link aimDifficultStrainCount} is contributed to by circles or sliders.
306
+ *
307
+ * A value closer to 0 indicates most of {@link aimDifficultStrainCount} is contributed by circles.
308
+ *
309
+ * A value closer to infinity indicates most of {@link aimDifficultStrainCount} is contributed by sliders.
310
+ */
311
+ aimTopWeightedSliderFactor: number;
312
+ /**
313
+ * The amount of notes that are considered difficult with respect to the reading skill.
314
+ */
315
+ readingDifficultNoteCount: number;
296
316
  }
297
317
 
298
318
  /**
@@ -314,6 +334,7 @@ declare abstract class DifficultyAttributes implements IDifficultyAttributes {
314
334
  maxCombo: number;
315
335
  aimDifficulty: number;
316
336
  flashlightDifficulty: number;
337
+ readingDifficulty: number;
317
338
  speedNoteCount: number;
318
339
  sliderFactor: number;
319
340
  clockRate: number;
@@ -323,6 +344,8 @@ declare abstract class DifficultyAttributes implements IDifficultyAttributes {
323
344
  spinnerCount: number;
324
345
  aimDifficultSliderCount: number;
325
346
  aimDifficultStrainCount: number;
347
+ aimTopWeightedSliderFactor: number;
348
+ readingDifficultNoteCount: number;
326
349
  constructor(cacheableAttributes?: CacheableDifficultyAttributes<IDifficultyAttributes>);
327
350
  /**
328
351
  * Converts this `DifficultyAttributes` instance to an attribute structure that can be cached.
@@ -391,17 +414,10 @@ declare abstract class Skill {
391
414
  */
392
415
  protected readonly mods: ModMap;
393
416
  private _objectDifficulties;
394
- private _objectTimes;
395
417
  /**
396
418
  * The difficulties of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
397
419
  */
398
420
  protected get objectDifficulties(): readonly number[];
399
- /**
400
- * The start times of {@link DifficultyHitObject}s, populated by {@link Skill.process}.
401
- *
402
- * Indices correspond to {@link objectDifficulties}.
403
- */
404
- protected get objectTimes(): readonly number[];
405
421
  constructor(mods: ModMap);
406
422
  /**
407
423
  * Calculates the strain value of a hitobject and stores the value in it.
@@ -653,10 +669,6 @@ declare class DroidDifficultyHitObject extends DifficultyHitObject {
653
669
  * The rhythm difficulty generated by the hitobject.
654
670
  */
655
671
  rhythmDifficulty: number;
656
- /**
657
- * The reading difficulty generated by the hitobject.
658
- */
659
- readingDifficulty: number;
660
672
  readonly normalizedRadius = 50;
661
673
  protected readonly mode = Modes.Droid;
662
674
  protected get maximumSliderRadius(): number;
@@ -711,26 +723,10 @@ interface IDroidDifficultyAttributes extends IDifficultyAttributes {
711
723
  * The difficulty corresponding to the rhythm skill.
712
724
  */
713
725
  rhythmDifficulty: number;
714
- /**
715
- * The difficulty corresponding to the reading skill.
716
- */
717
- readingDifficulty: number;
718
726
  /**
719
727
  * The amount of strains that are considered difficult with respect to the tap skill.
720
728
  */
721
729
  tapDifficultStrainCount: number;
722
- /**
723
- * The amount of notes that are considered difficult with respect to the reading skill.
724
- */
725
- readingDifficultNoteCount: number;
726
- /**
727
- * Describes how much of {@link aimDifficultStrainCount} is contributed to by circles or sliders.
728
- *
729
- * A value closer to 0 indicates most of {@link aimDifficultStrainCount} is contributed by circles.
730
- *
731
- * A value closer to infinity indicates most of {@link aimDifficultStrainCount} is contributed by sliders.
732
- */
733
- aimTopWeightedSliderFactor: number;
734
730
  /**
735
731
  * Describes how much of {@link tapDifficultStrainCount} is contributed to by circles or sliders.
736
732
  *
@@ -750,10 +746,7 @@ interface IDroidDifficultyAttributes extends IDifficultyAttributes {
750
746
  */
751
747
  declare class DroidDifficultyAttributes extends DifficultyAttributes implements IDroidDifficultyAttributes {
752
748
  tapDifficulty: number;
753
- readingDifficulty: number;
754
- aimTopWeightedSliderFactor: number;
755
749
  tapTopWeightedSliderFactor: number;
756
- readingDifficultNoteCount: number;
757
750
  rhythmDifficulty: number;
758
751
  tapDifficultStrainCount: number;
759
752
  maximumScore: number;
@@ -1176,32 +1169,21 @@ declare class OsuDifficultyHitObject extends DifficultyHitObject {
1176
1169
  speedStrain: number;
1177
1170
  readonly normalizedRadius = 50;
1178
1171
  get smallCircleBonus(): number;
1172
+ get overallDifficulty(): number;
1179
1173
  protected readonly mode = Modes.Osu;
1180
1174
  }
1181
1175
 
1182
1176
  /**
1183
- * An evaluator for calculating osu!standard Aim skill.
1177
+ * An evaluator for calculating osu!standard agility aim difficulty.
1184
1178
  */
1185
- declare abstract class OsuAimEvaluator {
1186
- private static readonly wideAngleMultiplier;
1187
- private static readonly acuteAngleMultiplier;
1188
- private static readonly sliderMultiplier;
1189
- private static readonly velocityChangeMultiplier;
1190
- private static readonly wiggleMultiplier;
1179
+ declare abstract class OsuAgilityEvaluator {
1191
1180
  /**
1192
- * Evaluates the difficulty of aiming the current object, based on:
1193
- *
1194
- * - cursor velocity to the current object,
1195
- * - angle difficulty,
1196
- * - sharp velocity increases,
1197
- * - and slider difficulty.
1181
+ * Evaluates the difficulty of fast aiming the current object.
1198
1182
  *
1199
1183
  * @param current The current object.
1200
- * @param withSliders Whether to take slider difficulty into account.
1201
1184
  */
1202
- static evaluateDifficultyOf(current: OsuDifficultyHitObject, withSliders: boolean): number;
1203
- private static calculateWideAngleBonus;
1204
- private static calculateAcuteAngleBonus;
1185
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1186
+ private static highBpmBonus;
1205
1187
  }
1206
1188
 
1207
1189
  /**
@@ -1229,132 +1211,143 @@ declare abstract class OsuFlashlightEvaluator {
1229
1211
  }
1230
1212
 
1231
1213
  /**
1232
- * An evaluator for calculating osu!standard Rhythm skill.
1214
+ * An evaluator for calculating osu!standard flow aim difficulty.
1233
1215
  */
1234
- declare abstract class OsuRhythmEvaluator {
1235
- private static readonly historyTimeMax;
1236
- private static readonly historyObjectsMax;
1237
- private static readonly rhythmOverallMultiplier;
1238
- private static readonly rhythmRatioMultiplier;
1239
- /**
1240
- * Calculates a rhythm multiplier for the difficulty of the tap associated
1241
- * with historic data of the current object.
1242
- *
1243
- * @param current The current object.
1244
- */
1245
- static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1216
+ declare abstract class OsuFlowAimEvaluator {
1217
+ private static readonly velocityChangeMultiplier;
1218
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject, withSliders: boolean): number;
1219
+ private static calculateOverlapFactor;
1246
1220
  }
1247
1221
 
1248
1222
  /**
1249
- * An evaluator for calculating osu!standard speed skill.
1223
+ * Evaluator for reading difficulty in osu!standard.
1250
1224
  */
1251
- declare abstract class OsuSpeedEvaluator {
1252
- private static readonly minSpeedBonus;
1253
- private static readonly DISTANCE_MULTIPLIER;
1225
+ declare abstract class OsuReadingEvaluator {
1226
+ private static readonly readingWindowSize;
1227
+ private static readonly hiddenMultiplier;
1228
+ private static readonly densityMultiplier;
1229
+ private static readonly densityDifficultyBase;
1230
+ private static readonly preemptBalancingFactor;
1231
+ private static readonly preemptStartingPoint;
1232
+ private static readonly minimumAngleRelevancyTime;
1233
+ private static readonly maximumAngleRelevancyTime;
1254
1234
  /**
1255
- * Evaluates the difficulty of tapping the current object, based on:
1256
- *
1257
- * - time between pressing the previous and current object,
1258
- * - distance between those objects,
1259
- * - and how easily they can be cheesed.
1260
- *
1261
- * @param current The current object.
1262
- * @param mods The mods applied.
1235
+ * Evaluates the difficulty of reading the object.
1263
1236
  */
1264
1237
  static evaluateDifficultyOf(current: OsuDifficultyHitObject, mods: ModMap): number;
1265
- }
1266
-
1267
- /**
1268
- * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1269
- * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1270
- */
1271
- declare abstract class StrainSkill extends Skill implements IHasPeakDifficulty {
1272
- /**
1273
- * The number of sections with the highest strains, which the peak strain reductions will apply to.
1274
- * This is done in order to decrease their impact on the overall difficulty of the map for this skill.
1275
- */
1276
- protected readonly reducedSectionCount: number;
1277
1238
  /**
1278
- * The baseline multiplier applied to the section with the biggest strain.
1239
+ * Calculates the density difficulty of the current object and how hard it is to aim it because of it based on:
1240
+ *
1241
+ * - cursor velocity to the current object,
1242
+ * - how many times the current object's angle was repeated,
1243
+ * - density of objects visible when the current object appears, and
1244
+ * - density of objects visible when the current object needs to be clicked.
1279
1245
  */
1280
- protected readonly reducedSectionBaseline: number;
1281
- protected readonly _objectStrains: number[];
1246
+ private static calculateDensityDifficulty;
1282
1247
  /**
1283
- * The strains of hitobjects.
1248
+ * Calculates the difficulty of aiming the current object when the approach rate is very high based on:
1249
+ *
1250
+ * - cursor velocity to the current object,
1251
+ * - how many times the current object's angle was repeated, and
1252
+ * - how many milliseconds elapse between the approach circle appearing and touching the inner circle.
1284
1253
  */
1285
- get objectStrains(): readonly number[];
1286
- protected readonly strainPeaks: number[];
1287
- private readonly strainPeakTimes;
1288
- get peaks(): readonly TimedStrainPeak[];
1289
- private readonly sectionLength;
1290
- private currentStrain;
1291
- private currentSectionPeak;
1292
- private currentSectionEnd;
1254
+ private static calculatePreemptDifficulty;
1293
1255
  /**
1294
- * Converts a difficulty value to a performance value.
1256
+ * Calculates the difficulty of aiming the current object when the Hidden mod is active based on:
1295
1257
  *
1296
- * @param difficulty The difficulty value to convert.
1297
- * @returns The performance value.
1258
+ * - cursor velocity to the current object,
1259
+ * - time the current object spends invisible,
1260
+ * - density of objects visible when the current object appears,
1261
+ * - density of objects visible when the current object needs to be clicked,
1262
+ * - how many times the current object's angle was repeated, and
1263
+ * - if the current object is perfectly stacked to the previous one.
1298
1264
  */
1299
- static difficultyToPerformance(difficulty: number): number;
1265
+ private static calculateHiddenDifficulty;
1266
+ private static getPastObjectDifficultyInfluence;
1300
1267
  /**
1301
- * Obtains the live strain peaks for each {@link sectionLength} of the beatmap, including the peak of the current section.
1268
+ * Returns a list of objects that are visible on screen at the point in time the current object becomes visible.
1302
1269
  */
1303
- get currentStrainPeaks(): number[];
1270
+ private static retrievePastVisibleObjects;
1304
1271
  /**
1305
- * Returns the number of strains weighed against the top strain.
1306
- *
1307
- * The result is scaled by clock rate as it affects the total number of strains.
1308
- *
1309
- * @param difficultyValue The final difficulty value.
1272
+ * Returns the density of objects visible at the point in time the current object needs to be clicked capped by the reading window.
1310
1273
  */
1311
- countTopWeightedStrains(difficultyValue: number): number;
1312
- protected processInternal(current: DifficultyHitObject): number;
1274
+ private static retrieveCurrentVisibleObjectDensity;
1313
1275
  /**
1314
- * Calculates the starting time of a strain section at an object.
1315
- *
1316
- * @param current The object at which the strain section starts.
1317
- * @returns The start time of the strain section.
1276
+ * Returns a factor of how often the current object's angle has been repeated in a certain time frame.
1277
+ * It does this by checking the difference in angle between current and past objects and sums them based on a range of similarity.
1278
+ * https://www.desmos.com/calculator/eb057a4822
1318
1279
  */
1319
- protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
1280
+ private static getConstantAngleNerfFactor;
1320
1281
  /**
1321
- * Calculates the strain value at a hitobject.
1322
- *
1323
- * @param current The hitobject to calculate.
1282
+ * Returns a nerfing factor for when objects are very distant in time, affecting reading less.
1324
1283
  */
1325
- protected abstract strainValueAt(current: DifficultyHitObject): number;
1284
+ private static getTimeNerfFactor;
1285
+ private static highBpmBonus;
1286
+ }
1287
+
1288
+ /**
1289
+ * An evaluator for calculating osu!standard Rhythm skill.
1290
+ */
1291
+ declare abstract class OsuRhythmEvaluator {
1292
+ private static readonly historyTimeMax;
1293
+ private static readonly historyObjectsMax;
1294
+ private static readonly rhythmOverallMultiplier;
1295
+ private static readonly rhythmRatioMultiplier;
1326
1296
  /**
1327
- * Retrieves the peak strain at a point in time.
1297
+ * Calculates a rhythm multiplier for the difficulty of the tap associated
1298
+ * with historic data of the current object.
1328
1299
  *
1329
- * @param time The time to retrieve the peak strain at.
1330
- * @param current The current hit object.
1331
- * @returns The peak strain.
1332
- */
1333
- protected abstract calculateInitialStrain(time: number, current: DifficultyHitObject): number;
1334
- /**
1335
- * Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
1300
+ * @param current The current object.
1336
1301
  */
1337
- private saveCurrentPeak;
1302
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1303
+ private static getEffectiveRatio;
1304
+ }
1305
+
1306
+ /**
1307
+ * An evaluator for calculating osu!standard snap aim difficulty.
1308
+ */
1309
+ declare abstract class OsuSnapAimEvaluator {
1310
+ private static readonly wideAngleMultiplier;
1311
+ private static readonly acuteAngleMultiplier;
1312
+ private static readonly sliderMultiplier;
1313
+ private static readonly velocityChangeMultiplier;
1314
+ private static readonly wiggleMultiplier;
1315
+ private static readonly angleRepetitionNoteLimit;
1316
+ private static readonly maximumRepetitionNerf;
1317
+ private static readonly maximumVectorInfluence;
1338
1318
  /**
1339
- * Sets the initial strain level for a new section.
1319
+ * Evaluates the difficulty of aiming the current object, based on:
1340
1320
  *
1341
- * @param time The beginning of the new section in milliseconds.
1342
- * @param current The current hitobject.
1321
+ * - cursor velocity to the current object,
1322
+ * - angle difficulty,
1323
+ * - sharp velocity increases,
1324
+ * - and slider difficulty.
1325
+ *
1326
+ * @param current The current object.
1327
+ * @param withSliders Whether to take slider difficulty into account.
1343
1328
  */
1344
- private startNewSectionFrom;
1329
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject, withSliders: boolean): number;
1330
+ private static calculateWideAngleAcuteness;
1331
+ static calculateAcuteAngleAcuteness(angle: number): number;
1332
+ private static highBpmBonus;
1333
+ private static calculateVectorAngleRepetition;
1345
1334
  }
1346
1335
 
1347
1336
  /**
1348
- * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1349
- * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1337
+ * An evaluator for calculating osu!standard speed skill.
1350
1338
  */
1351
- declare abstract class OsuSkill extends StrainSkill {
1339
+ declare abstract class OsuSpeedEvaluator {
1340
+ private static readonly minSpeedBonus;
1352
1341
  /**
1353
- * The weight by which each strain value decays.
1342
+ * Evaluates the difficulty of tapping the current object, based on:
1343
+ *
1344
+ * - time between pressing the previous and current object,
1345
+ * - and how easily they can be cheesed.
1346
+ *
1347
+ * @param current The current object.
1354
1348
  */
1355
- protected abstract readonly decayWeight: number;
1356
- protected difficulty: number;
1357
- difficultyValue(): number;
1349
+ static evaluateDifficultyOf(current: OsuDifficultyHitObject): number;
1350
+ private static highBpmBonus;
1358
1351
  }
1359
1352
 
1360
1353
  /**
@@ -1405,7 +1398,6 @@ declare class OsuDifficultyAttributes extends DifficultyAttributes implements IO
1405
1398
  drainRate: number;
1406
1399
  speedDifficulty: number;
1407
1400
  speedDifficultStrainCount: number;
1408
- aimTopWeightedSliderFactor: number;
1409
1401
  speedTopWeightedSliderFactor: number;
1410
1402
  constructor(cacheableAttributes?: CacheableDifficultyAttributes<IOsuDifficultyAttributes>);
1411
1403
  toString(): string;
@@ -1415,18 +1407,17 @@ declare class OsuDifficultyAttributes extends DifficultyAttributes implements IO
1415
1407
  * A difficulty calculator for osu!standard gamemode.
1416
1408
  */
1417
1409
  declare class OsuDifficultyCalculator extends DifficultyCalculator<OsuPlayableBeatmap, OsuDifficultyHitObject, OsuDifficultyAttributes> {
1418
- private readonly starRatingMultiplier;
1419
1410
  constructor();
1420
1411
  retainDifficultyAdjustmentMods(mods: Mod[]): Mod[];
1421
- protected createDifficultyAttributes(_beatmap: Beatmap, playableBeatmap: OsuPlayableBeatmap, skills: Skill[]): OsuDifficultyAttributes;
1412
+ protected createDifficultyAttributes(beatmap: Beatmap, playableBeatmap: OsuPlayableBeatmap, skills: Skill[]): OsuDifficultyAttributes;
1422
1413
  protected createPlayableBeatmap(beatmap: Beatmap, mods?: ModMap): OsuPlayableBeatmap;
1423
1414
  protected createDifficultyHitObjects(beatmap: OsuPlayableBeatmap): OsuDifficultyHitObject[];
1424
- protected createSkills(beatmap: OsuPlayableBeatmap): OsuSkill[];
1425
- protected createStrainPeakSkills(beatmap: OsuPlayableBeatmap): StrainSkill[];
1426
- private calculateMechanicalDifficultyRating;
1415
+ protected createSkills(beatmap: OsuPlayableBeatmap): Skill[];
1416
+ protected createStrainPeakSkills(beatmap: OsuPlayableBeatmap): (Skill & IHasPeakDifficulty)[];
1417
+ private calculateAimDifficultyRating;
1418
+ private calculateDifficultyRating;
1427
1419
  private calculateStarRating;
1428
- static calculateRateAdjustedApproachRate(approachRate: number, clockRate: number): number;
1429
- static calculateRateAdjustedOverallDifficulty(overallDifficulty: number, clockRate: number): number;
1420
+ static sumCognitionDifficulty(reading: number, flashlight: number): number;
1430
1421
  }
1431
1422
 
1432
1423
  /**
@@ -1449,11 +1440,16 @@ declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficu
1449
1440
  * The flashlight performance value.
1450
1441
  */
1451
1442
  flashlight: number;
1443
+ /**
1444
+ * The reading performance value.
1445
+ */
1446
+ reading: number;
1452
1447
  /**
1453
1448
  * The amount of misses, including slider breaks.
1454
1449
  */
1455
1450
  get effectiveMissCount(): number;
1456
- static readonly finalMultiplier = 1.14;
1451
+ static readonly finalMultiplier = 1.12;
1452
+ static readonly normExponent = 1.1;
1457
1453
  private greatWindow;
1458
1454
  private okWindow;
1459
1455
  private mehWindow;
@@ -1478,6 +1474,10 @@ declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficu
1478
1474
  * Calculates the flashlight performance value of the beatmap.
1479
1475
  */
1480
1476
  private calculateFlashlightValue;
1477
+ /**
1478
+ * Calculates the reading performance value of the beatmap.
1479
+ */
1480
+ private calculateReadingValue;
1481
1481
  /**
1482
1482
  * Calculates a strain-based miss penalty.
1483
1483
  *
@@ -1513,6 +1513,8 @@ declare class OsuPerformanceCalculator extends PerformanceCalculator<IOsuDifficu
1513
1513
  * Calculates the amount of misses + sliderbreaks from combo.
1514
1514
  */
1515
1515
  private calculateComboBasedEstimatedMissCount;
1516
+ private calculateTraceableBonus;
1517
+ private calculateRateAdjustedApproachRate;
1516
1518
  toString(): string;
1517
1519
  }
1518
1520
 
@@ -1667,6 +1669,86 @@ declare class DroidAim extends VariableLengthStrainSkill {
1667
1669
  private strainDecay;
1668
1670
  }
1669
1671
 
1672
+ /**
1673
+ * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1674
+ * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1675
+ */
1676
+ declare abstract class StrainSkill extends Skill implements IHasPeakDifficulty {
1677
+ /**
1678
+ * The number of sections with the highest strains, which the peak strain reductions will apply to.
1679
+ * This is done in order to decrease their impact on the overall difficulty of the map for this skill.
1680
+ */
1681
+ protected readonly reducedSectionCount: number;
1682
+ /**
1683
+ * The baseline multiplier applied to the section with the biggest strain.
1684
+ */
1685
+ protected readonly reducedSectionBaseline: number;
1686
+ protected readonly _objectStrains: number[];
1687
+ /**
1688
+ * The strains of hitobjects.
1689
+ */
1690
+ get objectStrains(): readonly number[];
1691
+ protected readonly strainPeaks: number[];
1692
+ private readonly strainPeakTimes;
1693
+ get peaks(): readonly TimedStrainPeak[];
1694
+ private readonly sectionLength;
1695
+ private currentStrain;
1696
+ private currentSectionPeak;
1697
+ private currentSectionEnd;
1698
+ /**
1699
+ * Converts a difficulty value to a performance value.
1700
+ *
1701
+ * @param difficulty The difficulty value to convert.
1702
+ * @returns The performance value.
1703
+ */
1704
+ static difficultyToPerformance(difficulty: number): number;
1705
+ /**
1706
+ * Obtains the live strain peaks for each {@link sectionLength} of the beatmap, including the peak of the current section.
1707
+ */
1708
+ get currentStrainPeaks(): number[];
1709
+ /**
1710
+ * Returns the number of strains weighed against the top strain.
1711
+ *
1712
+ * The result is scaled by clock rate as it affects the total number of strains.
1713
+ *
1714
+ * @param difficultyValue The final difficulty value.
1715
+ */
1716
+ countTopWeightedStrains(difficultyValue: number): number;
1717
+ protected processInternal(current: DifficultyHitObject): number;
1718
+ /**
1719
+ * Calculates the starting time of a strain section at an object.
1720
+ *
1721
+ * @param current The object at which the strain section starts.
1722
+ * @returns The start time of the strain section.
1723
+ */
1724
+ protected calculateCurrentSectionStart(current: DifficultyHitObject): number;
1725
+ /**
1726
+ * Calculates the strain value at a hitobject.
1727
+ *
1728
+ * @param current The hitobject to calculate.
1729
+ */
1730
+ protected abstract strainValueAt(current: DifficultyHitObject): number;
1731
+ /**
1732
+ * Retrieves the peak strain at a point in time.
1733
+ *
1734
+ * @param time The time to retrieve the peak strain at.
1735
+ * @param current The current hit object.
1736
+ * @returns The peak strain.
1737
+ */
1738
+ protected abstract calculateInitialStrain(time: number, current: DifficultyHitObject): number;
1739
+ /**
1740
+ * Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
1741
+ */
1742
+ private saveCurrentPeak;
1743
+ /**
1744
+ * Sets the initial strain level for a new section.
1745
+ *
1746
+ * @param time The beginning of the new section in milliseconds.
1747
+ * @param current The current hitobject.
1748
+ */
1749
+ private startNewSectionFrom;
1750
+ }
1751
+
1670
1752
  /**
1671
1753
  * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1672
1754
  * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
@@ -1715,12 +1797,19 @@ declare class DroidFlashlight extends DroidSkill {
1715
1797
  */
1716
1798
  declare abstract class HarmonicSkill extends Skill implements IHasPeakDifficulty {
1717
1799
  private _noteWeightSum;
1800
+ private _objectTimes;
1718
1801
  /**
1719
1802
  * The sum of note weights, calculated during summation.
1720
1803
  *
1721
1804
  * Required for any calculations that normalizes the difficulty value.
1722
1805
  */
1723
1806
  protected get noteWeightSum(): number;
1807
+ /**
1808
+ * The start times of {@link DifficultyHitObject}s, populated by {@link HarmonicSkill.process}.
1809
+ *
1810
+ * Indices correspond to {@link objectDifficulties}.
1811
+ */
1812
+ protected get objectTimes(): readonly number[];
1724
1813
  /**
1725
1814
  * Scaling factor applied as `x / (i + 1)`, where `x` is the skill's {@link harmonicScale} and `i`
1726
1815
  * is the index of the {@link DifficultyHitObject} being processed.
@@ -1751,6 +1840,7 @@ declare abstract class HarmonicSkill extends Skill implements IHasPeakDifficulty
1751
1840
  * @param difficulties The difficulties of {@link DifficultyHitObject}s to transform.
1752
1841
  */
1753
1842
  protected applyDifficultyTransformation(difficulties: number[]): void;
1843
+ process(current: DifficultyHitObject): void;
1754
1844
  protected processInternal(current: DifficultyHitObject): number;
1755
1845
  /**
1756
1846
  * Calculates the difficulty value of a {@link DifficultyHitObject}. This value is calculated with or without respect to previous objects.
@@ -1827,14 +1917,24 @@ declare class DroidTap extends HarmonicSkill {
1827
1917
  /**
1828
1918
  * Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
1829
1919
  */
1830
- declare class OsuAim extends OsuSkill {
1831
- private readonly strainDecayBase;
1832
- protected readonly reducedSectionCount = 10;
1833
- protected readonly reducedSectionBaseline = 0.75;
1834
- protected readonly decayWeight = 0.9;
1835
- private currentAimStrain;
1836
- private readonly skillMultiplier;
1920
+ declare class OsuAim extends VariableLengthStrainSkill {
1921
+ private currentStrain;
1922
+ private readonly skillMultiplierSnap;
1923
+ private readonly skillMultiplierAgility;
1924
+ private readonly skillMultiplierFlow;
1925
+ private readonly skillMultiplierTotal;
1926
+ private readonly combinedSnapNormExponent;
1927
+ /**
1928
+ * The number of sections with the highest strains, which the peak strain reductions will apply to.
1929
+ * This is done in order to decrease their impact on the overall difficulty of the beatmap.
1930
+ */
1931
+ private readonly reducedSectionTime;
1932
+ /**
1933
+ * The baseline multiplier applied to the section with the biggest strain.
1934
+ */
1935
+ private readonly reducedStrainBaseline;
1837
1936
  private readonly sliderStrains;
1937
+ private maxSliderStrain;
1838
1938
  readonly withSliders: boolean;
1839
1939
  constructor(mods: ModMap, withSliders: boolean);
1840
1940
  /**
@@ -1843,67 +1943,114 @@ declare class OsuAim extends OsuSkill {
1843
1943
  countDifficultSliders(): number;
1844
1944
  /**
1845
1945
  * Obtains the amount of sliders that are considered difficult in terms of relative strain, weighted by consistency.
1946
+ *
1947
+ * @param difficultyValue The final difficulty value.
1846
1948
  */
1847
- countTopWeightedSliders(): number;
1949
+ countTopWeightedSliders(difficultyValue: number): number;
1848
1950
  protected strainValueAt(current: OsuDifficultyHitObject): number;
1849
1951
  protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1952
+ protected saveToHitObject(current: OsuDifficultyHitObject): void;
1953
+ private calculateAdjustedDifficulty;
1954
+ private calculateTotalValue;
1850
1955
  /**
1851
- * @param current The hitobject to save to.
1956
+ * Converts the ratio of snap to flow into the probability of snapping or flowing.
1957
+ *
1958
+ * Constraints:
1959
+ * - `P(snap) + P(flow) = 1` (the object is always either snapped or flowed)
1960
+ * - `P(snap) = f(snap / flow)` and `P(flow) = f(flow/snap)` (i.e., snap and flow are symmetric and
1961
+ * reversible). This means `f(x) + f(1/x) = 1`
1962
+ * - `0 <= f(x) <= 1` (cannot have negative or greater than 100% probability of snapping or flowing)
1963
+ *
1964
+ * This logistic function is a solution, which fits nicely with the general idea of interpolation and
1965
+ * provides a tuneable constant.
1966
+ *
1967
+ * @param ratio The ratio.
1968
+ * @returns The probability.
1852
1969
  */
1853
- protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
1970
+ private calculateSnapFlowProbability;
1971
+ difficultyValue(): number;
1972
+ private getReducedStrainPeaks;
1854
1973
  private strainDecay;
1855
1974
  }
1856
1975
 
1976
+ /**
1977
+ * Used to processes strain values of difficulty hitobjects, keep track of strain levels caused by the processed objects
1978
+ * and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
1979
+ */
1980
+ declare abstract class OsuSkill extends StrainSkill {
1981
+ /**
1982
+ * The weight by which each strain value decays.
1983
+ */
1984
+ protected abstract readonly decayWeight: number;
1985
+ protected difficulty: number;
1986
+ difficultyValue(): number;
1987
+ }
1988
+
1857
1989
  /**
1858
1990
  * Represents the skill required to memorize and hit every object in a beatmap with the Flashlight mod enabled.
1859
1991
  */
1860
1992
  declare class OsuFlashlight extends OsuSkill {
1861
- private readonly strainDecayBase;
1993
+ private readonly totalObjects;
1862
1994
  protected readonly reducedSectionCount = 0;
1863
1995
  protected readonly reducedSectionBaseline = 1;
1864
1996
  protected readonly decayWeight = 1;
1865
1997
  private currentFlashlightStrain;
1866
1998
  private readonly skillMultiplier;
1867
1999
  static difficultyToPerformance(difficulty: number): number;
2000
+ constructor(mods: ModMap, totalObjects: number);
1868
2001
  difficultyValue(): number;
1869
2002
  protected strainValueAt(current: OsuDifficultyHitObject): number;
1870
2003
  protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1871
- protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
2004
+ protected saveToHitObject(current: OsuDifficultyHitObject): void;
2005
+ private calculateAdjustedDifficulty;
1872
2006
  private strainDecay;
1873
2007
  }
1874
2008
 
2009
+ /**
2010
+ * Represents the skill required to read every object in the beatmap.
2011
+ */
2012
+ declare class OsuReading extends HarmonicSkill {
2013
+ private readonly clockRate;
2014
+ private readonly hitObjects;
2015
+ private currentDifficulty;
2016
+ private readonly skillMultiplier;
2017
+ private readonly difficultyDecayBase;
2018
+ constructor(mods: ModMap, clockRate: number, hitObjects: readonly PlaceableHitObject[]);
2019
+ countTopWeightedObjectDifficulties(difficultyValue: number): number;
2020
+ protected objectDifficultyOf(current: OsuDifficultyHitObject): number;
2021
+ protected applyDifficultyTransformation(difficulties: number[]): void;
2022
+ protected saveToHitObject(current: DifficultyHitObject, difficulty: number): void;
2023
+ private calculateAdjustedDifficulty;
2024
+ private calculateReducedNoteCount;
2025
+ private difficultyDecay;
2026
+ }
2027
+
1875
2028
  /**
1876
2029
  * Represents the skill required to press keys or tap with regards to keeping up with the speed at which objects need to be hit.
1877
2030
  */
1878
- declare class OsuSpeed extends OsuSkill {
1879
- private readonly strainDecayBase;
1880
- protected readonly reducedSectionCount = 5;
1881
- protected readonly reducedSectionBaseline = 0.75;
1882
- protected readonly decayWeight = 0.9;
1883
- private currentSpeedStrain;
2031
+ declare class OsuSpeed extends HarmonicSkill {
2032
+ protected readonly harmonicScale = 20;
2033
+ private currentDifficulty;
1884
2034
  private currentRhythm;
1885
2035
  private readonly skillMultiplier;
1886
- private readonly sliderStrains;
1887
- private maxStrain;
2036
+ private readonly strainDecayBase;
2037
+ private readonly sliderDifficulties;
2038
+ private maxDifficulty;
1888
2039
  /**
1889
2040
  * The amount of notes that are relevant to the difficulty.
1890
2041
  */
1891
2042
  relevantNoteCount(): number;
1892
2043
  /**
1893
- * Obtains the amount of sliders that are considered difficult in terms of relative strain, weighted by consistency.
1894
- */
1895
- countTopWeightedSliders(): number;
1896
- /**
1897
- * @param current The hitobject to calculate.
1898
- */
1899
- protected strainValueAt(current: OsuDifficultyHitObject): number;
1900
- protected calculateInitialStrain(time: number, current: OsuDifficultyHitObject): number;
1901
- /**
1902
- * @param current The hitobject to save to.
2044
+ * Obtains the amount of sliders that are considered difficult in terms of relative difficulty, weighted by consistency.
2045
+ *
2046
+ * @param difficultyValue The final difficulty value.
1903
2047
  */
1904
- protected saveToHitObject(current: OsuDifficultyHitObject, difficulty: number): void;
2048
+ countTopWeightedSliders(difficultyValue: number): number;
2049
+ protected objectDifficultyOf(current: OsuDifficultyHitObject): number;
2050
+ protected saveToHitObject(current: OsuDifficultyHitObject): void;
2051
+ private calculateAdjustedDifficulty;
1905
2052
  private strainDecay;
1906
2053
  }
1907
2054
 
1908
- 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 };
2055
+ export { DifficultyAttributes, DifficultyCalculator, DifficultyHitObject, DroidAgilityEvaluator, DroidAim, DroidDifficultyAttributes, DroidDifficultyCalculator, DroidDifficultyHitObject, DroidFlashlight, DroidFlashlightEvaluator, DroidFlowAimEvaluator, DroidPerformanceCalculator, DroidReading, DroidReadingEvaluator, DroidRhythm, DroidRhythmEvaluator, DroidSnapAimEvaluator, DroidTap, DroidTapEvaluator, ExtendedDroidDifficultyAttributes, OsuAgilityEvaluator, OsuAim, OsuDifficultyAttributes, OsuDifficultyCalculator, OsuDifficultyHitObject, OsuFlashlight, OsuFlashlightEvaluator, OsuFlowAimEvaluator, OsuPerformanceCalculator, OsuReading, OsuReadingEvaluator, OsuRhythmEvaluator, OsuSnapAimEvaluator, OsuSpeed, OsuSpeedEvaluator, PerformanceCalculator };
1909
2056
  export type { CacheableDifficultyAttributes, DifficultSlider, HighStrainSection, IDifficultyAttributes, IDroidDifficultyAttributes, IExtendedDroidDifficultyAttributes, IOsuDifficultyAttributes, PerformanceCalculationOptions, StrainPeaks, TimedStrainPeak };