Skip to content

Commit

Permalink
Merge pull request #308 from bdach/medals-2024
Browse files Browse the repository at this point in the history
Add new medals
  • Loading branch information
peppy authored Dec 21, 2024
2 parents 8ceb6be + 41737e6 commit 9ebca62
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using Dapper;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
{
public class DailySproutTest : MedalAwarderTest
{
private readonly Beatmap beatmap;

public DailySproutTest()
{
beatmap = AddBeatmap();
AddMedal(336);
}

[Fact]
public void MedalNotAwardedIfNoDailyChallengesOnRecord()
{
SetScoreForBeatmap(beatmap.beatmap_id);
AssertNoMedalsAwarded();
}

[Fact]
public void MedalAwardedIfAtLeastOneDailyChallengeOnRecord()
{
using (var db = Processor.GetDatabaseConnection())
db.Execute("INSERT INTO `daily_challenge_user_stats` (`user_id`, `daily_streak_best`) VALUES (2, 1)");
SetScoreForBeatmap(beatmap.beatmap_id);
AssertSingleMedalAwarded(336);
}
}
}
42 changes: 42 additions & 0 deletions osu.Server.Queues.ScoreStatisticsProcessor.Tests/GameNightTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Game.Online.API;
using osu.Game.Rulesets.Osu.Mods;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
{
public class GameNightTest : MedalAwarderTest
{
private readonly Beatmap beatmap;

public GameNightTest()
{
AddMedal(340);
beatmap = AddBeatmap();
}

[Fact]
public void TestMedalAwarded()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModBubbles())]);
AssertSingleMedalAwarded(340);
}

[Fact]
public void TestMedalAwardedWithExtraMods()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModBubbles()), new APIMod(new OsuModClassic())]);
AssertSingleMedalAwarded(340);
}

[Fact]
public void TestMedalNotAwardedIfFunModsMissing()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModClassic())]);
AssertNoMedalsAwarded();
}
}
}
42 changes: 42 additions & 0 deletions osu.Server.Queues.ScoreStatisticsProcessor.Tests/GearShiftTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Game.Online.API;
using osu.Game.Rulesets.Osu.Mods;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
{
public class GearShiftTest : MedalAwarderTest
{
private readonly Beatmap beatmap;

public GearShiftTest()
{
AddMedal(339);
beatmap = AddBeatmap();
}

[Fact]
public void TestMedalAwarded()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModAlternate())]);
AssertMedalAwarded(339);
}

[Fact]
public void TestMedalAwardedWithExtraMods()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModAlternate()), new APIMod(new OsuModDoubleTime())]);
AssertMedalAwarded(339);
}

[Fact]
public void TestMedalNotAwardedIfConversionModsMissing()
{
SetScoreForBeatmap(beatmap.beatmap_id, s => s.Score.ScoreData.Mods = [new APIMod(new OsuModFreezeFrame())]);
AssertNoMedalsAwarded();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ protected MedalAwarderTest(AssemblyName[]? externalProcessorAssemblies = null)

db.Execute("TRUNCATE TABLE osu_beatmappacks");
db.Execute("TRUNCATE TABLE osu_beatmappacks_items");

db.Execute("TRUNCATE TABLE daily_challenge_user_stats");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using Dapper;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
{
public class MonthlyShrubTest : MedalAwarderTest
{
private readonly Beatmap beatmap;

public MonthlyShrubTest()
{
beatmap = AddBeatmap();
AddMedal(338);
}

[Theory]
[InlineData(0)]
[InlineData(9)]
[InlineData(26)]
public void MedalNotAwardedIfNotEnoughDailyChallengesOnRecord(int dailyChallengeCount)
{
using (var db = Processor.GetDatabaseConnection())
db.Execute($"INSERT INTO `daily_challenge_user_stats` (`user_id`, `daily_streak_best`) VALUES (2, {dailyChallengeCount})");
SetScoreForBeatmap(beatmap.beatmap_id);
AssertNoMedalsAwarded();
}

[Fact]
public void MedalAwardedIfAtLeastThirtyDailyChallengesOnRecord()
{
using (var db = Processor.GetDatabaseConnection())
db.Execute("INSERT INTO `daily_challenge_user_stats` (`user_id`, `daily_streak_best`) VALUES (2, 30)");
SetScoreForBeatmap(beatmap.beatmap_id);
AssertSingleMedalAwarded(338);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using Dapper;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
{
public class WeeklySaplingTest : MedalAwarderTest
{
private readonly Beatmap beatmap;

public WeeklySaplingTest()
{
beatmap = AddBeatmap();
AddMedal(337);
}

[Theory]
[InlineData(0)]
[InlineData(4)]
[InlineData(6)]
public void MedalNotAwardedIfNotEnoughDailyChallengesOnRecord(int dailyChallengeCount)
{
using (var db = Processor.GetDatabaseConnection())
db.Execute($"INSERT INTO `daily_challenge_user_stats` (`user_id`, `daily_streak_best`) VALUES (2, {dailyChallengeCount})");
SetScoreForBeatmap(beatmap.beatmap_id);
AssertNoMedalsAwarded();
}

[Fact]
public void MedalAwardedIfAtLeastSevenDailyChallengesOnRecord()
{
using (var db = Processor.GetDatabaseConnection())
db.Execute("INSERT INTO `daily_challenge_user_stats` (`user_id`, `daily_streak_best`) VALUES (2, 7)");
SetScoreForBeatmap(beatmap.beatmap_id);
AssertSingleMedalAwarded(337);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Diagnostics.CodeAnalysis;
using Dapper.Contrib.Extensions;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Models
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
[Serializable]
[Table("daily_challenge_user_stats")]
public record DailyChallengeUserStats
{
public uint daily_streak_current { get; set; }
public uint daily_streak_best { get; set; }
public uint playcount { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ namespace osu.Server.Queues.ScoreStatisticsProcessor.Models
/// </summary>
/// <param name="Score">The score to check for medals.</param>
/// <param name="UserStats">The calculated user statistics after <see cref="Score"/>.</param>
/// <param name="DailyChallengeUserStats">The user's daily challenge stats after <see cref="Score"/>.</param>
/// <param name="BeatmapStore">Allows retrieval of <see cref="Beatmap"/>s from database.</param>
/// <param name="Connection">MySQL connection for manual retrieval from database.</param>
/// <param name="Transaction">MySQL transaction for manual retrieval from database.</param>
public record MedalAwarderContext(
SoloScore Score,
UserStats UserStats,
DailyChallengeUserStats DailyChallengeUserStats,
BeatmapStore BeatmapStore,
MySqlConnection Connection,
MySqlTransaction Transaction);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Processors.MedalAwarders
{
[UsedImplicitly]
public class DailyChallengeMedalAwarder : IMedalAwarder
{
public bool RunOnFailedScores => false;
public bool RunOnLegacyScores => false;

public IEnumerable<Medal> Check(IEnumerable<Medal> medals, MedalAwarderContext context)
{
foreach (var medal in medals)
{
switch (medal.achievement_id)
{
case 336:
{
if (context.DailyChallengeUserStats.daily_streak_best >= 1)
yield return medal;

break;
}

case 337:
{
if (context.DailyChallengeUserStats.daily_streak_best >= 7)
yield return medal;

break;
}

case 338:
{
if (context.DailyChallengeUserStats.daily_streak_best >= 30)
yield return medal;

break;
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Server.Queues.ScoreStatisticsProcessor.Helpers;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Processors.MedalAwarders
{
[UsedImplicitly]
public class LazerModIntroductionMedalAwarder : IMedalAwarder
{
public bool RunOnFailedScores => false;
public bool RunOnLegacyScores => false;

public IEnumerable<Medal> Check(IEnumerable<Medal> medals, MedalAwarderContext context)
{
Ruleset ruleset = LegacyRulesetHelper.GetRulesetFromLegacyId(context.Score.ruleset_id);
Mod[] mods = context.Score.ScoreData.Mods.Select(m => m.ToMod(ruleset)).ToArray();

foreach (var medal in medals)
{
switch (medal.achievement_id)
{
// Gear Shift
case 339:
{
if (mods.Any(m => m.Type == ModType.Conversion))
yield return medal;

break;
}

// Game Night
case 340:
{
if (mods.Any(m => m.Type == ModType.Fun))
yield return medal;

break;
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,16 @@ public void ApplyToUserStats(SoloScore score, UserStats userStats, MySqlConnecti
.Where(m => !alreadyAchieved.Contains(m.achievement_id))
.ToArray();

var dailyChallengeUserStats = conn.QuerySingleOrDefault<DailyChallengeUserStats>(
@"SELECT * FROM `daily_challenge_user_stats` WHERE `user_id` = @user_id",
new
{
user_id = userStats.user_id
},
transaction) ?? new DailyChallengeUserStats();

var beatmapStore = BeatmapStore.CreateAsync(conn, transaction).Result;
var context = new MedalAwarderContext(score, userStats, beatmapStore, conn, transaction);
var context = new MedalAwarderContext(score, userStats, dailyChallengeUserStats, beatmapStore, conn, transaction);

foreach (var awarder in medal_awarders)
{
Expand Down

0 comments on commit 9ebca62

Please sign in to comment.