mirror of https://github.com/dirtbags/moth.git
work on p2 scoreboard
This commit is contained in:
parent
fa0324dbf8
commit
1c1b1ab22b
|
@ -1,84 +1,117 @@
|
||||||
#! /bin/sh
|
#! /bin/awk -f
|
||||||
|
|
||||||
# Calculate total points awarded so far
|
##
|
||||||
total=0
|
##
|
||||||
for i in ${1:-answers}/*; do
|
## I'm not super happy with how this code looks. Rest assured, though,
|
||||||
pts=$(awk '{print $2; exit;}' $i)
|
## the C version would look far, far worse.
|
||||||
total=$(expr $total + $pts)
|
##
|
||||||
done
|
##
|
||||||
|
|
||||||
render () {
|
function qsort(A, left, right, i, last) {
|
||||||
name=$1
|
if (left >= right)
|
||||||
cat=$2
|
return
|
||||||
score=$3
|
swap(A, left, left+int((right-left+1)*rand()))
|
||||||
width=$(awk "BEGIN{print 100 * $score / $total;}")
|
last = left
|
||||||
printf '<span class="%s" style="width: %0.2f%%" title="%s:%s:%d"><!--\n:%s %s %d\n-->%d</span>' \
|
for (i = left+1; i <= right; i++)
|
||||||
$cat $width $name $cat $score $name $cat $score $score
|
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 () {
|
function escape(s) {
|
||||||
cat=
|
gsub("&", "&", s)
|
||||||
score=0
|
gsub("<", "<", s)
|
||||||
while read c p; do
|
gsub(">", ">", s)
|
||||||
if [ "$cat" != "$c" ] && [ $score -gt 0 ]; then
|
return s
|
||||||
render $1 $cat $score
|
|
||||||
score=0
|
|
||||||
fi
|
|
||||||
cat=$c
|
|
||||||
score=$(expr $score + $p)
|
|
||||||
done
|
|
||||||
if [ $score -gt 0 ]; then
|
|
||||||
render $1 $cat $score
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
base = ENVIRON["CTF_BASE"]
|
||||||
|
if (! base) {
|
||||||
|
base = "/var/lib/ctf"
|
||||||
|
}
|
||||||
|
|
||||||
cat <<EOF
|
# Only display two decimal places
|
||||||
<!DOCTYPE html>
|
CONVFMT = "%.2f"
|
||||||
<html><head><title>Project 2 Scoreboard</title>
|
|
||||||
<meta http-equiv="refresh" content="60">
|
|
||||||
<style>
|
|
||||||
html {background: black url("p2inv.png") no-repeat top center; background-size: contain; min-height: 100%; color: white;}
|
|
||||||
body {background: black; opacity: 0.8; margin: 0;}
|
|
||||||
p {margin: 0;}
|
|
||||||
span {display: inline-block; margin: 0; border: 0;}
|
|
||||||
.c0 {background-color: #842;}
|
|
||||||
.c1 {background-color: #028;}
|
|
||||||
.c2 {background-color: #802;}
|
|
||||||
.c3 {background-color: #640;}
|
|
||||||
.c4 {background-color: #486;}
|
|
||||||
.c5 {background-color: #682;}
|
|
||||||
.c6 {background-color: #408;}
|
|
||||||
.c7 {background-color: #624;}
|
|
||||||
.name {position: absolute; right: 10px;}
|
|
||||||
#scores p {margin: 0; padding: 0; border: none; border-top: thin solid #222; clear: both;}
|
|
||||||
#scores p:hover {background-color: #222;}
|
|
||||||
</style>
|
|
||||||
</head><body>
|
|
||||||
<p>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
for dn in /opt/*/answers.txt; do
|
# New point at least every 2.5 minutes
|
||||||
c=$(echo $dn | cut -d/ -f2)
|
interval = 150
|
||||||
printf '<span class="%s">%s</span>\n' $c $c
|
tslen = 0
|
||||||
done
|
|
||||||
|
|
||||||
cat <<EOF
|
nteams = 0;
|
||||||
</p>
|
}
|
||||||
<div id="scores">
|
|
||||||
EOF
|
|
||||||
|
|
||||||
for d in users/*; do
|
# MAINLOOP
|
||||||
awk -v d=$d '{s+=$2;} END{print s " " d;}' $d/* 2>/dev/null
|
{
|
||||||
done | sort -nr | while read s d; do
|
time = $1
|
||||||
user=${d##*/}
|
hash = $2
|
||||||
echo '<p>'
|
cat = $3
|
||||||
printf '<span class="name">%s</span>\n' $user
|
points = int($4)
|
||||||
sort $d/* 2>/dev/null | scores $user
|
|
||||||
echo
|
|
||||||
echo '</p>'
|
|
||||||
done
|
|
||||||
|
|
||||||
cat <<EOF
|
# Build a list of team names
|
||||||
</div></body></html>
|
if (! (hash in team_names)) {
|
||||||
EOF
|
fn = sprintf("%s/teams/names/%s", base, hash)
|
||||||
|
getline team_names[hash] < fn
|
||||||
|
print (hash, team_names[hash])
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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("<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) {
|
||||||
|
printf("<!-- %s %s %s -->", cat, points, escape(name))
|
||||||
|
printf(" <span class=\"cat%d\" style=\"width: %.2f%%;\">%d</span>\n",
|
||||||
|
ncat, cat_score[hash, cat] * 100, cat_points[hash, cat])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue