Add function to init an application

This commit is contained in:
2020-03-15 18:01:10 +11:00
parent d2e8fdc352
commit d225fa80be
4 changed files with 306 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
package zombie
import "github.com/wahyd4/zombie/models"
type MoveCommand interface {
Execute(zombie models.Zombie)
}
type MoveUpCommand struct {}
func (command *MoveUpCommand) Execute(zombie models.Zombie) {
zombie.MoveUp()
}
type MoveDownCommand struct {}
func (command *MoveDownCommand) Execute(zombie models.Zombie) {
zombie.MoveDown()
}
type MoveLeftCommand struct {}
func (command *MoveLeftCommand) Execute(zombie models.Zombie) {
zombie.MoveLeft()
}
type MoveRightCommand struct {}
func (command *MoveRightCommand) Execute(zombie models.Zombie) {
zombie.MoveRight()
}
+102
View File
@@ -0,0 +1,102 @@
package zombie
import (
"bufio"
"fmt"
"github.com/wahyd4/zombie/models"
"log"
"os"
"strconv"
"strings"
)
const creatureSplitter = " "
var (
commandsMap = map[string]MoveCommand{
"U": &MoveUpCommand{},
"D": &MoveDownCommand{},
"L": &MoveLeftCommand{},
"R": &MoveRightCommand{},
}
)
// Application presents the actual the runner
type Application struct {
GridSize int
Zombie *models.Zombie
Creatures []*models.Creature
Commands []MoveCommand
}
// Init an application instance with given input file
func Init(input string) (*Application, error) {
file, err := os.Open(input)
if err != nil {
return nil, fmt.Errorf("failed to open file %v", err)
}
defer file.Close()
application := Application{
Zombie: &models.Zombie{},
}
scanner := bufio.NewScanner(file)
for lineIndex := 0; scanner.Scan(); lineIndex++ {
text := scanner.Text()
switch lineIndex {
case 0:
gridSize, _ := strconv.Atoi(text)
application.GridSize = gridSize
application.Zombie.GridSize = gridSize
case 1:
coordinate := parseCoordinate(text)
application.Zombie.Coordinate = coordinate
case 2:
creatures := parseCreatures(text)
application.Creatures = creatures
default:
commands := parseCommands(text)
application.Commands = commands
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to read content from file %v", err)
}
return &application, nil
}
func parseCommands(commandString string) []MoveCommand {
commands := make([]MoveCommand, 0)
for _, commandRune := range commandString {
commands = append(commands, commandsMap[string(commandRune)])
}
return commands
}
func parseCoordinate(coordinate string) models.Coordinate {
coordinateWithoutBrackets := coordinate[1 : len(coordinate)-1]
coordinateArr := strings.Split(coordinateWithoutBrackets, ",")
if len(coordinateArr) != 2 {
log.Panic("coordinate string is not valid")
}
axisValues := make([]int, 0)
for _, axisValue := range coordinateArr {
value, err := strconv.Atoi(axisValue)
if err != nil {
log.Panic("cannot convert coordinate string into integers:" + err.Error())
}
axisValues = append(axisValues, value)
}
return models.Coordinate{XAxis: axisValues[0], YAxis: axisValues[1]}
}
func parseCreatures(coordinates string) []*models.Creature {
creatureCoordinates := strings.Split(coordinates, creatureSplitter)
creatures := make([]*models.Creature, 0)
for _, coordinate := range creatureCoordinates {
creatures = append(creatures, &models.Creature{Coordinate: parseCoordinate(coordinate)})
}
return creatures
}
+168
View File
@@ -0,0 +1,168 @@
package zombie
import (
"github.com/wahyd4/zombie/models"
"reflect"
"testing"
)
func TestInit(t *testing.T) {
type args struct {
input string
}
tests := []struct {
name string
args args
want *Application
wantErr bool
}{
{
"can parse the input data file and init an application",
args{input: "test_data/input_test.txt"},
&Application{
GridSize: 4,
Zombie: &models.Zombie{
GridSize: 4,
Coordinate: models.Coordinate{
XAxis: 2,
YAxis: 1,
},
},
Creatures: []*models.Creature{
&models.Creature{Coordinate: models.Coordinate{0, 1}},
&models.Creature{Coordinate: models.Coordinate{XAxis: 1, YAxis: 2}},
&models.Creature{Coordinate: models.Coordinate{XAxis: 3, YAxis: 1}},
},
Commands: []MoveCommand{
&MoveDownCommand{},
&MoveLeftCommand{},
&MoveUpCommand{},
&MoveUpCommand{},
&MoveRightCommand{},
&MoveRightCommand{},
},
},
false,
},
{
"fail to init application due to file is not found",
args{input: "test_data/not_exist.txt"},
nil,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Init(tt.args.input)
if (err != nil) != tt.wantErr {
t.Errorf("Init() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Init() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_parseCoordinate(t *testing.T) {
type args struct {
coordinate string
}
tests := []struct {
name string
args args
want models.Coordinate
}{
{
"can parse a valid coordinate string",
args{coordinate: "(2,3)"},
models.Coordinate{
XAxis: 2,
YAxis: 3,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseCoordinate(tt.args.coordinate); !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseCoordinate() = %v, want %v", got, tt.want)
}
})
}
}
func Test_parseCreatures(t *testing.T) {
type args struct {
coordinates string
}
tests := []struct {
name string
args args
want []*models.Creature
}{
{
"can parse all the creatures from string",
args{"(0,1)"},
[]*models.Creature{
&models.Creature{Coordinate: models.Coordinate{0, 1}},
},
},
{
"can parse all the creatures from string",
args{"(0,1) (1,2) (3,1)"},
[]*models.Creature{
&models.Creature{Coordinate: models.Coordinate{0, 1}},
&models.Creature{Coordinate: models.Coordinate{1, 2}},
&models.Creature{Coordinate: models.Coordinate{3, 1}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseCreatures(tt.args.coordinates); !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseCreatures() = %v, want %v", got, tt.want)
}
})
}
}
func Test_parseCommands(t *testing.T) {
type args struct {
commandString string
}
tests := []struct {
name string
args args
want []MoveCommand
}{
{
"can parse the commands string into commands",
args{"LRRUD"},
[]MoveCommand{
&MoveLeftCommand{},
&MoveRightCommand{},
&MoveRightCommand{},
&MoveUpCommand{},
&MoveDownCommand{},
},
},
{
"can parse the commands string into commands",
args{"RRUU"},
[]MoveCommand{
&MoveRightCommand{},
&MoveRightCommand{},
&MoveUpCommand{},
&MoveUpCommand{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseCommands(tt.args.commandString); !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseCommands() = %v, want %v", got, tt.want)
}
})
}
}
+4
View File
@@ -0,0 +1,4 @@
4
(2,1)
(0,1) (1,2) (3,1)
DLUURR