Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
173 lines (151 loc) · 6.17 KB
/
Copy pathindex.html
File metadata and controls
173 lines (151 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hacknovate 2025: Live Tracker</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 20px;
}
h1 { color: #0056b3; }
h2 { border-bottom: 2px solid #ccc; padding-bottom: 5px; }
#leaderboard {
background-color: #fff;
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.team-entry {
margin-bottom: 10px;
padding: 10px;
border: 1px solid #eee;
border-radius: 5px;
}
.team-entry strong { font-size: 1.2em; }
.team-entry small { color: #555; display: block; }
</style>
</head>
<body>
<h1>Hacknovate 2025: Live Commit Tracker</h1>
<p>Data updates every 5 minutes. Dashboard refreshes every 30 seconds.</p>
<p id="last-updated">Loading...</p>
<h2>📊 Commit Leaderboard (Total)</h2>
<div id="graph-container" style="width:100%; max-width:600px;">
<canvas id="commitGraph"></canvas>
</div>
<h2>🏆 Team Rankings & Repos</h2>
<div id="leaderboard">
<p>Loading leaderboard...</p>
</div>
<script>
// --- CONFIGURATION ---
const RAW_URL_BASE = "https://raw.githubusercontent.com/MethodistCollege/hacknovate-commit-tracker/main/";
const LEADERBOARD_URL = `${RAW_URL_BASE}data/leaderboard.json`;
const HISTORY_URL = `${RAW_URL_BASE}data/history.json`;
const leaderboardDiv = document.getElementById('leaderboard');
const lastUpdatedP = document.getElementById('last-updated');
const ctx = document.getElementById('commitGraph').getContext('2d');
let myChart; // We store the chart in a variable to destroy it on update
// --- DATA FETCHER ---
async function fetchData() {
try {
// Add a cache-busting query parameter
const cacheBust = `?t=${Date.now()}`;
// Fetch both files
const [leaderboardRes, historyRes] = await Promise.all([
fetch(LEADERBOARD_URL + cacheBust),
fetch(HISTORY_URL + cacheBust)
]);
const leaderboardData = await leaderboardRes.json();
const historyData = await historyRes.json();
// Update the "Last Updated" text
lastUpdatedP.textContent = `Dashboard Last Refreshed: ${new Date().toLocaleTimeString()}`;
// --- 1. Update Leaderboard ---
updateLeaderboard(leaderboardData);
// --- 2. Update Graph ---
updateGraph(leaderboardData);
} catch (error) {
console.error("Error fetching data:", error);
leaderboardDiv.innerHTML = "<p>Error loading data. Check console.</p>";
}
}
// --- LEADERBOARD RENDER ---
function updateLeaderboard(data) {
// Clear old data
leaderboardDiv.innerHTML = "";
if (data.length === 0) {
leaderboardDiv.innerHTML = "<p>No team data yet. Waiting for first commit...</p>";
return;
}
// Data is already sorted by the GitHub Action, so we just display it
data.forEach((team, index) => {
const entry = document.createElement('div');
entry.className = 'team-entry';
// Get the repo list for the team (from data/teams.json)
// This is simple but assumes the data/teams.json structure
const repos = team.repos || ['No repo list found'];
entry.innerHTML = `
<strong>${index + 1}. ${team.name}: ${team.total_commits} Commits</strong>
<small>Repos: ${repos.join(', ')}</small>
`;
leaderboardDiv.appendChild(entry);
});
}
// --- GRAPH RENDER (using Chart.js) ---
function updateGraph(data) {
// Get labels (team names) and data (commit counts)
const labels = data.map(team => team.name);
const commitCounts = data.map(team => team.total_commits);
const colors = data.map(team => team.color || getRandomColor());
// Destroy the old chart if it exists (prevents flickering)
if (myChart) {
myChart.destroy();
}
// Create the new chart
myChart = new Chart(ctx, {
type: 'bar', // A simple bar chart
data: {
labels: labels,
datasets: [{
label: 'Total Commits',
data: commitCounts,
backgroundColor: colors,
borderColor: colors,
borderWidth: 1
}]
},
options: {
indexAxis: 'y', // Makes the bar chart horizontal
scales: {
x: {
beginAtZero: true
}
},
plugins: {
legend: {
display: false // Hide legend for a cleaner look
}
}
}
});
}
function getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
// --- RUN THE FETCHER ---
fetchData(); // Run on page load
setInterval(fetchData, 30000); // Run every 30 seconds
</script>
</body>
</html>