web/src/pages/leaderboard.astro
2024-02-26 03:00:29 +01:00

103 lines
No EOL
4.5 KiB
Text

---
import BaseLayout from '../layouts/base.astro';
import contributors from '../contributors.json';
const points = {}
let i = 0;
for (const c of contributors.items) {
const key = `c:${c.contributions}`
if (!points[key]) {
points[key] = { arr: [c.login], start: i }
} else {
points[key].arr.push(c.login)
}
i++
}
function getPoint (num){
const key = `c:${num}`
const obj = points[key];
return `${obj.start+1}${obj.arr.length > 1 ? '-'+(obj.start+obj.arr.length) : ''}`;
}
const median = arr => {
const mid = Math.floor(arr.length / 2),
nums = [...arr].sort((a, b) => a - b);
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
};
---
<BaseLayout title="Leaderboard" image="og_leaderboard">
<div class="middle-pane-medium mt-10 flex items-center justify-center">
<!--code><pre>
{JSON.stringify(points, null, 2)}
</pre></code-->
<table class="w3pn-leaderboard-table w-full sm:w-5/6 md:w-2/3 lg:w-1/2">
<thead>
<tr>
<th></th>
<th class="pb-4 uppercase" colspan="2">Contributor</th>
<th align="left" class="pb-4 uppercase"># Commits</th>
</tr>
</thead>
<tbody>
{contributors.items.map((contrib, i) => (
<tr>
<td align="right">
{[getPoint(contrib.contributions)].map((r) => (
<div>
{r < 4 &&
<span class="mr-4">
{r === "1" && "🥇"}
{r === "2" && "🥈"}
{r === "3" && "🥉"}
</span>
}
<b>{r}.</b>
</div>
))}
</td>
<td align="right" class="py-3 px-4"><div class="w-16 h-16"><img src={contrib.avatar_url} class="rounded-full border" /></div></td>
<td class="px-2">
<a href={contrib.html_url} target="_blank" class="hover:underline">{contrib.login}</a>
</td>
<td class="text-white pl-10 text-lg pr-4" align="left">{contrib.contributions}</td>
</tr>
))}
</tbody>
</table>
</div>
<div class="middle-pane-medium flex items-center justify-center">
<div class="mt-20">
<div class="mb-10">
<div><span class="text-white">{contributors.items.reduce((a, b) => (a + b.contributions), 0)}</span> total commits</div>
<div><span class="text-white">{contributors.items.length}</span> total contributors</div>
<div class="mt-4"><span class="text-white">{contributors.items.filter(c => c.contributions >= 2).length}</span> contributors with >= 2 commits</div>
<div><span class="text-white">{contributors.items.filter(c => c.contributions >= 5).length}</span> contributors with >= 5 commits</div>
<div><span class="text-white">{contributors.items.filter(c => c.contributions >= 10).length}</span> contributors with >= 10 commits</div>
<div><span class="text-white">{contributors.items.filter(c => c.contributions >= 50).length}</span> contributors with >= 50 commits</div>
<div><span class="text-white">{contributors.items.filter(c => c.contributions >= 100).length}</span> contributors with >= 100 commits</div>
<div class="mt-4">Median <span class="text-white">{median(contributors.items.map(c => c.contributions))}</span> commits per contributor</div>
<div>Average <span class="text-white">{(Math.round((contributors.items.reduce((a, b) => (a + b.contributions), 0) / contributors.items.length)*100)/100)}</span> commits per contributor</div>
</div>
<h2>Eligible repositories</h2>
<div class="mt-6">
{contributors.repos.map(repo => (
<div><a href=`https://github.com/${repo}` class="hover:underline">@{repo}</a></div>
))}
</div>
</div>
</div>
</BaseLayout>
<style>
.w3pn-leaderboard-table tbody tr:nth-child(2n+1) {
background-color: #0f0f0f;
}
</style>