#! /usr/bin/awk -f
##
##
## I'm not super happy with how this code looks. Rest assured, though,
## the C version would look far, far worse.
##
##
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("&", "&", s)
gsub("<", "<", s)
gsub(">", ">", s)
return s
}
function print_bar(cat, teamid, teamname, n, d) {
printf("
\n" \
" %s: %s\n" \
"
",
teamid,
100 * n / d,
teamid,
teamid,
cat, escape(name), n)
}
function output( t, c) {
for (t in teams) {
score = 0;
for (c in points_by_cat) {
if (points_by_cat[c] > 0) {
score += points_by_cat_team[c, t] / points_by_cat[c];
}
}
if (score > maxscore) {
maxscore = score
}
if (score > maxscores_by_team[t]) {
maxscores_by_team[t] = score
}
scores_by_team_time[t, lasttime] = score
}
timestamps[tslen++] = lasttime
}
BEGIN {
base = ENVIRON["CTF_BASE"]
if (! base) {
base = "/var/lib/ctf"
}
# Only display two decimal places
CONVFMT = "%.2f"
# New point at least every 2.5 minutes
interval = 150
tslen = 0
nteams = 0;
while (1 == getline) {
time = $1
team = $2
cat = $3
points = int($4)
if (! start) {
start = time
}
if (time > (outtime + interval)) {
outtime = time
output()
}
lasttime = time
teams[team] = nteams++
points_by_cat[cat] += points
points_by_cat_team[cat, team] += points
}
output()
# Get team colors and names
for (team in teams) {
# Busybox awk segfaults if you try to close a file that didn't
# exist. We work around it by calling cat.
cmd = sprintf("cat %s/teams/colors/%s", base, team)
cmd | getline color
if (! color) color = "cccccc";
colors_by_team[team] = color
close(cmd)
cmd = sprintf("cat %s/teams/names/%s", base, team)
cmd | getline name
if (! name) name = "Avengers"
names_by_team[team] = name
close(cmd)
}
# Sort categories
ncats = 0
for (cat in points_by_cat) {
cats[ncats++] = cat
}
qsort(cats, 0, ncats-1)
# 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)
# Now we can start writing the document
print ""
print ""
print " "
print " Scoreboard"
print " "
print " "
# Provide raw data for the chart
print " "
# Reload every minute
print " "
# Set up team colors and a few page-specific styles
print " "
print " "
print " "
print "
Scoreboard
"
print ""
print "
"
print "
"
print "
Overall
"
# Print out category names
for (i = 0; i < ncats; i += 1) {
cat = cats[i]
points = points_by_cat[cat]
if (0 == points) continue
printf("
%s (%d)
\n", cat, points)
}
print "
"
print "
"
# Print out teams, ranked by score
print "
"
for (i = 0; i < nteams; 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]
print_bar("total", teams[team], name, scores[i], ncats)
}
}
}
print "
"
# Print out scores within each category
for (i = 0; i < ncats; i += 1) {
cat = cats[i]
points = points_by_cat[cat]
if (0 == points) break;
print "
"
# 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-1)
# Print out teams, ranked by points
for (j = 0; j < n; 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]
print_bar(cat, teams[team], name, points, points_by_cat[cat])
}
}
}
print "