From 2303e4216964cbe1c70c356b8f8ef2abb3d3b88f Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 4 Oct 2024 17:53:40 +0900 Subject: [PATCH 1/2] Add new score replay count data --- app/Http/Controllers/ScoresController.php | 9 ++++++ app/Models/ScoreReplayStats.php | 14 +++++++++ ...10_04_082317_create_score_replay_stats.php | 30 +++++++++++++++++++ tests/Controllers/ScoresControllerTest.php | 19 +++++++++++- 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 app/Models/ScoreReplayStats.php create mode 100644 database/migrations/2024_10_04_082317_create_score_replay_stats.php diff --git a/app/Http/Controllers/ScoresController.php b/app/Http/Controllers/ScoresController.php index d91ba1c89ad..083cc3aa4f8 100644 --- a/app/Http/Controllers/ScoresController.php +++ b/app/Http/Controllers/ScoresController.php @@ -7,6 +7,7 @@ use App\Enums\Ruleset; use App\Models\Score\Best\Model as ScoreBest; +use App\Models\ScoreReplayStats; use App\Models\Solo\Score as SoloScore; use App\Transformers\ScoreTransformer; use App\Transformers\UserCompactTransformer; @@ -58,6 +59,8 @@ public function download($rulesetOrSoloId, $id = null) ::where('score_id', $id) ->where('replay', true) ->firstOrFail(); + + $soloScore = SoloScore::firstWhere('legacy_score_id', $score->getKey()); } $file = $score->getReplayFile(); @@ -89,6 +92,12 @@ public function download($rulesetOrSoloId, $id = null) ->firstOrCreate([], ['play_count' => 0]) ->incrementInstance('play_count'); } + + if ($soloScore !== null) { + ScoreReplayStats + ::createOrFirst(['score_id' => $soloScore->getKey()], ['user_id' => $soloScore->user_id]) + ->incrementInstance('watch_count'); + } } } diff --git a/app/Models/ScoreReplayStats.php b/app/Models/ScoreReplayStats.php new file mode 100644 index 00000000000..25dc7d59d17 --- /dev/null +++ b/app/Models/ScoreReplayStats.php @@ -0,0 +1,14 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Models; + +class ScoreReplayStats extends Model +{ + public $incrementing = false; + protected $primaryKey = 'score_id'; +} diff --git a/database/migrations/2024_10_04_082317_create_score_replay_stats.php b/database/migrations/2024_10_04_082317_create_score_replay_stats.php new file mode 100644 index 00000000000..0fbd51aa755 --- /dev/null +++ b/database/migrations/2024_10_04_082317_create_score_replay_stats.php @@ -0,0 +1,30 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class extends Migration +{ + public function up(): void + { + Schema::create('score_replay_stats', function (Blueprint $table) { + $table->bigInteger('score_id')->unsigned()->primary(); + $table->bigInteger('user_id')->unsigned(); + $table->integer('watch_count')->unsigned()->default(0); + $table->index(['user_id', 'watch_count']); + $table->index('watch_count'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('score_replay_stats'); + } +}; diff --git a/tests/Controllers/ScoresControllerTest.php b/tests/Controllers/ScoresControllerTest.php index 95fe1b834b3..82758d86c93 100644 --- a/tests/Controllers/ScoresControllerTest.php +++ b/tests/Controllers/ScoresControllerTest.php @@ -7,6 +7,7 @@ use App\Models\OAuth\Client; use App\Models\Score\Best\Osu; +use App\Models\ScoreReplayStats; use App\Models\Solo\Score as SoloScore; use App\Models\User; use App\Models\UserStatistics; @@ -17,6 +18,7 @@ class ScoresControllerTest extends TestCase { private Osu $score; + private SoloScore $soloScore; private User $user; private User $otherUser; @@ -25,6 +27,11 @@ private static function getLegacyScoreReplayViewCount(Osu $score): int return $score->replayViewCount()->first()?->play_count ?? 0; } + private static function getScoreReplayViewCount(SoloScore $score): int + { + return ScoreReplayStats::find($score->getKey())?->watch_count ?? 0; + } + private static function getUserReplaysWatchedCount(Osu|SoloScore $score): int { $month = format_month_column(new \DateTime()); @@ -40,6 +47,7 @@ private static function getUserReplayPopularity(Osu|SoloScore $score): int public function testDownloadApiSameUser() { $this->expectCountChange(fn () => static::getLegacyScoreReplayViewCount($this->score), 0); + $this->expectCountChange(fn () => static::getScoreReplayViewCount($this->soloScore), 0); $this->expectCountChange(fn () => static::getUserReplayPopularity($this->score), 0); $this->expectCountChange(fn () => static::getUserReplaysWatchedCount($this->score), 0); @@ -73,6 +81,7 @@ public function testDownloadApiSoloScoreSameUser() public function testDownload() { $this->expectCountChange(fn () => static::getLegacyScoreReplayViewCount($this->score), 0); + $this->expectCountChange(fn () => static::getScoreReplayViewCount($this->soloScore), 0); $this->expectCountChange(fn () => static::getUserReplayPopularity($this->score), 0); $this->expectCountChange(fn () => static::getUserReplaysWatchedCount($this->score), 0); @@ -86,9 +95,10 @@ public function testDownload() ->assertSuccessful(); } - public function testDownloadApi(): void + public function testDownloadApiZ(): void { $this->expectCountChange(fn () => static::getLegacyScoreReplayViewCount($this->score), 1); + $this->expectCountChange(fn () => static::getScoreReplayViewCount($this->soloScore), 1); $this->expectCountChange(fn () => static::getUserReplayPopularity($this->score), 1); $this->expectCountChange(fn () => static::getUserReplaysWatchedCount($this->score), 1); @@ -112,6 +122,7 @@ public function testDownloadApiTwiceNoCountChange(): void ->assertSuccessful(); $this->expectCountChange(fn () => static::getLegacyScoreReplayViewCount($this->score), 0); + $this->expectCountChange(fn () => static::getScoreReplayViewCount($this->soloScore), 0); $this->expectCountChange(fn () => static::getUserReplayPopularity($this->score), 0); $this->expectCountChange(fn () => static::getUserReplaysWatchedCount($this->score), 0); @@ -239,6 +250,12 @@ protected function setUp(): void UserStatistics\Osu::factory()->create(['user_id' => $this->user->user_id]); $this->score = Osu::factory()->withReplay()->create(['user_id' => $this->user->user_id]); + $this->soloScore = SoloScore::factory()->create([ + 'beatmap_id' => $this->score->beatmap_id, + 'data' => $this->score->data, + 'legacy_score_id' => $this->score->getKey(), + 'user_id' => $this->score->user_id, + ]); } private function actAsPasswordClientUser(User $user): static From ed2f4e7ee87d8845ffe0ca7bea5844cd1d11be66 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 8 Oct 2024 18:58:56 +0900 Subject: [PATCH 2/2] Undo accidentally committed test name shortcut --- tests/Controllers/ScoresControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controllers/ScoresControllerTest.php b/tests/Controllers/ScoresControllerTest.php index 82758d86c93..9aed65cdb09 100644 --- a/tests/Controllers/ScoresControllerTest.php +++ b/tests/Controllers/ScoresControllerTest.php @@ -95,7 +95,7 @@ public function testDownload() ->assertSuccessful(); } - public function testDownloadApiZ(): void + public function testDownloadApi(): void { $this->expectCountChange(fn () => static::getLegacyScoreReplayViewCount($this->score), 1); $this->expectCountChange(fn () => static::getScoreReplayViewCount($this->soloScore), 1);