Skip to content

Commit

Permalink
Merge pull request #166 from peppy/global-playcounts
Browse files Browse the repository at this point in the history
Add support for incrementing global and beatmap playcounts
  • Loading branch information
peppy authored Nov 9, 2023
2 parents 11bd453 + 30fee48 commit 37a0d6f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ protected DatabaseTest()
db.Execute("TRUNCATE TABLE solo_scores");
db.Execute("TRUNCATE TABLE solo_scores_process_history");
db.Execute("TRUNCATE TABLE solo_scores_performance");

db.Execute("REPLACE INTO osu_counts (name, count) VALUES ('playcount', 0)");
}

Task.Run(() => Processor.Run(CancellationToken), CancellationToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Tests
Expand All @@ -19,6 +22,36 @@ public void TestPlaycountIncreaseMania()
WaitForDatabaseState("SELECT playcount FROM osu_user_stats_mania WHERE user_id = 2", 2, CancellationToken);
}

[Fact]
public Task TestGlobalPlaycountsIncrement()
{
const int attempt_count = 100;

AddBeatmap();

var cts = new CancellationTokenSource();

var incrementTask = Task.Run(() =>
{
for (int i = 0; i < attempt_count; i++)
{
if (cts.IsCancellationRequested)
break;

int offset = i - attempt_count;
SetScoreForBeatmap(TEST_BEATMAP_ID, s => s.Score.created_at = DateTimeOffset.Now.AddMinutes(offset));
}
}, cts.Token);

WaitForDatabaseState("SELECT IF(count > 0, 1, 0) FROM osu_counts WHERE name = 'playcount'", 1, CancellationToken);
WaitForDatabaseState($"SELECT IF(playcount > 0, 1, 0) FROM osu_beatmaps WHERE beatmap_id = {TEST_BEATMAP_ID}", 1, CancellationToken);
WaitForDatabaseState($"SELECT IF(play_count > 0, 1, 0) FROM osu_beatmapsets WHERE beatmapset_id = {TEST_BEATMAP_SET_ID}", 1, CancellationToken);

cts.Cancel();

return incrementTask;
}

[Fact]
public void TestPlaycountIncrease()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
using Dapper;
using JetBrains.Annotations;
using MySqlConnector;
using osu.Framework.Development;
using osu.Framework.Utils;
using osu.Game.Online.API.Requests.Responses;
using osu.Server.Queues.ScoreStatisticsProcessor.Helpers;
using osu.Server.Queues.ScoreStatisticsProcessor.Models;

namespace osu.Server.Queues.ScoreStatisticsProcessor.Processors
Expand Down Expand Up @@ -49,13 +52,57 @@ public void ApplyToUserStats(SoloScoreInfo score, UserStats userStats, MySqlConn

adjustUserMonthlyPlaycount(score, conn, transaction);
adjustUserBeatmapPlaycount(score, conn, transaction);

adjustGlobalPlaycount(conn, transaction);
adjustGlobalBeatmapPlaycount(score, conn, transaction);
}
}

public void ApplyGlobal(SoloScoreInfo score, MySqlConnection conn)
{
}

private static void adjustGlobalPlaycount(MySqlConnection conn, MySqlTransaction transaction)
{
// We want to reduce database overhead here, so we only update the global playcount every n plays.
// Note that we use a non-round number to make the display more natural.
int increment = DebugUtils.IsNUnitRunning ? 5 : 99;

if (RNG.Next(0, increment) == 0)
{
conn.Execute("UPDATE osu_counts SET count = count + @increment WHERE name = 'playcount'", new
{
increment
}, transaction);
}
}

private static void adjustGlobalBeatmapPlaycount(SoloScoreInfo score, MySqlConnection conn, MySqlTransaction transaction)
{
// We want to reduce database overhead here, so we only update the global beatmap playcount every n plays.
// Note that we use a non-round number to make the display more natural.
int increment = score.Beatmap!.PlayCount < 1000 ? 1 : 9;

if (RNG.Next(0, increment) == 0)
{
conn.Execute("UPDATE osu_beatmaps SET playcount = playcount + @increment WHERE beatmap_id = @beatmapId; UPDATE osu_beatmapsets SET play_count = play_count + @increment WHERE beatmapset_id = @beatmapSetId", new
{
increment,
beatmapId = score.BeatmapID,
beatmapSetId = score.Beatmap.OnlineBeatmapSetID
}, transaction);

// Reindex beatmap occasionally.
if (RNG.Next(0, 10) == 0)
LegacyDatabaseHelper.RunLegacyIO("indexing/bulk", "POST", $"beatmapset[]={score.Beatmap.OnlineBeatmapSetID}");

// TODO: announce playcount milestones
// const int notify_amount = 1000000;
// if (score.Beatmap.PlayCount > 0 && Math.Abs((incrementedPlaycount % notify_amount) - (score.Beatmap.PlayCount % notify_amount)) > increment)
// throw new NotImplementedException("addEvent");
}
}

private static void adjustUserBeatmapPlaycount(SoloScoreInfo score, MySqlConnection conn, MySqlTransaction transaction, bool revert = false)
{
conn.Execute(
Expand Down

0 comments on commit 37a0d6f

Please sign in to comment.