Added argument parsing to run the solver correctly
This commit is contained in:
parent
5500007fb4
commit
a7dd3e1a81
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module maze-solver
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/akamensky/argparse v1.4.0
|
||||
github.com/mazznoer/colorgrad v0.9.1
|
||||
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -1,3 +1,5 @@
|
||||
github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc=
|
||||
github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mazznoer/colorgrad v0.9.1 h1:MB80JYVndKWSMEM1beNqnuOowWGhoQc3DXWXkFp6JlM=
|
||||
|
@ -1,5 +1,48 @@
|
||||
package reader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type Reader interface {
|
||||
Read() (*RawMaze, error)
|
||||
}
|
||||
|
||||
type ReaderFactory struct {
|
||||
Type string
|
||||
Filename *string
|
||||
PathChar, WallChar, SolutionChar *string
|
||||
CellWidth, CellHeight *int
|
||||
WallColor, PathColor color.Color
|
||||
}
|
||||
|
||||
const (
|
||||
_IMAGE = "image"
|
||||
_TEXT = "text"
|
||||
)
|
||||
|
||||
var TYPES = map[string]string{
|
||||
".png": _IMAGE,
|
||||
".txt": _TEXT,
|
||||
}
|
||||
|
||||
func (f *ReaderFactory) Get() Reader {
|
||||
switch f.Type {
|
||||
case _TEXT:
|
||||
return &TextReader{
|
||||
Filename: *f.Filename,
|
||||
PathChar: byte((*f.PathChar)[0]),
|
||||
WallChar: byte((*f.WallChar)[0]),
|
||||
}
|
||||
case _IMAGE:
|
||||
return &ImageReader{
|
||||
Filename: *f.Filename,
|
||||
CellWidth: *f.CellWidth,
|
||||
CellHeight: *f.CellHeight,
|
||||
WallColor: f.WallColor,
|
||||
PathColor: f.PathColor,
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("Unrecognized reader type %q", f.Type))
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ type TextReader struct {
|
||||
PathChar, WallChar byte
|
||||
}
|
||||
|
||||
func (r TextReader) Read() (*RawMaze, error) {
|
||||
func (r *TextReader) Read() (*RawMaze, error) {
|
||||
defer utils.Timer("Text Reader", 3)()
|
||||
lines, err := getLines(r.Filename)
|
||||
if err != nil {
|
||||
|
@ -1,5 +1,46 @@
|
||||
package writer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"maze-solver/maze"
|
||||
|
||||
"github.com/mazznoer/colorgrad"
|
||||
)
|
||||
|
||||
type Writer interface {
|
||||
Write() error
|
||||
}
|
||||
|
||||
type WriterFactory struct {
|
||||
Type string
|
||||
Filename *string
|
||||
PathChar, WallChar, SolutionChar *string
|
||||
CellWidth, CellHeight *int
|
||||
WallColor, PathColor color.Color
|
||||
SolutionGradient colorgrad.Gradient
|
||||
}
|
||||
|
||||
const (
|
||||
_IMAGE = "image"
|
||||
)
|
||||
|
||||
var TYPES = map[string]string{
|
||||
".png": _IMAGE,
|
||||
}
|
||||
|
||||
func (f *WriterFactory) Get(m *maze.SolvedMaze) Writer {
|
||||
switch f.Type {
|
||||
case _IMAGE:
|
||||
return &ImageWriter{
|
||||
Filename: *f.Filename,
|
||||
Maze: m,
|
||||
CellWidth: *f.CellWidth,
|
||||
CellHeight: *f.CellHeight,
|
||||
WallColor: f.WallColor,
|
||||
PathColor: f.PathColor,
|
||||
SolutionGradient: f.SolutionGradient,
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("Unrecognized writer type %q", f.Type))
|
||||
}
|
||||
|
143
main.go
143
main.go
@ -1,25 +1,154 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"maze-solver/io/reader"
|
||||
"maze-solver/io/writer"
|
||||
"maze-solver/maze/parser"
|
||||
"maze-solver/solver"
|
||||
"maze-solver/utils"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/akamensky/argparse"
|
||||
"github.com/mazznoer/colorgrad"
|
||||
)
|
||||
|
||||
func main() {
|
||||
output := "filename"
|
||||
argparser := argparse.NewParser("maze-solver", "Solves the given maze (insane, right? who would've guessed?)")
|
||||
|
||||
reader := &reader.TextReader{Filename: "filename", PathChar: ' ', WallChar: '#'}
|
||||
writer := &writer.ImageWriter{}
|
||||
var verboseLevel *int = argparser.FlagCounter("v", "verbose", &argparse.Options{
|
||||
Help: `Verbose level of the solver
|
||||
0: nothing printed to stdout
|
||||
1: print the total time taken by the solver (time of the main() function)
|
||||
2: prints the time the solving algorithm took to run
|
||||
3: prints the time taken by each section (reader, solving algorithm, writer)`,
|
||||
})
|
||||
|
||||
solver := &solver.Bfs{}
|
||||
readerFactory := reader.ReaderFactory{}
|
||||
writerFactory := writer.WriterFactory{}
|
||||
solverFactory := solver.SolverFactory{}
|
||||
|
||||
readerFactory.Type = reader.TYPES[".png"]
|
||||
readerFactory.Filename = argparser.String("i", "input", &argparse.Options{
|
||||
Help: "Input file",
|
||||
Default: "maze.png",
|
||||
Validate: func(args []string) error {
|
||||
var ok bool
|
||||
extension := args[0][len(args[0])-4:]
|
||||
readerFactory.Type, ok = reader.TYPES[extension]
|
||||
if ok {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New(fmt.Sprintf("Filetype not recognized %q", extension))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
writerFactory.Type = writer.TYPES[".png"]
|
||||
writerFactory.Filename = argparser.String("o", "output", &argparse.Options{
|
||||
Help: "Input file",
|
||||
Default: "maze_sol.png",
|
||||
Validate: func(args []string) error {
|
||||
var ok bool
|
||||
extension := args[0][len(args[0])-4:]
|
||||
writerFactory.Type, ok = writer.TYPES[extension]
|
||||
if ok {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New(fmt.Sprintf("Filetype not recognized %q", extension))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
readerFactory.PathChar = argparser.String("", "path-char-in", &argparse.Options{
|
||||
Help: "Character to represent the path in a input text file",
|
||||
Default: " ",
|
||||
Validate: func(args []string) error {
|
||||
if len(args[0]) > 1 {
|
||||
return errors.New("Character must a string of length 1")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
readerFactory.WallChar = argparser.String("", "wall-char-in", &argparse.Options{
|
||||
Help: "Character to represent the wall in a input text file",
|
||||
Default: "#",
|
||||
Validate: func(args []string) error {
|
||||
if len(args[0]) > 1 {
|
||||
return errors.New("Character must a string of length 1")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
writerFactory.PathChar = argparser.String("", "path-char-out", &argparse.Options{
|
||||
Help: "Character to represent the path in a output text file",
|
||||
Default: " ",
|
||||
Validate: func(args []string) error {
|
||||
if len(args[0]) > 1 {
|
||||
return errors.New("Character must a string of length 1")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
writerFactory.WallChar = argparser.String("", "wall-char-out", &argparse.Options{
|
||||
Help: "Character to represent the wall in a output text file",
|
||||
Default: "#",
|
||||
Validate: func(args []string) error {
|
||||
if len(args[0]) > 1 {
|
||||
return errors.New("Character must a string of length 1")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
cellSizeIn := argparser.Int("", "cell-size-in", &argparse.Options{
|
||||
Help: "Size of a cell (in pixels) for input file of image type",
|
||||
Default: 20,
|
||||
})
|
||||
|
||||
cellSizeOut := argparser.Int("", "cell-size-out", &argparse.Options{
|
||||
Help: "Size of a cell (in pixels) for output file of image type",
|
||||
Default: 20,
|
||||
})
|
||||
|
||||
solverFactory.Type = argparser.Selector("a", "algo", solver.TYPES, &argparse.Options{
|
||||
Help: fmt.Sprintf("Algorithm to solve the maze, avaiable options: %s", strings.Join(solver.TYPES, ", ")),
|
||||
Default: solver.TYPES[0],
|
||||
})
|
||||
|
||||
if err := argparser.Parse(os.Args); err != nil {
|
||||
fmt.Println(argparser.Usage(err))
|
||||
return
|
||||
}
|
||||
utils.VERBOSE_LEVEL = *verboseLevel
|
||||
|
||||
readerFactory.CellHeight, readerFactory.CellWidth = cellSizeIn, cellSizeIn
|
||||
readerFactory.WallColor = color.RGBA{0, 0, 0, 255}
|
||||
readerFactory.PathColor = color.RGBA{255, 255, 255, 255}
|
||||
|
||||
writerFactory.CellHeight, writerFactory.CellWidth = cellSizeOut, cellSizeOut
|
||||
writerFactory.WallColor = color.RGBA{0, 0, 0, 255}
|
||||
writerFactory.PathColor = color.RGBA{255, 255, 255, 255}
|
||||
writerFactory.SolutionGradient = colorgrad.Warm()
|
||||
|
||||
defer utils.Timer("TOTAL", 1)()
|
||||
|
||||
reader := readerFactory.Get()
|
||||
|
||||
maze, err := parser.Parse(reader)
|
||||
utils.Check(err, "Couldn't read maze from %q", reader.Filename)
|
||||
utils.Check(err, "Couldn't read maze")
|
||||
|
||||
solver := solverFactory.Get()
|
||||
solved := solver.Solve(maze)
|
||||
err = writer.Write(output, solved)
|
||||
utils.Check(err, "Couldn't write solved maze to %q", output)
|
||||
|
||||
writer := writerFactory.Get(solved)
|
||||
|
||||
err = writer.Write()
|
||||
utils.Check(err, "Couldn't write solved maze")
|
||||
}
|
||||
|
@ -1,7 +1,30 @@
|
||||
package solver
|
||||
|
||||
import "maze-solver/maze"
|
||||
import (
|
||||
"fmt"
|
||||
"maze-solver/maze"
|
||||
)
|
||||
|
||||
type Solver interface {
|
||||
Solve(*maze.Maze) *maze.SolvedMaze
|
||||
}
|
||||
|
||||
type SolverFactory struct {
|
||||
Type *string
|
||||
}
|
||||
|
||||
const (
|
||||
_TURN_LEFT = "turn-left"
|
||||
)
|
||||
|
||||
var TYPES = []string{
|
||||
_TURN_LEFT,
|
||||
}
|
||||
|
||||
func (f *SolverFactory) Get() Solver {
|
||||
switch *f.Type {
|
||||
case _TURN_LEFT:
|
||||
return &TurnLeftSolver{}
|
||||
}
|
||||
panic(fmt.Sprintf("Unrecognized solver type %q", *f.Type))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user