@rian8337/osu-difficulty-calculator 1.2.1 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,7 +26,7 @@ yarn add @rian8337/osu-base @rian8337/osu-difficulty-calculator
26
26
 
27
27
  # Usage
28
28
 
29
- ## General usage
29
+ ## Difficulty calculator
30
30
 
31
31
  ```js
32
32
  import { MapInfo } from "@rian8337/osu-base";
@@ -67,7 +67,7 @@ console.log(rating.droidStars);
67
67
  console.log(rating.pcStars);
68
68
  ```
69
69
 
70
- ## Specifying parameters
70
+ ### Specifying difficulty calculation parameters
71
71
 
72
72
  Parameters can be applied to alter the result of the calculation:
73
73
 
@@ -104,3 +104,103 @@ console.log(rating.droidStars);
104
104
  // osu!standard difficulty
105
105
  console.log(rating.pcStars);
106
106
  ```
107
+
108
+ ## Performance calculator
109
+
110
+ ```js
111
+ import { MapInfo } from "@rian8337/osu-base";
112
+ import {
113
+ DroidPerformanceCalculator,
114
+ MapStars,
115
+ OsuPerformanceCalculator,
116
+ } from "@rian8337/osu-difficulty-calculator";
117
+
118
+ const beatmapInfo = await MapInfo.getInformation({ beatmapID: 901854 });
119
+
120
+ if (!beatmapInfo.title) {
121
+ return console.log("Beatmap not found");
122
+ }
123
+
124
+ const rating = new MapStars().calculate({
125
+ map: beatmapInfo.map,
126
+ });
127
+
128
+ // osu!droid performance
129
+ const droidPerformance = new DroidPerformanceCalculator().calculate({
130
+ stars: rating.droidStars,
131
+ });
132
+
133
+ console.log(droidPerformance);
134
+
135
+ // osu!standard performance
136
+ const osuPerformance = new OsuPerformanceCalculator().calculate({
137
+ stars: rating.pcStars,
138
+ });
139
+
140
+ console.log(osuPerformance);
141
+ ```
142
+
143
+ ### Specifying performance calculation parameters
144
+
145
+ Parameters can be passed to alter the result of the calculation:
146
+
147
+ - Combo: The maximum combo achieved. Defaults to the beatmap's maximum combo.
148
+ - Accuracy: The accuracy achieved. Defaults to 100%.
149
+ - Misses: The amount of misses achieved.
150
+ - Tap penalty: Penalty given from three-finger detection. Only applied for osu!droid gamemode. Defaults to 1.
151
+ - Custom statistics: Used to apply a custom speed multiplier and force AR. Defaults to none.
152
+
153
+ ```js
154
+ import { Accuracy, MapInfo, MapStats } from "@rian8337/osu-base";
155
+ import {
156
+ OsuPerformanceCalculator,
157
+ OsuStarRating,
158
+ } from "@rian8337/osu-difficulty-calculator";
159
+
160
+ const beatmapInfo = await MapInfo.getInformation({ beatmapID: 901854 });
161
+
162
+ if (!beatmapInfo.title) {
163
+ return console.log("Beatmap not found");
164
+ }
165
+
166
+ const rating = new OsuStarRating().calculate({
167
+ map: beatmapInfo.map,
168
+ });
169
+
170
+ const accuracy = new Accuracy({
171
+ // Specify your misses here
172
+ nmiss: 1,
173
+
174
+ // The module provides a convenient way to specify accuracy based on the data that you have
175
+ // Remove the codes below as you see fit
176
+
177
+ // If you have hit data (amount of 300s, 100s, and 50s)
178
+ n300: 1000,
179
+ n100: 0,
180
+ n50: 0,
181
+
182
+ // If you have accuracy percentage
183
+ // While this method is more convenient to use, the amount of 300s, 100s, and 50s will be estimated
184
+ // This will lead to values being off when calculating for specific accuracies
185
+ percent: 100,
186
+ nobjects: beatmapInfo.objects,
187
+ });
188
+
189
+ const stats = new MapStats({
190
+ ar: 9.5,
191
+ isForceAR: true,
192
+ speedMultiplier: 1.25,
193
+ });
194
+
195
+ const performance = new OsuPerformanceCalculator().calculate({
196
+ stars: rating,
197
+ combo: 1250,
198
+ accPercent: accuracy,
199
+ // The tap penalty can be properly obtained by checking a replay for three finger usage
200
+ // However, a custom value can also be provided
201
+ tapPenalty: 1.5,
202
+ stats: stats,
203
+ });
204
+
205
+ console.log(performance);
206
+ ```
@@ -51,11 +51,8 @@ class DroidPerformanceCalculator extends PerformanceCalculator_1.PerformanceCalc
51
51
  */
52
52
  calculateAverageRhythmMultiplier() {
53
53
  // The first object doesn't have any rhythm multiplier, so we begin with the second object
54
- const rhythmMultipliers = this.stars.objects
55
- .map((v) => v.rhythmMultiplier)
56
- .slice(1);
57
- this.aggregatedRhythmMultiplier = Math.max(1, rhythmMultipliers.reduce((total, value) => total + value, 0) /
58
- Math.max(500, rhythmMultipliers.length));
54
+ const rhythmObjects = this.stars.objects.slice(1);
55
+ this.aggregatedRhythmMultiplier = Math.max(1, rhythmObjects.reduce((total, value) => total + value.rhythmMultiplier, 0) / Math.max(500, rhythmObjects.length));
59
56
  }
60
57
  /**
61
58
  * Calculates the aim performance value of the beatmap.
@@ -115,7 +115,9 @@ class DroidStarRating extends StarRating_1.StarRating {
115
115
  if (!isRelax) {
116
116
  this.postCalculateTap(tapSkill);
117
117
  }
118
- this.calculateSpeedNoteCount();
118
+ else {
119
+ this.calculateSpeedNoteCount();
120
+ }
119
121
  if (!isRelax) {
120
122
  this.postCalculateRhythm(rhythmSkill);
121
123
  }
@@ -35,15 +35,8 @@ class OsuStarRating extends StarRating_1.StarRating {
35
35
  calculateAim() {
36
36
  const aimSkill = new OsuAim_1.OsuAim(this.mods, true);
37
37
  const aimSkillWithoutSliders = new OsuAim_1.OsuAim(this.mods, false);
38
- this.calculateSkills(aimSkill);
39
- this.strainPeaks.aimWithSliders = aimSkill.strainPeaks;
40
- this.strainPeaks.aimWithoutSliders = aimSkillWithoutSliders.strainPeaks;
41
- this.aim = this.starValue(aimSkill.difficultyValue());
42
- if (this.aim) {
43
- this.attributes.sliderFactor =
44
- this.starValue(aimSkillWithoutSliders.difficultyValue()) /
45
- this.aim;
46
- }
38
+ this.calculateSkills(aimSkill, aimSkillWithoutSliders);
39
+ this.postCalculateAim(aimSkill, aimSkillWithoutSliders);
47
40
  }
48
41
  /**
49
42
  * Calculates the speed star rating of the beatmap and stores it in this instance.
@@ -54,8 +47,7 @@ class OsuStarRating extends StarRating_1.StarRating {
54
47
  }
55
48
  const speedSkill = new OsuSpeed_1.OsuSpeed(this.mods, new osu_base_1.OsuHitWindow(this.stats.od).hitWindowFor300());
56
49
  this.calculateSkills(speedSkill);
57
- this.strainPeaks.speed = speedSkill.strainPeaks;
58
- this.speed = this.starValue(speedSkill.difficultyValue());
50
+ this.postCalculateSpeed(speedSkill);
59
51
  }
60
52
  /**
61
53
  * Calculates the flashlight star rating of the beatmap and stores it in this instance.
@@ -63,8 +55,7 @@ class OsuStarRating extends StarRating_1.StarRating {
63
55
  calculateFlashlight() {
64
56
  const flashlightSkill = new OsuFlashlight_1.OsuFlashlight(this.mods);
65
57
  this.calculateSkills(flashlightSkill);
66
- this.strainPeaks.flashlight = flashlightSkill.strainPeaks;
67
- this.flashlight = this.starValue(flashlightSkill.difficultyValue());
58
+ this.postCalculateFlashlight(flashlightSkill);
68
59
  }
69
60
  calculateTotal() {
70
61
  const aimPerformanceValue = this.basePerformanceValue(this.aim);
@@ -87,10 +78,6 @@ class OsuStarRating extends StarRating_1.StarRating {
87
78
  calculateAll() {
88
79
  const skills = this.createSkills();
89
80
  const isRelax = this.mods.some((m) => m instanceof osu_base_1.ModRelax);
90
- if (isRelax) {
91
- // Remove speed skill to prevent overhead
92
- skills.splice(2, 1);
93
- }
94
81
  this.calculateSkills(...skills);
95
82
  const aimSkill = skills[0];
96
83
  const aimSkillWithoutSliders = skills[1];
@@ -103,20 +90,11 @@ class OsuStarRating extends StarRating_1.StarRating {
103
90
  speedSkill = skills[2];
104
91
  flashlightSkill = skills[3];
105
92
  }
106
- this.strainPeaks.aimWithSliders = aimSkill.strainPeaks;
107
- this.strainPeaks.aimWithoutSliders = aimSkillWithoutSliders.strainPeaks;
108
- this.aim = this.starValue(aimSkill.difficultyValue());
109
- if (this.aim) {
110
- this.attributes.sliderFactor =
111
- this.starValue(aimSkillWithoutSliders.difficultyValue()) /
112
- this.aim;
113
- }
93
+ this.postCalculateAim(aimSkill, aimSkillWithoutSliders);
114
94
  if (speedSkill) {
115
- this.strainPeaks.speed = speedSkill.strainPeaks;
116
- this.speed = this.starValue(speedSkill.difficultyValue());
95
+ this.postCalculateSpeed(speedSkill);
117
96
  }
118
- this.strainPeaks.flashlight = flashlightSkill.strainPeaks;
119
- this.flashlight = this.starValue(flashlightSkill.difficultyValue());
97
+ this.postCalculateFlashlight(flashlightSkill);
120
98
  this.calculateTotal();
121
99
  }
122
100
  /**
@@ -143,5 +121,39 @@ class OsuStarRating extends StarRating_1.StarRating {
143
121
  new OsuFlashlight_1.OsuFlashlight(this.mods),
144
122
  ];
145
123
  }
124
+ /**
125
+ * Called after aim skill calculation.
126
+ *
127
+ * @param aimSkill The aim skill that considers sliders.
128
+ * @param aimSkillWithoutSliders The aim skill that doesn't consider sliders.
129
+ */
130
+ postCalculateAim(aimSkill, aimSkillWithoutSliders) {
131
+ this.strainPeaks.aimWithSliders = aimSkill.strainPeaks;
132
+ this.strainPeaks.aimWithoutSliders = aimSkillWithoutSliders.strainPeaks;
133
+ this.aim = this.starValue(aimSkill.difficultyValue());
134
+ if (this.aim) {
135
+ this.attributes.sliderFactor =
136
+ this.starValue(aimSkillWithoutSliders.difficultyValue()) /
137
+ this.aim;
138
+ }
139
+ }
140
+ /**
141
+ * Called after speed skill calculation.
142
+ *
143
+ * @param speedSkill The speed skill.
144
+ */
145
+ postCalculateSpeed(speedSkill) {
146
+ this.strainPeaks.speed = speedSkill.strainPeaks;
147
+ this.speed = this.starValue(speedSkill.difficultyValue());
148
+ }
149
+ /**
150
+ * Called after flashlight skill calculation.
151
+ *
152
+ * @param flashlightSkill The flashlight skill.
153
+ */
154
+ postCalculateFlashlight(flashlightSkill) {
155
+ this.strainPeaks.flashlight = flashlightSkill.strainPeaks;
156
+ this.flashlight = this.starValue(flashlightSkill.difficultyValue());
157
+ }
146
158
  }
147
159
  exports.OsuStarRating = OsuStarRating;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rian8337/osu-difficulty-calculator",
3
- "version": "1.2.1",
3
+ "version": "1.2.9",
4
4
  "description": "A module for calculating osu!standard beatmap difficulty and performance value with respect to the current difficulty and performance algorithm.",
5
5
  "keywords": [
6
6
  "osu",
@@ -11,6 +11,7 @@
11
11
  "license": "MIT",
12
12
  "main": "dist/index.js",
13
13
  "types": "typings/index.d.ts",
14
+ "typedocMain": "src/index.ts",
14
15
  "files": [
15
16
  "dist/**",
16
17
  "typings/**"
@@ -21,7 +22,6 @@
21
22
  },
22
23
  "scripts": {
23
24
  "build": "tsc",
24
- "generate-docs": "typedoc src/index.ts",
25
25
  "lint": "eslint --ext ts",
26
26
  "prepare": "npm run build",
27
27
  "test": "jest -i"
@@ -30,10 +30,10 @@
30
30
  "url": "https://github.com/Rian8337/osu-droid-module/issues"
31
31
  },
32
32
  "dependencies": {
33
- "@rian8337/osu-base": "^1.2.1"
33
+ "@rian8337/osu-base": "^1.2.9"
34
34
  },
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
- "gitHead": "8c08cf8f2c3af4b9a306f9fe9ffedfe339b9b046"
38
+ "gitHead": "4bb4b0c00cf07d5624e1af644a01685697b2832c"
39
39
  }
@@ -414,16 +414,6 @@ declare module "@rian8337/osu-difficulty-calculator" {
414
414
  * @param flashlightSkill The flashlight skill.
415
415
  */
416
416
  private postCalculateFlashlight(flashlightSkill: DroidFlashlight): void;
417
- /**
418
- * Calculates the base rating value of a difficulty.
419
- */
420
- private baseRatingValue(difficulty: number): number;
421
- /**
422
- * Calculates the base performance value of a difficulty rating.
423
- *
424
- * @param rating The difficulty rating.
425
- */
426
- private basePerformanceValue(rating: number): number;
427
417
  }
428
418
 
429
419
  /**
@@ -716,17 +706,27 @@ declare module "@rian8337/osu-difficulty-calculator" {
716
706
  */
717
707
  protected override createSkills(): OsuSkill[];
718
708
  /**
719
- * Calculates the base performance value of a difficulty rating.
709
+ * Called after aim skill calculation.
720
710
  *
721
- * @param rating The difficulty rating.
711
+ * @param aimSkill The aim skill that considers sliders.
712
+ * @param aimSkillWithoutSliders The aim skill that doesn't consider sliders.
722
713
  */
723
- private basePerformanceValue(rating: number): number;
714
+ private postCalculateAim(
715
+ aimSkill: OsuAim,
716
+ aimSkillWithoutSliders: OsuAim
717
+ ): void;
724
718
  /**
725
- * Calculates the star rating value of a difficulty.
719
+ * Called after speed skill calculation.
726
720
  *
727
- * @param difficulty The difficulty to calculate.
721
+ * @param speedSkill The speed skill.
728
722
  */
729
- private starValue(difficulty: number): number;
723
+ private postCalculateSpeed(speedSkill: OsuSpeed): void;
724
+ /**
725
+ * Called after flashlight skill calculation.
726
+ *
727
+ * @param flashlightSkill The flashlight skill.
728
+ */
729
+ private postCalculateFlashlight(flashlightSkill: OsuFlashlight): void;
730
730
  }
731
731
 
732
732
  //#endregion
@@ -872,9 +872,9 @@ declare module "@rian8337/osu-difficulty-calculator" {
872
872
  */
873
873
  mode?: modes;
874
874
  /**
875
- * The speed penalty to apply for penalized scores. Only applies to droid gamemode.
875
+ * The tap penalty to apply for penalized scores. Only applies to droid gamemode.
876
876
  */
877
- speedPenalty?: number;
877
+ tapPenalty?: number;
878
878
  /**
879
879
  * Custom map statistics to apply custom speed multiplier and force AR values as well as old statistics.
880
880
  */
@@ -914,9 +914,9 @@ declare module "@rian8337/osu-difficulty-calculator" {
914
914
  */
915
915
  mode?: modes;
916
916
  /**
917
- * The speed penalty to apply for penalized scores.
917
+ * The tap penalty to apply for penalized scores.
918
918
  */
919
- speedPenalty?: number;
919
+ tapPenalty?: number;
920
920
  /**
921
921
  * Custom map statistics to apply custom speed multiplier and force AR values as well as old statistics.
922
922
  */
@@ -1061,6 +1061,18 @@ declare module "@rian8337/osu-difficulty-calculator" {
1061
1061
  * Creates skills to be calculated.
1062
1062
  */
1063
1063
  protected abstract createSkills(): Skill[];
1064
+ /**
1065
+ * Calculates the star rating value of a difficulty.
1066
+ *
1067
+ * @param difficulty The difficulty to calculate.
1068
+ */
1069
+ protected starValue(difficulty: number): number;
1070
+ /**
1071
+ * Calculates the base performance value of a difficulty rating.
1072
+ *
1073
+ * @param rating The difficulty rating.
1074
+ */
1075
+ protected basePerformanceValue(rating: number): number;
1064
1076
  }
1065
1077
 
1066
1078
  /**