Commit Graph

617 Commits

Author SHA1 Message Date
Dean Herbert 644e7d6fe6
Add migration 2024-01-22 21:43:32 +09:00
Dean Herbert c8521b49cd
Change S rank to require no miss 2024-01-22 21:43:32 +09:00
Bartłomiej Dach 17b9d842ab
Fix incorrect accuracy and rank population when decoding lazer replays
Closes https://github.com/ppy/osu/issues/24061.

The gist of this change is that if the `LegacyReplaySoloScoreInfo`
bolt-on is present in the replay, then it can (and is) used to recompute
the accuracy, and rank is computed based on that.

This was the missing part of
https://github.com/ppy/osu/issues/24061#issuecomment-1888438151.
The accuracy would change on import before that because the encode
process is _lossy_ if the `LegacyReplaySoloScoreInfo` bolt-on is not
used, as the legacy format only has 6 fields for encoding judgement
counts, and some judgements that affect accuracy in lazer do not fit
into that.

Note that this _only_ fixes _relatively_ new lazer scores looking wrong
after reimport.

- Very old lazer scores, i.e. ones that don't have the
  `LegacyReplaySoloScoreInfo` bolt-on, obviously can't use it
  to repopulate. There's really not much good that can be done there,
  so the stable pathways are used as a fallback that always works.

- For stable replays, `ScoreImporter` recalculates the accuracy of
  the score _again_ in

  15a5fd7e4c/osu.Game/Scoring/ScoreImporter.cs (L106-L110)

  as `StandardisedScoreMigrationTools.UpdateFromLegacy()` recomputes
  _both_ total score and accuracy.

  This makes a _semblance_ of sense as it attempts to make the accuracy
  of stable and lazer replays comparable. In most cases it also won't
  matter, as the only ruleset where accuracy changed between the legacy
  implementation and current lazer accuracy is mania.

  But it is also an inaccurate process (as, again, some of the required
  data is not in the replay, namely judgement counts of ticks
  and so on).

  For whatever's worth, a similar thing happens server-side in

  106c2948db/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Queue/BatchInserter.cs (L319)

- However, _ranks_ of stable scores will still use the local stable
  reimplementation of ranks, i.e. a 1-miss stable score in osu! ruleset
  will be an A rather than an S. See importer:

  106c2948db/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Queue/BatchInserter.cs (L237)

  (it's the same method which is renamed
  to `PopulateLegacyAccuracyAndRank()` in this commit).

  That is all a bit of a mess honestly, but I'm not sure where to even
  begin there...
2024-01-16 22:38:53 +01:00
Bartłomiej Dach 7c9adc7ad3
Fix incorrect score conversion on selected beatmaps due to incorrect `difficultyPeppyStars` rounding
Fixes issue that occurs on *about* 246 beatmaps and was first described
by me on discord:

    https://discord.com/channels/188630481301012481/188630652340404224/1154367700378865715

and then rediscovered again during work on
https://github.com/ppy/osu/pull/26405:

    https://gist.github.com/bdach/414d5289f65b0399fa8f9732245a4f7c#venenog-on-ultmate-end-by-blacky-overdose-631

It so happens that in stable, due to .NET Framework internals, float
math would be performed using x87 registers and opcodes.
.NET (Core) however uses SSE instructions on 32- and 64-bit words.
x87 registers are _80 bits_ wide. Which is notably wider than _both_
float and double. Therefore, on a significant number of beatmaps,
the rounding would not produce correct values due to insufficient
precision.

See following gist for corroboration of the above:

    https://gist.github.com/bdach/dcde58d5a3607b0408faa3aa2b67bf10

Thus, to crudely - but, seemingly accurately, after checking across
all ranked maps - emulate this, use `decimal`, which is slow, but has
bigger precision than `double`. The single known exception beatmap
in whose case this results in an incorrect result is

    https://osu.ppy.sh/beatmapsets/1156087#osu/2625853

which is considered an "acceptable casualty" of sorts.

Doing this requires some fooling of the compiler / runtime (see second
inline comment in new method). To corroborate that this is required,
you can try the following code snippet:

    Console.WriteLine(string.Join(' ', BitConverter.GetBytes(1.3f).Select(x => x.ToString("X2"))));
    Console.WriteLine(string.Join(' ', BitConverter.GetBytes(1.3).Select(x => x.ToString("X2"))));
    Console.WriteLine();

    decimal d1 = (decimal)1.3f;
    decimal d2 = (decimal)1.3;
    decimal d3 = (decimal)(double)1.3f;

    Console.WriteLine(string.Join(' ', decimal.GetBits(d1).SelectMany(BitConverter.GetBytes).Select(x => x.ToString("X2"))));
    Console.WriteLine(string.Join(' ', decimal.GetBits(d2).SelectMany(BitConverter.GetBytes).Select(x => x.ToString("X2"))));
    Console.WriteLine(string.Join(' ', decimal.GetBits(d3).SelectMany(BitConverter.GetBytes).Select(x => x.ToString("X2"))));

which will print

    66 66 A6 3F
    CD CC CC CC CC CC F4 3F

    0D 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
    0D 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
    8C 5D 89 FB 3B 76 00 00 00 00 00 00 00 00 0E 00

Note that despite `d1` being converted from a less-precise floating-
-point value than `d2`, it still is represented 100% accurately as
a decimal number.

After applying this change, recomputation of legacy scoring attributes
for *all* rulesets will be required.
2024-01-10 19:30:18 +01:00
Bartłomiej Dach 00a4c055b3
Merge branch 'master' into catch-scoring 2024-01-09 15:49:37 +01:00
Bartłomiej Dach 8c82bb006c
Fix mania score conversion using score V1 accuracy
Partially addresses https://github.com/ppy/osu/discussions/26416

As pointed out in the discussion thread above, the total score
conversion process for mania was using accuracy directly from the
replay. In mania accuracy is calculated differently in score V1 than in
score V2, which meant that scores coming from stable were treated more
favourably (due to weighting GREAT and PERFECT equally).

To fix, recompute accuracy locally and use that for the accuracy
portion.

Note that this will still not be (and cannot be made) 100% accurate, as
in stable score V2, as well as in lazer, hold notes are *two*
judgements, not one as in stable score V1, meaning that full and correct
score statistics are not available without playing back the replay.

The effects of the change can be previewed on the following spreadsheet:

https://docs.google.com/spreadsheets/d/1wxD4UwLjwcr7n9y5Yq7EN0lgiLBN93kpd4gBnAlG-E0/edit#gid=1711190356

Top 5 changed scores with replays:

| score                                                                                                                            | master  | this PR | replay  |
| :------------------------------------------------------------------------------------------------------------------------------- | ------: | ------: | ------: |
| [Outlasted on Uwa!! So Holiday by toby fox [[4K] easy] (0.71\*)](https://osu.ppy.sh/scores/mania/460404716)                      | 935,917 | 927,269 | 920,579 |
| [ag0 on Emotional Uplifting Orchestral by bradbreeck [[4K] Rocket's Normal] (0.76\*)](https://osu.ppy.sh/scores/mania/453133066) | 921,636 | 913,535 | 875,549 |
| [rlarkgus on Zen Zen Zense by Gom (HoneyWorks) [[5K] Normal] (1.68\*)](https://osu.ppy.sh/scores/mania/458368312)                | 934,340 | 926,787 | 918,855 |
| [YuJJun on Harumachi Clover by R3 Music Box [4K Catastrophe] (1.80\*)](https://osu.ppy.sh/scores/mania/548215786)                | 918,606 | 911,111 | 885,454 |
| [Fritte on 45-byou by respon feat. Hatsune Miku & Megpoid [[5K] Normal] (1.52\*)](https://osu.ppy.sh/scores/mania/516079410)     | 900,024 | 892,569 | 907,456 |
2024-01-08 16:38:43 +01:00
Bartłomiej Dach ea7078fab5
Implement approximate score conversion algorithm matching score V2 2024-01-05 20:46:11 +01:00
Dean Herbert 94531807e4
Make slider ends show on results screen again 2024-01-02 17:01:32 +09:00
Bartłomiej Dach d4423d4933
Store last set score to a `SessionStatic` 2023-12-27 19:13:42 +01:00
Bartłomiej Dach 3a2ed3677b
Fix standardised score conversion failing for scores set with 0.0x mod mutliplier
Closes https://github.com/ppy/osu/issues/26073.
2023-12-23 13:28:39 +01:00
Bartłomiej Dach fbf19ea598
Merge branch 'master' into add-score-version 2023-12-21 13:06:53 +01:00
Bartłomiej Dach 2baf579f7c
Serialise and deserialise `ClientVersion` to replays 2023-12-21 12:58:08 +01:00
Bartłomiej Dach 81bbdccee7
Rename `ScoreInfo.{ -> Client}Version` 2023-12-21 12:56:43 +01:00
Dean Herbert a4baa0a716
Add versioning of local scores
For any potential future usage
2023-12-21 18:37:15 +09:00
Dan Balasescu c3c1752a5a
Reconvert all legacy scores 2023-12-21 15:32:34 +09:00
Dan Balasescu eb072a1d24
Add accuracy conversion, fix usages 2023-12-21 15:09:56 +09:00
Dan Balasescu 6b4b2a57fc
Expose only as one method 2023-12-21 14:58:23 +09:00
Dan Balasescu 4e3b994142
Relocate HitResult numeric score to ScoreProcessor 2023-12-21 14:52:31 +09:00
Bartłomiej Dach 9515f7dbfa
Bump score version in order to recompute legacy scores 2023-12-20 16:01:59 +01:00
Bartłomiej Dach 017003deea
Fix osu! standardised score conversion sometimes exceeding bounds
Co-authored-by: Zyf <zyfarok@gmail.com>

Closes https://github.com/ppy/osu/issues/25860

Users reported that some stable scores would convert to large negative
total scores in lazer after the introduction of combo exponent. Those
large negative total scores were actually mangled NaNs.

The root cause of this was the following calculation going below zero
unexpectedly:

	8e8d9b2cd9/osu.Game/Database/StandardisedScoreMigrationTools.cs (L323)

which then propagates negative numbers onward until

	8e8d9b2cd9/osu.Game/Database/StandardisedScoreMigrationTools.cs (L337)

which yields a NaN due to attempting to take the square root of a
negative number.

To fix, clamp `comboPortionInScoreV1` to sane limits: to
`comboPortionFromLongestComboInScoreV1` from below, and to
`maximumAchievableComboPortionInScoreV1` from above. This is a less
direct fix than perhaps imagined, but it seems like a better one as it
will also affect the calculation of both the lower and the upper
estimate of the score.
2023-12-18 22:05:19 +01:00
Dan Balasescu 987fe9322e
Merge pull request #24166 from Zyfarok/scorev3
Modify osu! standardised scoring to introduce a combo exponent
2023-12-12 17:38:44 +09:00
Dean Herbert 3553717cc6
Fix results screen not including slider end misses in tick count 2023-11-29 21:28:25 +09:00
Bartłomiej Dach ca37e1afc2
Merge branch 'master' into scorev3 2023-11-24 10:37:10 +09:00
Bartłomiej Dach e28e0ef1cc
Fix classic scoring overflowing in osu! ruleset due to integer multiplication overflow
Closes https://github.com/ppy/osu/issues/25545.
2023-11-23 08:16:25 +09:00
Zyf cadd9b4ace Merge remote-tracking branch 'upstream/master' into scorev3 2023-11-19 23:53:05 +01:00
Dean Herbert c1c8e2968f
Move operation to after user population 2023-10-30 15:46:09 +09:00
Dean Herbert 96dd7b3333
Update the last played date of a beatmap when importing a replay by the local user 2023-10-30 15:44:16 +09:00
Bartłomiej Dach 96d784e06b
Delete `ScoreInfo.HasReplay` as no longer needed 2023-10-27 12:39:54 +02:00
Bartłomiej Dach 526ee6e140
Remove `IScoreInfo : IHasNamedFiles` inheritance 2023-10-26 14:58:33 +02:00
Bartłomiej Dach fb2293821a
Allow watching replay from multi/playlist results screens 2023-10-16 11:20:02 +02:00
Bartłomiej Dach b144cfd55c
Add `LegacyOnlineID` handling to places that definitely need it
Mostly places that can interact with imported replays.

There are other places that use the online ID as a sort tiebreaker, or
to check presence of a score on results screens, but they should
probably still continue to only use `OnlineID`, since all scores with a
legacy online ID should have an online ID, but the converse is not
generally true.
2023-10-16 11:20:02 +02:00
Bartłomiej Dach c53f4c144c
Encode/decode new `OnlineID` into/from `LegacyReplaySoloScoreInfo` 2023-10-16 11:20:02 +02:00
Bartłomiej Dach fa519984df
Move legacy online ID encode/decode to legacy property 2023-10-16 11:20:02 +02:00
Bartłomiej Dach c1a817fec6
Add `LegacyOnlineID` with backwards migration 2023-10-16 11:20:02 +02:00
Dean Herbert 5bb73632c4
Show maximum bonus statistics on results screen
Addresses https://github.com/ppy/osu/discussions/25088.
2023-10-12 14:55:16 +09:00
Bartłomiej Dach 24956588e9
Fix score importer looking up guest user by username online 2023-10-10 09:28:01 +02:00
Dan Balasescu b9ab4a2b7c Update score conversion to consider legacy multiplier 2023-10-02 16:56:15 +09:00
Dean Herbert d5472d3524
Merge pull request #24957 from bdach/solo-score-info-get-display-score
Add `GetDisplayScore()` extension for `SoloScoreInfo`
2023-09-29 13:09:16 +09:00
Dan Balasescu db9113b38e
Merge pull request #24924 from bdach/update-classic-scoring
Update classic scoring formula to closer match stable score V1
2023-09-28 20:19:23 +09:00
Bartłomiej Dach fc4390884f
Add `GetDisplayScore()` extension for `SoloScoreInfo`
To be used server-side for ppy/osu-queue-score-statistics#134.
2023-09-28 12:43:05 +02:00
Bartłomiej Dach 0769d0f49f
Merge branch 'master' into fix-batch-import-score-missing-notifications 2023-09-27 17:06:47 +02:00
Dean Herbert 2481c0b64b Don't show replay import "missing beatmap" notifications during stable import
Closes https://github.com/ppy/osu/issues/24926.
2023-09-27 17:04:43 +09:00
Dean Herbert 3708e79577 Adjust logging to still expose the underlying exception 2023-09-27 16:55:03 +09:00
Dean Herbert d1d82d2b49 Improve notification display when score import fails 2023-09-26 15:00:56 +09:00
Bartłomiej Dach 57c00e728b
Update classic scoring algorithm to closer match stable score V1 2023-09-25 19:16:18 +02:00
Dean Herbert f726c38215 Pass `ArchiveReader` instead of `Stream` to simplify resolution code 2023-09-19 17:49:15 +09:00
Dean Herbert 0593c76c57 Fix log output using incorrect name 2023-09-19 17:34:24 +09:00
Bartłomiej Dach 59b9a636d3
Fix grammar in comment 2023-09-18 10:46:14 +02:00
cdwcgt f68a12003a
check beatmap hash before try to import 2023-09-04 17:37:31 +09:00
cdwcgt 58844092d6
post a notification instead a screen 2023-09-04 16:17:21 +09:00
cdwcgt dfecddbf5d
Merge branch 'master' into missing-beatmap 2023-09-04 12:41:23 +09:00
Dean Herbert 5dee43815c Bump version to allow migration to re-run 2023-08-22 16:13:01 +09:00
Dean Herbert b3e7416972 Rename new flag and update xmldoc to match 2023-08-21 19:36:22 +09:00
Dean Herbert 662073c472
Fix some incorrect comments / test step descriptions
Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
2023-08-21 19:35:04 +09:00
cdwcgt 09047538c7
remove all memory stream dispose 2023-08-04 20:02:22 +09:00
cdwcgt 0e7e36f114
don't passing stream by exception 2023-08-02 22:04:29 +09:00
cdwcgt 6637a5e7bc
ensure Performer not null 2023-08-02 18:53:27 +09:00
cdwcgt 4c43c92329
ensure dispose stream 2023-08-02 17:58:17 +09:00
cdwcgt eef63b41da
fetch missing beatmap when import score with missing beatmap 2023-08-02 17:58:05 +09:00
Liam DeVoe 04ef04b902 only ignore the first negative frame among the first 3 replay frames 2023-07-27 21:12:08 -04:00
Liam DeVoe 7d174dd8bb dont count any of first three frames towards time deficit 2023-07-27 17:20:54 -04:00
Liam DeVoe a93561cab0 remove resolved comment 2023-07-27 02:12:43 -04:00
Liam DeVoe 217b07810f don't skip the negative break frame
investigation reveals this frame is played back by stable
2023-07-27 02:12:21 -04:00
Dean Herbert 30baac0f3d Avoid reprocessing scores which already failed an upgrade previously
Closes https://github.com/ppy/osu/issues/24301.
2023-07-26 16:22:10 +09:00
Dean Herbert c1ba8fe175 Rename `BackgroundBeatmapProcessor` to `BackgroundDataStoreProcessor` 2023-07-26 16:22:10 +09:00
Dean Herbert eb81eac635 Flag decoded scores more correctly 2023-07-15 12:19:18 +09:00
Dean Herbert d72765b6f8
Merge pull request #24114 from peppy/editor-save-local-score-management
Ensure scores always have the correct linked `BeatmapInfo`
2023-07-07 15:40:54 +09:00
Liam DeVoe cc6646c82b properly handle negative frame before a break
this was causing replay data before the skip to be...skipped.
2023-07-06 17:13:33 -04:00
Bartłomiej Dach ae2896ba7e
Sprinkle some more null-forgiving operators 2023-07-06 22:08:48 +02:00
Liam DeVoe 00250972c3 skip frames after a negative frame until the negative time is "paid back" 2023-07-06 02:31:12 -04:00
Dean Herbert a98a36872e Bring realm library up-to-date 2023-07-06 13:37:43 +09:00
Dean Herbert 9ff6b3fcd3 Merge branch 'master' into editor-save-local-score-management 2023-07-06 12:28:44 +09:00
Dean Herbert 00c68cad53 Fix new scoring related properties not storing to realm due to `internal` spec 2023-07-05 19:47:44 +09:00
Dean Herbert 5947c2b298 Throw if a null `BeatmapInfo` arrives during score import process 2023-07-05 16:08:06 +09:00
Bartłomiej Dach a55809733d
Expand `ScoreInfo.BeatmapInfo` xmldoc 2023-07-04 22:20:50 +02:00
Dean Herbert f2aa80f413 Rename and adjust xmldoc on `TotalScoreVersion` 2023-07-04 20:04:02 +09:00
Dean Herbert a0c3fa9c13 Move preconditions to realm migration step to simplify marker version logic 2023-07-04 17:53:53 +09:00
Dean Herbert d74b1e148d Make `ScoreInfo.BeatmapInfo` nullable 2023-07-04 14:50:34 +09:00
Dean Herbert 4203e2183d
Merge branch 'master' into diffcalc-total-scorev1 2023-07-04 14:15:24 +09:00
Cootz 8d25e2c3e1 Add importer update test 2023-07-01 09:49:06 +03:00
Dan Balasescu 6822871dab Move population of LegacyTotalScore to ScoreImporter 2023-06-29 17:21:24 +09:00
Dan Balasescu ddd870e843 Make LegacyTotalScore nullable 2023-06-29 17:19:10 +09:00
Dan Balasescu 1ca4e39fc3 Allow legacy scores to be displayed in "classic" scoring mode 2023-06-28 16:30:50 +09:00
Dan Balasescu 09bc8e45de Refactoring 2023-06-28 16:14:32 +09:00
Dan Balasescu e291dff5ad Fix imported scores not getting LegacyTotalScore 2023-06-28 14:50:16 +09:00
Dan Balasescu 6e2369e651 Add xmldoc on LegacyTotalScore 2023-06-27 17:18:32 +09:00
Dan Balasescu 0c5c09597c Store old total score as LegacyTotalScore 2023-06-27 14:59:40 +09:00
Dan Balasescu a9c65d200a Initial conversion of scores 2023-06-26 22:19:01 +09:00
Dan Balasescu 8e79510793 Add migration for total score conversion 2023-06-26 21:53:21 +09:00
Bartłomiej Dach 66ef199fa4
Revert nullability enable in `Score` (and related changes)
Causes several knock-on inspections in `OsuGame` et al. Probably best
addressed in a separate pass, because treatment is mixed at best (some
places nullcheck, some expect non-null).
2023-06-24 15:35:07 +02:00
Dean Herbert df5b389629 Manual fixes to reduce warnings to zero 2023-06-24 01:52:53 +09:00
Dean Herbert 0ab0c52ad5 Automated pass 2023-06-24 01:00:03 +09:00
Dean Herbert 362aa4b376 Also move `GetMaxAchievableCombo` 2023-06-16 15:26:13 +09:00
Dean Herbert ce41ef6e5d Move `OrderByTotalScore()` to an extension method 2023-06-16 15:24:30 +09:00
Bartłomiej Dach 51b5a0863f
Apply migration to new standardised score on normal reimport too 2023-06-15 21:53:15 +02:00
Dean Herbert 659a042065
Merge pull request #23844 from peppy/memory-caching-nrt
Apply NRT to `MemoryCachingComponent` classes
2023-06-09 23:28:21 +09:00
Bartłomiej Dach 52412c673d
Bump replay version in encoder after Score V2 changes
One release too late, but this may help in the future if we need to
discern replays set with Score V2 from older lazer replays.
2023-06-09 14:49:49 +02:00
Bartłomiej Dach 11694f35fe
Apply NRT in `MemoryCachingComponent` subclasses too 2023-06-09 13:47:35 +02:00
Dean Herbert c5e77e13de Add a very simple user cache to `ScoreImporter` 2023-06-09 19:03:28 +09:00
Dan Balasescu 76df11c398 Don't scale stable scores with the classic scoring mode 2023-06-08 21:38:10 +09:00