aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fl.fischer@fau.de>2017-02-06 14:16:30 +0100
committerFlorian Fischer <florian.fl.fischer@fau.de>2017-02-06 14:27:31 +0100
commit6c60d2fe8acdbcdfd7ea408350fb8b5461833677 (patch)
tree478447348aa2213133bd2dafb59c83eddd77a246
parentc433780cfacc384e424adb31187045ddf6a45650 (diff)
downloadgoffel-6c60d2fe8acdbcdfd7ea408350fb8b5461833677.tar.gz
goffel-6c60d2fe8acdbcdfd7ea408350fb8b5461833677.zip
generalise command parsing code
-rw-r--r--logic/cmd.go146
-rw-r--r--logic/cmd_test.go130
2 files changed, 276 insertions, 0 deletions
diff --git a/logic/cmd.go b/logic/cmd.go
new file mode 100644
index 0000000..76a95b9
--- /dev/null
+++ b/logic/cmd.go
@@ -0,0 +1,146 @@
+package logic
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+type Cmd struct {
+ Cmd string
+ Argv []int
+ Argc int
+}
+
+var cmdTable = map[string]int{
+ "d": 1, "dices": 1,
+ "p": 2, "print": 2,
+ "q": 3, "quit": 3,
+ "h": 4, "help": 4,
+ "i": 5, "insert": 5,
+ "c": 6, "cancel": 6,
+ "r": 7, "reroll": 7,
+ "pos": 8, "positions": 8,
+}
+
+// we ignore arguments which are to much
+func ParseCmd(s string) (Cmd, error) {
+ split := strings.Split(s, " ")
+ if len(split) == 0 {
+ return Cmd{}, errors.New("Empty command")
+ }
+
+ argv := make([]int, 0, 5)
+ argc := 0
+
+ switch split[0] {
+ case "d", "p", "q":
+ return Cmd{Cmd: split[0]}, nil
+ case "h":
+ if len(split) > 1 {
+ if i, exists := cmdTable[split[1]]; exists {
+ argv = append(argv, i)
+ argc++
+ }
+ }
+ if argc < 1 {
+ argv = append(argv, 0)
+ argc++
+ }
+ case "i", "c":
+ if len(split) < 2 {
+ return Cmd{}, errors.New(split[0] + ": missing argument")
+ }
+ if e, exists := ScorePositions[split[1]]; exists {
+ argv = append(argv, e)
+ } else if i, err := strconv.Atoi(split[1]); err != nil {
+ return Cmd{}, err
+ } else if i < 1 || i > 13 {
+ return Cmd{}, errors.New(split[0] + ": position out of range")
+ } else {
+ argv = append(argv, i-1)
+ }
+ argc++
+ case "r":
+ for _, v := range split[1:] {
+ i, err := strconv.Atoi(v)
+ if err != nil {
+ return Cmd{}, err
+ }
+ if i < 1 || i > 5 {
+ return Cmd{}, errors.New("r: dice index out of range")
+ }
+ argv = append(argv, i)
+ argc++
+ // ignore additional arguments
+ if argc == 5 {
+ break
+ }
+ }
+ case "pos":
+ split[0] = "h"
+ argv = append(argv, cmdTable["pos"])
+ argc++
+ default:
+ return Cmd{}, errors.New("Invalid command")
+ }
+
+ return Cmd{split[0], argv[0:argc], argc}, nil
+}
+
+func CmdHelp(cmd int) string {
+ s := ""
+ switch cmd {
+ case 1:
+ s += fmt.Sprintln("d - print dices")
+ s += fmt.Sprintln("Print out the dices")
+ case 2:
+ s += fmt.Sprintln("p - print score")
+ s += fmt.Sprintln("Print out your score")
+ case 3:
+ s += fmt.Sprintln("q - quit the game")
+ s += fmt.Sprintln("Terminates the game")
+ case 4:
+ s += fmt.Sprintln("h [cmd] - print help")
+ s += fmt.Sprintln("Print the help for a specific command or gernal help.")
+ case 5:
+ s += fmt.Sprintln("i [pos] - insert into score")
+ s += fmt.Sprintln("Insert your current dices into your score.")
+ s += fmt.Sprintln("See \"h pos\" for a explenation of the score entries")
+ case 6:
+ s += fmt.Sprintln("c [pos] - cancel a entry")
+ s += fmt.Sprintln("Write 0 into your score.")
+ s += fmt.Sprintln("See \"h pos\" for a explenation of the score entries")
+ case 7:
+ s += fmt.Sprintln("r [dices] - reroll some dices")
+ s += fmt.Sprintln("Reroll the specified dices.")
+ s += fmt.Sprintln("The dices to reroll are represented by a list of their indices in the dice set.")
+ s += fmt.Sprintln("Example:")
+ s += fmt.Sprintln("\t\"r 1 4 5\" rerolls dice number 1, 4 and 5")
+ s += fmt.Sprintln("\t\"r\" rerolls all dices")
+ case 8:
+ s += fmt.Sprintln("Positions:")
+ s += fmt.Sprintln("\t1: Aces")
+ s += fmt.Sprintln("\t2: Twos")
+ s += fmt.Sprintln("\t3: Threes")
+ s += fmt.Sprintln("\t4: Fours")
+ s += fmt.Sprintln("\t5: Fives")
+ s += fmt.Sprintln("\t6: Sixes")
+ s += fmt.Sprintln("\t7: ThreeOfAKind")
+ s += fmt.Sprintln("\t8: FourOfAKind")
+ s += fmt.Sprintln("\t9: FullHouse")
+ s += fmt.Sprintln("\t10: SmallStraight")
+ s += fmt.Sprintln("\t11: LargeStraight")
+ s += fmt.Sprintln("\t12: Yathzze")
+ s += fmt.Sprintln("\t13: Chance")
+ default:
+ s += fmt.Sprintln("h [cmd] - print help")
+ s += fmt.Sprintln("p - print score")
+ s += fmt.Sprintln("d - print dices")
+ s += fmt.Sprintln("i [pos] - insert into score")
+ s += fmt.Sprintln("r [dices] - reroll some dices")
+ s += fmt.Sprintln("c [pos] - cancel a entry")
+ }
+ return s
+}
diff --git a/logic/cmd_test.go b/logic/cmd_test.go
new file mode 100644
index 0000000..01dfc0c
--- /dev/null
+++ b/logic/cmd_test.go
@@ -0,0 +1,130 @@
+package logic
+
+import "testing"
+
+func TestParseCmd(t *testing.T) {
+ cmd, err := ParseCmd("")
+ if err == nil {
+ t.Errorf("Parsing an empty string should return an error")
+ }
+
+ for _, s := range []string{"d", "p", "h"} {
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != s {
+ t.Errorf("Parsing %v should return \"%v\" as command", s, s)
+ }
+ }
+
+ for _, c := range []string{"i", "c"} {
+ cmd, err := ParseCmd(c)
+ if err == nil {
+ t.Errorf("Parsing %v should return an error", c)
+ }
+ s := c + " -1"
+ cmd, err = ParseCmd(s)
+ if err == nil {
+ t.Errorf("Parsing %v should return an error", s)
+ }
+ s = c + " 13"
+ cmd, err = ParseCmd(s)
+ if err == nil {
+ t.Errorf("Parsing %v should return an error", s)
+ }
+ s = c + " boom!"
+ cmd, err = ParseCmd(s)
+ if err == nil {
+ t.Errorf("Parsing %v should return an error", s)
+ }
+ s = c + " 3"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != c {
+ t.Errorf("Parsing %v should return \"%v\" as command", s, c)
+ }
+ if cmd.Argc != 1 {
+ t.Errorf("Parsing %v should return argc==1", s)
+ }
+ if cmd.Argv[0] != 3 || len(cmd.Argv) != 1 {
+ t.Errorf("Parsing %v should return argv==[3]", s)
+ }
+ s = c + " FullHouse"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != c {
+ t.Errorf("Parsing %v should return \"%v\" as command", s, c)
+ }
+ if cmd.Argc != 1 {
+ t.Errorf("Parsing %v should return argc==1", s)
+ }
+ if cmd.Argv[0] != 8 || len(cmd.Argv) != 1 {
+ t.Errorf("Parsing %v should return argv==[8]", s)
+ }
+ }
+
+ s := "r"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing r should not return \"%v\"", err)
+ }
+ if cmd.Cmd != "r" {
+ t.Errorf("Parsing r should return \"r\" as command")
+ }
+
+ s = "r 1"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != "r" {
+ t.Errorf("Parsing %v should return \"r\" as command", s)
+ }
+ if cmd.Argc != 1 {
+ t.Errorf("Parsing %v should return argc==1", s)
+ }
+ if cmd.Argv[0] != 1 || len(cmd.Argv) != 1 {
+ t.Errorf("Parsing %v should return argv==[1]", s)
+ }
+
+ s = "r 1 3 4"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != "r" {
+ t.Errorf("Parsing %v should return \"r\" as command", s)
+ }
+ if cmd.Argc != 3 {
+ t.Errorf("Parsing %v should return argc==3", s)
+ }
+ r := []int{1, 3, 4}
+ for i, v := range r {
+ if cmd.Argv[i] != v {
+ t.Errorf("Parsing %v should return argv==%v", s, r)
+ }
+ }
+
+ s = "r 1 2 3 4 5 hut"
+ cmd, err = ParseCmd(s)
+ if err != nil {
+ t.Errorf("Parsing %v should not return \"%v\"", s, err)
+ }
+ if cmd.Cmd != "r" {
+ t.Errorf("Parsing %v should return \"r\" as command", s)
+ }
+ if cmd.Argc != 5 {
+ t.Errorf("Parsing %v should return argc==5", s)
+ }
+ r = []int{1, 2, 3, 4, 5}
+ for i, v := range r {
+ if cmd.Argv[i] != v {
+ t.Errorf("Parsing %v should return argv==%v", s, r)
+ }
+ }
+}