1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-17 22:33:47 +08:00
Files
osu-lazer/osu.Game/Screens/Select/Leaderboards/GameplayLeaderboardScore.cs
T

157 lines
6.2 KiB
C#

// 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.Bindables;
using osu.Framework.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osu.Game.Screens.Play;
using osu.Game.Users;
namespace osu.Game.Screens.Select.Leaderboards
{
/// <summary>
/// Represents a score shown on a gameplay leaderboard.
/// The score is expected to update itself as gameplay progresses.
/// </summary>
public class GameplayLeaderboardScore
{
/// <summary>
/// The user playing.
/// </summary>
public IUser User { get; }
/// <summary>
/// Whether the score is being tracked.
/// Generally understood as true when this score is the score of the local user currently playing.
/// </summary>
public bool Tracked { get; }
/// <summary>
/// The current total of the score.
/// </summary>
public BindableLong TotalScore { get; } = new BindableLong();
/// <summary>
/// The current accuracy of the score.
/// </summary>
public BindableDouble Accuracy { get; } = new BindableDouble();
/// <summary>
/// The combo of the score to display.
/// Can be either highest combo or current combo, depending on constructor parameters.
/// </summary>
public BindableInt Combo { get; } = new BindableInt();
/// <summary>
/// Whether the user playing has quit.
/// </summary>
public BindableBool HasQuit { get; } = new BindableBool();
/// <summary>
/// An optional value to guarantee stable ordering.
/// Lower numbers will appear higher in cases of <see cref="TotalScore"/> ties.
/// </summary>
public long TotalScoreTiebreaker { get; init; }
/// <summary>
/// A custom function which handles converting a score to a display score using a provided <see cref="ScoringMode"/>.
/// </summary>
/// <remarks>
/// If no function is provided, <see cref="TotalScore"/> will be used verbatim.
/// </remarks>
public Func<ScoringMode, long> GetDisplayScore { get; set; }
/// <summary>
/// The colour of the team that the user playing is on, if any.
/// </summary>
public Colour4? TeamColour { get; init; }
/// <summary>
/// The initial position of the score on the leaderboard.
/// Mostly used for cases like the local user's best score on the global leaderboard (which will not be contiguous with the other scores).
/// </summary>
public int? InitialPosition { get; init; }
/// <summary>
/// The displayed rank of the score on the leaderboard.
/// </summary>
public Bindable<int?> Position { get; } = new Bindable<int?>();
/// <summary>
/// The index of the score on the leaderboard.
/// This differs from <see cref="Position"/> in that it is required (must always be known)
/// and that it doesn't represent the score's position on global leaderboards.
/// It's a property completely local to and relative to all scores provided by the managing <see cref="IGameplayLeaderboardProvider"/>.
/// </summary>
public Bindable<long> DisplayOrder { get; } = new BindableLong();
public GameplayLeaderboardScore(GameplayState gameplayState, bool tracked, ComboDisplayMode comboMode)
{
User = gameplayState.Score.ScoreInfo.User;
Tracked = tracked;
var scoreProcessor = gameplayState.ScoreProcessor;
TotalScore.BindTarget = scoreProcessor.TotalScore;
Accuracy.BindTarget = scoreProcessor.Accuracy;
Combo.BindTarget = comboMode == ComboDisplayMode.Current ? scoreProcessor.Combo : scoreProcessor.HighestCombo;
GetDisplayScore = scoreProcessor.GetDisplayScore;
}
public GameplayLeaderboardScore(IUser user, SpectatorScoreProcessor scoreProcessor, bool tracked, ComboDisplayMode comboMode)
{
User = user;
Tracked = tracked;
TotalScore.BindTarget = scoreProcessor.TotalScore;
Accuracy.BindTarget = scoreProcessor.Accuracy;
Combo.BindTarget = comboMode == ComboDisplayMode.Current ? scoreProcessor.Combo : scoreProcessor.HighestCombo;
GetDisplayScore = scoreProcessor.GetDisplayScore;
}
public GameplayLeaderboardScore(ScoreInfo scoreInfo, bool tracked, ComboDisplayMode comboMode)
{
User = scoreInfo.User;
Tracked = tracked;
TotalScore.Value = scoreInfo.TotalScore;
Accuracy.Value = scoreInfo.Accuracy;
Combo.Value = comboMode == ComboDisplayMode.Current ? scoreInfo.Combo : scoreInfo.MaxCombo;
TotalScoreTiebreaker = scoreInfo.OnlineID > 0 ? scoreInfo.OnlineID : scoreInfo.Date.ToUnixTimeSeconds();
GetDisplayScore = scoreInfo.GetDisplayScore;
InitialPosition = scoreInfo.Position;
}
public GameplayLeaderboardScore(MultiplayerScore score, bool tracked, ComboDisplayMode comboMode)
{
User = score.User;
Tracked = tracked;
TotalScore.Value = score.TotalScore;
Accuracy.Value = score.Accuracy;
Combo.Value = comboMode == ComboDisplayMode.Highest ? score.MaxCombo : throw new NotSupportedException($"{comboMode} {nameof(comboMode)} is not supported.");
TotalScoreTiebreaker = score.ID;
GetDisplayScore = score.GetDisplayScore;
InitialPosition = score.Position;
}
/// <remarks>
/// Used for testing.
/// </remarks>
internal GameplayLeaderboardScore(IUser user, bool tracked, Bindable<long> displayScore)
{
User = user;
Tracked = tracked;
TotalScore.BindTarget = displayScore;
GetDisplayScore = _ => displayScore.Value;
}
public enum ComboDisplayMode
{
Current,
Highest,
}
}
}