diff --git a/example-puzzles/example/1/puzzle.moth b/example-puzzles/example/1/puzzle.moth new file mode 100644 index 0000000..294c99c --- /dev/null +++ b/example-puzzles/example/1/puzzle.moth @@ -0,0 +1,45 @@ +Author: neale +Summary: static puzzles +Answer: puzzle.moth + +Puzzle categories are laid out on the filesystem: + + example/ + ├─1 + │ └─puzzle.moth + ├─2 + │ ├─puzzle.moth + │ └─salad.jpg + ├─3 + │ └─puzzle.py + ├─10 + │ └─puzzle.py + └─100 + └─puzzle.moth + +In this example, +there are puzzles with point values 1, 2, 3, 10, and 100. + +Puzzles 1, 2, and 100 are "static" puzzles: +their content was written by hand. + +Puzzles 3 and 10 are "dynamic" puzzles: +they are generated from a Python module. + +To create a static puzzle, all you must have is a +`puzzle.moth` file in the puzzle's directory. +This file is in the following format: + + Author: [name of the person who wrote this puzzle] + Summary: [brief description of the puzzle] + Answer: [answer to this puzzle] + Answer: [second acceptable answer to this puzzle] + + This is the puzzle body. + It is Markdown formatted: + you can read more about Markdown on the Internet. + +To move to the next puzzle in a category, +someone on some team must provide an answer to the highest-point puzzle in that category. + +The answer to this puzzle is the name of the file required to make a static puzzle. diff --git a/example-puzzles/example/2/puzzle.moth b/example-puzzles/example/2/puzzle.moth new file mode 100644 index 0000000..61b63ec --- /dev/null +++ b/example-puzzles/example/2/puzzle.moth @@ -0,0 +1,14 @@ +Author: neale +Summary: Static puzzle resource files +Answer: salad + +You can include additional resources in a static puzzle, +by just dropping them in the directory. + +You can refer to them directly in your Markdown, +or use them however else you see fit. +They will appear in the same directory on the web server once the exercise is running. + +![Leafy Green Deliciousness](salad.jpg) + +The answer for this page is what is featured in the photograph. diff --git a/example-puzzles/example/2/salad.jpg b/example-puzzles/example/2/salad.jpg new file mode 100644 index 0000000..cf2239e Binary files /dev/null and b/example-puzzles/example/2/salad.jpg differ diff --git a/example-puzzles/example/3/puzzle.py b/example-puzzles/example/3/puzzle.py new file mode 100644 index 0000000..39636f7 --- /dev/null +++ b/example-puzzles/example/3/puzzle.py @@ -0,0 +1,20 @@ +#!/usr/bin/python3 + +def make(puzzle): + puzzle.author = 'neale' + puzzle.summary = 'dynamic puzzles' + answer = puzzle.randword() + puzzle.answers.append(answer) + + puzzle.body.write("To generate a dynamic puzzle, you need to write a Python module.\n") + puzzle.body.write("\n") + puzzle.body.write("The passed-in puzzle object provides some handy methods.\n") + puzzle.body.write("In particular, please use the `puzzle.rand` object to guarantee that rebuilding a category\n") + puzzle.body.write("won't change puzzles and answers.\n") + puzzle.body.write("(Participants don't like it when puzzles and answers change.)\n") + puzzle.body.write("\n") + + number = puzzle.rand.randint(20, 500) + puzzle.log("One is the loneliest number, but {} is the saddest number.".format(number)) + + puzzle.body.write("The answer for this page is {}.\n".format(answer)) diff --git a/src/www/res/Dosis-Bold.ttf b/src/www/res/Dosis-Bold.ttf deleted file mode 100644 index d5e938e..0000000 Binary files a/src/www/res/Dosis-Bold.ttf and /dev/null differ diff --git a/src/www/res/Dosis-ExtraBold.ttf b/src/www/res/Dosis-ExtraBold.ttf deleted file mode 100644 index 2144a25..0000000 Binary files a/src/www/res/Dosis-ExtraBold.ttf and /dev/null differ diff --git a/src/www/res/Dosis-ExtraLight.ttf b/src/www/res/Dosis-ExtraLight.ttf deleted file mode 100644 index 2e3bf1b..0000000 Binary files a/src/www/res/Dosis-ExtraLight.ttf and /dev/null differ diff --git a/src/www/res/Dosis-Light.ttf b/src/www/res/Dosis-Light.ttf deleted file mode 100644 index a22e7d7..0000000 Binary files a/src/www/res/Dosis-Light.ttf and /dev/null differ diff --git a/src/www/res/Dosis-Medium.ttf b/src/www/res/Dosis-Medium.ttf deleted file mode 100644 index 3254ef5..0000000 Binary files a/src/www/res/Dosis-Medium.ttf and /dev/null differ diff --git a/src/www/res/Dosis-Regular.ttf b/src/www/res/Dosis-Regular.ttf deleted file mode 100644 index 4b20862..0000000 Binary files a/src/www/res/Dosis-Regular.ttf and /dev/null differ diff --git a/src/www/res/Dosis-SemiBold.ttf b/src/www/res/Dosis-SemiBold.ttf deleted file mode 100644 index 5f48caf..0000000 Binary files a/src/www/res/Dosis-SemiBold.ttf and /dev/null differ diff --git a/src/www/res/Dosis.css b/src/www/res/Dosis.css deleted file mode 100644 index 2945a7f..0000000 --- a/src/www/res/Dosis.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - font-family: 'Dosis'; - font-style: normal; - font-weight: 400; - src: local('Dosis Regular'), local('Dosis-Regular'), url(Dosis-Regular.ttf) format('truetype'); -} diff --git a/src/www/res/Inconsolata-Bold.ttf b/src/www/res/Inconsolata-Bold.ttf new file mode 100644 index 0000000..035d579 Binary files /dev/null and b/src/www/res/Inconsolata-Bold.ttf differ diff --git a/src/www/res/Inconsolata-Regular.ttf b/src/www/res/Inconsolata-Regular.ttf new file mode 100644 index 0000000..bbc9647 Binary files /dev/null and b/src/www/res/Inconsolata-Regular.ttf differ diff --git a/src/www/res/style.css b/src/www/res/style.css index f6802c1..c8ab4de 100644 --- a/src/www/res/style.css +++ b/src/www/res/style.css @@ -17,10 +17,10 @@ src: local('Lato Italic'), local('Lato-Italic'), url(Lato-Italic.ttf) format('truetype'); } @font-face { - font-family: 'Dosis'; + font-family: 'Inconsolata'; font-style: normal; font-weight: 400; - src: local('Dosis Regular'), local('Dosis-Regular'), url(Dosis-Regular.ttf) format('truetype'); + src: local('Inconsolata Regular'), local('Inconsolata-Regular'), url(Inconsolata-Regular.ttf) format('truetype'); } @@ -38,7 +38,7 @@ body { } pre, tt { - font-family: 'Dosis', monospace; + font-family: Inconsolata, monospace; background-color: rgba(0, 0, 0, 0.3); } diff --git a/tools/devel-server.py b/tools/devel-server.py index 7332ed1..5c7d879 100755 --- a/tools/devel-server.py +++ b/tools/devel-server.py @@ -21,6 +21,8 @@ except ImportError: NOT_FOUND = 404 INTERNAL_SERVER_ERROR = 500 +sys.dont_write_bytecode = True + # XXX: This will eventually cause a problem. Do something more clever here. seed = 1 @@ -48,7 +50,7 @@ def mdpage(body): title = "Result" title = title.lstrip("#") title = title.strip() - return page(title, mistune.markdown(body)) + return page(title, mistune.markdown(body, escape=False)) class ThreadingServer(socketserver.ThreadingMixIn, http.server.HTTPServer): @@ -162,11 +164,12 @@ you are a fool. body.write("") body.write("

Author

{}

".format(puzzle.author)) body.write("

Summary

{}

".format(puzzle.summary)) - body.write("

Debug Log

") - body.write('") + if puzzle.logs: + body.write("

Debug Log

") + body.write('") elif len(parts) == 5: # Serve up a puzzle file try: diff --git a/tools/moth.py b/tools/moth.py index 25ee393..7ba1a23 100644 --- a/tools/moth.py +++ b/tools/moth.py @@ -146,6 +146,11 @@ class Puzzle: name = self.random_hash() self.files[name] = PuzzleFile(stream, name, visible) + def randword(self): + """Return a randomly-chosen word""" + + return self.rand.choice(ANSWER_WORDS) + def make_answer(self, word_count, sep=' '): """Generate and return a new answer. It's automatically added to the puzzle answer list. :param int word_count: The number of words to include in the answer. @@ -153,7 +158,8 @@ class Puzzle: :returns: The answer string """ - answer = sep.join(self.rand.sample(ANSWER_WORDS, word_count)) + words = [self.randword() for i in range(word_count)] + answer = sep.join(words) self.answers.append(answer) return answer @@ -162,7 +168,7 @@ class Puzzle: def html_body(self): """Format and return the markdown for the puzzle body.""" - return mistune.markdown(self.get_body()) + return mistune.markdown(self.get_body(), escape=False) def hashes(self): "Return a list of answer hashes"