From 1c1b1ab22bee5750084eb364bf2999ccc83eacbd Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Wed, 6 Jun 2012 14:55:09 -0600 Subject: [PATCH] work on p2 scoreboard --- packages/p2/bin/scoreboard | 179 ++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 73 deletions(-) diff --git a/packages/p2/bin/scoreboard b/packages/p2/bin/scoreboard index 613727d..fe873e0 100755 --- a/packages/p2/bin/scoreboard +++ b/packages/p2/bin/scoreboard @@ -1,84 +1,117 @@ -#! /bin/sh +#! /bin/awk -f -# Calculate total points awarded so far -total=0 -for i in ${1:-answers}/*; do - pts=$(awk '{print $2; exit;}' $i) - total=$(expr $total + $pts) -done +## +## +## I'm not super happy with how this code looks. Rest assured, though, +## the C version would look far, far worse. +## +## -render () { - name=$1 - cat=$2 - score=$3 - width=$(awk "BEGIN{print 100 * $score / $total;}") - printf '%d' \ - $cat $width $name $cat $score $name $cat $score $score +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 } -scores () { - cat= - score=0 - while read c p; do - if [ "$cat" != "$c" ] && [ $score -gt 0 ]; then - render $1 $cat $score - score=0 - fi - cat=$c - score=$(expr $score + $p) - done - if [ $score -gt 0 ]; then - render $1 $cat $score - fi +function escape(s) { + gsub("&", "&", s) + gsub("<", "<", s) + gsub(">", ">", s) + return s } +BEGIN { + base = ENVIRON["CTF_BASE"] + if (! base) { + base = "/var/lib/ctf" + } -cat < -Project 2 Scoreboard - - - -

-EOF + # Only display two decimal places + CONVFMT = "%.2f" + + # New point at least every 2.5 minutes + interval = 150 + tslen = 0 -for dn in /opt/*/answers.txt; do - c=$(echo $dn | cut -d/ -f2) - printf '%s\n' $c $c -done + nteams = 0; +} -cat < -

-EOF +# MAINLOOP +{ + time = $1 + hash = $2 + cat = $3 + points = int($4) -for d in users/*; do - awk -v d=$d '{s+=$2;} END{print s " " d;}' $d/* 2>/dev/null -done | sort -nr | while read s d; do - user=${d##*/} - echo '

' - printf '%s\n' $user - sort $d/* 2>/dev/null | scores $user - echo - echo '

' -done + # Build a list of team names + if (! (hash in team_names)) { + fn = sprintf("%s/teams/names/%s", base, hash) + getline team_names[hash] < fn + print (hash, team_names[hash]) + close(fn) + } -cat < -EOF + # 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] + } + + # Sort scores + qsort(scores, 0, nteams-1) + + 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 = team_names[hash] + printf("%s\n", name) + + for (ncat = 0; ncat < ncats; ncat += 1) { + cat = categories[ncat]; + points = cat_points[hash, cat]; + + if (cat_points[hash, cat] > 0) { + printf("", cat, points, escape(name)) + printf(" %d\n", + ncat, cat_score[hash, cat] * 100, cat_points[hash, cat]) + } + } + } + } +}