mirror of https://github.com/dirtbags/moth.git
Add usability feature to scoreboard (highlighting on hover)
This commit is contained in:
parent
1aff408b66
commit
03c6d4e17b
159
src/scoreboard
159
src/scoreboard
|
@ -1,5 +1,11 @@
|
||||||
#! /usr/bin/awk -f
|
#! /usr/bin/awk -f
|
||||||
|
|
||||||
|
##
|
||||||
|
##
|
||||||
|
## I'm not happy with how this code looks. I've
|
||||||
|
##
|
||||||
|
##
|
||||||
|
|
||||||
function qsort(A, left, right, i, last) {
|
function qsort(A, left, right, i, last) {
|
||||||
if (left >= right)
|
if (left >= right)
|
||||||
return
|
return
|
||||||
|
@ -23,6 +29,20 @@ function escape(s) {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function print_bar(cat, team, n, d) {
|
||||||
|
printf("<div class=\"b%s score\"" \
|
||||||
|
" style=\"height: %.2f%%;\"" \
|
||||||
|
" onmouseover=\"highlight('%s')\"" \
|
||||||
|
" onmouseout=\"restore('%s')\">\n" \
|
||||||
|
"<!-- %s --> %s: %.2f\n" \
|
||||||
|
"</div>",
|
||||||
|
team,
|
||||||
|
100 * n / d,
|
||||||
|
team,
|
||||||
|
team,
|
||||||
|
cat, escape(names_by_team[team]), n)
|
||||||
|
}
|
||||||
|
|
||||||
function output( t, c) {
|
function output( t, c) {
|
||||||
for (t in teams) {
|
for (t in teams) {
|
||||||
score = 0;
|
score = 0;
|
||||||
|
@ -56,7 +76,7 @@ BEGIN {
|
||||||
colors[8] = "8db6cd"
|
colors[8] = "8db6cd"
|
||||||
ncolors = 9
|
ncolors = 9
|
||||||
|
|
||||||
# Every 2.5 minutes
|
# New point at least every 2.5 minutes
|
||||||
interval = 150
|
interval = 150
|
||||||
tslen = 0
|
tslen = 0
|
||||||
|
|
||||||
|
@ -94,45 +114,6 @@ BEGIN {
|
||||||
close(fn)
|
close(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get team names
|
|
||||||
|
|
||||||
width = lasttime - start
|
|
||||||
print "<!DOCTYPE html>"
|
|
||||||
print "<html>"
|
|
||||||
print " <head>"
|
|
||||||
print " <title>foo</title>"
|
|
||||||
print " <link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">"
|
|
||||||
print " <script type=\"application/javascript\" src=\"plot.js\"></script>"
|
|
||||||
print " <script type=\"application/javascript\">"
|
|
||||||
print "function draw() {"
|
|
||||||
printf("plot(\"chart\", %d, %.2f, [\n", tslen, maxscore)
|
|
||||||
c = 0
|
|
||||||
for (team in teams) {
|
|
||||||
if (maxscores_by_team[team] / maxscore < 0.01) continue
|
|
||||||
printf("[\"#%s\",[", colors_by_team[team])
|
|
||||||
for (i = 1; i < tslen; i += 1) {
|
|
||||||
time = timestamps[i]
|
|
||||||
printf("[%d,%.2f],",
|
|
||||||
i, scores_by_team_time[team, time])
|
|
||||||
}
|
|
||||||
printf("]],\n");
|
|
||||||
}
|
|
||||||
print "]);"
|
|
||||||
print "}"
|
|
||||||
print "window.onload = draw;"
|
|
||||||
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 " <body>"
|
|
||||||
print " <h1>Scoreboard</h1>"
|
|
||||||
print " <table class=\"scoreboard\">"
|
|
||||||
print " <tr><th>Overall</th>"
|
|
||||||
|
|
||||||
# Sort categories
|
# Sort categories
|
||||||
ncats = 0
|
ncats = 0
|
||||||
for (cat in points_by_cat) {
|
for (cat in points_by_cat) {
|
||||||
|
@ -140,19 +121,6 @@ BEGIN {
|
||||||
}
|
}
|
||||||
qsort(cats, 0, ncats-1)
|
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
|
# Create a sorted list of scores
|
||||||
nteams = 0
|
nteams = 0
|
||||||
for (team in teams) {
|
for (team in teams) {
|
||||||
|
@ -160,21 +128,77 @@ BEGIN {
|
||||||
}
|
}
|
||||||
qsort(scores, 0, nteams-1)
|
qsort(scores, 0, nteams-1)
|
||||||
|
|
||||||
|
|
||||||
|
# Now we can start writing the document
|
||||||
|
print "<!DOCTYPE html>"
|
||||||
|
print "<html>"
|
||||||
|
print " <head>"
|
||||||
|
print " <title>Scoreboard</title>"
|
||||||
|
print " <link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">"
|
||||||
|
print " <script type=\"application/javascript\" src=\"scoreboard.js\"></script>"
|
||||||
|
|
||||||
|
# Provide raw data for the chart
|
||||||
|
print " <script type=\"application/javascript\">"
|
||||||
|
print "function draw() {"
|
||||||
|
printf("plot(\"chart\", %d, %.2f, {\n", tslen, maxscore)
|
||||||
|
c = 0
|
||||||
|
for (team in teams) {
|
||||||
|
if (maxscores_by_team[team] / maxscore < 0.01) continue
|
||||||
|
printf("\"%s\": [\"#%s\",[", team, colors_by_team[team])
|
||||||
|
for (i = 1; i < tslen; i += 1) {
|
||||||
|
time = timestamps[i]
|
||||||
|
printf("[%d,%.2f],",
|
||||||
|
i, scores_by_team_time[team, time])
|
||||||
|
}
|
||||||
|
printf("]],\n");
|
||||||
|
}
|
||||||
|
print "});"
|
||||||
|
print "}"
|
||||||
|
print "window.onload = draw;"
|
||||||
|
print " </script>"
|
||||||
|
|
||||||
|
# Set up team colors
|
||||||
|
print " <style type=\"text/css\">"
|
||||||
|
print " .score { overflow: hidden; color: black; }"
|
||||||
|
for (team in teams) {
|
||||||
|
printf(" .b%s { background-color: #%s; }\n",
|
||||||
|
team, colors_by_team[team])
|
||||||
|
}
|
||||||
|
print " </style>"
|
||||||
|
|
||||||
|
print " </head>"
|
||||||
|
print " <body>"
|
||||||
|
print " <h1>Scoreboard</h1>"
|
||||||
|
print "<p id=\"debug\"></p>"
|
||||||
|
print " <table class=\"scoreboard\">"
|
||||||
|
print " <tr>"
|
||||||
|
print " <th>Overall</th>"
|
||||||
|
|
||||||
|
# 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 out teams, ranked by score
|
# Print out teams, ranked by score
|
||||||
bottom = nteams - 10
|
print " <td>"
|
||||||
if (bottom < 0) bottom = 0
|
for (i = 0; i < nteams; i += 1) {
|
||||||
for (i = nteams-1; i >= bottom; i -= 1) {
|
|
||||||
if (scores[i] == scores[i-1]) continue;
|
if (scores[i] == scores[i-1]) continue;
|
||||||
for (team in teams) {
|
for (team in teams) {
|
||||||
if (scores[i] == scores_by_team_time[team, lasttime]) {
|
if (scores[i] == scores_by_team_time[team, lasttime]) {
|
||||||
name = names_by_team[team]
|
name = names_by_team[team]
|
||||||
printf("<li><span class=\"t%s\">%s (%.2f)</span></li>\n",
|
print_bar("total", team, scores[i], ncats)
|
||||||
team, escape(name), scores[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print " </ol>"
|
|
||||||
print " </td>"
|
print " </td>"
|
||||||
|
|
||||||
|
# Print out scores within each category
|
||||||
for (i = 0; i < ncats; i += 1) {
|
for (i = 0; i < ncats; i += 1) {
|
||||||
cat = cats[i]
|
cat = cats[i]
|
||||||
points = points_by_cat[cat]
|
points = points_by_cat[cat]
|
||||||
|
@ -187,23 +211,17 @@ BEGIN {
|
||||||
for (team in teams) {
|
for (team in teams) {
|
||||||
l[n++] = points_by_cat_team[cat, team];
|
l[n++] = points_by_cat_team[cat, team];
|
||||||
}
|
}
|
||||||
qsort(l, 0, n)
|
qsort(l, 0, n-1)
|
||||||
|
|
||||||
# Print out teams, ranked by points
|
# Print out teams, ranked by points
|
||||||
for (j = n; j > 0; j -= 1) {
|
for (j = 0; j < n; j += 1) {
|
||||||
if (l[j] == l[j-1]) continue;
|
if (l[j] == l[j-1]) continue;
|
||||||
if (0 == l[j]) break;
|
if (0 == l[j]) break;
|
||||||
for (team in teams) {
|
for (team in teams) {
|
||||||
points = points_by_cat_team[cat, team]
|
points = points_by_cat_team[cat, team]
|
||||||
if (l[j] == points) {
|
if (l[j] == points) {
|
||||||
name = names_by_team[team]
|
name = names_by_team[team]
|
||||||
printf("<div class=\"t%s\" style=\"height: %.2f%%; overflow: hidden; color: black; border-top: \">\n",
|
print_bar(cat, team, points, points_by_cat[cat])
|
||||||
team,
|
|
||||||
100 * points / points_by_cat[cat],
|
|
||||||
colors_by_team[team])
|
|
||||||
printf("<!-- category: %s --> %s: %d\n",
|
|
||||||
cat, escape(name), points)
|
|
||||||
printf("</div>\n")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,10 +229,9 @@ BEGIN {
|
||||||
print "</td>"
|
print "</td>"
|
||||||
}
|
}
|
||||||
print " </tr>"
|
print " </tr>"
|
||||||
|
|
||||||
print " </table>"
|
print " </table>"
|
||||||
|
print " <canvas id=\"chart\" width=\"800\" height=\"200\"></canvas>"
|
||||||
|
|
||||||
print " <canvas id=\"chart\" width=\"800\" height=\"400\"></canvas>"
|
|
||||||
print " </body>"
|
print " </body>"
|
||||||
print "</html>"
|
print "</html>"
|
||||||
}
|
}
|
||||||
|
|
66
www/plot.js
66
www/plot.js
|
@ -1,66 +0,0 @@
|
||||||
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 ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
// We'll let the canvas do all the tricksy math
|
|
||||||
var xscale = canvas.width/width;
|
|
||||||
var yscale = canvas.height/height;
|
|
||||||
var nlines = lines.length;
|
|
||||||
|
|
||||||
function moveTo(x, y) {
|
|
||||||
ctx.moveTo(Math.round(x * xscale), Math.round((height - y) * yscale));
|
|
||||||
}
|
|
||||||
function lineTo(x, y) {
|
|
||||||
ctx.lineTo(Math.round(x * xscale), Math.round((height - y) * yscale));
|
|
||||||
}
|
|
||||||
|
|
||||||
function draw(line) {
|
|
||||||
var color = line[0];
|
|
||||||
var values = line[1];
|
|
||||||
var lasty = 0;
|
|
||||||
|
|
||||||
ctx.strokeStyle = torgba(color, 0.99);
|
|
||||||
ctx.lineWidth = 2;
|
|
||||||
ctx.beginPath();
|
|
||||||
moveTo(values[0][0], 0);
|
|
||||||
for (i in values) {
|
|
||||||
var x = values[i][0];
|
|
||||||
var y = values[i][1];
|
|
||||||
lineTo(x, lasty);
|
|
||||||
lineTo(x, y);
|
|
||||||
lasty = y;
|
|
||||||
}
|
|
||||||
lineTo(width, lasty);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var cur = 0;
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
var line = lines[cur];
|
|
||||||
|
|
||||||
draw(line);
|
|
||||||
cur = (cur + 1) % nlines;
|
|
||||||
|
|
||||||
if (cur > 0) {
|
|
||||||
setTimeout(update, 66);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
update()
|
|
||||||
}
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
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 Chart(id, width, height, lines) {
|
||||||
|
var canvas = document.getElementById(id);
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// We'll let the canvas do all the tricksy math
|
||||||
|
var xscale = canvas.width/width;
|
||||||
|
var yscale = canvas.height/height;
|
||||||
|
var nlines = lines.length;
|
||||||
|
|
||||||
|
function moveTo(x, y) {
|
||||||
|
ctx.moveTo(Math.round(x * xscale), Math.round((height - y) * yscale));
|
||||||
|
}
|
||||||
|
function lineTo(x, y) {
|
||||||
|
ctx.lineTo(Math.round(x * xscale), Math.round((height - y) * yscale));
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(color, values) {
|
||||||
|
var lasty = 0;
|
||||||
|
|
||||||
|
ctx.strokeStyle = torgba(color, 0.99);
|
||||||
|
ctx.lineWidth = 4;
|
||||||
|
ctx.beginPath();
|
||||||
|
moveTo(values[0][0], 0);
|
||||||
|
for (i in values) {
|
||||||
|
var x = values[i][0];
|
||||||
|
var y = values[i][1];
|
||||||
|
lineTo(x, lasty);
|
||||||
|
lineTo(x, y);
|
||||||
|
lasty = y;
|
||||||
|
}
|
||||||
|
lineTo(width, lasty);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.highlight = function(id, color) {
|
||||||
|
var line = lines[id];
|
||||||
|
if (! color) color = line[0];
|
||||||
|
|
||||||
|
draw(color, line[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id in lines) {
|
||||||
|
var line = lines[id];
|
||||||
|
|
||||||
|
draw(line[0], line[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var thechart;
|
||||||
|
|
||||||
|
function plot(id, width, height, lines) {
|
||||||
|
thechart = new Chart(id, width, height, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementsByClass( searchClass, domNode, tagName) {
|
||||||
|
if (domNode == null) domNode = document;
|
||||||
|
if (tagName == null) tagName = '*';
|
||||||
|
var el = new Array();
|
||||||
|
var tags = domNode.getElementsByTagName(tagName);
|
||||||
|
var tcl = " "+searchClass+" ";
|
||||||
|
for(i=0,j=0; i<tags.length; i++) {
|
||||||
|
var test = " " + tags[i].className + " ";
|
||||||
|
if (test.indexOf(tcl) != -1)
|
||||||
|
el[j++] = tags[i];
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(cls, color) {
|
||||||
|
if (! color) color = "#ffff00";
|
||||||
|
elements = getElementsByClass("b" + cls);
|
||||||
|
for (i in elements) {
|
||||||
|
e = elements[i];
|
||||||
|
e.style.borderColor = e.style.backgroundColor;
|
||||||
|
e.style.backgroundColor = color;
|
||||||
|
}
|
||||||
|
thechart.highlight(cls, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restore(cls) {
|
||||||
|
elements = getElementsByClass("b" + cls);
|
||||||
|
for (i in elements) {
|
||||||
|
e = elements[i];
|
||||||
|
e.style.backgroundColor = e.style.borderColor;
|
||||||
|
}
|
||||||
|
thechart.highlight(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue