new: usr: add more stats and a dialog for the recent battle that can be shareable #4
This commit is contained in:
@@ -45,14 +45,147 @@ class ProfileController extends AbstractController
|
||||
$user = $this->getUser();
|
||||
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');
|
||||
|
||||
$total = $this->repo->countFinishedForUser($user);
|
||||
$wins = $this->repo->countWinsForUser($user);
|
||||
$losses = $this->repo->countLossesForUser($user);
|
||||
$draws = $this->repo->countDrawsForUser($user);
|
||||
|
||||
// Build monthly buckets for the last 6 months
|
||||
$monthlyData = [];
|
||||
for ($i = 5; $i >= 0; $i--) {
|
||||
$dt = new \DateTime("first day of -$i months midnight");
|
||||
$key = $dt->format('Y-m');
|
||||
$monthlyData[$key] = ['label' => $dt->format('M'), 'wins' => 0, 'losses' => 0, 'draws' => 0];
|
||||
}
|
||||
|
||||
$since = new \DateTime('first day of -5 months midnight');
|
||||
$recentGames = $this->repo->findFinishedForUserSince($user, $since);
|
||||
$userId = $user->getId();
|
||||
|
||||
foreach ($recentGames as $game) {
|
||||
if (!$game->getUpdated()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$month = $game->getUpdated()->format('Y-m');
|
||||
if (!isset($monthlyData[$month])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isRed = $game->getRed()?->getId() === $userId;
|
||||
$myPts = $isRed ? $game->getRedPoints() : $game->getBluePoints();
|
||||
$oppPts = $isRed ? $game->getBluePoints() : $game->getRedPoints();
|
||||
$resign = $game->getResign();
|
||||
$myColor = $isRed ? 'red' : 'blue';
|
||||
$oppColor = $isRed ? 'blue' : 'red';
|
||||
|
||||
$result = 'draws';
|
||||
if ($resign === $myColor) {
|
||||
$result = 'losses';
|
||||
} elseif ($resign === $oppColor) {
|
||||
$result = 'wins';
|
||||
} elseif ($myPts !== null && $oppPts !== null) {
|
||||
if ($myPts > $oppPts) $result = 'wins';
|
||||
elseif ($myPts < $oppPts) $result = 'losses';
|
||||
}
|
||||
|
||||
$monthlyData[$month][$result]++;
|
||||
}
|
||||
|
||||
$months = array_column(array_values($monthlyData), 'label');
|
||||
|
||||
return $this->render('Security/profile.html.twig', [
|
||||
'stats' => [
|
||||
'total' => $this->repo->countFinishedForUser($user),
|
||||
'wins' => $this->repo->countWinsForUser($user),
|
||||
'losses' => $this->repo->countLossesForUser($user),
|
||||
'bombs' => $this->repo->countBombsForUser($user),
|
||||
'stats' => [
|
||||
'total' => $total,
|
||||
'wins' => $wins,
|
||||
'losses' => $losses,
|
||||
'draws' => $draws,
|
||||
'bombs' => $this->repo->countBombsForUser($user),
|
||||
'winRate' => $total > 0 ? (int) round($wins / $total * 100) : 0,
|
||||
'avgScore' => $this->repo->findAvgScoreForUser($user),
|
||||
'bestScore' => $this->repo->findBestScoreForUser($user),
|
||||
],
|
||||
'recent' => $this->repo->findRecentFinishedForUser($user),
|
||||
'recent' => ($recent = $this->repo->findRecentFinishedForUser($user)),
|
||||
'gamesData' => array_map(static function (\App\Entity\PlayedGame $game) use ($userId): array {
|
||||
$isRed = $game->getRed()?->getId() === $userId;
|
||||
$resign = $game->getResign();
|
||||
$myColor = $isRed ? 'red' : 'blue';
|
||||
$oppColor = $isRed ? 'blue' : 'red';
|
||||
$myPts = $isRed ? $game->getRedPoints() : $game->getBluePoints();
|
||||
$oppPts = $isRed ? $game->getBluePoints() : $game->getRedPoints();
|
||||
|
||||
$result = 'draw';
|
||||
if ($resign === $myColor) $result = 'loss';
|
||||
elseif ($resign === $oppColor) $result = 'win';
|
||||
elseif ($myPts !== null && $oppPts !== null) {
|
||||
if ($myPts > $oppPts) $result = 'win';
|
||||
elseif ($myPts < $oppPts) $result = 'loss';
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $game->getId(),
|
||||
'redName' => $game->getRed()?->getUsername() ?? $game->getRedAnon()?->getUserName() ?? 'Guest',
|
||||
'blueName' => $game->getBlue()?->getUsername() ?? $game->getBlueAnon()?->getUserName() ?? 'Guest',
|
||||
'redPoints' => $game->getRedPoints(),
|
||||
'bluePoints' => $game->getBluePoints(),
|
||||
'redExplodedBomb' => $game->getRedExplodedBomb(),
|
||||
'blueExplodedBomb' => $game->getBlueExplodedBomb(),
|
||||
'resign' => $resign,
|
||||
'created' => $game->getCreated()?->format('Y-m-d H:i'),
|
||||
'date' => $game->getUpdated()?->format('Y-m-d H:i'),
|
||||
'isRed' => $isRed,
|
||||
'result' => $result,
|
||||
'myPoints' => $myPts,
|
||||
'oppPoints' => $oppPts,
|
||||
];
|
||||
}, $recent),
|
||||
'chartData' => [
|
||||
'months' => $months,
|
||||
'wins' => array_column(array_values($monthlyData), 'wins'),
|
||||
'losses' => array_column(array_values($monthlyData), 'losses'),
|
||||
'draws' => array_column(array_values($monthlyData), 'draws'),
|
||||
'pieWins' => $wins,
|
||||
'pieLosses' => $losses,
|
||||
'pieDraws' => $draws,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/battle/{id}', name: 'MineSeekerBundle_battle_share', requirements: ['id' => '\d+'], methods: ['GET'])]
|
||||
public function battleShare(int $id): Response
|
||||
{
|
||||
$game = $this->repo->find($id);
|
||||
if (!$game) {
|
||||
throw $this->createNotFoundException('Battle not found.');
|
||||
}
|
||||
|
||||
$redName = $game->getRed()?->getUsername() ?? $game->getRedAnon()?->getUserName() ?? 'Guest';
|
||||
$blueName = $game->getBlue()?->getUsername() ?? $game->getBlueAnon()?->getUserName() ?? 'Guest';
|
||||
$redPts = $game->getRedPoints();
|
||||
$bluePts = $game->getBluePoints();
|
||||
$resign = $game->getResign();
|
||||
|
||||
if ($resign === 'red') {
|
||||
$summary = "$redName resigned — $blueName wins";
|
||||
} elseif ($resign === 'blue') {
|
||||
$summary = "$blueName resigned — $redName wins";
|
||||
} elseif ($redPts !== null && $bluePts !== null) {
|
||||
if ($redPts > $bluePts) $summary = "$redName defeated $blueName ($redPts – $bluePts)";
|
||||
elseif ($bluePts > $redPts) $summary = "$blueName defeated $redName ($bluePts – $redPts)";
|
||||
else $summary = "$redName and $blueName drew ($redPts – $bluePts)";
|
||||
} else {
|
||||
$summary = "$redName vs $blueName";
|
||||
}
|
||||
|
||||
return $this->render('Game/battle_share.html.twig', [
|
||||
'game' => $game,
|
||||
'redName' => $redName,
|
||||
'blueName' => $blueName,
|
||||
'redPts' => $redPts,
|
||||
'bluePts' => $bluePts,
|
||||
'resign' => $resign,
|
||||
'ogTitle' => "MineSeeker · $summary",
|
||||
'ogDesc' => "Watch the battle replay: $summary — played on MineSeeker, the multiplayer minesweeper.",
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user