Devel server now serves static puzzles, yay

This commit is contained in:
Neale Pickett 2016-10-16 20:32:00 -06:00
parent 6f5569e9a1
commit 240087205f
3 changed files with 114 additions and 11 deletions

View File

@ -5,6 +5,7 @@ import http.server
import mistune import mistune
import os import os
import pathlib import pathlib
import puzzles
import socketserver import socketserver
HTTPStatus = http.server.HTTPStatus HTTPStatus = http.server.HTTPStatus
@ -17,7 +18,7 @@ def page(title, body):
<link rel="stylesheet" href="/files/www/res/style.css"> <link rel="stylesheet" href="/files/www/res/style.css">
</head> </head>
<body> <body>
<div id="body" class="terminal"> <div id="preview" class="terminal">
{} {}
</div> </div>
</body> </body>
@ -72,24 +73,37 @@ you are a fool.
def serve_puzzles(self): def serve_puzzles(self):
body = [] body = []
parts = self.path.split("/") path = self.path.rstrip('/')
parts = path.split("/")
if len(parts) < 3: if len(parts) < 3:
# List all categories # List all categories
body.append("# Puzzle Categories") body.append("# Puzzle Categories")
for i in glob.glob(os.path.join("puzzles", "*", "")): for i in glob.glob(os.path.join("puzzles", "*", "")):
body.append("* [{}](/{})".format(i, i)) body.append("* [{}](/{})".format(i, i))
elif len(parts) == 4: elif len(parts) == 3:
# List all point values in a category # List all point values in a category
body.append("# Puzzles in category `{}`".format(parts[2])) body.append("# Puzzles in category `{}`".format(parts[2]))
puzzles = [] puzz = []
for i in glob.glob(os.path.join("puzzles", parts[2], "*", "")): for i in glob.glob(os.path.join("puzzles", parts[2], "*.moth")):
pparts = os.path.split(i[:-1]) base = os.path.basename(i)
points = int(pparts[-1]) root, _ = os.path.splitext(base)
puzzles.append(points) points = int(root)
for puzzle in sorted(puzzles): puzz.append(points)
for puzzle in sorted(puzz):
body.append("* [puzzles/{cat}/{points}](/puzzles/{cat}/{points}/)".format(cat=parts[2], points=puzzle)) body.append("* [puzzles/{cat}/{points}](/puzzles/{cat}/{points}/)".format(cat=parts[2], points=puzzle))
elif len(parts) == 5: elif len(parts) == 4:
body.append("# {} puzzle {}".format(parts[2], parts[3])) body.append("# {} puzzle {}".format(parts[2], parts[3]))
with open("puzzles/{}/{}.moth".format(parts[2], parts[3])) as f:
p = puzzles.Puzzle(f)
body.append("* Author: `{}`".format(p.fields.get("author")))
body.append("* Summary: `{}`".format(p.fields.get("summary")))
body.append('')
body.append("## Body")
body.append(p.body)
body.append("## Answers:")
for a in p.answers:
body.append("* `{}`".format(a))
body.append("")
else: else:
body.append("# Not Implemented Yet") body.append("# Not Implemented Yet")
self.serve_md('\n'.join(body)) self.serve_md('\n'.join(body))

87
puzzles.py Normal file
View File

@ -0,0 +1,87 @@
#!/usr/bin/python3
import hmac
import base64
import argparse
import glob
import json
import os
import mistune
import random
messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
def djb2hash(buf):
h = 5381
for c in buf:
h = ((h * 33) + c) & 0xffffffff
return h
class Puzzle:
def __init__(self, stream):
self.message = bytes(random.choice(messageChars) for i in range(20))
self.fields = {}
self.answers = []
self.hashes = []
body = []
header = True
for line in stream:
if header:
line = line.strip()
if not line.strip():
header = False
continue
key, val = line.split(':', 1)
key = key.lower()
val = val.strip()
self._add_field(key, val)
else:
body.append(line)
self.body = ''.join(body)
def _add_field(self, key, val):
if key == 'answer':
h = djb2hash(val.encode('utf8'))
self.answers.append(val)
self.hashes.append(h)
else:
self.fields[key] = val
def htmlify(self):
return mistune.markdown(self.body)
def publish(self):
obj = {
'author': self.fields['author'],
'hashes': self.hashes,
'body': self.htmlify(),
}
return obj
def secrets(self):
obj = {
'answers': self.answers,
'summary': self.fields['summary'],
}
return obj
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Build a puzzle category')
parser.add_argument('puzzledir', nargs='+', help='Directory of puzzle source')
args = parser.parse_args()
for puzzledir in args.puzzledir:
puzzles = {}
secrets = {}
for puzzlePath in glob.glob(os.path.join(puzzledir, "*.moth")):
filename = os.path.basename(puzzlePath)
points, ext = os.path.splitext(filename)
points = int(points)
puzzle = Puzzle(open(puzzlePath))
puzzles[points] = puzzle
for points in sorted(puzzles):
puzzle = puzzles[points]
print(puzzle.secrets())

View File

@ -55,7 +55,9 @@ pre, tt {
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
} }
#body { #preview {
background-image: url(preview.png);
background-size: contain;
max-width: 40em; max-width: 40em;
display: block; display: block;
margin: 1% auto; margin: 1% auto;