mirror of
https://github.com/wahyd4/zombie.git
synced 2026-08-08 20:25:56 +10:00
Add function to init an application
This commit is contained in:
+32
@@ -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()
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
4
|
||||
(2,1)
|
||||
(0,1) (1,2) (3,1)
|
||||
DLUURR
|
||||
Reference in New Issue
Block a user