1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-23 20:20:16 +08:00

Add daily challenge streak display and tooltip

This commit is contained in:
Salman Ahmed
2024-07-28 05:24:29 +03:00
Unverified
parent 0c89210bd7
commit 17f5d58be2
3 changed files with 418 additions and 0 deletions
@@ -0,0 +1,63 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Rulesets.Osu;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
public partial class TestSceneUserProfileDailyChallenge : OsuManualInputManagerTestScene
{
[Cached]
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>(new UserProfileData(new APIUser(), new OsuRuleset().RulesetInfo));
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
protected override void LoadComplete()
{
base.LoadComplete();
DailyChallengeStreakDisplay display = null!;
AddSliderStep("daily", 0, 999, 2, v => update(s => s.DailyStreakCurrent = v));
AddSliderStep("daily best", 0, 999, 2, v => update(s => s.DailyStreakBest = v));
AddSliderStep("weekly", 0, 250, 1, v => update(s => s.WeeklyStreakCurrent = v));
AddSliderStep("weekly best", 0, 250, 1, v => update(s => s.WeeklyStreakBest = v));
AddSliderStep("top 10%", 0, 999, 0, v => update(s => s.Top10PercentPlacements = v));
AddSliderStep("top 50%", 0, 999, 0, v => update(s => s.Top50PercentPlacements = v));
AddStep("create", () =>
{
Clear();
Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background2,
});
Add(display = new DailyChallengeStreakDisplay
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1f),
User = { BindTarget = User },
});
});
AddStep("hover", () => InputManager.MoveMouseTo(display));
}
private void update(Action<APIUserDailyChallengeStatistics> change)
{
change.Invoke(User.Value!.User.DailyChallengeStatistics);
User.Value = new UserProfileData(User.Value.User, User.Value.Ruleset);
}
}
}
@@ -0,0 +1,112 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class DailyChallengeStreakDisplay : CompositeDrawable, IHasCustomTooltip<APIUserDailyChallengeStatistics>
{
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public APIUserDailyChallengeStatistics? TooltipContent { get; private set; }
private OsuSpriteText dailyStreak = null!;
[Resolved]
private OverlayColourProvider colourProvider { get; set; } = null!;
[Resolved]
private OsuColour colours { get; set; } = null!;
[BackgroundDependencyLoader]
private void load()
{
AutoSizeAxes = Axes.Both;
CornerRadius = 5;
Masking = true;
InternalChildren = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4,
},
new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Padding = new MarginPadding(5f),
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12))
{
AutoSizeAxes = Axes.Both,
// Text = UsersStrings.ShowDailyChallengeTitle
Text = "Daily\nChallenge",
Margin = new MarginPadding { Horizontal = 5f, Bottom = 2f },
},
new Container
{
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
CornerRadius = 5f,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background6,
},
dailyStreak = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
UseFullGlyphHeight = false,
Colour = colourProvider.Content2,
Margin = new MarginPadding { Horizontal = 10f, Vertical = 5f },
},
}
},
}
},
};
}
protected override void LoadComplete()
{
base.LoadComplete();
User.BindValueChanged(_ => updateDisplay(), true);
}
private void updateDisplay()
{
if (User.Value == null)
{
dailyStreak.Text = "-";
return;
}
var statistics = User.Value.User.DailyChallengeStatistics;
// dailyStreak.Text = UsersStrings.ShowDailyChallengeUnitDay(statistics.DailyStreakCurrent);
dailyStreak.Text = $"{statistics.DailyStreakCurrent}d";
dailyStreak.Colour = colours.ForRankingTier(DailyChallengeStreakTooltip.TierForDaily(statistics.DailyStreakCurrent));
TooltipContent = statistics;
}
public ITooltip<APIUserDailyChallengeStatistics> GetCustomTooltip() => new DailyChallengeStreakTooltip(colourProvider);
}
}
@@ -0,0 +1,243 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Scoring;
using osuTK;
namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class DailyChallengeStreakTooltip : VisibilityContainer, ITooltip<APIUserDailyChallengeStatistics>
{
[Cached]
private readonly OverlayColourProvider colourProvider;
private StreakPiece currentDaily = null!;
private StreakPiece currentWeekly = null!;
private StatisticsPiece bestDaily = null!;
private StatisticsPiece bestWeekly = null!;
private StatisticsPiece topTen = null!;
private StatisticsPiece topFifty = null!;
[Resolved]
private OsuColour colours { get; set; } = null!;
public DailyChallengeStreakTooltip(OverlayColourProvider colourProvider)
{
this.colourProvider = colourProvider;
}
[BackgroundDependencyLoader]
private void load()
{
AutoSizeAxes = Axes.Both;
CornerRadius = 20f;
Masking = true;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4,
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new Container
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background5,
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Padding = new MarginPadding(15f),
Spacing = new Vector2(30f),
Children = new[]
{
// currentDaily = new StreakPiece(UsersStrings.ShowDailyChallengeDailyStreakCurrent),
// currentWeekly = new StreakPiece(UsersStrings.ShowDailyChallengeWeeklyStreakCurrent),
currentDaily = new StreakPiece("Current Daily Streak"),
currentWeekly = new StreakPiece("Current Weekly Streak"),
}
},
}
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding(15f),
Spacing = new Vector2(10f),
Children = new[]
{
// bestDaily = new StatisticsPiece(UsersStrings.ShowDailyChallengeDailyStreakBest),
// bestWeekly = new StatisticsPiece(UsersStrings.ShowDailyChallengeWeeklyStreakBest),
// topTen = new StatisticsPiece(UsersStrings.ShowDailyChallengeTop10pPlacements),
// topFifty = new StatisticsPiece(UsersStrings.ShowDailyChallengeTop50pPlacements),
bestDaily = new StatisticsPiece("Best Daily Streak"),
bestWeekly = new StatisticsPiece("Best Weekly Streak"),
topTen = new StatisticsPiece("Top 10% Placements"),
topFifty = new StatisticsPiece("Top 50% Placements"),
}
},
}
}
};
}
public void SetContent(APIUserDailyChallengeStatistics content)
{
// currentDaily.Value = UsersStrings.ShowDailyChallengeUnitDay(content.DailyStreakCurrent.ToLocalisableString(@"N0"));
currentDaily.Value = $"{content.DailyStreakCurrent:N0}d";
currentDaily.ValueColour = colours.ForRankingTier(TierForDaily(content.DailyStreakCurrent));
// currentWeekly.Value = UsersStrings.ShowDailyChallengeUnitWeek(content.WeeklyStreakCurrent.ToLocalisableString(@"N0"));
currentWeekly.Value = $"{content.WeeklyStreakCurrent:N0}w";
currentWeekly.ValueColour = colours.ForRankingTier(TierForWeekly(content.WeeklyStreakCurrent));
// bestDaily.Value = UsersStrings.ShowDailyChallengeUnitDay(content.DailyStreakBest.ToLocalisableString(@"N0"));
bestDaily.Value = $"{content.DailyStreakBest:N0}d";
bestDaily.ValueColour = colours.ForRankingTier(TierForDaily(content.DailyStreakBest));
// bestWeekly.Value = UsersStrings.ShowDailyChallengeUnitWeek(content.WeeklyStreakBest.ToLocalisableString(@"N0"));
bestWeekly.Value = $"{content.WeeklyStreakBest:N0}w";
bestWeekly.ValueColour = colours.ForRankingTier(TierForWeekly(content.WeeklyStreakBest));
topTen.Value = content.Top10PercentPlacements.ToLocalisableString(@"N0");
topFifty.Value = content.Top50PercentPlacements.ToLocalisableString(@"N0");
}
// reference: https://github.com/ppy/osu-web/blob/8206e0e91eeea80ccf92f0586561346dd40e085e/resources/js/profile-page/daily-challenge.tsx#L13-L43
public static RankingTier TierForDaily(int daily)
{
if (daily > 360)
return RankingTier.Lustrous;
if (daily > 240)
return RankingTier.Radiant;
if (daily > 120)
return RankingTier.Rhodium;
if (daily > 60)
return RankingTier.Platinum;
if (daily > 30)
return RankingTier.Gold;
if (daily > 10)
return RankingTier.Silver;
if (daily > 5)
return RankingTier.Bronze;
return RankingTier.Iron;
}
public static RankingTier TierForWeekly(int weekly) => TierForDaily((weekly - 1) * 7);
protected override void PopIn() => this.FadeIn(200, Easing.OutQuint);
protected override void PopOut() => this.FadeOut(200, Easing.OutQuint);
public void Move(Vector2 pos) => Position = pos;
private partial class StreakPiece : FillFlowContainer
{
private readonly OsuSpriteText valueText;
public LocalisableString Value
{
set => valueText.Text = value;
}
public ColourInfo ValueColour
{
set => valueText.Colour = value;
}
public StreakPiece(LocalisableString title)
{
AutoSizeAxes = Axes.Both;
Direction = FillDirection.Vertical;
Children = new Drawable[]
{
new OsuSpriteText
{
Font = OsuFont.GetFont(size: 12),
Text = title,
},
valueText = new OsuSpriteText
{
// Colour = colour
Font = OsuFont.GetFont(size: 40, weight: FontWeight.Light),
}
};
}
}
private partial class StatisticsPiece : CompositeDrawable
{
private readonly OsuSpriteText valueText;
public LocalisableString Value
{
set => valueText.Text = value;
}
public ColourInfo ValueColour
{
set => valueText.Colour = value;
}
public StatisticsPiece(LocalisableString title)
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
InternalChildren = new Drawable[]
{
new OsuSpriteText
{
Font = OsuFont.GetFont(size: 12),
Text = title,
},
valueText = new OsuSpriteText
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Font = OsuFont.GetFont(size: 12),
}
};
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
valueText.Colour = colourProvider.Content2;
}
}
}
}