Skip to content

Commit

Permalink
Merge pull request #189 from th-ch/skasch/aggregated-leaderboard
Browse files Browse the repository at this point in the history
Create aggregated leaderboard
  • Loading branch information
skasch authored Dec 26, 2023
2 parents 38fb7cc + abee471 commit 5b0c8da
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
64 changes: 62 additions & 2 deletions tool/leaderboard/leaderboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from collections import defaultdict
import dataclasses
from typing import NamedTuple
from jinja2 import Environment, FileSystemLoader
import itertools

Expand All @@ -10,6 +12,18 @@
template = templateEnv.get_template("leaderboard_template.html")


class AggregatedAuthorResult(NamedTuple):
author: str
languages: list[str]
stars: int
total_execution_time: float


class LeaderboardData(NamedTuple):
results_by_day_and_part: list[list[list[Result]]]
aggregated_author_results: list[AggregatedAuthorResult]


def group_by_day_and_part(
results: list[list[Result]],
) -> list[list[list[Result]]]:
Expand All @@ -20,14 +34,60 @@ def group_by_day_and_part(
results_by_part_by_day[result.problem.day][result.problem.part].append(result)
return [
[
results_by_part_by_day[day][part]
sorted(results_by_part_by_day[day][part], key=lambda r: r.duration)
for part in sorted(results_by_part_by_day[day])
]
for day in sorted(results_by_part_by_day)
]


@dataclasses.dataclass
class CumulativeAuthorResults:
languages: set[str] = dataclasses.field(default_factory=set)
stars: int = 0
total_execution_time: float = 0.0


def aggregate_author_results(
results_by_day_and_part: list[list[list[Result]]],
) -> list[AggregatedAuthorResult]:
results_by_author: defaultdict[str, CumulativeAuthorResults] = defaultdict(
CumulativeAuthorResults
)
for results_by_part in results_by_day_and_part:
for results in results_by_part:
best_result_by_author: dict[str, Result] = {}
for result in results:
author = result.submission.author
if (
author not in best_result_by_author
or result.duration < best_result_by_author[author].duration
):
best_result_by_author[author] = result
for author, result in best_result_by_author.items():
results_by_author[author].languages.add(result.submission.language)
results_by_author[author].stars += 1
results_by_author[author].total_execution_time += result.duration
return sorted(
(
AggregatedAuthorResult(
author, sorted(c.languages), c.stars, c.total_execution_time
)
for author, c in results_by_author.items()
),
key=lambda a: (-a.stars, a.total_execution_time),
)


def build_leaderboard_data(results: list[list[Result]]) -> LeaderboardData:
results_by_day_and_part = group_by_day_and_part(results)
res = LeaderboardData(
results_by_day_and_part, aggregate_author_results(results_by_day_and_part)
)
return res


def generate_leaderboard(results: list[list[Result]]) -> None:
rendered = template.render(res=group_by_day_and_part(results))
rendered = template.render(res=build_leaderboard_data(results))
with open("./leaderboard/index.html", "w+") as f:
f.write(rendered)
29 changes: 28 additions & 1 deletion tool/leaderboard/leaderboard_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,34 @@ <h1>Advent of Code - Leaderboard</h1>

<div class="sf sf2" style="top:-3.89em; left:43.83vw; animation-delay:-5.71s;"></div><div class="sf sf0" style="top:-1.81em; left:17.92vw; animation-delay:-16.97s;"></div><div class="sf sf0" style="top:-1.93em; left:22.57vw; animation-delay:-1.22s;"></div><div class="sf sf2" style="top:-3.69em; left:24.19vw; animation-delay:-19.57s;"></div><div class="sf sf2" style="top:-3.28em; left:34.98vw; animation-delay:-16.53s;"></div><div class="sf sf2" style="top:-3.74em; left:23.41vw; animation-delay:-9.65s;"></div><div class="sf sf3" style="top:-4.00em; left:82.39vw; animation-delay:-17.78s;"></div><div class="sf sf0" style="top:-1.01em; left:58.41vw; animation-delay:-16.37s;"></div><div class="sf sf1" style="top:-2.77em; left:73.45vw; animation-delay:-18.33s;"></div><div class="sf sf3" style="top:-4.16em; left:39.07vw; animation-delay:-12.29s;"></div><div class="sf sf0" style="top:-1.26em; left:27.63vw; animation-delay:-19.29s;"></div><div class="sf sf1" style="top:-2.86em; left:6.93vw; animation-delay:-18.35s;"></div><div class="sf sf2" style="top:-3.51em; left:27.99vw; animation-delay:-5.75s;"></div><div class="sf sf0" style="top:-1.84em; left:38.02vw; animation-delay:-0.36s;"></div><div class="sf sf0" style="top:-1.12em; left:34.52vw; animation-delay:-5.59s;"></div><div class="sf sf1" style="top:-2.28em; left:93.46vw; animation-delay:-18.95s;"></div><div class="sf sf2" style="top:-3.59em; left:84.10vw; animation-delay:-13.30s;"></div><div class="sf sf0" style="top:-1.57em; left:20.12vw; animation-delay:-14.29s;"></div><div class="sf sf3" style="top:-4.36em; left:38.37vw; animation-delay:-10.11s;"></div><div class="sf sf1" style="top:-2.44em; left:61.66vw; animation-delay:-9.94s;"></div><div class="sf sf2" style="top:-3.33em; left:29.27vw; animation-delay:-13.36s;"></div><div class="sf sf1" style="top:-2.47em; left:1.26vw; animation-delay:-5.73s;"></div><div class="sf sf2" style="top:-3.72em; left:15.63vw; animation-delay:-2.96s;"></div><div class="sf sf3" style="top:-4.23em; left:18.82vw; animation-delay:-18.88s;"></div><div class="sf sf1" style="top:-2.23em; left:45.89vw; animation-delay:-1.06s;"></div><div class="sf sf1" style="top:-2.68em; left:75.05vw; animation-delay:-4.41s;"></div><div class="sf sf0" style="top:-1.31em; left:44.50vw; animation-delay:-2.15s;"></div><div class="sf sf2" style="top:-3.70em; left:29.50vw; animation-delay:-1.54s;"></div><div class="sf sf2" style="top:-3.19em; left:34.35vw; animation-delay:-4.88s;"></div><div class="sf sf0" style="top:-1.90em; left:92.88vw; animation-delay:-10.64s;"></div><div class="sf sf2" style="top:-3.11em; left:28.52vw; animation-delay:-4.79s;"></div><div class="sf sf0" style="top:-1.65em; left:12.00vw; animation-delay:-7.27s;"></div><div class="sf sf0" style="top:-1.85em; left:23.02vw; animation-delay:-7.35s;"></div><div class="sf sf3" style="top:-4.63em; left:52.31vw; animation-delay:-4.18s;"></div><div class="sf sf2" style="top:-3.02em; left:36.57vw; animation-delay:-14.53s;"></div><div class="sf sf3" style="top:-4.69em; left:89.60vw; animation-delay:-0.07s;"></div><div class="sf sf2" style="top:-3.38em; left:65.06vw; animation-delay:-4.90s;"></div><div class="sf sf0" style="top:-1.92em; left:27.45vw; animation-delay:-4.60s;"></div><div class="sf sf2" style="top:-3.40em; left:51.38vw; animation-delay:-7.31s;"></div><div class="sf sf3" style="top:-4.29em; left:51.95vw; animation-delay:-3.39s;"></div><div class="sf sf2" style="top:-3.98em; left:41.28vw; animation-delay:-1.02s;"></div><div class="sf sf3" style="top:-4.98em; left:18.76vw; animation-delay:-3.64s;"></div><div class="sf sf0" style="top:-1.03em; left:32.34vw; animation-delay:-1.72s;"></div><div class="sf sf0" style="top:-1.85em; left:25.99vw; animation-delay:-1.45s;"></div><div class="sf sf3" style="top:-4.93em; left:1.59vw; animation-delay:-11.77s;"></div><div class="sf sf2" style="top:-3.19em; left:28.29vw; animation-delay:-15.05s;"></div><div class="sf sf1" style="top:-2.89em; left:82.21vw; animation-delay:-5.79s;"></div><div class="sf sf2" style="top:-3.76em; left:14.37vw; animation-delay:-15.05s;"></div><div class="sf sf1" style="top:-2.92em; left:86.55vw; animation-delay:-8.01s;"></div><div class="sf sf2" style="top:-3.06em; left:25.52vw; animation-delay:-12.01s;"></div><div class="sf sf2" style="top:-3.21em; left:56.10vw; animation-delay:-16.80s;"></div><div class="sf sf3" style="top:-4.86em; left:68.19vw; animation-delay:-14.67s;"></div><div class="sf sf2" style="top:-3.07em; left:44.30vw; animation-delay:-3.23s;"></div><div class="sf sf3" style="top:-4.36em; left:62.12vw; animation-delay:-7.94s;"></div><div class="sf sf1" style="top:-2.68em; left:64.82vw; animation-delay:-15.77s;"></div><div class="sf sf3" style="top:-4.94em; left:34.56vw; animation-delay:-18.84s;"></div><div class="sf sf1" style="top:-2.83em; left:91.76vw; animation-delay:-1.27s;"></div><div class="sf sf2" style="top:-3.48em; left:58.32vw; animation-delay:-0.63s;"></div><div class="sf sf1" style="top:-2.83em; left:23.33vw; animation-delay:-3.21s;"></div><div class="sf sf1" style="top:-2.11em; left:28.23vw; animation-delay:-10.61s;"></div><div class="sf sf1" style="top:-2.64em; left:47.79vw; animation-delay:-3.10s;"></div><div class="sf sf1" style="top:-2.56em; left:41.88vw; animation-delay:-5.53s;"></div><div class="sf sf2" style="top:-3.86em; left:29.05vw; animation-delay:-7.84s;"></div><div class="sf sf2" style="top:-3.22em; left:45.38vw; animation-delay:-10.04s;"></div><div class="sf sf0" style="top:-1.12em; left:54.92vw; animation-delay:-16.65s;"></div><div class="sf sf1" style="top:-2.23em; left:29.65vw; animation-delay:-8.17s;"></div><div class="sf sf0" style="top:-1.56em; left:53.22vw; animation-delay:-4.94s;"></div><div class="sf sf2" style="top:-3.52em; left:11.33vw; animation-delay:-5.60s;"></div><div class="sf sf3" style="top:-4.08em; left:54.68vw; animation-delay:-19.00s;"></div><div class="sf sf2" style="top:-3.71em; left:95.26vw; animation-delay:-11.48s;"></div><div class="sf sf3" style="top:-4.93em; left:17.50vw; animation-delay:-5.84s;"></div><div class="sf sf1" style="top:-2.39em; left:57.66vw; animation-delay:-12.36s;"></div><div class="sf sf2" style="top:-3.68em; left:50.60vw; animation-delay:-4.92s;"></div><div class="sf sf1" style="top:-2.83em; left:50.50vw; animation-delay:-18.10s;"></div><div class="sf sf0" style="top:-1.85em; left:21.59vw; animation-delay:-5.36s;"></div><div class="sf sf1" style="top:-2.91em; left:88.04vw; animation-delay:-9.82s;"></div><div class="sf sf2" style="top:-3.46em; left:81.63vw; animation-delay:-1.04s;"></div><div class="sf sf0" style="top:-1.14em; left:91.39vw; animation-delay:-13.24s;"></div><div class="sf sf1" style="top:-2.76em; left:36.47vw; animation-delay:-18.71s;"></div><div class="sf sf3" style="top:-4.29em; left:90.82vw; animation-delay:-17.42s;"></div><div class="sf sf1" style="top:-2.25em; left:87.36vw; animation-delay:-9.69s;"></div><div class="sf sf2" style="top:-3.07em; left:78.94vw; animation-delay:-18.45s;"></div><div class="sf sf1" style="top:-2.19em; left:16.65vw; animation-delay:-4.52s;"></div><div class="sf sf1" style="top:-2.71em; left:20.11vw; animation-delay:-10.38s;"></div><div class="sf sf1" style="top:-2.94em; left:60.21vw; animation-delay:-11.57s;"></div><div class="sf sf2" style="top:-3.06em; left:88.22vw; animation-delay:-11.63s;"></div><div class="sf sf1" style="top:-2.76em; left:78.44vw; animation-delay:-15.74s;"></div><div class="sf sf2" style="top:-3.03em; left:85.91vw; animation-delay:-4.02s;"></div><div class="sf sf1" style="top:-2.70em; left:48.78vw; animation-delay:-1.43s;"></div><div class="sf sf3" style="top:-4.82em; left:38.14vw; animation-delay:-13.78s;"></div><div class="sf sf3" style="top:-4.78em; left:35.16vw; animation-delay:-4.89s;"></div><div class="sf sf1" style="top:-2.30em; left:37.62vw; animation-delay:-19.22s;"></div><div class="sf sf0" style="top:-1.30em; left:74.83vw; animation-delay:-15.88s;"></div><div class="sf sf0" style="top:-1.38em; left:38.07vw; animation-delay:-7.76s;"></div><div class="sf sf3" style="top:-4.72em; left:73.78vw; animation-delay:-15.42s;"></div><div class="sf sf1" style="top:-2.16em; left:38.79vw; animation-delay:-7.11s;"></div><div class="sf sf0" style="top:-1.42em; left:50.43vw; animation-delay:-17.45s;"></div><div class="sf sf0" style="top:-1.47em; left:71.33vw; animation-delay:-19.50s;"></div><div class="sf sf1" style="top:-2.11em; left:11.46vw; animation-delay:-15.74s;"></div><div class="sf sf0" style="top:-1.56em; left:55.07vw; animation-delay:-15.74s;"></div>

{% for day in res %}
<section>
<h2>Aggregated results</h2>
<div class="leaderboard">
<div>
<div>Author</div>
<div>Languages</div>
<div>Stars</div>
<div>Total execution time</div>
</div>
{% for author_results in res["aggregated_author_results"] %}
<div>
<div>
{{ author_results.author }}
</div>
<div>
{{ author_results.languages | join(', ') }}
</div>
<div>
{{ author_results.stars }}
</div>
<div>
{{ "%.3f"|format(author_results.total_execution_time) }}ms
</div>
</div>
{% endfor %}
</div>
</section>
{% for day in res["results_by_day_and_part"] %}
<section>
<div class="leaderboard-day">
{% for part in day %}
Expand Down

0 comments on commit 5b0c8da

Please sign in to comment.