puzzle.json: move Pre and Post out to top-level

This commit is contained in:
Neale Pickett 2021-02-24 16:34:35 -07:00
parent 2e0dfb601a
commit 1fffeb0060
19 changed files with 119 additions and 146 deletions

View File

@ -15,13 +15,12 @@ import (
var testMothYaml = []byte(`---
answers:
- YAML answer
pre:
authors:
- Arthur
- Buster
- DW
attachments:
- filename: moo.txt
authors:
- Arthur
- Buster
- DW
attachments:
- filename: moo.txt
---
YAML body
`)
@ -189,4 +188,4 @@ func TestFilesystem(t *testing.T) {
if !strings.Contains(stdout.String(), "Moo.") {
t.Error("Wrong file pulled", stdout.String())
}
}
}

View File

@ -11,10 +11,8 @@ case $1:$2 in
cat <<EOT
{
"Answers": ["$answer"],
"Pre": {
"Authors": ["neale"],
"Body": "I am a generated puzzle."
}
"Authors": ["neale"],
"Body": "I am a generated puzzle."
}
EOT
;;

View File

@ -18,10 +18,8 @@ EOT
cat <<EOT
{
"Answers": ["answer1.0"],
"Pre": {
"Authors": ["author1.0"],
"Body": "<h1>moo.</h1>"
}
"Authors": ["author1.0"],
"Body": "<h1>moo.</h1>"
}
EOT
;;

View File

@ -1,7 +1,6 @@
---
pre:
authors:
- neale
authors:
- neale
debug:
summary: static puzzles
answers:

View File

@ -1,7 +1,6 @@
---
pre:
authors:
- neale
authors:
- neale
debug:
summary: Making excellent puzzles
answers:

View File

@ -1,11 +1,10 @@
---
pre:
authors:
- neale
attachments:
- filename: salad.jpg
- filename: s2.jpg
filesystempath: salad2.jpg
authors:
- neale
attachments:
- filename: salad.jpg
- filename: s2.jpg
filesystempath: salad2.jpg
debug:
summary: Static puzzle resource files
answers:

View File

@ -15,15 +15,13 @@ answer = ' '.join(random.sample(words, 4))
def puzzle():
number = random.randint(20, 500)
obj = {
"Pre": {
"Authors": ["neale"],
"Body": (
"<p>Dynamic puzzles are provided with a JSON-generating <code>mkpuzzles</code> program in the puzzle directory.</p>"
"<p>You can write <code>mkpuzzles</code> in any language you like. This puzzle was written in Python 3.</p>"
"<p>Here is some salad:<img src='salad.jpg'></p>"
),
"Attachments": ["salad.jpg"],
},
"Authors": ["neale"],
"Body": (
"<p>Dynamic puzzles are provided with a JSON-generating <code>mkpuzzles</code> program in the puzzle directory.</p>"
"<p>You can write <code>mkpuzzles</code> in any language you like. This puzzle was written in Python 3.</p>"
"<p>Here is some salad:<img src='salad.jpg'></p>"
),
"Attachments": ["salad.jpg"],
"Answers": [
answer,
],

View File

@ -1,10 +1,9 @@
---
pre:
authors:
- neale
scripts:
- filename: helpers.js
- filename: draggable.js
authors:
- neale
scripts:
- filename: helpers.js
- filename: draggable.js
answers:
- helper
debug:

View File

@ -1,6 +1,5 @@
---
pre:
authors: ["neale"]
authors: ["neale"]
answers: ["6"]
---
This category shows off how to use the transpiler from an

View File

@ -1,6 +1,5 @@
---
pre:
authors: ["neale"]
authors: ["neale"]
answers: ["C", "c"]
---
2 4 6 8 A _

View File

@ -1,6 +1,5 @@
---
pre:
authors: ["neale"]
authors: ["neale"]
answers: ["17"]
---
1 2 3 5 7 11 13 _

View File

@ -59,16 +59,16 @@ func TestOsFsCategory(t *testing.T) {
if p, err := static.Puzzle(1); err != nil {
t.Error(err)
} else if len(p.Pre.Authors) != 1 {
t.Error("Wrong authors list", p.Pre.Authors)
} else if p.Pre.Authors[0] != "neale" {
t.Error("Wrong authors", p.Pre.Authors)
} else if len(p.Authors) != 1 {
t.Error("Wrong authors list", p.Authors)
} else if p.Authors[0] != "neale" {
t.Error("Wrong authors", p.Authors)
}
if p, err := static.Puzzle(3); err != nil {
t.Error(err)
} else if len(p.Pre.Authors) != 1 {
t.Error("Wrong authors", p.Pre.Authors)
} else if len(p.Authors) != 1 {
t.Error("Wrong authors", p.Authors)
}
generated := NewFsCategory(fs, "generated")

View File

@ -7,13 +7,12 @@ import (
var testMothYaml = []byte(`---
answers:
- YAML answer
pre:
authors:
- Arthur
- Buster
- DW
attachments:
- moo.txt
authors:
- Arthur
- Buster
- DW
attachments:
- moo.txt
---
YAML body
`)
@ -27,9 +26,8 @@ RFC822 body
var testMothMarkdown = []byte(`---
answers:
- answer
pre:
authors:
- Fred
authors:
- Fred
---
one | two

View File

@ -53,7 +53,7 @@ func Mothball(c Category, w io.Writer) error {
}
// Write out all attachments and scripts
attachments := append(puzzle.Pre.Attachments, puzzle.Pre.Scripts...)
attachments := append(puzzle.Attachments, puzzle.Scripts...)
for _, att := range attachments {
attPath := fmt.Sprintf("%d/%s", points, att)
aw, err := zf.Create(attPath)

View File

@ -32,28 +32,26 @@ type AnswerResponse struct {
// Puzzle contains everything about a puzzle that a client would see.
type Puzzle struct {
Pre struct {
Authors []string
Attachments []string
Scripts []string
Body string
AnswerPattern string
AnswerHashes []string
}
Post struct {
Objective string
Success struct {
Acceptable string
Mastery string
}
KSAs []string
}
Debug struct {
Log []string
Errors []string
Hints []string
Summary string
}
Authors []string
Attachments []string
Scripts []string
Body string
AnswerPattern string
AnswerHashes []string
Objective string
KSAs []string
Success struct {
Acceptable string
Mastery string
}
// Answers will be empty in a mothball
Answers []string
}
@ -61,30 +59,26 @@ func (puzzle *Puzzle) computeAnswerHashes() {
if len(puzzle.Answers) == 0 {
return
}
puzzle.Pre.AnswerHashes = make([]string, len(puzzle.Answers))
puzzle.AnswerHashes = make([]string, len(puzzle.Answers))
for i, answer := range puzzle.Answers {
sum := sha256.Sum256([]byte(answer))
hexsum := fmt.Sprintf("%x", sum)
puzzle.Pre.AnswerHashes[i] = hexsum
puzzle.AnswerHashes[i] = hexsum
}
}
// StaticPuzzle contains everything a static puzzle might tell us.
type StaticPuzzle struct {
Pre struct {
Authors []string
Attachments []StaticAttachment
Scripts []StaticAttachment
AnswerPattern string
}
Post struct {
Objective string
Success struct {
Acceptable string
Mastery string
}
KSAs []string
Authors []string
Attachments []StaticAttachment
Scripts []StaticAttachment
AnswerPattern string
Objective string
Success struct {
Acceptable string
Mastery string
}
KSAs []string
Debug struct {
Log []string
Errors []string
@ -187,7 +181,7 @@ type FsPuzzle struct {
// Puzzle returns a Puzzle struct for the current puzzle.
func (fp FsPuzzle) Puzzle() (Puzzle, error) {
var puzzle Puzzle
puzzle := Puzzle{}
static, body, err := fp.staticPuzzle()
if err != nil {
@ -195,20 +189,21 @@ func (fp FsPuzzle) Puzzle() (Puzzle, error) {
}
// Convert to an exportable Puzzle
puzzle.Post = static.Post
puzzle.Debug = static.Debug
puzzle.Answers = static.Answers
puzzle.Pre.Authors = static.Pre.Authors
puzzle.Pre.Body = string(body)
puzzle.Pre.AnswerPattern = static.Pre.AnswerPattern
puzzle.Pre.Attachments = make([]string, len(static.Pre.Attachments))
for i, attachment := range static.Pre.Attachments {
puzzle.Pre.Attachments[i] = attachment.Filename
puzzle.Authors = static.Authors
puzzle.Body = string(body)
puzzle.AnswerPattern = static.AnswerPattern
puzzle.Attachments = make([]string, len(static.Attachments))
for i, attachment := range static.Attachments {
puzzle.Attachments[i] = attachment.Filename
}
puzzle.Pre.Scripts = make([]string, len(static.Pre.Scripts))
for i, script := range static.Pre.Scripts {
puzzle.Pre.Scripts[i] = script.Filename
puzzle.Scripts = make([]string, len(static.Scripts))
for i, script := range static.Scripts {
puzzle.Scripts[i] = script.Filename
}
empty := Puzzle{}
puzzle.Debug = empty.Debug
puzzle.computeAnswerHashes()
return puzzle, nil
@ -223,7 +218,7 @@ func (fp FsPuzzle) Open(name string) (ReadSeekCloser, error) {
}
var fsPath string
for _, attachment := range append(static.Pre.Attachments, static.Pre.Scripts...) {
for _, attachment := range append(static.Attachments, static.Scripts...) {
if attachment.Filename == name {
if attachment.FilesystemPath == "" {
fsPath = attachment.Filename
@ -337,13 +332,13 @@ func rfc822HeaderParser(r io.Reader) (StaticPuzzle, error) {
key = strings.ToLower(key)
switch key {
case "author":
p.Pre.Authors = val
p.Authors = val
case "pattern":
p.Pre.AnswerPattern = val[0]
p.AnswerPattern = val[0]
case "script":
p.Pre.Scripts = legacyAttachmentParser(val)
p.Scripts = legacyAttachmentParser(val)
case "file":
p.Pre.Attachments = legacyAttachmentParser(val)
p.Attachments = legacyAttachmentParser(val)
case "answer":
p.Answers = val
case "summary":
@ -353,13 +348,13 @@ func rfc822HeaderParser(r io.Reader) (StaticPuzzle, error) {
case "solution":
p.Debug.Hints = val
case "ksa":
p.Post.KSAs = val
p.KSAs = val
case "objective":
p.Post.Objective = val[0]
p.Objective = val[0]
case "success.acceptable":
p.Post.Success.Acceptable = val[0]
p.Success.Acceptable = val[0]
case "success.mastery":
p.Post.Success.Mastery = val[0]
p.Success.Mastery = val[0]
default:
return p, fmt.Errorf("Unknown header field: %s", key)
}

View File

@ -23,11 +23,11 @@ func TestPuzzle(t *testing.T) {
if (len(p.Answers) == 0) || (p.Answers[0] != "YAML answer") {
t.Error("Answers are wrong", p.Answers)
}
if (len(p.Pre.Authors) != 3) || (p.Pre.Authors[1] != "Buster") {
t.Error("Authors are wrong", p.Pre.Authors)
if (len(p.Authors) != 3) || (p.Authors[1] != "Buster") {
t.Error("Authors are wrong", p.Authors)
}
if p.Pre.Body != "<p>YAML body</p>\n" {
t.Errorf("Body parsed wrong: %#v", p.Pre.Body)
if p.Body != "<p>YAML body</p>\n" {
t.Errorf("Body parsed wrong: %#v", p.Body)
}
f, err := pd.Open("moo.txt")
@ -52,11 +52,11 @@ func TestPuzzle(t *testing.T) {
if (len(p.Answers) == 0) || (p.Answers[0] != "RFC822 answer") {
t.Error("Answers are wrong", p.Answers)
}
if (len(p.Pre.Authors) != 3) || (p.Pre.Authors[1] != "Arthur") {
t.Error("Authors are wrong", p.Pre.Authors)
if (len(p.Authors) != 3) || (p.Authors[1] != "Arthur") {
t.Error("Authors are wrong", p.Authors)
}
if p.Pre.Body != "<p>RFC822 body</p>\n" {
t.Errorf("Body parsed wrong: %#v", p.Pre.Body)
if p.Body != "<p>RFC822 body</p>\n" {
t.Errorf("Body parsed wrong: %#v", p.Body)
}
}
@ -66,9 +66,9 @@ func TestPuzzle(t *testing.T) {
if puzzle, err := NewFsPuzzlePoints(catFs, 4).Puzzle(); err != nil {
t.Error("Markdown test file:", err)
} else if !strings.Contains(puzzle.Pre.Body, "<table>") {
} else if !strings.Contains(puzzle.Body, "<table>") {
t.Error("Markdown table extension isn't making tables")
} else if !strings.Contains(puzzle.Pre.Body, "<dl>") {
} else if !strings.Contains(puzzle.Body, "<dl>") {
t.Error("Markdown dictionary extension isn't making tables")
}
@ -110,7 +110,7 @@ func TestFsPuzzle(t *testing.T) {
if puzzle, err := NewFsPuzzlePoints(catFs, 2).Puzzle(); err != nil {
t.Error(err)
} else if !strings.Contains(puzzle.Pre.Body, "class=\"moo\"") {
} else if !strings.Contains(puzzle.Body, "class=\"moo\"") {
t.Error("Raw HTML didn't make it through")
}
@ -150,11 +150,10 @@ func TestFsPuzzle(t *testing.T) {
func TestAttachment(t *testing.T) {
buf := bytes.NewBufferString(`
pre:
attachments:
- simple
- filename: complex
filesystempath: backingfile
attachments:
- simple
- filename: complex
filesystempath: backingfile
`)
p, err := yamlHeaderParser(buf)
if err != nil {
@ -162,7 +161,7 @@ pre:
return
}
att := p.Pre.Attachments
att := p.Attachments
if len(att) != 2 {
t.Error("Wrong number of attachments", att)
}

View File

@ -18,10 +18,8 @@ EOT
cat <<EOT
{
"Answers": ["answer1.0"],
"Pre": {
"Authors": ["author1.0"],
"Body": "<h1>moo.</h1>"
}
"Authors": ["author1.0"],
"Body": "<h1>moo.</h1>"
}
EOT
;;

View File

@ -1,7 +1,6 @@
---
pre:
authors:
- neale
authors:
- neale
answers:
- moo
---

View File

@ -10,10 +10,8 @@ case $1:$2 in
cat <<'EOT'
{
"Answers": ["answer"],
"Pre": {
"Authors": ["neale"],
"Body": "I am a generated puzzle."
}
"Authors": ["neale"],
"Body": "I am a generated puzzle."
}
EOT
;;