mirror of https://github.com/dirtbags/moth.git
JSON points generator
This commit is contained in:
parent
76f9ed4318
commit
a86f5bfd8e
|
@ -0,0 +1,167 @@
|
||||||
|
#! /bin/sh -e
|
||||||
|
|
||||||
|
indir=$1; shift
|
||||||
|
|
||||||
|
if ! [ -d $indir ]; then
|
||||||
|
echo "Usage: $0 PUZZLEDIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo "$@" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
escape () {
|
||||||
|
sed 's/&/\&/g;s/</\</g;s/>/\>/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
template () {
|
||||||
|
cat="$1"; shift
|
||||||
|
points="$1"; shift
|
||||||
|
author=$(echo $1 | escape); shift
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>$cat $points</title>
|
||||||
|
<link rel="stylesheet" href="/css/style.css" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>$cat for $points points</h1>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "<section id=\"readme\">"
|
||||||
|
cat
|
||||||
|
echo "</section>"
|
||||||
|
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
echo "<section id=\"files\">"
|
||||||
|
echo "<h2>Associated files:</h2>"
|
||||||
|
echo "<ul>"
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
fn="$1"; shift
|
||||||
|
efn="$(echo $fn | escape)"
|
||||||
|
echo "<li><a href=\"$fn\">$efn</a></li>"
|
||||||
|
done
|
||||||
|
echo "</ul>"
|
||||||
|
echo "</section>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
<section id="form">
|
||||||
|
<form id="puzzler" action="/puzzler.cgi" method="post" accept-charset="utf-8">
|
||||||
|
<input type="hidden" name="c" value="$cat">
|
||||||
|
<input type="hidden" name="p" value="$points">
|
||||||
|
Team hash:<input name="t" size="8">
|
||||||
|
Answer:<input name="a" size="20">
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<address>Puzzle by <span class="author" data-handle="$author">$author</span></address>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
cat=$(basename $indir)
|
||||||
|
outdir=$(dirname $0)/puzzles/$cat
|
||||||
|
uanswers=$outdir/answers.unsorted
|
||||||
|
usummary=$outdir/summary.unsorted
|
||||||
|
umap=$outdir/map.unsorted
|
||||||
|
|
||||||
|
if ! [ -r $outdir/mkpuzzles.salt ]; then
|
||||||
|
dd if=/dev/urandom bs=1 count=16 2>/dev/null | md5sum | cut -d\ -f1 > $outdir/salt
|
||||||
|
fi
|
||||||
|
read salt < $outdir/salt
|
||||||
|
|
||||||
|
> $uanswers
|
||||||
|
rm -f $usummary
|
||||||
|
|
||||||
|
for dn in $indir/[0-9]*; do
|
||||||
|
[ -d $dn ] || continue
|
||||||
|
points=$(basename $dn)
|
||||||
|
|
||||||
|
echo $dn
|
||||||
|
|
||||||
|
odn=$(printf "%s/%s/%s" "$salt" "$cat" "$points" | md5sum | sed 's/\(....\)/\1./g' | cut -b 1-19)
|
||||||
|
tgt=$outdir/puzzles/$odn
|
||||||
|
mkdir -p $tgt
|
||||||
|
#touch $tgt/index.html
|
||||||
|
|
||||||
|
if [ -f $dn/Makefile ]; then
|
||||||
|
# If there's a Makefile, run make
|
||||||
|
make DESTDIR=$(pwd)/$tgt -C $dn || exit 1
|
||||||
|
files=$(ls -1 $tgt | grep -v index.html || true)
|
||||||
|
elif [ -f $dn/00manifest.txt ]; then
|
||||||
|
# If there's a manifest, use that
|
||||||
|
files=
|
||||||
|
while read fn; do
|
||||||
|
ln -f $dn/$fn $tgt/
|
||||||
|
case $fn in
|
||||||
|
,*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
files="$files $fn"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < $dn/00manifest.txt
|
||||||
|
else
|
||||||
|
# Otherwise, look for special files and copy the rest
|
||||||
|
files=
|
||||||
|
for fn in $dn/*; do
|
||||||
|
case $(basename $fn) in
|
||||||
|
00*)
|
||||||
|
# Handle meta-information later
|
||||||
|
;;
|
||||||
|
*~|"#"*)
|
||||||
|
# Don't copy temporary or backup files
|
||||||
|
;;
|
||||||
|
,*)
|
||||||
|
# Copy but don't list
|
||||||
|
ln -f $fn $tgt/
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
#ext=$(echo $fn | sed -ne 's/.*\././p')
|
||||||
|
cfn=$(md5sum $fn | cut -b -8)$ext
|
||||||
|
ln -f $fn $tgt/$cfn
|
||||||
|
files="$files $cfn"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append answers
|
||||||
|
if [ -f $dn/00answer.txt ]; then
|
||||||
|
awk -v P=$points '/./ { printf("%d %s\n", P, $0); }' < $dn/00answer.txt >> $uanswers
|
||||||
|
else
|
||||||
|
die "$dn/00answer.txt: No such file or directory"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append summary
|
||||||
|
if [ -f $dn/00summary.txt ]; then
|
||||||
|
awk -v P=$points '/./ { printf("%d %s\n", P, $0); }' < $dn/00summary.txt >> $usummary
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read author
|
||||||
|
if [ -f $dn/00author.txt ]; then
|
||||||
|
author=$(cat $dn/00author.txt)
|
||||||
|
else
|
||||||
|
die "$dn/00author.txt does not exist."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate index now that we have a list of files
|
||||||
|
if [ -f $dn/00index.mdwn ]; then
|
||||||
|
markdown --html4tags $dn/00index.mdwn
|
||||||
|
fi | template $cat $points "$author" $files > $tgt/index.html
|
||||||
|
|
||||||
|
# Write to map
|
||||||
|
printf "%d %s\n" $points $odn >> $umap
|
||||||
|
done
|
||||||
|
|
||||||
|
sort -n $umap > $outdir/map.txt
|
||||||
|
sort -n $uanswers > $outdir/answers.txt
|
||||||
|
[ -f $usummary ] && sort -ns $usummary > $outdir/summary.txt
|
||||||
|
rm -f $uanswers $usummary $umap
|
|
@ -0,0 +1,58 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
echo "Figuring out web user..."
|
||||||
|
for www in www-data http _; do
|
||||||
|
id $www && break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $www = _ ]; then
|
||||||
|
echo "Unable to determine httpd user on this system. Dying."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
initialize () {
|
||||||
|
for i in points.new points.tmp teams; do
|
||||||
|
mkdir -p state/$i
|
||||||
|
setfacl -m ${www}:rwx state/$i
|
||||||
|
done
|
||||||
|
|
||||||
|
>> state/points.log
|
||||||
|
hd < /dev/urandom | awk '{print $3 $4 $5 $6;}' | head -n 100 > state/teams/assigned.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
once () {
|
||||||
|
if [ -f disabled ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -d state ]; then
|
||||||
|
initialize $1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect new points
|
||||||
|
find state/points.new -type f | while read fn; do
|
||||||
|
cat $fn >> state/points.log
|
||||||
|
rm $fn
|
||||||
|
done
|
||||||
|
|
||||||
|
# Generate new puzzles.html
|
||||||
|
if $KOTH_BASE/puzzles.cgi > www/puzzles.new; then
|
||||||
|
mv www/puzzles.new www/puzzles.html
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate new points.json
|
||||||
|
if $KOTH_BASE/points > www/points.new; then
|
||||||
|
mv www/points.new www/points.json
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cd $(basename $0)
|
||||||
|
KOTH_BASE=$(pwd)
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
for dn in $KOTH_BASE/*; do
|
||||||
|
cd $dn
|
||||||
|
once
|
||||||
|
done
|
||||||
|
sleep 5
|
||||||
|
done
|
|
@ -0,0 +1,45 @@
|
||||||
|
#! /usr/bin/awk -f
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
nteams = 0;
|
||||||
|
print "{";
|
||||||
|
print " \"points\": [";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ts = $1;
|
||||||
|
hash = $2;
|
||||||
|
cat = $3;
|
||||||
|
points = $4;
|
||||||
|
|
||||||
|
teamno = teams[hash];
|
||||||
|
if (! teamno) {
|
||||||
|
teamno = ++nteams;
|
||||||
|
teams[hash] = teamno;
|
||||||
|
|
||||||
|
getline teamnames[teamno] < ("state/teams/" hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NR > 1) {
|
||||||
|
# JSON sucks.
|
||||||
|
print ",";
|
||||||
|
}
|
||||||
|
printf("[%d, \"%d\", \"%s\", %d]", ts, teamno, cat, points);
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "";
|
||||||
|
print " ],";
|
||||||
|
print " \"teams\": {";
|
||||||
|
|
||||||
|
for (i in teamnames) {
|
||||||
|
if (i > 1) {
|
||||||
|
print ",";
|
||||||
|
}
|
||||||
|
printf("\"%d\": \"%s\"", i, teamnames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
print "";
|
||||||
|
print " }";
|
||||||
|
print "}";
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ pre {
|
||||||
font-family: "Ubuntu Mono", monospace;
|
font-family: "Ubuntu Mono", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt, code, kbd, samp {
|
code, kbd, samp {
|
||||||
font-family: "Ubuntu Mono", monospace;
|
font-family: "Ubuntu Mono", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +104,26 @@ hr {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**** Section ****/
|
||||||
|
|
||||||
|
section, nav {
|
||||||
|
color: #35170c;
|
||||||
|
max-width: 35em;
|
||||||
|
border-radius: 0.6em;
|
||||||
|
margin: 1em auto;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
background: #e1c3b8;
|
||||||
|
}
|
||||||
|
|
||||||
/*** navigation bar ***/
|
/*** navigation bar ***/
|
||||||
|
|
||||||
|
nav {
|
||||||
|
background: #b9e0ef;
|
||||||
|
}
|
||||||
|
|
||||||
nav h2 {
|
nav h2 {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +131,7 @@ nav h2 {
|
||||||
nav ul {
|
nav ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav li {
|
nav li {
|
||||||
|
@ -128,15 +147,6 @@ nav li + li:before {
|
||||||
content: " | ";
|
content: " | ";
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
|
||||||
background: #e1c3b8;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
color: #35170c;
|
|
||||||
max-width: 35em;
|
|
||||||
border-radius: 0.6em;
|
|
||||||
margin: 1em auto;
|
|
||||||
padding: 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Terminal ****/
|
/**** Terminal ****/
|
||||||
|
|
||||||
|
|
|
@ -4,24 +4,44 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Welcome</title>
|
<title>Welcome</title>
|
||||||
<link rel="stylesheet" href="css/style.css" type="text/css">
|
<link rel="stylesheet" href="css/style.css" type="text/css">
|
||||||
<script src="js/terminal.js" async></script>
|
|
||||||
<script>
|
|
||||||
function init() {
|
|
||||||
output("Hello world.");
|
|
||||||
output("This is the new Tracer FIRE terminal.")
|
|
||||||
output("This is going to be your primary interface to Tracer FIRE 6 and 7. All of your interactions with the system will go through this interface, which is sort of like the old school terminal we had previously, but not exactly? I guess it's like steampunk or weird western, but for the 1980s.")
|
|
||||||
output("I sincerely hope you like it. Personally, I am pretty psyched about how it looks. If I could go back and show it to myself when I was 13 I would have been bowled over.")
|
|
||||||
output(" - Neale Pickett")
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("load", init);
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Tracer FIRE 6E</h1>
|
<h1>Tracer FIRE 6E</h1>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
Here's some stuff.
|
<p>
|
||||||
|
Here is what you need to do:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<a href="register.html">Register</a> your team.
|
||||||
|
This only needs to happen once per team,
|
||||||
|
so if somebody else on your team has already done it,
|
||||||
|
you don't need to.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Get an <a href="puzzles.html">overview of puzzles</a>,
|
||||||
|
and start working on something.
|
||||||
|
The list of open puzzles changes over time,
|
||||||
|
you need to reload the page to get the current version!
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Check the <a href="scoreboard.html">scoreboard</a>
|
||||||
|
in another tab,
|
||||||
|
to see how your team is doing.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li><a href="register.html">Register</a></li>
|
||||||
|
<li><a href="puzzles.html">Puzzles</a></li>
|
||||||
|
<li><a href="scoreboard.html">Scoreboard</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
5726
html/points.json
5726
html/points.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue