Fixes for mania simulate command
- Fixes total hits calculation for mania scores with CL mod (hold notes should only count as a single hit in stable)
- Implements GetAccuracy for mania simulate command (both for CL and non-CL scores)
Would you mind doing the same for GUI? https://github.com/ppy/osu-tools/blob/master/PerformanceCalculatorGUI/RulesetHelper.cs
Would you mind doing the same for GUI? https://github.com/ppy/osu-tools/blob/master/PerformanceCalculatorGUI/RulesetHelper.cs
Not too familiar with the GUI code but I think this does the trick
~On Lazer, even with CL it still does the Lazer way of doing hits, therefore you cannot simply check for CL here.~ ~This is a bit troublesome as there's no way to tell apart Lazer and Stable, so I think the best that can be done is some command-line parameter:~
[UsedImplicitly] [Option(Template = "-S|--stable", Description = "The score is considered an osu! stable score.")] public bool IsStable { get; }~(source: I forgot but when I refactored all this stuff I ran into this issue, I think @Givikap120 knows more about it)~
Edit: I backread older PRs, and read that CL does not exist on Mania. Does that mean CL is a definitive marker for the score origining from Stable? And also, can't you use
GetMaxComboon mania to get the total hits?
Honestly I am not too involved with mania but from what I've learnt today it seems to be all over the place. There are currently three different ways of calculating accuracy: the stable way (with CL), the Lazer way (without CL) and the website way (with judgements according to CL logic but accuracy calculation according to non-CL logic) and even on the site it matters if you have Lazer mode enabled or not.
I implemented it this way because this would make the most sense, with CL plays (only possible on stable) following stable logic and non-CL plays (only possible on Lazer) following Lazer logic. I think adding another parameter like this is just going to make the mess even worse.
GetMaxCombo returns the Lazer max combo so it's not a viable option, unless you want to subtract the LN count which is pretty much equivalent to what is happening here
GetMaxCombo returns the Lazer max combo so it's not a viable option right.
Wonder if that can be PRd to Lazer instead but I'm not sure how much sense that'd make because CL basically only acts as a stable marker on Lazers' mania.
generateHitResults still assumes perfects and greats to generate the same accuracy value but GetAccuracy distinguishes the two by either 305 or 300 values.
generateHitResultsstill assumes perfects and greats to generate the same accuracy value butGetAccuracydistinguishes the two by either305or300values.
The math works the same way so it'll look very similar
// Let Perfect=61, Great=60, Good=40, Ok=20, Meh=10, Miss=0. The total should be this.
int targetTotal = (int)Math.Round(accuracy * totalHits * 61);
// Start by assuming every non miss is a meh
// This is how much increase is needed by the rest
int remainingHits = totalHits - countMiss;
int delta = targetTotal - 10 * remainingHits;
// Each perfect increases total by 51 (perfect - meh = 51)
int perfects = Math.Min(delta / 51, remainingHits);
delta -= perfects * 51;
remainingHits -= perfects;
// Each great increases total by 50 (great - meh = 50)
int greats = Math.Min(delta / 50, remainingHits);
delta -= greats * 50;
remainingHits -= greats;
// Each good increases total by 30 (good - meh = 30).
countGood = Math.Min(delta / 30, remainingHits);
delta -= countGood.Value * 30;
remainingHits -= countGood.Value;
// Each ok increases total by 10 (ok - meh = 10).
int oks = delta / 10;
remainingHits -= oks;
// Everything else is a meh, as initially assumed.
countMeh = remainingHits;
Just need to check whether stable or lazer accuracy is required and chose the formula accordingly.
generateHitResultsstill assumes perfects and greats to generate the same accuracy value butGetAccuracydistinguishes the two by either305or300values.The math works the same way so it'll look very similar
// Let Perfect=61, Great=60, Good=40, Ok=20, Meh=10, Miss=0. The total should be this. int targetTotal = (int)Math.Round(accuracy * totalHits * 61); // Start by assuming every non miss is a meh // This is how much increase is needed by the rest int remainingHits = totalHits - countMiss; int delta = targetTotal - 10 * remainingHits; // Each perfect increases total by 51 (perfect - meh = 51) int perfects = Math.Min(delta / 51, remainingHits); delta -= perfects * 51; remainingHits -= perfects; // Each great increases total by 50 (great - meh = 50) int greats = Math.Min(delta / 50, remainingHits); delta -= greats * 50; remainingHits -= greats; // Each good increases total by 30 (good - meh = 30). countGood = Math.Min(delta / 30, remainingHits); delta -= countGood.Value * 30; remainingHits -= countGood.Value; // Each ok increases total by 10 (ok - meh = 10). int oks = delta / 10; remainingHits -= oks; // Everything else is a meh, as initially assumed. countMeh = remainingHits;Just need to check whether stable or lazer accuracy is required and chose the formula accordingly.
I refactored this method so it handles both types of logic similarly to the rest of the class
Found two remaining flaws on edge cases with my last snippet as mentioned above, the rest looks fine to me 👍
Thanks, should be all good now
You've forgot to update hitresult generation for GUI
You've forgot to update hitresult generation for GUI
Oops, updated that as well