diff --git a/kadai3-1/nas/simpletype/Makefile b/kadai3-1/nas/simpletype/Makefile new file mode 100644 index 0000000..26017d0 --- /dev/null +++ b/kadai3-1/nas/simpletype/Makefile @@ -0,0 +1,38 @@ +# CONST +BINARYNAME=simpletype + +export GO111MODULE=on + +# command +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: build +build: ## go build + go build -v -o ${BINARYNAME} + +#.PHONY: test +#test: ## go test +# go test -v -cover ./pkg/${BINARYNAME} + +.PHONY: clean +clean: ## go clean + go clean -cache -testcache + +.PHONY: analyze +analyze: ## do static code analysis + goimports -l -w . + go vet ./... + golint ./... + +.PHONY: test +test: ## go test ... + go test ./... + +.PHONY: remove +remove: ## remove binary and test output data + rm -f ./${BINARYNAME} + +.PHONY: all +all: remove clean test analyze build ## run 'build' with 'remove', 'clean', 'test' and 'analyze' diff --git a/kadai3-1/nas/simpletype/cli.go b/kadai3-1/nas/simpletype/cli.go new file mode 100644 index 0000000..fd64e80 --- /dev/null +++ b/kadai3-1/nas/simpletype/cli.go @@ -0,0 +1,70 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "os" + "time" + + "github.com/gopherdojo/dojo7/kadai3-1/nas/simpletype/pkg/exercise" +) + +// Cli は command line tool 用の 情報を保持します。 +type Cli struct { + InputReader + Correct int +} + +// InputReader は 入出デバイス用インターフェイス +type InputReader interface { + Answer() <-chan string +} + +// Reader は 標準入力です。 +type Reader struct{} + +// Answer は 標準入力を受け取り、それらをチャンネルとして返します。 +func (r *Reader) Answer() <-chan string { + ch := make(chan string) + + go func() { + s := bufio.NewScanner(os.Stdin) + for s.Scan() { + ch <- s.Text() + } + close(ch) + }() + return ch +} + +// Run はタイピングゲームを実行します。 +func (c *Cli) Run(e *exercise.Exercise, t time.Duration) { + bc := context.Background() + ctx, cancel := context.WithTimeout(bc, t) + defer cancel() + if !e.Next() { + fmt.Fprintf(os.Stderr, "問題がありません\n") + return + } + answer := c.InputReader.Answer() + for { + q := e.Get() + if q != "" { + fmt.Printf("%s > ", q) + } + select { + case <-ctx.Done(): + fmt.Fprintf(os.Stdout, "\n終了 : 正解数 >> %d\n", c.Correct) + return + case a := <-answer: + if a != q { + continue + } + c.Correct++ + if !e.Next() { + cancel() + } + } + } +} diff --git a/kadai3-1/nas/simpletype/cli_test.go b/kadai3-1/nas/simpletype/cli_test.go new file mode 100644 index 0000000..1e3aae3 --- /dev/null +++ b/kadai3-1/nas/simpletype/cli_test.go @@ -0,0 +1,53 @@ +package main + +import ( + "testing" + "time" + + "github.com/gopherdojo/dojo7/kadai3-1/nas/simpletype/pkg/exercise" +) + +type MockReader struct { + Words []string +} + +func (mr *MockReader) Answer() <-chan string { + ch := make(chan string) + + go func() { + for _, w := range mr.Words { + ch <- w + time.Sleep(1 * time.Second) + } + close(ch) + }() + return ch +} + +func TestCliRun(t *testing.T) { + cases := []struct { + name string + duration int + words []string + want int + }{ + {"Success", 10, []string{"apple", "banana", "cat", "dog", "egg", "fish"}, 6}, + {"Time out", 3, []string{"apple", "banana", "cat", "dog", "egg", "fish"}, 3}, + {"No Exercise", 10, []string{}, 0}, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + e := &exercise.Exercise{ + Questions: tt.words, + } + d := time.Duration(tt.duration) * time.Second + c := &Cli{InputReader: &MockReader{tt.words}} + c.Run(e, d) + if got := c.Correct; tt.want != got { + t.Errorf("c.Run(%v, %v) >> c.Count => %d, but want %d", e, d, tt.want, c.Correct) + } + }) + + } +} diff --git a/kadai3-1/nas/simpletype/go.mod b/kadai3-1/nas/simpletype/go.mod new file mode 100644 index 0000000..a9f4cd1 --- /dev/null +++ b/kadai3-1/nas/simpletype/go.mod @@ -0,0 +1,3 @@ +module github.com/gopherdojo/dojo7/kadai3-1/nas/simpletype + +go 1.13 diff --git a/kadai3-1/nas/simpletype/main.go b/kadai3-1/nas/simpletype/main.go new file mode 100644 index 0000000..d983a2c --- /dev/null +++ b/kadai3-1/nas/simpletype/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "time" + + "github.com/gopherdojo/dojo7/kadai3-1/nas/simpletype/pkg/exercise" +) + +func main() { + e := &exercise.Exercise{ + Questions: []string{"apple", "banana", "cat", "dog", "egg", "fish"}, + } + t := 10 * time.Second + c := &Cli{InputReader: &Reader{}} + c.Run(e, t) +} diff --git a/kadai3-1/nas/simpletype/pkg/exercise/exercise.go b/kadai3-1/nas/simpletype/pkg/exercise/exercise.go new file mode 100644 index 0000000..88e5ec3 --- /dev/null +++ b/kadai3-1/nas/simpletype/pkg/exercise/exercise.go @@ -0,0 +1,28 @@ +package exercise + +// Exercise has questions and now question number +type Exercise struct { + Questions []string + NowQuestionNum int +} + +// Next return Question stil has questions or not +func (e *Exercise) Next() bool { + if e.NowQuestionNum >= len(e.Questions) { + e.NowQuestionNum++ + return false + } + e.NowQuestionNum++ + return true +} + +// Get return question +func (e *Exercise) Get() string { + if e.NowQuestionNum == 0 { + return "" + } + if e.NowQuestionNum > len(e.Questions) { + return "" + } + return e.Questions[e.NowQuestionNum-1] +} diff --git a/kadai3-1/nas/simpletype/pkg/exercise/exercise_test.go b/kadai3-1/nas/simpletype/pkg/exercise/exercise_test.go new file mode 100644 index 0000000..2f40c89 --- /dev/null +++ b/kadai3-1/nas/simpletype/pkg/exercise/exercise_test.go @@ -0,0 +1,49 @@ +package exercise + +import "testing" + +func setup(t *testing.T) *Exercise { + t.Helper() + e := &Exercise{ + Questions: []string{"apple", "banana", "cat", "dog", "egg", "fish"}, + } + return e +} + +func TestExerciseNext(t *testing.T) { + e := setup(t) + if want, got := true, e.Next(); want != got { + t.Errorf("e.Next() => %t, but want %t", got, want) + } +} + +func TestExerciseNextFalse(t *testing.T) { + e := setup(t) + e.NowQuestionNum = 6 + if want, got := false, e.Next(); want != got { + t.Errorf("e.Next() => %t, but want %t", got, want) + } +} + +func TestExerciseGet(t *testing.T) { + e := setup(t) + e.Next() + if want, got := "apple", e.Get(); want != got { + t.Errorf("e.Got() => %s, but want %s", got, want) + } +} + +func TestExerciseGetNoNext(t *testing.T) { + e := setup(t) + if want, got := "", e.Get(); want != got { + t.Errorf("e.Got() => %s, but want %s", got, want) + } +} + +func TestExerciseGetFinished(t *testing.T) { + e := setup(t) + e.NowQuestionNum = 7 + if want, got := "", e.Get(); want != got { + t.Errorf("e.Got() => %s, but want %s", got, want) + } +}