Skip to content

Commit 1cd6d49

Browse files
alexp8claude
andauthored
Add points field to daily stats API and optimize query performance (#523) (#525)
* Add points field to daily stats API and optimize query performance Reduces database queries from 3 to 1 by replacing correlated subqueries with eager loading and PHP-based aggregation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * show streamer name --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1536e33 commit 1cd6d49

2 files changed

Lines changed: 36 additions & 34 deletions

File tree

cncnet-api/app/Http/Controllers/ApiLadderController.php

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -926,51 +926,49 @@ public function getPlayerDailyStats(Request $request, $game = null, $player = nu
926926
$startOfDay = Carbon::now()->startOfDay();
927927
$endOfDay = Carbon::now()->endOfDay();
928928

929-
// Count wins for today - check if player's team won (handles 2v2 where player may have died but team won)
930-
$wins = PlayerGameReport::where('player_game_reports.player_id', '=', $playerModel->id)
929+
// Single optimized query - fetch all player's games for today with teammate data
930+
$playerGames = PlayerGameReport::where('player_game_reports.player_id', '=', $playerModel->id)
931931
->where('player_game_reports.spectator', '=', false)
932932
->whereBetween('player_game_reports.created_at', [$startOfDay, $endOfDay])
933933
->join('game_reports', 'game_reports.id', '=', 'player_game_reports.game_report_id')
934934
->join('games', 'games.id', '=', 'game_reports.game_id')
935935
->where('games.ladder_history_id', '=', $history->id)
936936
->where('game_reports.valid', '=', true)
937937
->where('game_reports.best_report', '=', true)
938-
->whereExists(function ($query) {
939-
$query->selectRaw(1)
940-
->from('player_game_reports as teammate_reports')
941-
->whereColumn('teammate_reports.game_report_id', 'player_game_reports.game_report_id')
942-
->whereColumn('teammate_reports.team', 'player_game_reports.team')
943-
->where('teammate_reports.won', '=', true)
944-
->where('teammate_reports.spectator', '=', false);
945-
})
946-
->count();
947-
948-
// Count losses for today - check if player's team lost (no teammate won, excluding draws)
949-
$losses = PlayerGameReport::where('player_game_reports.player_id', '=', $playerModel->id)
950-
->where('player_game_reports.draw', '=', false)
951-
->where('player_game_reports.spectator', '=', false)
952-
->whereBetween('player_game_reports.created_at', [$startOfDay, $endOfDay])
953-
->join('game_reports', 'game_reports.id', '=', 'player_game_reports.game_report_id')
954-
->join('games', 'games.id', '=', 'game_reports.game_id')
955-
->where('games.ladder_history_id', '=', $history->id)
956-
->where('game_reports.valid', '=', true)
957-
->where('game_reports.best_report', '=', true)
958-
->whereNotExists(function ($query) {
959-
$query->selectRaw(1)
960-
->from('player_game_reports as teammate_reports')
961-
->whereColumn('teammate_reports.game_report_id', 'player_game_reports.game_report_id')
962-
->whereColumn('teammate_reports.team', 'player_game_reports.team')
963-
->where('teammate_reports.won', '=', true)
964-
->where('teammate_reports.spectator', '=', false);
965-
})
966-
->count();
938+
->select('player_game_reports.*')
939+
->with(['gameReport.playerGameReports' => function($q) {
940+
$q->where('spectator', false)->select('id', 'game_report_id', 'team', 'won', 'spectator');
941+
}])
942+
->get();
943+
944+
// Process results in PHP to calculate wins, losses, and points
945+
$wins = 0;
946+
$losses = 0;
947+
$points = 0;
948+
949+
foreach ($playerGames as $pgr) {
950+
$points += $pgr->points ?? 0;
951+
952+
// Check if any teammate on same team won
953+
$teammateWon = $pgr->gameReport->playerGameReports
954+
->where('team', $pgr->team)
955+
->where('won', true)
956+
->isNotEmpty();
957+
958+
if ($teammateWon) {
959+
$wins++;
960+
} else if (!$pgr->draw) {
961+
$losses++;
962+
}
963+
}
967964

968965
return response()->json([
969966
'player' => $player,
970967
'ladder' => $game,
971968
'date' => Carbon::now()->format('Y-m-d'),
972969
'wins' => $wins,
973-
'losses' => $losses
970+
'losses' => $losses,
971+
'points' => $points
974972
], 200);
975973
});
976974
}

cncnet-api/app/Http/Controllers/ApiQuickMatchController.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,11 @@ private function getActivePlayerMatchesData(array $sides, $qmPlayers, bool $show
297297
->values()
298298
->map(function ($qmPlayer, $index) use ($sides, $showRealNames)
299299
{
300+
// Show real name if globally unmasked OR if player is streaming
301+
$useRealName = $showRealNames || ($qmPlayer->twitch_live_at_start ?? false);
302+
300303
return [
301-
"playerName" => $showRealNames ? $qmPlayer->player->username : "Player" . ($index + 1),
304+
"playerName" => $useRealName ? $qmPlayer->player->username : "Player" . ($index + 1),
302305
"playerFaction" => $sides[$qmPlayer->actual_side] ?? '',
303306
"playerColor" => $qmPlayer->color,
304307
"twitchProfile" => $qmPlayer->player?->user?->twitch_profile,
@@ -316,7 +319,8 @@ private function getTeamActivePlayerMatchesData(array $sides, $qmPlayers, bool $
316319
->values()
317320
->map(function ($qmPlayer, $index) use ($sides, $showRealNames)
318321
{
319-
$useRealName = $showRealNames || $qmPlayer->team === "observer";
322+
// Show real name if globally unmasked OR observer OR player is streaming
323+
$useRealName = $showRealNames || $qmPlayer->team === "observer" || ($qmPlayer->twitch_live_at_start ?? false);
320324
$faction = $qmPlayer->team === "observer" ? "Observer" : $sides[$qmPlayer->actual_side] ?? '';
321325
return [
322326
"teamId" => $qmPlayer->team,

0 commit comments

Comments
 (0)