diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs new file mode 100644 index 0000000000..74470f22fc --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Game.Utils; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneMetricNumbers : OsuTestScene + { + public TestSceneMetricNumbers() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new DrawableNumber(0), + new DrawableNumber(1001), + new DrawableNumber(999_999), + new DrawableNumber(1_000_000), + new DrawableNumber(845_006_456), + new DrawableNumber(999_999_999), + new DrawableNumber(1_000_000_000), + new DrawableNumber(7_875_454_545), + new DrawableNumber(999_999_999_999), + new DrawableNumber(1_000_000_000_000), + new DrawableNumber(687_545_454_554_545), + new DrawableNumber(999_999_999_999_999), + new DrawableNumber(1_000_000_000_000_000), + new DrawableNumber(587_545_454_554_545_455), + new DrawableNumber(999_999_999_999_999_999), + new DrawableNumber(1_000_000_000_000_000_000), + new DrawableNumber(long.MaxValue), + } + }; + } + + private class DrawableNumber : SpriteText, IHasTooltip + { + public string TooltipText => value.ToString("F0"); + + private readonly long value; + + public DrawableNumber(long value) + { + this.value = value; + Text = HumanizerUtils.ToMetric(value); + } + } + } +} diff --git a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs new file mode 100644 index 0000000000..3bd772732f --- /dev/null +++ b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Online.API.Requests +{ + public class GetCountryRankingsRequest : GetRankingsRequest + { + public GetCountryRankingsRequest(RulesetInfo ruleset, int page = 1) + : base(ruleset, page) + { + } + + protected override string TargetPostfix() => "country"; + } +} diff --git a/osu.Game/Online/API/Requests/GetRankingsRequest.cs b/osu.Game/Online/API/Requests/GetRankingsRequest.cs new file mode 100644 index 0000000000..efaaa2cb40 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetRankingsRequest.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using osu.Game.Rulesets; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests +{ + public abstract class GetRankingsRequest : APIRequest> + { + private readonly RulesetInfo ruleset; + private readonly int page; + + protected GetRankingsRequest(RulesetInfo ruleset, int page = 1) + { + this.ruleset = ruleset; + this.page = page; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.AddParameter("page", page.ToString()); + + return req; + } + + protected override string Target => $"rankings/{ruleset.ShortName}/{TargetPostfix()}"; + + protected abstract string TargetPostfix(); + } +} diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs new file mode 100644 index 0000000000..bbba6a210d --- /dev/null +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Online.API.Requests +{ + public class GetUserRankingsRequest : GetRankingsRequest + { + private readonly string country; + private readonly UserRankingsType type; + + public GetUserRankingsRequest(RulesetInfo ruleset, UserRankingsType type = UserRankingsType.Performance, int page = 1, string country = null) + : base(ruleset, page) + { + this.type = type; + this.country = country; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + if (country != null) + req.AddParameter("country", country); + + return req; + } + + protected override string TargetPostfix() => type.ToString().ToLowerInvariant(); + } + + public enum UserRankingsType + { + Performance, + Score + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs b/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs new file mode 100644 index 0000000000..91086876a9 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APICountryRankings : CountryStatistics + { + [JsonProperty] + public Country Country; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs b/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs new file mode 100644 index 0000000000..1cdb6ecb8c --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIUserRankings : UserStatistics + { + [JsonProperty] + public User User; + } +} diff --git a/osu.Game/Users/CountryStatistics.cs b/osu.Game/Users/CountryStatistics.cs new file mode 100644 index 0000000000..53fa70f0d4 --- /dev/null +++ b/osu.Game/Users/CountryStatistics.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; + +namespace osu.Game.Users +{ + public class CountryStatistics + { + [JsonProperty(@"code")] + public string FlagName; + + [JsonProperty(@"active_users")] + public long ActiveUsers; + + [JsonProperty(@"play_count")] + public long PlayCount; + + [JsonProperty(@"ranked_score")] + public long RankedScore; + + [JsonProperty(@"performance")] + public long Performance; + } +} diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index 5b7c3630d9..ee6f6f95a3 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -26,5 +26,32 @@ namespace osu.Game.Utils return input.Humanize(culture: new CultureInfo("en-US")); } } + + /// + /// Turns the current or provided big number into a readable string. + /// + /// The number to be humanized. + /// Simplified number with a suffix. + public static string ToMetric(long input) + { + const int k = 1000; + + if (input < k) + return input.ToString(); + + int i = (int)Math.Floor(Math.Round(Math.Log(input, k))); + return $"{input / Math.Pow(k, i):F} {suffixes[i]}"; + } + + private static readonly string[] suffixes = new[] + { + "", + "k", + "million", + "billion", + "trillion", + "quadrillion", + "quintillion", + }; } }