mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:18:22 +08:00
Merge pull request #29542 from frenzibyte/show-daily-challenge-intro-once-per-session
Show daily challenge intro screen once per session
This commit is contained in:
commit
e79604cc13
@ -2,19 +2,21 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Metadata;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.OnlinePlay.DailyChallenge;
|
||||
using osu.Game.Tests.Visual.Metadata;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
using CreateRoomRequest = osu.Game.Online.Rooms.CreateRoomRequest;
|
||||
|
||||
namespace osu.Game.Tests.Visual.DailyChallenge
|
||||
@ -27,63 +29,61 @@ namespace osu.Game.Tests.Visual.DailyChallenge
|
||||
[Cached(typeof(INotificationOverlay))]
|
||||
private NotificationOverlay notificationOverlay = new NotificationOverlay();
|
||||
|
||||
private Room room = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
base.Content.Add(notificationOverlay);
|
||||
base.Content.Add(metadataClient);
|
||||
Add(notificationOverlay);
|
||||
Add(metadataClient);
|
||||
|
||||
// add button to observe for daily challenge changes and perform its logic.
|
||||
Add(new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), _ => { }, 0, Key.D));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Solo]
|
||||
public void TestDailyChallenge()
|
||||
{
|
||||
var room = new Room
|
||||
{
|
||||
RoomID = { Value = 1234 },
|
||||
Name = { Value = "Daily Challenge: June 4, 2024" },
|
||||
Playlist =
|
||||
{
|
||||
new PlaylistItem(CreateAPIBeatmapSet().Beatmaps.First())
|
||||
{
|
||||
RequiredMods = [new APIMod(new OsuModTraceable())],
|
||||
AllowedMods = [new APIMod(new OsuModDoubleTime())]
|
||||
}
|
||||
},
|
||||
EndDate = { Value = DateTimeOffset.Now.AddHours(12) },
|
||||
Category = { Value = RoomCategory.DailyChallenge }
|
||||
};
|
||||
|
||||
AddStep("add room", () => API.Perform(new CreateRoomRequest(room)));
|
||||
AddStep("push screen", () => LoadScreen(new Screens.OnlinePlay.DailyChallenge.DailyChallengeIntro(room)));
|
||||
startChallenge(1234);
|
||||
AddStep("push screen", () => LoadScreen(new DailyChallengeIntro(room)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNotifications()
|
||||
public void TestPlayIntroOnceFlag()
|
||||
{
|
||||
var room = new Room
|
||||
startChallenge(1234);
|
||||
AddStep("set intro played flag", () => Dependencies.Get<SessionStatics>().SetValue(Static.DailyChallengeIntroPlayed, true));
|
||||
|
||||
startChallenge(1235);
|
||||
|
||||
AddAssert("intro played flag reset", () => Dependencies.Get<SessionStatics>().Get<bool>(Static.DailyChallengeIntroPlayed), () => Is.False);
|
||||
|
||||
AddStep("push screen", () => LoadScreen(new DailyChallengeIntro(room)));
|
||||
AddUntilStep("intro played flag set", () => Dependencies.Get<SessionStatics>().Get<bool>(Static.DailyChallengeIntroPlayed), () => Is.True);
|
||||
}
|
||||
|
||||
private void startChallenge(int roomId)
|
||||
{
|
||||
AddStep("add room", () =>
|
||||
{
|
||||
RoomID = { Value = 1234 },
|
||||
Name = { Value = "Daily Challenge: June 4, 2024" },
|
||||
Playlist =
|
||||
API.Perform(new CreateRoomRequest(room = new Room
|
||||
{
|
||||
new PlaylistItem(TestResources.CreateTestBeatmapSetInfo().Beatmaps.First())
|
||||
RoomID = { Value = roomId },
|
||||
Name = { Value = "Daily Challenge: June 4, 2024" },
|
||||
Playlist =
|
||||
{
|
||||
RequiredMods = [new APIMod(new OsuModTraceable())],
|
||||
AllowedMods = [new APIMod(new OsuModDoubleTime())]
|
||||
}
|
||||
},
|
||||
EndDate = { Value = DateTimeOffset.Now.AddHours(12) },
|
||||
Category = { Value = RoomCategory.DailyChallenge }
|
||||
};
|
||||
|
||||
AddStep("add room", () => API.Perform(new CreateRoomRequest(room)));
|
||||
AddStep("set daily challenge info", () => metadataClient.DailyChallengeInfo.Value = new DailyChallengeInfo { RoomID = 1234 });
|
||||
|
||||
Screens.OnlinePlay.DailyChallenge.DailyChallenge screen = null!;
|
||||
AddStep("push screen", () => LoadScreen(screen = new Screens.OnlinePlay.DailyChallenge.DailyChallenge(room)));
|
||||
AddUntilStep("wait for screen", () => screen.IsCurrentScreen());
|
||||
AddStep("daily challenge ended", () => metadataClient.DailyChallengeInfo.Value = null);
|
||||
new PlaylistItem(CreateAPIBeatmap(new OsuRuleset().RulesetInfo))
|
||||
{
|
||||
RequiredMods = [new APIMod(new OsuModTraceable())],
|
||||
AllowedMods = [new APIMod(new OsuModDoubleTime())]
|
||||
}
|
||||
},
|
||||
StartDate = { Value = DateTimeOffset.Now },
|
||||
EndDate = { Value = DateTimeOffset.Now.AddHours(24) },
|
||||
Category = { Value = RoomCategory.DailyChallenge }
|
||||
}));
|
||||
});
|
||||
AddStep("signal client", () => metadataClient.DailyChallengeUpdated(new DailyChallengeInfo { RoomID = roomId }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,15 +103,79 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
foreach (var notification in notificationOverlay.AllNotifications)
|
||||
notification.Close(runFlingAnimation: false);
|
||||
});
|
||||
|
||||
AddStep("beatmap of the day not active", () => metadataClient.DailyChallengeUpdated(null));
|
||||
AddAssert("no notification posted", () => notificationOverlay.AllNotifications.Count(), () => Is.Zero);
|
||||
|
||||
AddStep("hide button's parent", () => buttonContainer.Hide());
|
||||
|
||||
AddStep("beatmap of the day active", () => metadataClient.DailyChallengeUpdated(new DailyChallengeInfo
|
||||
{
|
||||
RoomID = 1234,
|
||||
}));
|
||||
AddAssert("no notification posted", () => notificationOverlay.AllNotifications.Count(), () => Is.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDailyChallengeButtonOldChallenge()
|
||||
{
|
||||
AddStep("set up API", () => dummyAPI.HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case GetRoomRequest getRoomRequest:
|
||||
if (getRoomRequest.RoomId != 1234)
|
||||
return false;
|
||||
|
||||
var beatmap = CreateAPIBeatmap();
|
||||
beatmap.OnlineID = 1001;
|
||||
getRoomRequest.TriggerSuccess(new Room
|
||||
{
|
||||
RoomID = { Value = 1234 },
|
||||
Playlist =
|
||||
{
|
||||
new PlaylistItem(beatmap)
|
||||
},
|
||||
StartDate = { Value = DateTimeOffset.Now.AddMinutes(-50) },
|
||||
EndDate = { Value = DateTimeOffset.Now.AddSeconds(30) }
|
||||
});
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
NotificationOverlay notificationOverlay = null!;
|
||||
|
||||
AddStep("beatmap of the day not active", () => metadataClient.DailyChallengeUpdated(null));
|
||||
AddStep("add content", () =>
|
||||
{
|
||||
notificationOverlay = new NotificationOverlay();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
notificationOverlay,
|
||||
new DependencyProvidingContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
CachedDependencies = [(typeof(INotificationOverlay), notificationOverlay)],
|
||||
Child = new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), _ => { }, 0, Key.D)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
ButtonSystemState = ButtonSystemState.TopLevel,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("beatmap of the day active", () => metadataClient.DailyChallengeUpdated(new DailyChallengeInfo
|
||||
{
|
||||
RoomID = 1234
|
||||
}));
|
||||
AddAssert("no notification posted", () => notificationOverlay.AllNotifications.Count(), () => Is.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,5 +80,11 @@ namespace osu.Game.Configuration
|
||||
/// Stores the local user's last score (can be completed or aborted).
|
||||
/// </summary>
|
||||
LastLocalUserScore,
|
||||
|
||||
/// <summary>
|
||||
/// Whether the intro animation for the daily challenge screen has been played once.
|
||||
/// This is reset when a new challenge is up.
|
||||
/// </summary>
|
||||
DailyChallengeIntroPlayed,
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Localisation;
|
||||
@ -46,6 +47,9 @@ namespace osu.Game.Screens.Menu
|
||||
[Resolved]
|
||||
private INotificationOverlay? notificationOverlay { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private SessionStatics statics { get; set; } = null!;
|
||||
|
||||
public DailyChallengeButton(string sampleName, Color4 colour, Action<MainMenuButton>? clickAction = null, params Key[] triggerKeys)
|
||||
: base(ButtonSystemStrings.DailyChallenge, sampleName, OsuIcon.DailyChallenge, colour, clickAction, triggerKeys)
|
||||
{
|
||||
@ -128,7 +132,7 @@ namespace osu.Game.Screens.Menu
|
||||
}
|
||||
}
|
||||
|
||||
private long? lastNotifiedDailyChallengeRoomId;
|
||||
private long? lastDailyChallengeRoomID;
|
||||
|
||||
private void dailyChallengeChanged(ValueChangedEvent<DailyChallengeInfo?> _)
|
||||
{
|
||||
@ -151,13 +155,16 @@ namespace osu.Game.Screens.Menu
|
||||
Room = room;
|
||||
cover.OnlineInfo = TooltipContent = room.Playlist.FirstOrDefault()?.Beatmap.BeatmapSet as APIBeatmapSet;
|
||||
|
||||
// We only want to notify the user if a new challenge recently went live.
|
||||
if (room.StartDate.Value != null
|
||||
&& Math.Abs((DateTimeOffset.Now - room.StartDate.Value!.Value).TotalSeconds) < 1800
|
||||
&& room.RoomID.Value != lastNotifiedDailyChallengeRoomId)
|
||||
if (room.StartDate.Value != null && room.RoomID.Value != lastDailyChallengeRoomID)
|
||||
{
|
||||
lastNotifiedDailyChallengeRoomId = room.RoomID.Value;
|
||||
notificationOverlay?.Post(new NewDailyChallengeNotification(room));
|
||||
lastDailyChallengeRoomID = room.RoomID.Value;
|
||||
|
||||
// new challenge is live, reset intro played static.
|
||||
statics.SetValue(Static.DailyChallengeIntroPlayed, false);
|
||||
|
||||
// we only want to notify the user if the new challenge just went live.
|
||||
if (Math.Abs((DateTimeOffset.Now - room.StartDate.Value!.Value).TotalSeconds) < 1800)
|
||||
notificationOverlay?.Post(new NewDailyChallengeNotification(room));
|
||||
}
|
||||
|
||||
updateCountdown();
|
||||
|
@ -148,7 +148,10 @@ namespace osu.Game.Screens.Menu
|
||||
OnPlaylists = () => this.Push(new Playlists()),
|
||||
OnDailyChallenge = room =>
|
||||
{
|
||||
this.Push(new DailyChallengeIntro(room));
|
||||
if (statics.Get<bool>(Static.DailyChallengeIntroPlayed))
|
||||
this.Push(new DailyChallenge(room));
|
||||
else
|
||||
this.Push(new DailyChallengeIntro(room));
|
||||
},
|
||||
OnExit = () =>
|
||||
{
|
||||
|
@ -70,6 +70,9 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
[Resolved]
|
||||
private MusicController musicController { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private SessionStatics statics { get; set; } = null!;
|
||||
|
||||
private Sample? dateWindupSample;
|
||||
private Sample? dateImpactSample;
|
||||
private Sample? beatmapWindupSample;
|
||||
@ -462,6 +465,8 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
statics.SetValue(Static.DailyChallengeIntroPlayed, true);
|
||||
|
||||
if (this.IsCurrentScreen())
|
||||
this.Push(new DailyChallenge(room));
|
||||
});
|
||||
|
@ -19,6 +19,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
{
|
||||
@ -278,11 +279,18 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
var result = JsonConvert.DeserializeObject<Room>(JsonConvert.SerializeObject(source));
|
||||
Debug.Assert(result != null);
|
||||
|
||||
// Playlist item IDs aren't serialised.
|
||||
// Playlist item IDs and beatmaps aren't serialised.
|
||||
if (source.CurrentPlaylistItem.Value != null)
|
||||
{
|
||||
result.CurrentPlaylistItem.Value = result.CurrentPlaylistItem.Value.With(new Optional<IBeatmapInfo>(source.CurrentPlaylistItem.Value.Beatmap));
|
||||
result.CurrentPlaylistItem.Value.ID = source.CurrentPlaylistItem.Value.ID;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Playlist.Count; i++)
|
||||
{
|
||||
result.Playlist[i] = result.Playlist[i].With(new Optional<IBeatmapInfo>(source.Playlist[i].Beatmap));
|
||||
result.Playlist[i].ID = source.Playlist[i].ID;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Utils
|
||||
/// </remarks>
|
||||
public readonly bool HasValue;
|
||||
|
||||
private Optional(T value)
|
||||
public Optional(T value)
|
||||
{
|
||||
Value = value;
|
||||
HasValue = true;
|
||||
|
Loading…
Reference in New Issue
Block a user