Skip to content

Commit

Permalink
feat(overview): Implement Leaderboard
Browse files Browse the repository at this point in the history
  • Loading branch information
pan93412 committed Oct 3, 2024
1 parent 19dfaf9 commit d248839
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/Controller/OverviewCardsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,18 @@ public function eventDailyChart(
'chart' => $chart,
]);
}

/**
* List the top users with the highest solved questions.
*/
#[Route('/leaderboard', name: 'leaderboard')]
public function leaderboard(
SolutionEventRepository $solutionEventRepository,
): Response {
$leaderboard = $solutionEventRepository->listLeaderboard('7 days');

return $this->render('overview/cards/leaderboard.html.twig', [
'leaderboard' => $leaderboard,
]);
}
}
46 changes: 46 additions & 0 deletions src/Repository/SolutionEventRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,50 @@ public function getSolveState(Question $question, User $user): ?SolutionEventSta

return null;
}

/**
* List the users leaderboard by the number of questions they have solved.
*
* @param string $interval The interval to count the leaderboard
*
* @return list<array{user: User, count: int}> The leaderboard
*/
public function listLeaderboard(string $interval): array
{
$startedFrom = new \DateTimeImmutable("-$interval");

$qb = $this->createQueryBuilder('e')
->from(User::class, 'u')
->select('u AS user', 'COUNT(e.id) AS count')
->where('e.submitter = u')
->andWhere('e.status = :status')
->andWhere('e.createdAt >= :startedFrom')
->groupBy('u.id')
->orderBy('count', 'DESC')
->setParameter('status', SolutionEventStatus::Passed)
->setParameter('startedFrom', $startedFrom);

$result = $qb->getQuery()->getResult();
\assert(\is_array($result) && array_is_list($result));

/**
* @var list<array{user: User, count: int}> $leaderboard
*/
$leaderboard = [];

foreach ($result as $item) {
\assert(\is_array($item));
\assert(\array_key_exists('user', $item));
\assert(\array_key_exists('count', $item));
\assert($item['user'] instanceof User);
\assert(\is_int($item['count']));

$leaderboard[] = [
'user' => $item['user'],
'count' => $item['count'],
];
}

return $leaderboard;
}
}
22 changes: 22 additions & 0 deletions templates/overview/cards/leaderboard.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends 'base.html.twig' %}

{% block body %}
<turbo-frame id="leaderboard">
<table class="table table-hover table-light">
<thead>
<tr>
<th scope="col">名字</th>
<th scope="col">解題數</th>
</tr>
</thead>
<tbody>
{% for item in leaderboard %}
<tr>
<th scope="row">{{ item['user'].name }}</th>
<td>{{ item['count'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</turbo-frame>
{% endblock %}
2 changes: 1 addition & 1 deletion templates/overview/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

<section class="app-overview-dashboard__leaderboard">
<h3 class="mb-3">週排行榜</h3>

<turbo-frame id="leaderboard" src="{{ path('app_overview_cards_leaderboard') }}"></turbo-frame>
</section>
</main>
{% endblock %}

0 comments on commit d248839

Please sign in to comment.