#! /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 head() { print "<!DOCTYPE html>" print "<html><head><title>Project 2 Scoreboard</title>" print "<meta http-equiv=\"refresh\" content=\"60\">" print "<style>" print "html {background: black url(\"p2inv.png\") no-repeat top center; background-size: contain; min-height: 100%; color: white;}" print "body {background: black; opacity: 0.92; margin: 0;}" print "p {margin: 0;}" print "span {display: inline-block; margin: 0; border: 0;}" print ".cat0 {background-color: #a6cee3; color: black;}" print ".cat1 {background-color: #1f78b4;}" print ".cat2 {background-color: #b2df8a; color: black;}" print ".cat3 {background-color: #33a02c;}" print ".cat4 {background-color: #fb9a99;}" print ".cat5 {background-color: #e31a1c;}" print ".cat6 {background-color: #fdbf6f;}" print ".cat7 {background-color: #ff7f00;}" print ".cat8 {background-color: #cab2d6;}" print ".name {position: absolute; right: 10px;}" print "#scores p {margin: 0; padding: 0; border: thin solid #222; opacity: 0.92;}" print "#scores p:hover {border: thin solid yellow;}" print "</style>" print "</head><body>" print "<div id=\"scores\">" } function foot() { print " </div>" print " <pre style=\"position: fixed; bottom: 0; left: 20%; font-size: 250%;" print " opacity: 0.8; background-color: black\">" print "Project 2<br>" print "<p>A CTF for people with limited time/patience/self-confidence.</p>" print "<p>Plug in ethernet at this table, download puzzles, go think.</p>" print "<p>http://10.0.0.2/</p>" print "<p>Use the terminal to claim points when you've figured something out.</p>" print " </pre>" print " </body>" print "</body></html>" } BEGIN { base = ENVIRON["CTF_BASE"] if (! base) { base = "/var/lib/ctf" } head() } # MAINLOOP { time = $1 hash = $2 cat = $3 points = int($4) # Build a list of team names if (! (hash in team_names)) { fn = sprintf("%s/teams/names/%s", base, hash) getline team_names[hash] < fn close(fn) } # Total points possible so far in this category if (! ((cat, points) in cat_pointval)) { cat_total[cat] += points cat_pointval[cat, points] = 1 } # Enumerate categories if (! (cat in seen_cats)) { seen_cats[cat] = 1 categories[ncats++] = cat } # Points this team has in this category cat_points[hash, cat] += points } END { # Adjust per-category points to a per-category percentage complete for (hash in team_names) { for (cat in cat_total) { cat_score[hash, cat] = cat_points[hash, cat] / cat_total[cat] total_score[hash] += cat_score[hash, cat] } scores[nteams++] = total_score[hash] if (total_score[hash] > max_score) { max_score = total_score[hash] } } # Sort scores qsort(scores, 0, nteams-1) print "<p>" for (ncat = 0; ncat < ncats; ncat += 1) { printf("<span class=\"cat%d\">%s</span>\n", ncat, categories[ncat]); } print "</p>" for (i = nteams-1; i >= 0; i -= 1) { score = scores[i]; if (score == scores[i-1]) continue; # Skip duplicates for (hash in team_names) { if (total_score[hash] != score) { continue; } name = escape(team_names[hash]) print "<p>" printf("<span class=\"name\">%s</span>\n", name) for (ncat = 0; ncat < ncats; ncat += 1) { cat = categories[ncat]; points = cat_points[hash, cat]; if (cat_points[hash, cat] > 0) { width = cat_score[hash, cat] / max_score * 90 printf("<!-- %s %s %s -->", cat, points, name) printf("<span class=\"cat%d\" style=\"width: %.2f%%;\">%d</span>", ncat, width, cat_points[hash, cat]) } } print "</p>" } } foot() }