Skip to content

Commit 3b746ec

Browse files
committed
Added average hit error and unstable rate to the ranking graph tooltip.
Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
1 parent dd93a25 commit 3b746ec

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/itdelatrisu/opsu/GameData.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@
3333
import itdelatrisu.opsu.replay.ReplayFrame;
3434
import itdelatrisu.opsu.ui.Colors;
3535
import itdelatrisu.opsu.ui.Fonts;
36+
import itdelatrisu.opsu.ui.UI;
3637
import itdelatrisu.opsu.ui.animations.AnimationEquation;
3738
import itdelatrisu.opsu.user.UserList;
3839

3940
import java.io.File;
41+
import java.util.ArrayList;
4042
import java.util.Date;
4143
import java.util.HashMap;
4244
import java.util.Iterator;
45+
import java.util.List;
4346
import java.util.Random;
4447
import java.util.concurrent.LinkedBlockingDeque;
4548

@@ -239,6 +242,12 @@ public HitErrorInfo(int time, int x, int y, int timeDiff) {
239242
/** List containing recent hit error information. */
240243
private LinkedBlockingDeque<HitErrorInfo> hitErrorList;
241244

245+
/** List containing all hit error time differences. */
246+
private List<Integer> hitErrors;
247+
248+
/** Performance string containing hit error averages and unstable rate. */
249+
private String performanceString = null;
250+
242251
/** Hit object types, used for drawing results. */
243252
public enum HitObjectType { CIRCLE, SLIDERTICK, SLIDER_FIRST, SLIDER_LAST, SPINNER }
244253

@@ -394,6 +403,8 @@ public void clear() {
394403
}
395404
hitResultList = new LinkedBlockingDeque<HitObjectResult>();
396405
hitErrorList = new LinkedBlockingDeque<HitErrorInfo>();
406+
hitErrors = new ArrayList<Integer>();
407+
performanceString = null;
397408
fullObjectCount = 0;
398409
combo = 0;
399410
comboMax = 0;
@@ -1321,6 +1332,26 @@ public void updateDisplays(int delta) {
13211332
}
13221333
}
13231334

1335+
/**
1336+
* Updates displayed ranking elements based on a delta value.
1337+
* @param delta the delta interval since the last call
1338+
* @param mouseX the mouse x coordinate
1339+
* @param mouseY the mouse y coordinate
1340+
*/
1341+
public void updateRankingDisplays(int delta, int mouseX, int mouseY) {
1342+
// graph tooltip
1343+
Image graphImg = GameImage.RANKING_GRAPH.getImage();
1344+
float graphX = 416 * GameImage.getUIscale();
1345+
float graphY = 688 * GameImage.getUIscale();
1346+
if (isGameplay &&
1347+
mouseX >= graphX - graphImg.getWidth() / 2f && mouseX <= graphX + graphImg.getWidth() / 2f &&
1348+
mouseY >= graphY - graphImg.getHeight() / 2f && mouseY <= graphY + graphImg.getHeight() / 2f) {
1349+
if (performanceString == null)
1350+
performanceString = getPerformanceString(hitErrors);
1351+
UI.updateTooltip(delta, performanceString, true);
1352+
}
1353+
}
1354+
13241355
/**
13251356
* Returns the current combo streak.
13261357
*/
@@ -1728,5 +1759,31 @@ public Replay getReplay(ReplayFrame[] frames, LifeFrame[] lifeFrames, Beatmap be
17281759
*/
17291760
public void addHitError(int time, int x, int y, int timeDiff) {
17301761
hitErrorList.addFirst(new HitErrorInfo(time, x, y, timeDiff));
1762+
hitErrors.add(timeDiff);
1763+
}
1764+
1765+
/**
1766+
* Computes the error values and unstable rate for the map.
1767+
* @see <a href="https://osu.ppy.sh/wiki/Accuracy#Performance_Graph">https://osu.ppy.sh/wiki/Accuracy#Performance_Graph</a>
1768+
*/
1769+
private String getPerformanceString(List<Integer> errors) {
1770+
int earlyCount = 0, lateCount = 0;
1771+
int earlySum = 0, lateSum = 0;
1772+
for (int diff : errors) {
1773+
if (diff < 0) {
1774+
earlyCount++;
1775+
earlySum += diff;
1776+
} else if (diff > 0) {
1777+
lateCount++;
1778+
lateSum += diff;
1779+
}
1780+
}
1781+
float hitErrorEarly = (earlyCount > 0) ? (float) earlySum / earlyCount : 0f;
1782+
float hitErrorLate = (lateCount > 0) ? (float) lateSum / lateCount : 0f;
1783+
float unstableRate = (!errors.isEmpty()) ? (float) (Utils.standardDeviation(errors) * 10) : 0f;
1784+
return String.format(
1785+
"Accuracy:\nError: %.2fms - %.2fms avg\nUnstable Rate: %.2f",
1786+
hitErrorEarly, hitErrorLate, unstableRate
1787+
);
17311788
}
17321789
}

src/itdelatrisu/opsu/Utils.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import java.text.SimpleDateFormat;
5555
import java.util.Arrays;
5656
import java.util.Date;
57+
import java.util.List;
5758
import java.util.Scanner;
5859
import java.util.jar.JarFile;
5960

@@ -255,6 +256,21 @@ public static float lerp(float a, float b, float t) {
255256
return a * (1 - t) + b * t;
256257
}
257258

259+
/**
260+
* Calculates the standard deviation of the numbers in the list.
261+
*/
262+
public static double standardDeviation(List<Integer> list) {
263+
float avg = 0f;
264+
for (int i : list)
265+
avg += i;
266+
avg /= list.size();
267+
float var = 0f;
268+
for (int i : list)
269+
var += (i - avg) * (i - avg);
270+
var /= list.size();
271+
return Math.sqrt(var);
272+
}
273+
258274
/**
259275
* Maps a difficulty value to the given range.
260276
* @param difficulty the difficulty value

src/itdelatrisu/opsu/states/GameRanking.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ public void update(GameContainer container, StateBasedGame game, int delta)
154154
MusicController.loopTrackIfEnded(true);
155155
UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
156156
animationProgress.update(delta);
157+
data.updateRankingDisplays(delta, mouseX, mouseY);
157158
}
158159

159160
@Override

0 commit comments

Comments
 (0)