From 506e0ace6bbc85a112972e9afcca2bec2b7a0c5d Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sun, 25 Aug 2019 18:50:38 -0600 Subject: [PATCH] Transpiler can now render individual puzles --- cmd/transpile/category.go | 99 ++++++++++++++++----------------------- cmd/transpile/main.go | 69 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 58 deletions(-) create mode 100644 cmd/transpile/main.go diff --git a/cmd/transpile/category.go b/cmd/transpile/category.go index 80aaaa6..3f303c3 100644 --- a/cmd/transpile/category.go +++ b/cmd/transpile/category.go @@ -2,7 +2,6 @@ package main import ( "os" - "flag" "fmt" "log" "path/filepath" @@ -37,7 +36,7 @@ func PrngOfStrings(input ...string) (*rand.Rand) { func runPuzzleGen(puzzlePath string, seed string) (*Puzzle, error) { - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() cmd := exec.CommandContext(ctx, puzzlePath) @@ -61,6 +60,38 @@ func runPuzzleGen(puzzlePath string, seed string) (*Puzzle, error) { return puzzle, nil } +func ParsePuzzle(puzzlePath string, puzzleSeed string) (*Puzzle, error) { + var puzzle *Puzzle + + // Try the .moth file first + puzzleMothPath := filepath.Join(puzzlePath, "puzzle.moth") + puzzleFd, err := os.Open(puzzleMothPath) + if err == nil { + defer puzzleFd.Close() + puzzle, err = ParseMoth(puzzleFd) + if err != nil { + return nil, err + } + } else if os.IsNotExist(err) { + var genErr error + + puzzleGenPath := filepath.Join(puzzlePath, "mkpuzzle") + puzzle, genErr = runPuzzleGen(puzzleGenPath, puzzlePath) + if genErr != nil { + bigErr := fmt.Errorf( + "%v; (%s: %v)", + genErr, + filepath.Base(puzzleMothPath), err, + ) + return nil, bigErr + } + } else { + return nil, err + } + + return puzzle, nil +} + func ParseCategory(categoryPath string, seed string) ([]PuzzleEntry, error) { categoryFd, err := os.Open(categoryPath) @@ -76,41 +107,20 @@ func ParseCategory(categoryPath string, seed string) ([]PuzzleEntry, error) { puzzleEntries := make([]PuzzleEntry, 0, len(puzzleDirs)) for _, puzzleDir := range puzzleDirs { - var puzzle *Puzzle - puzzlePath := filepath.Join(categoryPath, puzzleDir) - - // Determine point value from directory name - points, err := strconv.Atoi(puzzleDir) + puzzleSeed := fmt.Sprintf("%s/%s", seed, puzzleDir) + puzzle, err := ParsePuzzle(puzzlePath, puzzleSeed) if err != nil { log.Printf("Skipping %s: %v", puzzlePath, err) continue } - - // Try the .moth file first - puzzleMothPath := filepath.Join(puzzlePath, "puzzle.moth") - puzzleFd, err := os.Open(puzzleMothPath) - if err == nil { - defer puzzleFd.Close() - puzzle, err = ParseMoth(puzzleFd) - if err != nil { - log.Printf("Skipping %s: %v", puzzleMothPath, err) - continue - } - } else if os.IsNotExist(err) { - var genErr error - puzzleGenPath := filepath.Join(puzzlePath, "mkpuzzle") - puzzle, genErr = runPuzzleGen(puzzleGenPath, puzzlePath) - if genErr != nil { - log.Printf("Skipping %20s: %v", puzzleMothPath, err) - log.Printf("Skipping %20s: %v", puzzleGenPath, genErr) - continue - } - } else { - log.Printf("Skipping %s: %v", puzzleMothPath, err) - continue - } + // Determine point value from directory name + points, err := strconv.Atoi(puzzleDir) + if err != nil { + return nil, err + } + // Create a category entry for this prng := PrngOfStrings(puzzlePath) idBytes := make([]byte, 16) @@ -126,30 +136,3 @@ func ParseCategory(categoryPath string, seed string) ([]PuzzleEntry, error) { return puzzleEntries, nil } - - -func main() { - // XXX: We need a way to pass in "only run this one point value puzzle" - // XXX: Convert puzzle.py to standalone thingies - flag.Parse() - baseSeedString := os.Getenv("SEED") - - jsenc := json.NewEncoder(os.Stdout) - jsenc.SetEscapeHTML(false) - jsenc.SetIndent("", " ") - - for _, dirname := range flag.Args() { - categoryName := filepath.Base(dirname) - categorySeed := fmt.Sprintf("%s/%s", baseSeedString, categoryName) - puzzles, err := ParseCategory(dirname, categorySeed) - if err != nil { - log.Print(err) - continue - } - - if err := jsenc.Encode(puzzles); err != nil { - log.Print(err) - continue - } - } -} diff --git a/cmd/transpile/main.go b/cmd/transpile/main.go new file mode 100644 index 0000000..e589c71 --- /dev/null +++ b/cmd/transpile/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "flag" + "encoding/json" + "path/filepath" + "strconv" + "strings" + "os" + "log" + "fmt" +) + +func seedJoin(parts ...string) string { + return strings.Join(parts, "::") +} + +func usage() { + out := flag.CommandLine.Output() + name := flag.CommandLine.Name() + fmt.Fprintf(out, "Usage: %s [OPTIONS] CATEGORY [CATEGORY ...]\n", name) + flag.PrintDefaults() +} + +func main() { + // XXX: We need a way to pass in "only run this one point value puzzle" + // XXX: Convert puzzle.py to standalone thingies + + flag.Usage = usage + points := flag.Int("points", 0, "Transpile only this point value puzzle") + flag.Parse() + + baseSeedString := os.Getenv("MOTH_SEED") + + jsenc := json.NewEncoder(os.Stdout) + jsenc.SetEscapeHTML(false) + jsenc.SetIndent("", " ") + + for _, categoryPath := range flag.Args() { + categoryName := filepath.Base(categoryPath) + categorySeed := seedJoin(baseSeedString, categoryName) + + if *points > 0 { + puzzleDir := strconv.Itoa(*points) + puzzleSeed := seedJoin(categorySeed, puzzleDir) + puzzlePath := filepath.Join(categoryPath, puzzleDir) + puzzle, err := ParsePuzzle(puzzlePath, puzzleSeed) + if err != nil { + log.Print(err) + continue + } + + if err := jsenc.Encode(puzzle); err != nil { + log.Fatal(err) + } + } else { + puzzles, err := ParseCategory(categoryPath, categorySeed) + if err != nil { + log.Print(err) + continue + } + + if err := jsenc.Encode(puzzles); err != nil { + log.Print(err) + continue + } + } + } +}