diff options
| author | Florian Fischer <florian.fl.fischer@fau.de> | 2017-02-06 14:16:30 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fl.fischer@fau.de> | 2017-02-06 14:27:31 +0100 |
| commit | 6c60d2fe8acdbcdfd7ea408350fb8b5461833677 (patch) | |
| tree | 478447348aa2213133bd2dafb59c83eddd77a246 | |
| parent | c433780cfacc384e424adb31187045ddf6a45650 (diff) | |
| download | goffel-6c60d2fe8acdbcdfd7ea408350fb8b5461833677.tar.gz goffel-6c60d2fe8acdbcdfd7ea408350fb8b5461833677.zip | |
generalise command parsing code
| -rw-r--r-- | logic/cmd.go | 146 | ||||
| -rw-r--r-- | logic/cmd_test.go | 130 |
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) + } + } +} |
