Working scoreboard with table

This commit is contained in:
Neale Pickett 2010-09-08 17:39:28 -06:00
parent f043173cf4
commit 1aff408b66
2 changed files with 203 additions and 44 deletions

View File

@ -1,30 +1,61 @@
#! /usr/bin/awk -f #! /usr/bin/awk -f
function output() { function qsort(A, left, right, i, last) {
if (left >= right)
return
swap(A, left, left+int((right-left+1)*rand()))
last = left
for (i = left+1; i <= right; i++)
if (A[i] < A[left])
swap(A, ++last, i)
swap(A, left, last)
qsort(A, left, last-1)
qsort(A, last+1, right)
}
function swap(A, i, j, t) {
t = A[i]; A[i] = A[j]; A[j] = t
}
function escape(s) {
gsub("&", "&amp;", s)
gsub("<", "&lt;", s)
gsub(">", "&gt;", s)
return s
}
function output( t, c) {
for (t in teams) { for (t in teams) {
score = 0; score = 0;
for (c in points_by_cat) { for (c in points_by_cat) {
score += points_by_cat_team[c, t] / points_by_cat[c]; if (points_by_cat[c] > 0) {
score += points_by_cat_team[c, t] / points_by_cat[c];
}
} }
if (score > maxscore) { if (score > maxscore) {
maxscore = score maxscore = score
} }
if (score > maxscores_by_team[t]) {
maxscores_by_team[t] = score
}
scores_by_team_time[t, lasttime] = score scores_by_team_time[t, lasttime] = score
} }
timestamps[tslen++] = lasttime timestamps[tslen++] = lasttime
} }
BEGIN { BEGIN {
# High-contrast colors for accessibility # It took me like 7 hours to find a color palette that worked for
colors[0] = "e41a1c" # people with protanopia. Don't change these colors.
colors[1] = "377eb8" colors[0] = "33cc33"
colors[2] = "4daf4a" colors[1] = "863a3a"
colors[3] = "984ea3" colors[2] = "5c5ce6"
colors[4] = "ff7f00" colors[3] = "bfbf4d"
colors[5] = "ffff33" colors[4] = "408080"
colors[6] = "a65628" colors[5] = "b336b2"
colors[7] = "f781bf" colors[6] = "ffa500"
colors[7] = "00bfff"
colors[8] = "8db6cd"
ncolors = 9
# Every 2.5 minutes # Every 2.5 minutes
interval = 150 interval = 150
tslen = 0 tslen = 0
@ -52,34 +83,138 @@ BEGIN {
output() output()
# Get team colors and names
for (team in teams) {
fn = "/var/lib/ctf/teams/colors/" team ".color"
getline colors_by_team[team] < fn
close(fn)
fn = "/var/lib/ctf/teams/" team
getline names_by_team[team] < fn
close(fn)
}
# Get team names
width = lasttime - start width = lasttime - start
print "<!DOCTYPE html>" print "<!DOCTYPE html>"
print "<html>" print "<html>"
print " <head>" print " <head>"
print " <title>foo</title>" print " <title>foo</title>"
print " <style type=\"text/css\">" print " <link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">"
print " body { background: black; }" print " <script type=\"application/javascript\" src=\"plot.js\"></script>"
print " </style>"
print " <script type=\"application/javascript\" src=\"file:///home/neale/src/ctf/www/plot.js\"></script>"
print " <script type=\"application/javascript\">" print " <script type=\"application/javascript\">"
print "function draw() {" print "function draw() {"
printf("p = new Plot(\"chart\", %d, %.2f)\n", width, maxscore * 1.1); printf("plot(\"chart\", %d, %.2f, [\n", tslen, maxscore)
c = 0 c = 0
for (team in teams) { for (team in teams) {
printf("p.line(\"#%s\",[", colors[c++ % 8]) if (maxscores_by_team[team] / maxscore < 0.01) continue
printf("[\"#%s\",[", colors_by_team[team])
for (i = 1; i < tslen; i += 1) { for (i = 1; i < tslen; i += 1) {
time = timestamps[i] time = timestamps[i]
printf("[%d,%.2f],", printf("[%d,%.2f],",
time - start, scores_by_team_time[team, time]) i, scores_by_team_time[team, time])
} }
printf("]);\n"); printf("]],\n");
} }
print "]);"
print "}" print "}"
print "window.onload = draw;" print "window.onload = draw;"
print " </script>" print " </script>"
print " <style type=\"text/css\">"
for (team in teams) {
printf(".t%s { background-color: #%s; }\n",
team, colors_by_team[team])
}
print " </style>"
print " </head>" print " </head>"
print " <body>" print " <body>"
print " <canvas id=\"chart\"></canvas>" print " <h1>Scoreboard</h1>"
print " <table class=\"scoreboard\">"
print " <tr><th>Overall</th>"
# Sort categories
ncats = 0
for (cat in points_by_cat) {
cats[ncats++] = cat
}
qsort(cats, 0, ncats-1)
# Print out category names
for (i = 0; i < ncats; i += 1) {
cat = cats[i]
points = points_by_cat[cat]
if (0 == points) continue
printf("<th>%s (%d)</th>\n", cat, points)
}
print " </tr>"
print " <tr>"
print " <td>"
print " <ol>"
# Create a sorted list of scores
nteams = 0
for (team in teams) {
scores[nteams++] = scores_by_team_time[team, lasttime]
}
qsort(scores, 0, nteams-1)
# Print out teams, ranked by score
bottom = nteams - 10
if (bottom < 0) bottom = 0
for (i = nteams-1; i >= bottom; i -= 1) {
if (scores[i] == scores[i-1]) continue;
for (team in teams) {
if (scores[i] == scores_by_team_time[team, lasttime]) {
name = names_by_team[team]
printf("<li><span class=\"t%s\">%s (%.2f)</span></li>\n",
team, escape(name), scores[i])
}
}
}
print " </ol>"
print " </td>"
for (i = 0; i < ncats; i += 1) {
cat = cats[i]
points = points_by_cat[cat]
if (0 == points) break;
print "<td>"
# Create sorted list of scores in this category
n = 0
for (team in teams) {
l[n++] = points_by_cat_team[cat, team];
}
qsort(l, 0, n)
# Print out teams, ranked by points
for (j = n; j > 0; j -= 1) {
if (l[j] == l[j-1]) continue;
if (0 == l[j]) break;
for (team in teams) {
points = points_by_cat_team[cat, team]
if (l[j] == points) {
name = names_by_team[team]
printf("<div class=\"t%s\" style=\"height: %.2f%%; overflow: hidden; color: black; border-top: \">\n",
team,
100 * points / points_by_cat[cat],
colors_by_team[team])
printf("<!-- category: %s --> %s: %d\n",
cat, escape(name), points)
printf("</div>\n")
}
}
}
print "</td>"
}
print " </tr>"
print " </table>"
print " <canvas id=\"chart\" width=\"800\" height=\"400\"></canvas>"
print " </body>" print " </body>"
print "</html>" print "</html>"
} }

View File

@ -1,42 +1,66 @@
function Plot(id, width, height) { function dbg(o) {
e = document.getElementById("debug");
e.innerHTML = o;
}
function torgba(color, alpha) {
var r = parseInt(color.substring(1,3), 16);
var g = parseInt(color.substring(3,5), 16);
var b = parseInt(color.substring(5,7), 16);
return "rgba(" + r + "," + g + "," + b + "," + alpha + ")";
}
function plot(id, width, height, lines) {
var canvas = document.getElementById(id); var canvas = document.getElementById(id);
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 200;
// We'll let the canvas do all the tricksy math // We'll let the canvas do all the tricksy math
xscale = canvas.width/width; var xscale = canvas.width/width;
yscale = canvas.height/height; var yscale = canvas.height/height;
ctx.lineWidth = 2; var nlines = lines.length;
function moveTo(x, y) { function moveTo(x, y) {
ctx.moveTo(Math.round(x * xscale), Math.round(y * yscale)); ctx.moveTo(Math.round(x * xscale), Math.round((height - y) * yscale));
} }
function lineTo(x, y) { function lineTo(x, y) {
ctx.lineTo(Math.round(x * xscale), Math.round(y * yscale)); ctx.lineTo(Math.round(x * xscale), Math.round((height - y) * yscale));
} }
function draw(values) { function draw(line) {
ctx.beginPath(); var color = line[0];
moveTo(values[0][0], height); var values = line[1];
var lasty = 0; var lasty = 0;
ctx.strokeStyle = torgba(color, 0.99);
ctx.lineWidth = 2;
ctx.beginPath();
moveTo(values[0][0], 0);
for (i in values) { for (i in values) {
var x = values[i][0]; var x = values[i][0];
var y = values[i][1]; var y = values[i][1];
lineTo(x, height - lasty); lineTo(x, lasty);
lineTo(x, height - y); lineTo(x, y);
lasty = y; lasty = y;
} }
lineTo(width, height - lasty); lineTo(width, lasty);
}
this.line = function(color, values) {
ctx.fillStyle = color;
ctx.strokeStyle = color;
draw(values);
ctx.stroke(); ctx.stroke();
} }
var cur = 0;
function update() {
var line = lines[cur];
draw(line);
cur = (cur + 1) % nlines;
if (cur > 0) {
setTimeout(update, 66);
}
}
update()
} }