2019-07-29 11:52:42 +08:00
// 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.
2022-06-17 15:37:17 +08:00
#nullable disable
2019-07-29 11:52:42 +08:00
using System.Linq ;
using NUnit.Framework ;
using osu.Framework.Bindables ;
2023-09-06 21:49:13 +08:00
using osu.Framework.Extensions.Color4Extensions ;
2022-09-21 13:42:02 +08:00
using osu.Framework.Extensions.PolygonExtensions ;
2019-07-29 11:52:42 +08:00
using osu.Framework.Graphics ;
2022-09-21 13:42:02 +08:00
using osu.Framework.Graphics.Containers ;
2023-09-06 21:49:13 +08:00
using osu.Framework.Graphics.Shapes ;
2020-12-15 14:22:14 +08:00
using osu.Framework.Testing ;
2020-12-18 15:20:42 +08:00
using osu.Framework.Utils ;
2023-09-06 21:49:13 +08:00
using osu.Game.Online.API ;
2021-11-04 17:02:44 +08:00
using osu.Game.Online.API.Requests.Responses ;
2020-12-15 14:27:26 +08:00
using osu.Game.Screens.Play.HUD ;
2019-07-29 11:52:42 +08:00
using osuTK ;
namespace osu.Game.Tests.Visual.Gameplay
{
[TestFixture]
2020-12-15 14:27:26 +08:00
public partial class TestSceneGameplayLeaderboard : OsuTestScene
2019-07-29 11:52:42 +08:00
{
2022-09-21 13:42:02 +08:00
private TestGameplayLeaderboard leaderboard ;
2019-07-29 11:52:42 +08:00
2022-11-07 06:59:27 +08:00
private readonly BindableLong playerScore = new BindableLong ( ) ;
2020-12-15 14:27:26 +08:00
public TestSceneGameplayLeaderboard ( )
2019-07-29 11:52:42 +08:00
{
2022-09-21 13:42:02 +08:00
AddStep ( "toggle expanded" , ( ) = >
2019-07-29 11:52:42 +08:00
{
2022-09-21 13:42:02 +08:00
if ( leaderboard ! = null )
leaderboard . Expanded . Value = ! leaderboard . Expanded . Value ;
2019-07-29 11:52:42 +08:00
} ) ;
2022-09-21 13:42:02 +08:00
AddSliderStep ( "set player score" , 50 , 5000000 , 1222333 , v = > playerScore . Value = v ) ;
2019-07-29 11:52:42 +08:00
}
2022-09-21 13:42:02 +08:00
[Test]
public void TestLayoutWithManyScores ( )
2019-08-04 23:28:40 +08:00
{
2022-09-21 13:42:02 +08:00
createLeaderboard ( ) ;
AddStep ( "add many scores in one go" , ( ) = >
2020-12-15 14:22:14 +08:00
{
2022-09-21 13:42:02 +08:00
for ( int i = 0 ; i < 32 ; i + + )
createRandomScore ( new APIUser { Username = $"Player {i + 1}" } ) ;
// Add player at end to force an animation down the whole list.
playerScore . Value = 0 ;
createLeaderboardScore ( playerScore , new APIUser { Username = "You" , Id = 3 } , true ) ;
2020-12-15 14:22:14 +08:00
} ) ;
2022-09-21 13:42:02 +08:00
// Gameplay leaderboard has custom scroll logic, which when coupled with LayoutDuration
// has caused layout to not work in the past.
AddUntilStep ( "wait for fill flow layout" ,
( ) = > leaderboard . ChildrenOfType < FillFlowContainer < GameplayLeaderboardScore > > ( ) . First ( ) . ScreenSpaceDrawQuad . Intersects ( leaderboard . ScreenSpaceDrawQuad ) ) ;
AddUntilStep ( "wait for some scores not masked away" ,
( ) = > leaderboard . ChildrenOfType < GameplayLeaderboardScore > ( ) . Any ( s = > leaderboard . ScreenSpaceDrawQuad . Contains ( s . ScreenSpaceDrawQuad . Centre ) ) ) ;
2022-09-28 14:57:30 +08:00
AddUntilStep ( "wait for tracked score fully visible" , ( ) = > leaderboard . ScreenSpaceDrawQuad . Intersects ( leaderboard . TrackedScore ! . ScreenSpaceDrawQuad ) ) ;
AddStep ( "change score to middle" , ( ) = > playerScore . Value = 1000000 ) ;
AddWaitStep ( "wait for movement" , 5 ) ;
AddUntilStep ( "wait for tracked score fully visible" , ( ) = > leaderboard . ScreenSpaceDrawQuad . Intersects ( leaderboard . TrackedScore ! . ScreenSpaceDrawQuad ) ) ;
AddStep ( "change score to first" , ( ) = > playerScore . Value = 5000000 ) ;
AddWaitStep ( "wait for movement" , 5 ) ;
AddUntilStep ( "wait for tracked score fully visible" , ( ) = > leaderboard . ScreenSpaceDrawQuad . Intersects ( leaderboard . TrackedScore ! . ScreenSpaceDrawQuad ) ) ;
2019-08-04 23:28:40 +08:00
}
2019-07-30 17:37:01 +08:00
2019-07-29 11:52:42 +08:00
[Test]
public void TestPlayerScore ( )
{
2022-09-21 13:42:02 +08:00
createLeaderboard ( ) ;
addLocalPlayer ( ) ;
2022-11-07 06:59:27 +08:00
var player2Score = new BindableLong ( 1234567 ) ;
var player3Score = new BindableLong ( 1111111 ) ;
2019-07-29 11:52:42 +08:00
2021-11-04 17:02:44 +08:00
AddStep ( "add player 2" , ( ) = > createLeaderboardScore ( player2Score , new APIUser { Username = "Player 2" } ) ) ;
AddStep ( "add player 3" , ( ) = > createLeaderboardScore ( player3Score , new APIUser { Username = "Player 3" } ) ) ;
2019-07-29 11:52:42 +08:00
2020-12-24 21:28:25 +08:00
AddUntilStep ( "is player 2 position #1" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 2" , 1 ) ) ;
AddUntilStep ( "is player position #2" , ( ) = > leaderboard . CheckPositionByUsername ( "You" , 2 ) ) ;
AddUntilStep ( "is player 3 position #3" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 3" , 3 ) ) ;
2019-07-29 11:52:42 +08:00
AddStep ( "set score above player 3" , ( ) = > player2Score . Value = playerScore . Value - 500 ) ;
2020-12-24 21:28:25 +08:00
AddUntilStep ( "is player position #1" , ( ) = > leaderboard . CheckPositionByUsername ( "You" , 1 ) ) ;
AddUntilStep ( "is player 2 position #2" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 2" , 2 ) ) ;
AddUntilStep ( "is player 3 position #3" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 3" , 3 ) ) ;
2019-07-29 11:52:42 +08:00
AddStep ( "set score below players" , ( ) = > player2Score . Value = playerScore . Value - 123456 ) ;
2020-12-24 21:28:25 +08:00
AddUntilStep ( "is player position #1" , ( ) = > leaderboard . CheckPositionByUsername ( "You" , 1 ) ) ;
AddUntilStep ( "is player 3 position #2" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 3" , 2 ) ) ;
AddUntilStep ( "is player 2 position #3" , ( ) = > leaderboard . CheckPositionByUsername ( "Player 2" , 3 ) ) ;
2019-07-29 11:52:42 +08:00
}
2020-12-18 15:20:42 +08:00
[Test]
public void TestRandomScores ( )
{
2022-09-21 13:42:02 +08:00
createLeaderboard ( ) ;
addLocalPlayer ( ) ;
2020-12-18 15:20:42 +08:00
int playerNumber = 1 ;
2021-11-04 17:02:44 +08:00
AddRepeatStep ( "add player with random score" , ( ) = > createRandomScore ( new APIUser { Username = $"Player {playerNumber++}" } ) , 10 ) ;
2020-12-18 15:20:42 +08:00
}
2020-12-18 18:13:31 +08:00
[Test]
public void TestExistingUsers ( )
{
2022-09-21 13:42:02 +08:00
createLeaderboard ( ) ;
addLocalPlayer ( ) ;
2021-11-04 17:02:44 +08:00
AddStep ( "add peppy" , ( ) = > createRandomScore ( new APIUser { Username = "peppy" , Id = 2 } ) ) ;
AddStep ( "add smoogipoo" , ( ) = > createRandomScore ( new APIUser { Username = "smoogipoo" , Id = 1040328 } ) ) ;
AddStep ( "add flyte" , ( ) = > createRandomScore ( new APIUser { Username = "flyte" , Id = 3103765 } ) ) ;
AddStep ( "add frenzibyte" , ( ) = > createRandomScore ( new APIUser { Username = "frenzibyte" , Id = 14210502 } ) ) ;
2020-12-18 18:13:31 +08:00
}
2021-08-12 15:17:14 +08:00
[Test]
public void TestMaxHeight ( )
{
2022-09-21 13:42:02 +08:00
createLeaderboard ( ) ;
addLocalPlayer ( ) ;
2021-08-12 15:17:14 +08:00
int playerNumber = 1 ;
2021-11-04 17:02:44 +08:00
AddRepeatStep ( "add 3 other players" , ( ) = > createRandomScore ( new APIUser { Username = $"Player {playerNumber++}" } ) , 3 ) ;
2021-08-12 15:17:14 +08:00
checkHeight ( 4 ) ;
2021-11-04 17:02:44 +08:00
AddRepeatStep ( "add 4 other players" , ( ) = > createRandomScore ( new APIUser { Username = $"Player {playerNumber++}" } ) , 4 ) ;
2021-08-12 15:17:14 +08:00
checkHeight ( 8 ) ;
2021-11-04 17:02:44 +08:00
AddRepeatStep ( "add 4 other players" , ( ) = > createRandomScore ( new APIUser { Username = $"Player {playerNumber++}" } ) , 4 ) ;
2021-08-12 15:17:14 +08:00
checkHeight ( 8 ) ;
void checkHeight ( int panelCount )
= > AddAssert ( $"leaderboard height is {panelCount} panels high" , ( ) = > leaderboard . DrawHeight = = ( GameplayLeaderboardScore . PANEL_HEIGHT + leaderboard . Spacing ) * panelCount ) ;
}
2023-09-06 21:49:13 +08:00
[Test]
public void TestFriendScore ( )
{
APIUser friend = new APIUser { Username = "my friend" , Id = 10000 } ;
createLeaderboard ( ) ;
addLocalPlayer ( ) ;
AddStep ( "initialize api" , ( ) = >
{
var api = ( DummyAPIAccess ) API ;
api . Friends . Add ( friend ) ;
} ) ;
int playerNumber = 1 ;
AddRepeatStep ( "add 3 other players" , ( ) = > createRandomScore ( new APIUser { Username = $"Player {playerNumber++}" } ) , 3 ) ;
AddUntilStep ( "there are no pink color score" , ( ) = > leaderboard . ChildrenOfType < Box > ( ) . All ( b = > b . Colour ! = Color4Extensions . FromHex ( "ff549a" ) ) ) ;
AddRepeatStep ( "add 3 friend score" , ( ) = > createRandomScore ( friend ) , 3 ) ;
AddUntilStep ( "there are pink color for friend score" , ( ) = > leaderboard . GetScoreByUsername ( "my friend" ) . ChildrenOfType < Box > ( ) . Any ( b = > b . Colour = = Color4Extensions . FromHex ( "ff549a" ) ) ) ;
}
2022-09-21 13:42:02 +08:00
private void addLocalPlayer ( )
{
AddStep ( "add local player" , ( ) = >
{
playerScore . Value = 1222333 ;
createLeaderboardScore ( playerScore , new APIUser { Username = "You" , Id = 3 } , true ) ;
} ) ;
}
private void createLeaderboard ( )
{
AddStep ( "create leaderboard" , ( ) = >
{
Child = leaderboard = new TestGameplayLeaderboard
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
Scale = new Vector2 ( 2 ) ,
} ;
} ) ;
}
2022-11-07 06:59:27 +08:00
private void createRandomScore ( APIUser user ) = > createLeaderboardScore ( new BindableLong ( RNG . Next ( 0 , 5_000_000 ) ) , user ) ;
2020-12-18 18:13:31 +08:00
2022-11-07 06:59:27 +08:00
private void createLeaderboardScore ( BindableLong score , APIUser user , bool isTracked = false )
2020-12-18 08:34:33 +08:00
{
2021-08-12 15:17:27 +08:00
var leaderboardScore = leaderboard . Add ( user , isTracked ) ;
2020-12-18 16:07:38 +08:00
leaderboardScore . TotalScore . BindTo ( score ) ;
2020-12-18 08:34:33 +08:00
}
2020-12-15 14:27:26 +08:00
private partial class TestGameplayLeaderboard : GameplayLeaderboard
2019-07-29 11:52:42 +08:00
{
2021-08-12 15:17:14 +08:00
public float Spacing = > Flow . Spacing . Y ;
2020-12-15 14:27:26 +08:00
public bool CheckPositionByUsername ( string username , int? expectedPosition )
2019-07-29 11:52:42 +08:00
{
2021-08-12 15:17:14 +08:00
var scoreItem = Flow . FirstOrDefault ( i = > i . User ? . Username = = username ) ;
2019-07-29 11:52:42 +08:00
2020-12-15 14:27:26 +08:00
return scoreItem ! = null & & scoreItem . ScorePosition = = expectedPosition ;
2019-07-29 11:52:42 +08:00
}
2023-09-06 21:49:13 +08:00
public GameplayLeaderboardScore GetScoreByUsername ( string username )
{
return Flow . FirstOrDefault ( i = > i . User ? . Username = = username ) ;
}
2019-07-29 11:52:42 +08:00
}
}
}