From d6e6e7f0d953087018929b8041472d0c02b8c939 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Tue, 28 Nov 2023 06:14:00 -0500 Subject: [PATCH 1/6] chore: remove FEATURE_BEAT flag (#2059) --- .env.example | 2 +- .env.testing | 3 +- app/Helpers/render/game.php | 2 +- app/Helpers/render/user.php | 4 +- app/Platform/Components/GameCard.php | 5 +- .../BeatenGamesLeaderboardController.php | 4 -- .../PlayerCompletionProgressController.php | 4 -- config/envy.php | 2 +- config/feature.php | 9 ++-- public/gameInfo.php | 2 +- public/userInfo.php | 3 +- .../global-statistics.blade.php | 20 +++----- .../views/components/feature-flags.blade.php | 9 ---- .../views/components/menu/account.blade.php | 5 +- .../views/components/menu/main.blade.php | 4 +- resources/views/content/top-links.blade.php | 10 ++-- .../achievements-list-item.blade.php | 50 +++++++++---------- .../big-status-label.blade.php | 32 ++++++------ 18 files changed, 63 insertions(+), 107 deletions(-) diff --git a/.env.example b/.env.example index b1cd6f22e3..0922e9bff8 100644 --- a/.env.example +++ b/.env.example @@ -15,7 +15,7 @@ FORWARD_PHPMYADMIN_PORT=64080 # Feature Flags -FEATURE_BEAT=true +#FEATURE_EXAMPLE=true # Application diff --git a/.env.testing b/.env.testing index 3008f06a9e..05ab7241b1 100644 --- a/.env.testing +++ b/.env.testing @@ -10,5 +10,4 @@ SCOUT_DRIVER=null SESSION_DRIVER=array TELESCOPE_ENABLED=false DEBUGBAR_ENABLED=false -CSP_ENABLED=false -FEATURE_BEAT=true \ No newline at end of file +CSP_ENABLED=false \ No newline at end of file diff --git a/app/Helpers/render/game.php b/app/Helpers/render/game.php index ea00743f41..12ab98d457 100644 --- a/app/Helpers/render/game.php +++ b/app/Helpers/render/game.php @@ -184,7 +184,7 @@ function RenderGameSort( // } echo "Points$mark4 - "; echo "Title$mark5"; - if (config('feature.beat') && $canSortByType) { + if ($canSortByType) { echo " - "; echo "Type$mark6"; } diff --git a/app/Helpers/render/user.php b/app/Helpers/render/user.php index d10e2f0d1e..aa7b1c4779 100644 --- a/app/Helpers/render/user.php +++ b/app/Helpers/render/user.php @@ -96,9 +96,7 @@ function RenderCompletedGamesList( HTML; - if (config('feature.beat')) { - echo "more..."; - } + echo "more..."; echo ""; echo "
"; diff --git a/app/Platform/Components/GameCard.php b/app/Platform/Components/GameCard.php index bcf5dfa233..53900991f3 100644 --- a/app/Platform/Components/GameCard.php +++ b/app/Platform/Components/GameCard.php @@ -243,10 +243,7 @@ private function buildCardUserProgressionData(array $userGameProgressionAwards, $highestProgressionStatus = null; $highestProgressionAwardDate = null; - $progressionTypes = ['completed', 'mastered']; - if (config('feature.beat')) { - $progressionTypes = ['beaten-softcore', 'beaten-hardcore', 'completed', 'mastered']; - } + $progressionTypes = ['beaten-softcore', 'beaten-hardcore', 'completed', 'mastered']; foreach ($progressionTypes as $progressionType) { if (isset($userGameProgressionAwards[$progressionType])) { diff --git a/app/Platform/Controllers/BeatenGamesLeaderboardController.php b/app/Platform/Controllers/BeatenGamesLeaderboardController.php index 7c46b330ea..7994b29b06 100644 --- a/app/Platform/Controllers/BeatenGamesLeaderboardController.php +++ b/app/Platform/Controllers/BeatenGamesLeaderboardController.php @@ -22,10 +22,6 @@ class BeatenGamesLeaderboardController extends Controller public function __invoke(Request $request): View { - if (!config('feature.beat')) { - abort(404); - } - $validatedData = $request->validate([ 'page.number' => 'sometimes|integer|min:1', 'filter.system' => 'sometimes|integer', diff --git a/app/Platform/Controllers/PlayerCompletionProgressController.php b/app/Platform/Controllers/PlayerCompletionProgressController.php index 2695f398f3..58770fded1 100644 --- a/app/Platform/Controllers/PlayerCompletionProgressController.php +++ b/app/Platform/Controllers/PlayerCompletionProgressController.php @@ -22,10 +22,6 @@ public function __construct(protected PlayerProgressionService $playerProgressio public function __invoke(Request $request): View { - if (!config('feature.beat')) { - abort(404); - } - $targetUsername = $request->route()->parameters['user']; $validatedData = $request->validate([ 'page.number' => 'sometimes|integer|min:1', diff --git a/config/envy.php b/config/envy.php index 9e2c4dee9d..3383e9aa68 100644 --- a/config/envy.php +++ b/config/envy.php @@ -80,7 +80,7 @@ 'REDIS_CACHE_DB', 'MYSQL_ATTR_SSL_CA', // config/feature.php - 'FEATURE_BEAT', + // // config/filesystem.php 'AWS_ENDPOINT', 'AWS_URL', diff --git a/config/feature.php b/config/feature.php index 2b7d4c4d27..734674a807 100644 --- a/config/feature.php +++ b/config/feature.php @@ -1,10 +1,7 @@ env('FEATURE_BEAT', false), - +/** + * 'example' => env('FEATURE_EXAMPLE', false), + */ ]; diff --git a/public/gameInfo.php b/public/gameInfo.php index 88a083efe7..f53083c620 100644 --- a/public/gameInfo.php +++ b/public/gameInfo.php @@ -833,7 +833,7 @@ function () { ', [ 'beatenGameCreditDialogContext' => $beatenGameCreditDialogContext, 'gameId' => $gameID, - 'isBeatable' => $isGameBeatable && config('feature.beat') === true, + 'isBeatable' => $isGameBeatable, 'isBeatenHardcore' => $isBeatenHardcore, 'isBeatenSoftcore' => $isBeatenSoftcore, 'isCompleted' => !is_null($userGameProgressionAwards['completed']), diff --git a/public/userInfo.php b/public/userInfo.php index 2023b1dcf2..e3c12cdab6 100644 --- a/public/userInfo.php +++ b/public/userInfo.php @@ -485,8 +485,7 @@ function resize() { } $canShowProgressionStatusComponent = - config('feature.beat') - && !empty($userCompletedGamesList) + !empty($userCompletedGamesList) // Needs at least one non-event game. && count(array_filter($userCompletedGamesList, fn ($game) => $game['ConsoleID'] != 101)) > 0; diff --git a/resources/views/community/components/global-statistics/global-statistics.blade.php b/resources/views/community/components/global-statistics/global-statistics.blade.php index 83fec3fda1..e3b218e522 100644 --- a/resources/views/community/components/global-statistics/global-statistics.blade.php +++ b/resources/views/community/components/global-statistics/global-statistics.blade.php @@ -6,10 +6,8 @@
- @hasfeature("beat") - - - @endhasfeature + +
@@ -31,14 +29,12 @@ :timestamp="$lastMasteredTimeAgo" /> - @hasfeature("beat") - - @endhasfeature +
@if ($lastRegisteredUser) diff --git a/resources/views/components/feature-flags.blade.php b/resources/views/components/feature-flags.blade.php index 660b0e2eb4..4812c75f06 100644 --- a/resources/views/components/feature-flags.blade.php +++ b/resources/views/components/feature-flags.blade.php @@ -19,15 +19,6 @@ function handleToggleCookie(cookieName) { } -
-

Beaten Games Player-facing UX

- @hasfeature("beat") - Enabled - @else - Disabled - @endhasfeature -
- {{-- EXAMPLE

Aggregate Queries

diff --git a/resources/views/components/menu/account.blade.php b/resources/views/components/menu/account.blade.php index c911055f3b..e506dc7af7 100644 --- a/resources/views/components/menu/account.blade.php +++ b/resources/views/components/menu/account.blade.php @@ -51,10 +51,7 @@ {{ $user->username }} {{ __res('profile', 1) }} - - @hasfeature("beat") - Completion Progress - @endhasfeature + Completion Progress @if($user->Permissions >= Permissions::Registered) Want to Play Games diff --git a/resources/views/components/menu/main.blade.php b/resources/views/components/menu/main.blade.php index 68be1b0841..7173bb1d64 100644 --- a/resources/views/components/menu/main.blade.php +++ b/resources/views/components/menu/main.blade.php @@ -154,9 +154,7 @@ {{ __res('user') }} Global Points Ranking - @hasfeature("beat") - Global Beaten Games Ranking - @endhasfeature + Global Beaten Games Ranking Recent Game Awards Developer Stats diff --git a/resources/views/content/top-links.blade.php b/resources/views/content/top-links.blade.php index f7f8e202bc..f9ab59ef78 100644 --- a/resources/views/content/top-links.blade.php +++ b/resources/views/content/top-links.blade.php @@ -7,12 +7,10 @@ Global Points Ranking - @hasfeature("beat") - - - Global Beaten Games Ranking - - @endhasfeature + + + Global Beaten Games Ranking + @if(config('services.discord.invite_id')) diff --git a/resources/views/platform/components/game/achievements-list/achievements-list-item.blade.php b/resources/views/platform/components/game/achievements-list/achievements-list-item.blade.php index 43000962e1..65dc7436ae 100644 --- a/resources/views/platform/components/game/achievements-list/achievements-list-item.blade.php +++ b/resources/views/platform/components/game/achievements-list/achievements-list-item.blade.php @@ -67,21 +67,19 @@ @endif
- @hasfeature("beat") - @if ($achievement['type'] && !$useMinimalLayout) -
-
- -
+ @if ($achievement['type'] && !$useMinimalLayout) +
+
+
- @endif - @endhasfeature +
+ @endif

@@ -106,19 +104,17 @@

- @hasfeature("beat") - @if ($achievement['type'] && !$useMinimalLayout) - - @endif - @endhasfeature + @if ($achievement['type'] && !$useMinimalLayout) + + @endif @if (!$useMinimalLayout)

{{ $statusLabel }}

- @hasfeature('beat') - @if (!$isBeaten && $isBeatable) - - - - - - @endif - @endhasfeature + @if (!$isBeaten && $isBeatable) + + + + + + @endif
\ No newline at end of file From d6e97555991f23bd65b1d8b71c1c1f320f572962 Mon Sep 17 00:00:00 2001 From: Jamiras <32680403+Jamiras@users.noreply.github.com> Date: Fri, 1 Dec 2023 07:44:16 -0700 Subject: [PATCH 2/6] allow separators other than comma in copy tool (#2064) --- public/admin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/admin.php b/public/admin.php index 831c7cd37c..da036f7aa9 100644 --- a/public/admin.php +++ b/public/admin.php @@ -91,9 +91,9 @@ } if ($action === 'copy-unlocks') { - $fromAchievementIds = explode(',', requestInputSanitized('s')); + $fromAchievementIds = separateList(requestInputSanitized('s')); $fromAchievementCount = count($fromAchievementIds); - $toAchievementIds = explode(',', requestInputSanitized('a')); + $toAchievementIds = separateList(requestInputSanitized('a')); // determine which players have earned all of the required achievements $existing = PlayerAchievement::whereIn('achievement_id', $fromAchievementIds) From f5d814a127f50697b44c4f8226f111e4f14bae45 Mon Sep 17 00:00:00 2001 From: Jamiras <32680403+Jamiras@users.noreply.github.com> Date: Sat, 2 Dec 2023 08:03:13 -0700 Subject: [PATCH 3/6] don't return recent games from API_GetUserSummary without explicitly being asked to (#2066) --- app/Helpers/database/user-activity.php | 6 ++++ public/API/API_GetUserSummary.php | 14 ++++++-- tests/Feature/Api/V1/UserSummaryTest.php | 41 ++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/app/Helpers/database/user-activity.php b/app/Helpers/database/user-activity.php index cb7b795c16..9a28ad81dc 100644 --- a/app/Helpers/database/user-activity.php +++ b/app/Helpers/database/user-activity.php @@ -128,6 +128,12 @@ function expireRecentlyPlayedGames(string $user): void function getRecentlyPlayedGames(string $user, int $offset, int $count, ?array &$dataOut): int { + if ($count < 1) { + $dataOut = []; + + return 0; + } + $query = "SELECT pg.last_played_at AS LastPlayed, pg.game_id AS GameID, pg.achievements_total FROM player_games pg INNER JOIN UserAccounts ua ON ua.ID = pg.user_id diff --git a/public/API/API_GetUserSummary.php b/public/API/API_GetUserSummary.php index 6dc2f10e8b..5339223a37 100644 --- a/public/API/API_GetUserSummary.php +++ b/public/API/API_GetUserSummary.php @@ -3,8 +3,12 @@ /* * API_GetUserSummary * u : username - * g : number of recent games to return (default: 5) + * g : number of recent games to return (default: 0) * a : number of recent achievements to return (default: 10) + * NOTE: Recent achievements are pulled from recent games, so if you ask for + * 1 game and 10 achievements, and the user has only earned 8 achievements in + * the most recent game, you'll only get 8 recent achievements back. Similarly, + * with the default of 0 recent games, no recent achievements will be returned. * * int ID unique identifier of the user * int TotalPoints number of hardcore points the user has @@ -84,12 +88,12 @@ $input = Validator::validate(Arr::wrap(request()->query()), [ 'u' => ['required', 'min:2', 'max:20', new CtypeAlnum()], - 'g' => 'nullable|integer|min:0', + 'g' => 'nullable|integer|min:0|max:100', 'a' => 'nullable|integer|min:0', ]); $user = request()->query('u'); -$recentGamesPlayed = (int) request()->query('g', '5'); +$recentGamesPlayed = (int) request()->query('g', '0'); $recentAchievementsEarned = (int) request()->query('a', '10'); $retVal = getUserPageInfo($user, $recentGamesPlayed, $recentAchievementsEarned); @@ -108,6 +112,10 @@ if (array_key_exists('LastGame', $retVal)) { unset($retVal['LastGame']['RichPresencePatch']); unset($retVal['LastGame']['system']); +} elseif ($recentGamesPlayed === 0) { + // if no games were requested, initialize empty arrays for Awarded and RecentAchievements + $retVal['Awarded'] = []; + $retVal['RecentAchievements'] = []; } $retVal['LastActivity'] = [ diff --git a/tests/Feature/Api/V1/UserSummaryTest.php b/tests/Feature/Api/V1/UserSummaryTest.php index e78710437e..fb9028449b 100644 --- a/tests/Feature/Api/V1/UserSummaryTest.php +++ b/tests/Feature/Api/V1/UserSummaryTest.php @@ -141,7 +141,44 @@ public function testGetUserSummary(): void $this->user->RAPoints = 1_234_567; $this->user->save(); + // default parameters returns no games $this->get($this->apiUrl('GetUserSummary', ['u' => $user->User])) + ->assertSuccessful() + ->assertJson([ + 'ID' => $user->ID, + 'TotalPoints' => $user->RAPoints, + 'TotalSoftcorePoints' => $user->RASoftcorePoints, + 'TotalTruePoints' => $user->TrueRAPoints, + 'Permissions' => $user->Permissions, + 'MemberSince' => $user->Created->__toString(), + 'Untracked' => $user->Untracked, + 'UserPic' => '/UserPic/' . $user->User . '.png', + 'Motto' => $user->Motto, + 'UserWallActive' => $user->UserWallActive, + 'ContribCount' => $user->ContribCount, + 'ContribYield' => $user->ContribYield, + 'Rank' => 2, + 'TotalRanked' => 2, // $this->user and $user + 'LastGameID' => $game->id, + 'RichPresenceMsg' => 'Playing ' . $game->title, + 'RecentlyPlayedCount' => 0, + 'RecentlyPlayed' => [], + 'LastActivity' => [ + 'ID' => 0, + 'timestamp' => null, + 'lastupdate' => null, + 'activitytype' => null, + 'User' => $user->User, + 'data' => null, + 'data2' => null, + ], + 'Status' => 'Offline', + 'Awarded' => [], + 'RecentAchievements' => [], + ]); + + // request more games than are available + $this->get($this->apiUrl('GetUserSummary', ['u' => $user->User, 'g' => 5])) ->assertSuccessful() ->assertJson([ 'ID' => $user->ID, @@ -355,7 +392,7 @@ public function testGetUserSummaryLimitRecentAchievements(): void $this->addHardcoreUnlock($this->user, $publishedAchievements2->get(2), $now->clone()->subMinutes(90)); - $this->get($this->apiUrl('GetUserSummary', ['u' => $this->user->User, 'a' => 2])) + $this->get($this->apiUrl('GetUserSummary', ['u' => $this->user->User, 'g' => 5, 'a' => 2])) ->assertSuccessful() ->assertJson([ 'ID' => $this->user->ID, @@ -388,7 +425,7 @@ public function testGetUserSummaryLimitRecentAchievements(): void ->assertJsonCount(2, "RecentAchievements.{$game->ID}"); // user only has 6 unlocks, so return all of them, and nothing more - $this->get($this->apiUrl('GetUserSummary', ['u' => $this->user->User, 'a' => 7])) + $this->get($this->apiUrl('GetUserSummary', ['u' => $this->user->User, 'g' => 5, 'a' => 7])) ->assertSuccessful() ->assertJson([ 'ID' => $this->user->ID, From d800d16b618906b363769c6646815eb0c643d288 Mon Sep 17 00:00:00 2001 From: luchaos Date: Sat, 2 Dec 2023 19:03:14 +0100 Subject: [PATCH 4/6] feat: allow redirects to login page (#2067) --- app/Exceptions/Handler.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 0bd4dadcae..801203a7d4 100755 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -171,16 +171,6 @@ public function render($request, Throwable $e): Response } } - if ($e instanceof AuthenticationException) { - // parent::render will call parent::unauthenticated for AuthenticationException, - // which redirects to route('login') unless the exception specifies another target. - // Since we don't define a login route, this causes an exception. If no redirect - // route is provided, just fail with 401 Not Authorized. - if (empty($e->redirectTo())) { - abort(401); - } - } - return parent::render($request, $e); } } From 27deff3c972ed1e5f3d6bff11889250f75e158fb Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sun, 3 Dec 2023 09:39:47 -0500 Subject: [PATCH 5/6] fix(beaten-leaderboard): add 'stat_updated_at' column to player_stats (#2050) * fix: add 'last_affected_at' column to player_stats * fix: address pr feedback --- app/Platform/Actions/UpdatePlayerStats.php | 8 +++---- .../BeatenGamesLeaderboardController.php | 6 ++--- app/Platform/Models/PlayerStat.php | 3 ++- ...11_20_000000_update_player_stats_table.php | 23 +++++++++++++++++++ .../Platform/Action/UpdatePlayerStatsTest.php | 6 ++--- 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 database/migrations/platform/2023_11_20_000000_update_player_stats_table.php diff --git a/app/Platform/Actions/UpdatePlayerStats.php b/app/Platform/Actions/UpdatePlayerStats.php index d1e0fe0ebe..6c2ba0ee57 100644 --- a/app/Platform/Actions/UpdatePlayerStats.php +++ b/app/Platform/Actions/UpdatePlayerStats.php @@ -149,10 +149,10 @@ private function upsertAllPlayerStats(User $user, array $aggregatedPlayerStatVal // Now, loop through each stat type for this system. foreach ($systemStats as $statType => $values) { // Extract the value and most recent game ID. - [$value, $lastGameId, $updatedAt] = $values; + [$value, $lastGameId, $statUpdatedAt] = $values; if ($value > 0) { - $this->upsertPlayerStat($user, $statType, $value, $systemId, $lastGameId, $updatedAt); + $this->upsertPlayerStat($user, $statType, $value, $systemId, $lastGameId, $statUpdatedAt); $updatedCount++; } } @@ -167,7 +167,7 @@ private function upsertPlayerStat( int $value, ?int $systemId, ?int $lastGameId, - ?string $updatedAt + ?string $statUpdatedAt ): void { PlayerStat::updateOrCreate( [ @@ -178,7 +178,7 @@ private function upsertPlayerStat( [ 'last_game_id' => $lastGameId, 'value' => $value, - 'updated_at' => $updatedAt, + 'stat_updated_at' => $statUpdatedAt, ] ); diff --git a/app/Platform/Controllers/BeatenGamesLeaderboardController.php b/app/Platform/Controllers/BeatenGamesLeaderboardController.php index 7994b29b06..d91a45d068 100644 --- a/app/Platform/Controllers/BeatenGamesLeaderboardController.php +++ b/app/Platform/Controllers/BeatenGamesLeaderboardController.php @@ -125,7 +125,7 @@ private function buildAggregatedLeaderboardQuery(array $gameKindFilterOptions = $aggregateSubquery = PlayerStat::selectRaw( 'user_id, SUM(value) AS total_awards, - MAX(updated_at) AS last_beaten_date' + MAX(stat_updated_at) AS last_beaten_date' ) ->when($targetSystemId, function ($query) use ($targetSystemId) { return $query->where('system_id', $targetSystemId); @@ -138,14 +138,14 @@ private function buildAggregatedLeaderboardQuery(array $gameKindFilterOptions = $query = PlayerStat::selectRaw( 'sub.user_id, MAX(CASE WHEN player_stats.type IN (\'' . implode("', '", $includedTypes) . '\') THEN player_stats.last_game_id ELSE NULL END) AS last_game_id, - MAX(CASE WHEN player_stats.type IN (\'' . implode("', '", $includedTypes) . '\') THEN player_stats.updated_at ELSE NULL END) as last_beaten_date, + MAX(CASE WHEN player_stats.type IN (\'' . implode("', '", $includedTypes) . '\') THEN player_stats.stat_updated_at ELSE NULL END) as last_beaten_date, sub.total_awards, RANK() OVER (ORDER BY sub.total_awards DESC) as rank_number, ROW_NUMBER() OVER (ORDER BY sub.total_awards DESC, sub.last_beaten_date ASC) as leaderboard_row_number' ) ->joinSub($aggregateSubquery, 'sub', function ($join) use ($targetSystemId) { $join->on('sub.user_id', '=', 'player_stats.user_id') - ->on('sub.last_beaten_date', '=', 'player_stats.updated_at'); + ->on('sub.last_beaten_date', '=', 'player_stats.stat_updated_at'); if (isset($targetSystemId) && $targetSystemId > 0) { $join->where('player_stats.system_id', '=', $targetSystemId); diff --git a/app/Platform/Models/PlayerStat.php b/app/Platform/Models/PlayerStat.php index d0ba3c207c..8105eee442 100644 --- a/app/Platform/Models/PlayerStat.php +++ b/app/Platform/Models/PlayerStat.php @@ -18,13 +18,14 @@ class PlayerStat extends BaseModel 'last_game_id', 'type', 'value', - 'updated_at', + 'stat_updated_at', ]; protected $casts = [ 'user_id' => 'integer', 'system_id' => 'integer', 'last_game_id' => 'integer', + 'stat_updated_at' => 'datetime', 'value' => 'integer', ]; diff --git a/database/migrations/platform/2023_11_20_000000_update_player_stats_table.php b/database/migrations/platform/2023_11_20_000000_update_player_stats_table.php new file mode 100644 index 0000000000..3e3ec1c368 --- /dev/null +++ b/database/migrations/platform/2023_11_20_000000_update_player_stats_table.php @@ -0,0 +1,23 @@ +timestampTz('stat_updated_at')->nullable()->after('last_game_id'); + }); + } + + public function down(): void + { + Schema::table('player_stats', function (Blueprint $table) { + $table->dropColumn('stat_updated_at'); + }); + } +}; diff --git a/tests/Feature/Platform/Action/UpdatePlayerStatsTest.php b/tests/Feature/Platform/Action/UpdatePlayerStatsTest.php index 446a6781ee..2508ebd17e 100644 --- a/tests/Feature/Platform/Action/UpdatePlayerStatsTest.php +++ b/tests/Feature/Platform/Action/UpdatePlayerStatsTest.php @@ -73,7 +73,7 @@ public function testItUpsertsStatsIfHardcoreBeatenPlayerGames(): void $this->assertEquals($game->id, $overallStats->last_game_id); $this->assertEquals(PlayerStatType::GamesBeatenHardcoreRetail, $overallStats->type); $this->assertEquals(1, $overallStats->value); - $this->assertEquals(Carbon::create(2023, 1, 1), $overallStats->updated_at); + $this->assertEquals(Carbon::create(2023, 1, 1), $overallStats->stat_updated_at); $systemStats = $userStats->whereNotNull('system_id')->first(); $this->assertEquals($system->ID, $systemStats->system_id); @@ -81,7 +81,7 @@ public function testItUpsertsStatsIfHardcoreBeatenPlayerGames(): void $this->assertEquals($game->id, $systemStats->last_game_id); $this->assertEquals(PlayerStatType::GamesBeatenHardcoreRetail, $systemStats->type); $this->assertEquals(1, $systemStats->value); - $this->assertEquals(Carbon::create(2023, 1, 1), $systemStats->updated_at); + $this->assertEquals(Carbon::create(2023, 1, 1), $systemStats->stat_updated_at); } public function testItUpsertsDifferentTypesOfStats(): void @@ -183,6 +183,6 @@ protected function assertPlayerStatDetails( $stat = $query->first(); $this->assertNotNull($stat); - $this->assertEquals($expectedDate->toDateTimeString(), $stat->updated_at->toDateTimeString()); + $this->assertEquals($expectedDate->toDateTimeString(), $stat->stat_updated_at->toDateTimeString()); } } From d1663a03372b50e8255adf019e6761e0ef7480b9 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sun, 3 Dec 2023 09:42:47 -0500 Subject: [PATCH 6/6] feat(beaten-leaderboard): exclude homebrew systems from retail games (#2051) * feat(beaten-leaderboard): exclude homebrew systems from retail games * fix: address pr feedback --- app/Platform/Actions/UpdatePlayerStats.php | 11 ++++++-- app/Platform/Models/System.php | 13 +++++++++ .../game-kind-filter-radio.blade.php | 6 ++-- .../meta-panel/game-kind-filters.blade.php | 2 ++ .../meta-panel/index.blade.php | 25 +++++++++++++++-- .../Platform/Action/UpdatePlayerStatsTest.php | 28 +++++++++++++++++++ 6 files changed, 79 insertions(+), 6 deletions(-) diff --git a/app/Platform/Actions/UpdatePlayerStats.php b/app/Platform/Actions/UpdatePlayerStats.php index 6c2ba0ee57..34bf2691dd 100644 --- a/app/Platform/Actions/UpdatePlayerStats.php +++ b/app/Platform/Actions/UpdatePlayerStats.php @@ -9,6 +9,7 @@ use App\Platform\Enums\UnlockMode; use App\Platform\Events\PlayerStatsUpdated; use App\Platform\Models\PlayerStat; +use App\Platform\Models\System; use App\Site\Models\User; class UpdatePlayerStats @@ -83,7 +84,7 @@ private function calculateAggregatedGameBeatenHardcoreStatValues(mixed $playerBe foreach ($playerBeatenHardcoreGames as $playerGame) { $gameConsoleId = $playerGame['game']['ConsoleID']; - $gameKind = $this->deriveGameKindFromTitle($playerGame['game']['Title']); + $gameKind = $this->determineGameKind($playerGame['game']['Title'], $gameConsoleId); $statTypeKey = $gameKindToStatType[$gameKind] ?? PlayerStatType::GamesBeatenHardcoreRetail; // Update the overall aggregates. @@ -117,7 +118,7 @@ private function clearExistingUntrackedStats(User $user): void PlayerStat::where('user_id', $user->ID)->delete(); } - private function deriveGameKindFromTitle(string $gameTitle): string + private function determineGameKind(string $gameTitle, int $gameConsoleId): string { $sanitizedTitle = mb_strtolower($gameTitle); $gameKinds = [ @@ -132,6 +133,12 @@ private function deriveGameKindFromTitle(string $gameTitle): string if (str_contains($sanitizedTitle, $keyword)) { return $kind; } + + // Some consoles were never sold in stores and are considered "homebrew". + // Their games fall back to "homebrew" rather than "retail". + if (System::isHomebrewSystem($gameConsoleId)) { + return 'homebrew'; + } } return 'retail'; diff --git a/app/Platform/Models/System.php b/app/Platform/Models/System.php index 19114027ef..5360caf7fd 100644 --- a/app/Platform/Models/System.php +++ b/app/Platform/Models/System.php @@ -69,14 +69,27 @@ protected static function newFactory(): SystemFactory // == constants + public const Arduboy = 71; + public const WASM4 = 72; + public const Uzebox = 80; public const Hubs = 100; public const Events = 101; + public static function getHomebrewSystems(): array + { + return [System::Arduboy, System::WASM4, System::Uzebox]; + } + public static function isGameSystem(int $type): bool { return $type != System::Hubs && $type != System::Events; } + public static function isHomebrewSystem(int $type): bool + { + return in_array($type, self::getHomebrewSystems()); + } + // == media public function registerMediaCollections(): void diff --git a/resources/views/platform/components/beaten-games-leaderboard/meta-panel/game-kind-filter-radio.blade.php b/resources/views/platform/components/beaten-games-leaderboard/meta-panel/game-kind-filter-radio.blade.php index 6d9af98c2a..4c5e370475 100644 --- a/resources/views/platform/components/beaten-games-leaderboard/meta-panel/game-kind-filter-radio.blade.php +++ b/resources/views/platform/components/beaten-games-leaderboard/meta-panel/game-kind-filter-radio.blade.php @@ -1,12 +1,14 @@ @props([ + 'disabled' => false, 'selectedValue' => '', 'value' => '', ]) -