Skip to content

Fix hitwindow formula in osu! performance calculator #34033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 8, 2025

Conversation

Givikap120
Copy link
Contributor

The fact that this PR aims at master instead of pp-dev is intentional. Because pp values in master was changed due to the fact how new hitwindows work.
Since the hitwindow formula was changed - this PR is also updating reverse (hitwindow to OD) formula. This will still make values different from live but at least they would be correct.

Rate change conversion of OD in PerformanceCalculator:
Before:
OD10 -> OD10.0833
OD9.9 -> OD10.0833

After:
OD10 -> OD10
OD9.9 -> OD10

@peppy
Copy link
Member

peppy commented Jul 8, 2025

cc @ppy/osu-pp-committee we are rolling out the new hit windows in the next release and curious whether this should be merged as a priority. seems like the consensus in the OP is that "this can wait" since it has been wrong for half the cases until now, but i want to confirm thoughts on the matter.

also questioning that this doesn't fail any tests.

@stanriders
Copy link
Member

This is fine to roll out with the hitwindow release imo - it's better to at least have values that represent what they're supposed to be instead of something that's completely incorrect. I'm not sure if having new values serverside for new scores would be good or bad, but I think considering we're getting close to a pp deploy it shouldn't matter too much plus technically in that case it'd be correct since the game changed together with the pp output.

Tests don't fail because we only have difficulty calculation test, and this changes only the performance calculation. The only place we use hitwindows in difficulty calculation right now is doubletap detection, and that uses actual hit window instead of OD so the difference is either 0 (test maps don't trigger it) or so small it's within tolerance.

I've checked other rulesets just in case and seems like they either don't use hitwindows at all or do it through actual hitwindows instead of OD so it's all good

@tsunyoku
Copy link
Member

tsunyoku commented Jul 8, 2025

On a basic test of this PR, the OD outputted at various ODs seem to be wrong. As an example, it outputs OD 9.33 for https://osu.ppy.sh/beatmapsets/1347474#osu/2790477 (it should be OD 9.2). Note that something to the effect of IBeatmapDifficultyInfo.InverseDifficultyRange(greatHitWindow, OsuHitWindows.GREAT_WINDOW_RANGE) gives a different (but also incorrect) answer of OD 9.41. I may be missing something.

I'm not 100% sure what the correct way forward is. Given the hit window changes are matching stable I didn't expect something like great hit window to OD conversion to be wrong in at least 3 different ways of calculating it (at first glance). Hopefully @peppy or @bdach you may have some ideas/comments on calculating it correctly?

As far as priority goes, people will frequently ask about mismatched PP values if left in its current state. I think corrected calculations should make less of a difference to PP in 99% of cases, so it's probably an improvement when we get something correct.

As for tests not failing, OD is used in performance calculations and not difficulty calculations and I don't think we have any tests set up for PP, only difficulty.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2025

you may have some ideas/comments on calculating it correctly?

After the hit window adjustments to match stable it is no longer possible to unambiguously recover the OD from a hit window millisecond range, because the flooring operation applied is lossy, or in other words, the duration of hit window as a function of overall difficulty is no longer an invertible function. See desmos.

In your cited case, plugging in OD 9.2 results in a great hit window of 23.5ms, which can be produced by ODs in the entire range of [9.166..., 9.333...]

The absolute best that could be done in a manner of speaking is to aim in the dead center of the bin, being (9.166... + 9.333...) / 2 = 9.2, but that's a pure coincidence and you will get artifacting for some values of OD (e.g. 9.3 converted to hit window duration and then back to OD will return 9.2 too, if calculated that way).

@tsunyoku
Copy link
Member

tsunyoku commented Jul 8, 2025

Okay, in that case, would you say that this change should consistently produce the upper-most OD in the range? I'm fine to go ahead with this solong as it will consistently output from the top of the range.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2025

Well that's more of a you question to be quite honest, because whether that is fine or not depends on what you're doing with the value you're getting out of there, but without reading the OD directly from the map, any arbitrary choice within the bin is as good as you're going to get. Which point of the bin you end up sampling for the pp calculation is of little concern to me specifically at this stage.

@tsunyoku
Copy link
Member

tsunyoku commented Jul 8, 2025

Yes, I'm asking if the formula provided in this PR would consistently produce the upper-most OD value. I'm not suggesting which OD we use is your concern.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2025

Yes, I'm asking if the formula provided in this PR would consistently produce the upper-most OD value.

Looking at desmos, it seems pretty clear to me that would indeed be the case, yes:

Screenshot 2025-07-08 at 11 22 03

Vague hint of a visual proof based on the above is that the red line labeled as $g_2(x)$ is the inverse of the formula that this PR is proposing to use, and meets the rightmost endpoints of every step on the step function. Which means that if you plug anything into the green function, you get a value matching one of the steps, and if you plug that value into the inverse of $g_2(x)$, you'll get the argument of the green function wherein the matching step ends.

@tsunyoku
Copy link
Member

tsunyoku commented Jul 8, 2025

Sounds good. In that case I'm happy to go ahead with this PR.

@bdach bdach changed the title Fix hitwindow formula in OsuPerformanceCalculator Fix hitwindow formula in osu! performance calculator Jul 8, 2025
@bdach bdach merged commit 15878f7 into ppy:master Jul 8, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants