1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-13 19:54:15 +08:00

Added "LN Ratio" display in Mania in the place of useless "key count" (#37581)

The "Key Count" metric in mania is very useless since you are already
expected to play maps with a specific Key Count when you are queueing.
This PR inserts the proportion of LNs (Long Notes) in the place of that
metric since it is one of the ways players can gudge their skillsets
(This idea comes from reddit)
Also improved the test suite for other skillsets by making the
architecture more minor ruleset friendly

Addresses https://github.com/ppy/osu/discussions/37568.

---------

Co-authored-by: Dan Balasescu <smoogipoo@smgi.me>
Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
Kao Li Chin (Gao Li Jin)
2026-05-08 17:04:29 +08:00
committed by GitHub
Unverified
parent e6fdd37e76
commit 53f945b7ac
12 changed files with 149 additions and 23 deletions
+16
View File
@@ -485,6 +485,22 @@ namespace osu.Game.Rulesets.Mania
};
}
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForRankedPlayCard(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
{
var attributes = GetBeatmapAttributesForDisplay(beatmapInfo, mods).ToList();
// Key count attribute isn't relevant to ranked play (it's decided by the pool).
attributes.RemoveAll(a => a.Acronym == "KC");
float holdNoteRatio = beatmapInfo.TotalObjectCount == 0 ? 0 : (float)beatmapInfo.EndTimeObjectCount / beatmapInfo.TotalObjectCount;
attributes.Insert(0, new RulesetBeatmapAttribute("Hold notes", @"HN", holdNoteRatio, holdNoteRatio, 1)
{
ValueFormat = "P0"
});
return attributes;
}
public override IRulesetFilterCriteria CreateRulesetFilterCriteria()
{
return new ManiaFilterCriteria();
@@ -0,0 +1,8 @@
[
{"beatmapset_id":2529695,"difficulty_rating":7.61701,"id":5590715,"mode":"mania","status":"ranked","total_length":396,"user_id":13371424,"version":"[4K] Memoriae Effervescentes","accuracy":7.2,"ar":5,"bpm":220,"convert":false,"count_circles":2097,"count_sliders":3556,"count_spinners":0,"cs":4,"deleted_at":null,"drain":8.2,"hit_length":395,"is_scoreable":true,"last_updated":"2026-04-21T08:35:33Z","mode_int":3,"passcount":1485,"playcount":4006,"ranked":1,"url":"https:\/\/osu.ppy.sh\/beatmaps\/5590715","checksum":"5b43b30845408f6bf0cc02d19fa475a4","beatmapset":{"anime_cover":false,"artist":"Laur","artist_unicode":"Laur","covers":{"cover":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/cover.jpg?1776760548","cover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/cover@2x.jpg?1776760548","card":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/card.jpg?1776760548","card@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/card@2x.jpg?1776760548","list":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/list.jpg?1776760548","list@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/list@2x.jpg?1776760548","slimcover":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/slimcover.jpg?1776760548","slimcover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2529695\/covers\/slimcover@2x.jpg?1776760548"},"creator":"Ainer","favourite_count":55,"genre_id":10,"hype":null,"id":2529695,"language_id":5,"nsfw":false,"offset":0,"play_count":4102,"preview_url":"https:\/\/b.ppy.sh\/preview\/2529695.mp3","source":"osu!mania 7K World Cup 2026","spotlight":false,"status":"ranked","title":"SEV-26","title_unicode":"SEV-26","track_id":11695,"user_id":13371424,"video":false,"bpm":180,"can_be_hyped":false,"deleted_at":null,"discussion_enabled":true,"discussion_locked":false,"is_scoreable":true,"last_updated":"2026-04-21T08:35:32Z","legacy_thread_url":"https:\/\/osu.ppy.sh\/community\/forums\/topics\/2191856","nominations_summary":{"current":2,"eligible_main_rulesets":["mania"],"required_meta":{"main_ruleset":2,"non_main_ruleset":1}},"ranked":1,"ranked_date":"2026-04-28T09:22:15Z","rating":8.96296,"storyboard":false,"submitted_date":"2026-03-28T00:58:23Z","tags":"featured artist fa mappers' guild mg mpg osu! original electronic instrumental neurofunk hardcore psytrance speedcore tearout dubstep orchestral artcore sev26 sylvatic encephalitis virus grand finals grandfinals gf mwc 2026 world cup mwc2026 mwc7k2026 tb tiebreaker alicia antipole symmatrix- sardines bruh_shen tehfire polytetral hourius naraicat alexdunk lowgraphics sakura006","availability":{"download_disabled":false,"more_information":null},"ratings":[0,3,0,0,0,0,0,0,0,1,23]},"current_user_playcount":0,"failtimes":{"fail":[0,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,18,18,0,0,0,0,0,0,0,0,9,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,18,9,9,18,0,18,9,0,0,0,0,0],"exit":[0,36,36,45,63,9,9,54,18,63,72,18,9,0,9,9,0,18,27,18,18,45,0,9,9,9,9,27,9,9,9,9,9,0,0,9,0,9,0,0,0,0,0,0,18,0,0,0,0,9,0,9,0,0,0,0,18,18,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,9,9,0,0,9,18,0,9,0,0,0,0,0,0,0]},"max_combo":9163,"owners":[{"id":13371424,"username":"Ainer"},{"id":17258072,"username":"Alicia"}]},
{"beatmapset_id":2518293,"difficulty_rating":3.61767,"id":5602450,"mode":"mania","status":"ranked","total_length":282,"user_id":8425052,"version":"[4K] Innocence","accuracy":8,"ar":5,"bpm":140,"convert":false,"count_circles":3618,"count_sliders":0,"count_spinners":0,"cs":4,"deleted_at":null,"drain":8,"hit_length":281,"is_scoreable":true,"last_updated":"2026-04-13T00:00:32Z","mode_int":3,"passcount":369,"playcount":1963,"ranked":1,"url":"https:\/\/osu.ppy.sh\/beatmaps\/5602450","checksum":"51319d68b9373eb98807ea5a2187d803","beatmapset":{"anime_cover":false,"artist":"rejection","artist_unicode":"rejection","covers":{"cover":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/cover.jpg?1776038446","cover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/cover@2x.jpg?1776038446","card":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/card.jpg?1776038446","card@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/card@2x.jpg?1776038446","list":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/list.jpg?1776038446","list@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/list@2x.jpg?1776038446","slimcover":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/slimcover.jpg?1776038446","slimcover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2518293\/covers\/slimcover@2x.jpg?1776038446"},"creator":"Stella-","favourite_count":48,"genre_id":10,"hype":null,"id":2518293,"language_id":3,"nsfw":false,"offset":0,"play_count":2031,"preview_url":"https:\/\/b.ppy.sh\/preview\/2518293.mp3","source":"","spotlight":false,"status":"ranked","title":"White Canvas (feat. Aitsuki Nakuru)","title_unicode":"White Canvas (feat. \u85cd\u6708\u306a\u304f\u308b)","track_id":5057,"user_id":8425052,"video":false,"bpm":140,"can_be_hyped":false,"deleted_at":null,"discussion_enabled":true,"discussion_locked":false,"is_scoreable":true,"last_updated":"2026-04-13T00:00:32Z","legacy_thread_url":"https:\/\/osu.ppy.sh\/community\/forums\/topics\/2185354","nominations_summary":{"current":2,"eligible_main_rulesets":["mania"],"required_meta":{"main_ruleset":2,"non_main_ruleset":1}},"ranked":1,"ranked_date":"2026-04-21T23:42:39Z","rating":8.66667,"storyboard":false,"submitted_date":"2026-03-06T10:45:47Z","tags":"fa featured artist japanese pop jpop j-pop electronic encore emotional -emotional vocal pop 02- 2 megarex mrx-074 mrx074 female vocals vocalist m3-2020\u79cb fall m3-46 muse dash the future","availability":{"download_disabled":false,"more_information":null},"ratings":[0,0,0,0,0,1,0,1,0,0,4]},"current_user_playcount":0,"failtimes":{"fail":[0,0,0,0,9,0,9,0,0,9,0,0,0,0,0,0,0,0,0,0,0,9,0,9,0,0,0,9,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"exit":[0,0,18,18,9,63,9,27,18,9,18,9,18,9,27,9,36,0,0,9,9,0,9,0,18,27,0,0,0,9,9,0,0,0,0,9,0,9,0,9,9,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,9,0,0,0,9,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"max_combo":3618,"owners":[{"id":8425052,"username":"Stella-"}]},
{"beatmapset_id":1665948,"difficulty_rating":4.87529,"id":3871759,"mode":"mania","status":"ranked","total_length":379,"user_id":17272017,"version":"[4K] Time Freeze Illusion","accuracy":8.5,"ar":5,"bpm":200,"convert":false,"count_circles":5264,"count_sliders":629,"count_spinners":0,"cs":4,"deleted_at":null,"drain":8,"hit_length":377,"is_scoreable":true,"last_updated":"2026-04-13T09:52:53Z","mode_int":3,"passcount":308,"playcount":1738,"ranked":1,"url":"https:\/\/osu.ppy.sh\/beatmaps\/3871759","checksum":"34b98351e32ca3db24ea9fc0055a923b","beatmapset":{"anime_cover":true,"artist":"Release Hallucination","artist_unicode":"Release Hallucination","covers":{"cover":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/cover.jpg?1776073987","cover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/cover@2x.jpg?1776073987","card":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/card.jpg?1776073987","card@2x":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/card@2x.jpg?1776073987","list":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/list.jpg?1776073987","list@2x":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/list@2x.jpg?1776073987","slimcover":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/slimcover.jpg?1776073987","slimcover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/1665948\/covers\/slimcover@2x.jpg?1776073987"},"creator":"Lazurent","favourite_count":51,"genre_id":11,"hype":null,"id":1665948,"language_id":3,"nsfw":false,"offset":0,"play_count":4811,"preview_url":"https:\/\/b.ppy.sh\/preview\/1665948.mp3","source":"","spotlight":false,"status":"ranked","title":"Chronostasis","title_unicode":"Chronostasis","track_id":4954,"user_id":17272017,"video":false,"bpm":200,"can_be_hyped":false,"deleted_at":null,"discussion_enabled":true,"discussion_locked":false,"is_scoreable":true,"last_updated":"2026-04-13T09:52:53Z","legacy_thread_url":"https:\/\/osu.ppy.sh\/community\/forums\/topics\/1494910","nominations_summary":{"current":2,"eligible_main_rulesets":["mania"],"required_meta":{"main_ruleset":2,"non_main_ruleset":1}},"ranked":1,"ranked_date":"2026-04-20T11:25:45Z","rating":8.33333,"storyboard":false,"submitted_date":"2022-01-03T14:00:15Z","tags":"m3-38 symphonic progressive metal marathon emi gothic kaorin kaoru hirato japanese \u30af\u30ed\u30ce\u30b9\u30bf\u30b7\u30b9 fa featured artist mg mpg mappers' guild l43yrnt","availability":{"download_disabled":false,"more_information":null},"ratings":[0,1,0,0,0,0,0,0,0,1,4]},"current_user_playcount":0,"failtimes":{"fail":[0,0,0,0,9,9,63,18,45,18,45,27,0,0,0,0,0,9,0,0,0,0,9,18,0,0,0,9,9,0,0,0,0,0,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0],"exit":[0,0,18,63,63,135,261,216,126,81,81,36,18,27,45,27,27,36,9,9,0,18,18,81,27,18,9,18,18,9,0,0,0,36,45,36,0,0,0,0,0,0,9,9,0,18,0,0,9,0,9,0,9,0,0,9,0,9,9,0,0,9,0,0,0,9,0,0,0,0,0,0,0,0,0,9,9,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,9,0,0,0,0,9]},"max_combo":6974,"owners":[{"id":17272017,"username":"Lazurent"}]},
{"beatmapset_id":2535368,"difficulty_rating":5.82018,"id":5606802,"mode":"mania","status":"ranked","total_length":296,"user_id":10085090,"version":"[4K] Desperate Soul","accuracy":8.5,"ar":5,"bpm":240,"convert":false,"count_circles":6288,"count_sliders":0,"count_spinners":0,"cs":4,"deleted_at":null,"drain":8,"hit_length":290,"is_scoreable":true,"last_updated":"2026-04-16T18:03:43Z","mode_int":3,"passcount":208,"playcount":1738,"ranked":1,"url":"https:\/\/osu.ppy.sh\/beatmaps\/5606802","checksum":"55451c2f43654e4ec7b9bb156b93148e","beatmapset":{"anime_cover":false,"artist":"Imperial Circus Dead Decadence","artist_unicode":"Imperial Circus Dead Decadence","covers":{"cover":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/cover.jpg?1776362637","cover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/cover@2x.jpg?1776362637","card":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/card.jpg?1776362637","card@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/card@2x.jpg?1776362637","list":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/list.jpg?1776362637","list@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/list@2x.jpg?1776362637","slimcover":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/slimcover.jpg?1776362637","slimcover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2535368\/covers\/slimcover@2x.jpg?1776362637"},"creator":"Carpihat","favourite_count":48,"genre_id":11,"hype":null,"id":2535368,"language_id":3,"nsfw":false,"offset":0,"play_count":1961,"preview_url":"https:\/\/b.ppy.sh\/preview\/2535368.mp3","source":"","spotlight":false,"status":"ranked","title":"Jashin no Konrei, Gi wa Ai to Shiru.","title_unicode":"\u90aa\u795e\u306e\u5a5a\u793c\u3001\u5100\u306f\u611b\u3068\u77e5\u308b\u3002","track_id":862,"user_id":10085090,"video":false,"bpm":240,"can_be_hyped":false,"deleted_at":null,"discussion_enabled":true,"discussion_locked":false,"is_scoreable":true,"last_updated":"2026-04-16T18:03:42Z","legacy_thread_url":"https:\/\/osu.ppy.sh\/community\/forums\/topics\/2195210","nominations_summary":{"current":2,"eligible_main_rulesets":["mania"],"required_meta":{"main_ruleset":2,"non_main_ruleset":1}},"ranked":1,"ranked_date":"2026-04-18T18:05:56Z","rating":10,"storyboard":false,"submitted_date":"2026-04-07T09:36:37Z","tags":"cthulhu wedding blackened melodic symphonic death black metal melodeath icdd \u72c2\u304a\u3057\u304f\u54b2\u3044\u305f\u51c4\u60e8\u306a\u9ab8\u306f\u594f\u3067\u3001\u611b\u304a\u3057\u304f\u88c2\u3044\u305f\u5c11\u5973\u306f\u8056\u9910\u306e\u8a5e\u3092\u8b33\u3046\u3002 kurooshiku saita seisan na mukuro wa kanaderu itooshiku shoujo seisen no kotoba wo utau fa featured artist japanese mpg mg mappers' guild","availability":{"download_disabled":false,"more_information":null},"ratings":[0,0,0,0,0,0,0,0,0,0,1]},"current_user_playcount":0,"failtimes":{"fail":[0,0,0,9,27,27,27,9,9,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"exit":[0,0,0,27,63,117,108,36,63,36,9,45,9,27,9,0,9,9,0,36,9,36,0,9,0,9,9,0,0,0,27,9,9,0,0,0,0,0,9,0,9,27,9,0,9,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"max_combo":6288,"owners":[{"id":10085090,"username":"Carpihat"}]},
{"beatmapset_id":2348607,"difficulty_rating":5.57212,"id":5140134,"mode":"mania","status":"ranked","total_length":263,"user_id":23384715,"version":"[4K] Enraged Apparition","accuracy":8,"ar":10,"bpm":250,"convert":false,"count_circles":4682,"count_sliders":120,"count_spinners":0,"cs":4,"deleted_at":null,"drain":8,"hit_length":251,"is_scoreable":true,"last_updated":"2026-03-26T20:54:51Z","mode_int":3,"passcount":404,"playcount":2674,"ranked":1,"url":"https:\/\/osu.ppy.sh\/beatmaps\/5140134","checksum":"a2dd0c1b8aa0d3396b47621b758c6adf","beatmapset":{"anime_cover":true,"artist":"Imperial Circus Dead Decadence","artist_unicode":"Imperial Circus Dead Decadence","covers":{"cover":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/cover.jpg?1774558514","cover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/cover@2x.jpg?1774558514","card":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/card.jpg?1774558514","card@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/card@2x.jpg?1774558514","list":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/list.jpg?1774558514","list@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/list@2x.jpg?1774558514","slimcover":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/slimcover.jpg?1774558514","slimcover@2x":"https:\/\/assets.ppy.sh\/beatmaps\/2348607\/covers\/slimcover@2x.jpg?1774558514"},"creator":"Sayuka","favourite_count":435,"genre_id":11,"hype":null,"id":2348607,"language_id":3,"nsfw":false,"offset":0,"play_count":118018,"preview_url":"https:\/\/b.ppy.sh\/preview\/2348607.mp3","source":"","spotlight":false,"status":"ranked","title":"Shinbatsu o Tadori Kyoukotsu ni Itaru","title_unicode":"\u795e\u7f70\u3092\u8fbf\u308a\u72c2\u9aa8\u306b\u81f3\u308b","track_id":8223,"user_id":11322604,"video":false,"bpm":250,"can_be_hyped":false,"deleted_at":null,"discussion_enabled":true,"discussion_locked":false,"is_scoreable":true,"last_updated":"2026-03-26T20:54:46Z","legacy_thread_url":"https:\/\/osu.ppy.sh\/community\/forums\/topics\/2061550","nominations_summary":{"current":3,"eligible_main_rulesets":["osu"],"required_meta":{"main_ruleset":2,"non_main_ruleset":1}},"ranked":1,"ranked_date":"2026-04-12T17:43:03Z","rating":9.11539,"storyboard":false,"submitted_date":"2025-04-02T11:30:44Z","tags":"maaadbot rhythmnoodles ciiyus icdd sinyus20 oomf chan ciyus miapah fort danilmaz1 mekadon -aly arthro roupus julie maiev worthlessnut9 frawog mithew m1ts shoyeu take amats sprixx chocomilk \u9ec4\u6cc9\u3088\u308a\u8074\u3053\u3086\u3001\u7687\u56fd\u306e\u71c8\u3068\u7114\u306e\u5c11\u5973\u3002 japanese male vocals symphonic melodic black death metal doujin hull kim rib:y(uhki) rib yuhki shuhei js jumpstream hs handstream stream stamina jack chordjack rice fa featured artist","availability":{"download_disabled":false,"more_information":null},"ratings":[0,7,0,0,1,0,1,1,3,10,81]},"current_user_playcount":0,"failtimes":{"fail":[0,0,0,18,72,54,36,36,18,9,9,9,0,0,0,9,63,18,0,0,0,0,0,0,9,0,0,0,9,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0],"exit":[0,0,9,243,90,198,216,126,18,81,63,36,9,0,18,135,45,27,27,18,18,9,0,0,0,0,9,9,18,27,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,27,18,9,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,27,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,9,0]},"max_combo":5113,"owners":[{"id":16018038,"username":"frawog"},{"id":23384715,"username":"Worthlessnut9"}]}
]
@@ -9,6 +9,7 @@ using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
using osu.Game.Tests.Resources;
using osu.Game.Tests.Visual.Multiplayer;
@@ -18,14 +19,26 @@ namespace osu.Game.Tests.Visual.RankedPlay
public abstract partial class RankedPlayTestScene : MultiplayerTestScene
{
/// <summary>
/// Returns 5 sample <see cref="APIBeatmap"/>s.
/// Returns 5 sample of the chosen ruleset <see cref="APIBeatmap"/>s.
/// </summary>
protected static APIBeatmap[] GetSampleBeatmaps()
protected static APIBeatmap[] GetSampleBeatmaps(RulesetInfo ruleset)
{
using var resourceStream = TestResources.OpenResource("Requests/api-beatmaps-rankedplay.json");
using var reader = new StreamReader(resourceStream);
switch (ruleset.OnlineID)
{
case 3:
{
using var resourceStream = TestResources.OpenResource("Requests/api-beatmaps-rankedplay-mania4k.json");
using var reader = new StreamReader(resourceStream);
return JsonConvert.DeserializeObject<APIBeatmap[]>(reader.ReadToEnd())!;
}
return JsonConvert.DeserializeObject<APIBeatmap[]>(reader.ReadToEnd())!;
default:
{
using var resourceStream = TestResources.OpenResource("Requests/api-beatmaps-rankedplay.json");
using var reader = new StreamReader(resourceStream);
return JsonConvert.DeserializeObject<APIBeatmap[]>(reader.ReadToEnd())!;
}
}
}
/// <summary>
@@ -33,7 +46,12 @@ namespace osu.Game.Tests.Visual.RankedPlay
/// </summary>
public class BeatmapRequestHandler
{
public readonly APIBeatmap[] Beatmaps = GetSampleBeatmaps();
public APIBeatmap[] Beatmaps;
public BeatmapRequestHandler(RulesetInfo ruleset)
{
Beatmaps = GetSampleBeatmaps(ruleset);
}
public bool HandleRequest(APIRequest request)
{
@@ -6,6 +6,7 @@ using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
namespace osu.Game.Tests.Visual.RankedPlay
@@ -26,7 +27,8 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddUntilStep("screen loaded", () => screen.IsLoaded);
var requestHandler = new BeatmapRequestHandler();
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -6,6 +6,7 @@ using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
namespace osu.Game.Tests.Visual.RankedPlay
@@ -26,7 +27,8 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddUntilStep("screen loaded", () => screen.IsLoaded);
var requestHandler = new BeatmapRequestHandler();
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
@@ -9,6 +10,8 @@ using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
using osuTK.Input;
@@ -30,8 +33,63 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddUntilStep("screen loaded", () => screen.IsLoaded);
}
var requestHandler = new BeatmapRequestHandler();
[Test]
public void TestOsu()
{
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
AddWaitStep("wait some", 5);
AddStep("reveal cards", () =>
{
for (int i = 0; i < 5; i++)
{
int i2 = i;
MultiplayerClient.RankedPlayRevealCard(hand => hand[i2], new MultiplayerPlaylistItem
{
ID = i2,
BeatmapID = requestHandler.Beatmaps[i2].OnlineID
}).WaitSafely();
}
});
for (int i = 0; i < 3; i++)
{
int i2 = i;
AddStep($"click card {i2}", () =>
{
InputManager.MoveMouseTo(this.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>().ElementAt(i2));
InputManager.Click(MouseButton.Left);
});
}
AddWaitStep("wait", 3);
AddStep("click play button", () =>
{
var button = screen
.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>()
.First(it => it.Selected)
.ChildrenOfType<ShearedButton>()
.First();
InputManager.MoveMouseTo(button);
InputManager.Click(MouseButton.Left);
});
}
[Test]
public void TestMania()
{
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new ManiaRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -12,6 +12,10 @@ using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
using osuTK;
@@ -31,8 +35,6 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Cached]
private readonly SongPreviewParticleContainer particleContainer;
private readonly BeatmapRequestHandler requestHandler = new BeatmapRequestHandler();
public TestSceneRankedPlayCard()
{
base.Content.AddRange(new Drawable[]
@@ -121,6 +123,8 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestCardHand()
{
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
AddStep("add cards", () =>
@@ -143,13 +147,16 @@ namespace osu.Game.Tests.Visual.RankedPlay
});
}
[Resolved]
private RulesetStore rulesetStore { get; set; } = null!;
[Test]
public void TestRulesets()
{
var rulesets = rulesetStore.AvailableRulesets.Where(it => it.OnlineID >= 0);
RulesetInfo[] rulesets =
[
new OsuRuleset().RulesetInfo,
new TaikoRuleset().RulesetInfo,
new CatchRuleset().RulesetInfo,
new ManiaRuleset().RulesetInfo
];
foreach (var ruleset in rulesets)
{
@@ -11,6 +11,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
@@ -108,7 +109,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
var requestHandler = new BeatmapRequestHandler();
var requestHandler = new BeatmapRequestHandler(Ruleset.Value);
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -224,7 +225,8 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
var requestHandler = new BeatmapRequestHandler();
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -7,6 +7,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
using osuTK;
@@ -17,18 +18,18 @@ namespace osu.Game.Tests.Visual.RankedPlay
{
private readonly Bindable<bool> previewEnabled = new BindableBool(true);
private readonly BeatmapRequestHandler requestHandler = new BeatmapRequestHandler();
public override void SetUpSteps()
{
base.SetUpSteps();
BeatmapRequestHandler requestHandler = null!;
AddStep("setup ruleset", () => requestHandler = new BeatmapRequestHandler(new OsuRuleset().RulesetInfo));
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
AddStep("add cards", () =>
{
PlayerHandOfCards handOfCards;
Child = handOfCards = new PlayerHandOfCards
{
RelativeSizeAxes = Axes.Both,
@@ -53,6 +53,11 @@ namespace osu.Game.Rulesets.Difficulty
/// </summary>
public AdditionalMetric[] AdditionalMetrics { get; init; } = [];
/// <summary>
/// An optional formatting specifier for the values of this attribute.
/// </summary>
public string ValueFormat { get; init; } = string.Empty;
public RulesetBeatmapAttribute(LocalisableString label, string acronym, float originalValue, float adjustedValue, float maxValue)
{
Label = label;
+6
View File
@@ -430,6 +430,12 @@ namespace osu.Game.Rulesets
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10);
}
/// <summary>
/// Overload of <see cref="GetAdjustedDisplayDifficulty"/> for display on Ranked Cards
/// </summary>
public virtual IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForRankedPlayCard(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods) =>
GetBeatmapAttributesForDisplay(beatmapInfo, mods);
/// <summary>
/// Creates ruleset-specific beatmap filter criteria to be used on the song select screen.
/// </summary>
@@ -97,8 +97,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card
},
]
},
..ruleset.GetBeatmapAttributesForDisplay(beatmap, [])
.Select(attribute => new AttributeRow(attribute))
..ruleset.GetBeatmapAttributesForRankedPlayCard(beatmap, []).Select(attribute => new AttributeRow(attribute))
]
};
}
@@ -126,7 +125,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card
new OsuSpriteText
{
RelativePositionAxes = Axes.X,
Text = attribute.AdjustedValue.ToStandardFormattedString(maxDecimalDigits: 1),
Text = string.IsNullOrEmpty(attribute.ValueFormat)
? attribute.AdjustedValue.ToStandardFormattedString(maxDecimalDigits: 1)
: attribute.AdjustedValue.ToString(attribute.ValueFormat),
Font = OsuFont.GetFont(size: 9, weight: FontWeight.SemiBold),
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreRight,