// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Online.API.Requests; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Screens.Select; using osu.Game.Users; namespace osu.Game.Screens.Play.HUD { public partial class SoloGameplayLeaderboard : GameplayLeaderboard { private const int duration = 100; private readonly Bindable configVisibility = new Bindable(); private readonly Bindable scoreSource = new Bindable(); private readonly IUser trackingUser; public readonly IBindableList Scores = new BindableList(); [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; /// /// Whether the leaderboard should be visible regardless of the configuration value. /// This is true by default, but can be changed. /// public readonly Bindable AlwaysVisible = new Bindable(true); public SoloGameplayLeaderboard(IUser trackingUser) { this.trackingUser = trackingUser; } [BackgroundDependencyLoader] private void load(OsuConfigManager config) { config.BindWith(OsuSetting.GameplayLeaderboard, configVisibility); config.BindWith(OsuSetting.BeatmapDetailTab, scoreSource); } protected override void LoadComplete() { base.LoadComplete(); Scores.BindCollectionChanged((_, _) => Scheduler.AddOnce(showScores), true); // Alpha will be updated via `updateVisibility` below. Alpha = 0; AlwaysVisible.BindValueChanged(_ => updateVisibility()); configVisibility.BindValueChanged(_ => updateVisibility(), true); } private void showScores() { Clear(); if (!Scores.Any()) return; foreach (var s in Scores) { var score = Add(s.User, false); score.GetDisplayScore = s.GetDisplayScore; score.TotalScore.Value = s.TotalScore; score.Accuracy.Value = s.Accuracy; score.Combo.Value = s.MaxCombo; score.DisplayOrder.Value = s.OnlineID > 0 ? s.OnlineID : s.Date.ToUnixTimeSeconds(); } ILeaderboardScore local = Add(trackingUser, true); local.GetDisplayScore = scoreProcessor.GetDisplayScore; local.TotalScore.BindTarget = scoreProcessor.TotalScore; local.Accuracy.BindTarget = scoreProcessor.Accuracy; local.Combo.BindTarget = scoreProcessor.HighestCombo; // Local score should always show lower than any existing scores in cases of ties. local.DisplayOrder.Value = long.MaxValue; } protected override bool CheckValidScorePosition(GameplayLeaderboardScore score, int position) { // change displayed position to '-' when there are 50 already submitted scores and tracked score is last if (score.Tracked && scoreSource.Value != PlayBeatmapDetailArea.TabType.Local) { if (position == Flow.Count && Flow.Count > GetScoresRequest.MAX_SCORES_PER_REQUEST) return false; } return base.CheckValidScorePosition(score, position); } private void updateVisibility() => this.FadeTo(AlwaysVisible.Value || configVisibility.Value ? 1 : 0, duration); } }