From 4336153ea3a4ebfeb15dc02d8f43fb8994933230 Mon Sep 17 00:00:00 2001 From: mi-bear Date: Sun, 4 Aug 2019 15:56:01 +0900 Subject: [PATCH 1/3] [wip] kadai3-1-micchie first commit --- kadai3/micchie/typing-game/.gitignore | 1 + kadai3/micchie/typing-game/Makefile | 40 +++++++++++ kadai3/micchie/typing-game/README.md | 6 ++ kadai3/micchie/typing-game/config.yml | 14 ++++ kadai3/micchie/typing-game/game/game.go | 94 +++++++++++++++++++++++++ kadai3/micchie/typing-game/go.mod | 8 +++ kadai3/micchie/typing-game/go.sum | 9 +++ kadai3/micchie/typing-game/main.go | 42 +++++++++++ 8 files changed, 214 insertions(+) create mode 100644 kadai3/micchie/typing-game/.gitignore create mode 100644 kadai3/micchie/typing-game/Makefile create mode 100644 kadai3/micchie/typing-game/README.md create mode 100644 kadai3/micchie/typing-game/config.yml create mode 100644 kadai3/micchie/typing-game/game/game.go create mode 100644 kadai3/micchie/typing-game/go.mod create mode 100644 kadai3/micchie/typing-game/go.sum create mode 100644 kadai3/micchie/typing-game/main.go diff --git a/kadai3/micchie/typing-game/.gitignore b/kadai3/micchie/typing-game/.gitignore new file mode 100644 index 0000000..4584eaf --- /dev/null +++ b/kadai3/micchie/typing-game/.gitignore @@ -0,0 +1 @@ +typing-game diff --git a/kadai3/micchie/typing-game/Makefile b/kadai3/micchie/typing-game/Makefile new file mode 100644 index 0000000..4ad1876 --- /dev/null +++ b/kadai3/micchie/typing-game/Makefile @@ -0,0 +1,40 @@ +NAME := typing-game +SRCS := $(shell find ./ -type f -name '*.go') +VERSION := v0.0.1 +REVISION := $(shell git rev-parse --short HEAD) +PKGPATH := github.com/gopherdojo/dojo6/kadai3/micchie/typing-game +LDFLAGS := -ldflags \ + '-s -w \ + -X "$(PKGPATH)/cmd.Version=$(VERSION)" \ + -X "$(PKGPATH)/cmd.Revision=$(REVISION)" \ + -extldflags "-static"' + +DIST_DIRS := find * -type d -exec + +$(NAME): $(SRCS) + go build -a -tags netgo -installsuffix netgo $(LDFLAGS) -o $(NAME) + +.PHONY: install +install: + go install $(LDFLAGS) + +.PHONY: clean +clean: + rm -rf $(NAME) + +.PHONY: cross-build +cross-build: deps + for os in darwin linux windows; do \ + for arch in amd64 386; do \ + GOOS=$$os GOARCH=$$arch CGO_ENABLED=0 go build -a -tags netgo -installsuffix netgo $(LDFLAGS) -o dist/$$os-$$arch/$(NAME); \ + done; \ + done + +.PHONY: dist +dist: + cd dist && \ + $(DIST_DIRS) cp ../LICENSE {} \; && \ + $(DIST_DIRS) cp ../README.md {} \; && \ + $(DIST_DIRS) tar -zcf $(NAME)-$(VERSION)-{}.tar.gz {} \; && \ + $(DIST_DIRS) zip -r $(NAME)-$(VERSION)-{}.zip {} \; && \ + cd .. \ No newline at end of file diff --git a/kadai3/micchie/typing-game/README.md b/kadai3/micchie/typing-game/README.md new file mode 100644 index 0000000..0374c74 --- /dev/null +++ b/kadai3/micchie/typing-game/README.md @@ -0,0 +1,6 @@ +# Gopher 道場 +## 6-3-1: タイピングゲームを作ろう +- 標準出力に英単語を出す +- 標準入力から1行受け取る +- 制限時間内に何問解けたか表示する + diff --git a/kadai3/micchie/typing-game/config.yml b/kadai3/micchie/typing-game/config.yml new file mode 100644 index 0000000..fcf5610 --- /dev/null +++ b/kadai3/micchie/typing-game/config.yml @@ -0,0 +1,14 @@ +limit: 10 + +words: + - gopher + - polarbear + - blackbear + - elephant + - tiger + - camel + - lion + - panda + - leopard + - kangaroo + diff --git a/kadai3/micchie/typing-game/game/game.go b/kadai3/micchie/typing-game/game/game.go new file mode 100644 index 0000000..2e448f9 --- /dev/null +++ b/kadai3/micchie/typing-game/game/game.go @@ -0,0 +1,94 @@ +package game + +import ( + "bufio" + "context" + "fmt" + "io" + "time" +) + +// Game はtタイピングゲームのコンテキストや入出力などの情報を格納します. +type Game struct { + Context context.Context + Output io.Writer + Input io.Reader + TimeLimit time.Duration + Words []string + Score Score +} + +// Score はゲーム結果を格納します. +type Score struct { + Count int + CorrectNumber int +} + +// NewGame は Gme の構造体を新しく作ります. +func NewGame(ctx context.Context, w io.Writer, r io.Reader, t time.Duration, words []string) *Game { + return &Game{ + Context: ctx, + Output: w, + Input: r, + TimeLimit: t, + Words: words, + } +} + +// Run は TimeLimit に経過時間が達するまで Words をランダムに表示します. +// Word と同じ文字列を入力すると, correct!! 異なった文字列を入力すると, incorrect!! と表示されます. +func (g *Game) Run() error { + fmt.Fprintln(g.Output, "===== Typing Game Start =====") + + scan := make(chan string) + go func() { + scanner := bufio.NewScanner(g.Input) + defer close(scan) + for scanner.Scan() { + scan <- scanner.Text() + } + }() + + for { + word := g.Words[g.Score.Count] + fmt.Fprintln(g.Output, fmt.Sprintf("> %v", word)) + g.Score.Count++ + + switch { + case g.Score.Count == len(g.Words): + fmt.Fprintln(g.Output, fmt.Sprintf( + "\n===== Typing Game Finished =====\n%vwords completed. %v times corrected.\n", + g.Score.Count, + g.Score.CorrectNumber, + )) + return nil + + } + + select { + case <-g.Context.Done(): + fmt.Fprintln(g.Output, fmt.Sprintf( + "\n===== Typing Game Finished =====\n%v have passed. %v times corrected.\n", + g.TimeLimit, + g.Score.CorrectNumber, + )) + return nil + case input := <-scan: + switch { + case g.Judgment(word, input): + fmt.Fprintln(g.Output, "correct!!") + default: + fmt.Fprintln(g.Output, "incorrect!!") + } + } + } +} + +// Judgment は Word と同じ文字列が入力されているかを判断し, 正解数をインクリメントします. +func (g *Game) Judgment(word, input string) bool { + if word == input { + g.Score.CorrectNumber++ + return true + } + return false +} diff --git a/kadai3/micchie/typing-game/go.mod b/kadai3/micchie/typing-game/go.mod new file mode 100644 index 0000000..e290609 --- /dev/null +++ b/kadai3/micchie/typing-game/go.mod @@ -0,0 +1,8 @@ +module github.com/gopherdojo/dojo6/kadai3/micchie/typing-game + +go 1.12 + +require ( + github.com/jinzhu/configor v1.1.1 + github.com/pkg/errors v0.8.1 +) diff --git a/kadai3/micchie/typing-game/go.sum b/kadai3/micchie/typing-game/go.sum new file mode 100644 index 0000000..623197a --- /dev/null +++ b/kadai3/micchie/typing-game/go.sum @@ -0,0 +1,9 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/jinzhu/configor v1.1.1 h1:gntDP+ffGhs7aJ0u8JvjCDts2OsxsI7bnz3q+jC+hSY= +github.com/jinzhu/configor v1.1.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/kadai3/micchie/typing-game/main.go b/kadai3/micchie/typing-game/main.go new file mode 100644 index 0000000..20025f8 --- /dev/null +++ b/kadai3/micchie/typing-game/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "math/rand" + "os" + "time" + + "github.com/gopherdojo/dojo6/kadai3/micchie/typing-game/game" + "github.com/jinzhu/configor" +) + +// Config is a structure of config.yml. +var Config = struct { + Limit time.Duration `default:"30"` + Words []string +}{} + +func main() { + configor.Load(&Config, "config.yml") + + t := Config.Limit * time.Second + + ctx, cancel := context.WithTimeout(context.Background(), t) + defer cancel() + + list := Config.Words + shuffle(list) + + g := game.NewGame(ctx, os.Stdout, os.Stdin, t, list) + if err := g.Run(); err != nil { + os.Exit(0) + } +} + +func shuffle(list []string) { + rand.Seed(time.Now().UnixNano()) + for i := range list { + j := rand.Intn(i + 1) + list[i], list[j] = list[j], list[i] + } +} From 8a56ed63a3e23df427431835d6b2ebeaa2f66ecb Mon Sep 17 00:00:00 2001 From: mi-bear Date: Sun, 4 Aug 2019 22:12:53 +0900 Subject: [PATCH 2/3] add judgment test --- .../typing-game/game_test/game_test.go | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 kadai3/micchie/typing-game/game_test/game_test.go diff --git a/kadai3/micchie/typing-game/game_test/game_test.go b/kadai3/micchie/typing-game/game_test/game_test.go new file mode 100644 index 0000000..0de819d --- /dev/null +++ b/kadai3/micchie/typing-game/game_test/game_test.go @@ -0,0 +1,47 @@ +package game_test + +import ( + "testing" + + "github.com/gopherdojo/dojo6/kadai3/micchie/typing-game/game" +) + +func TestGame_Run(t *testing.T) { +} + +func TestGame_Judgment(t *testing.T) { + g := &game.Game{} + tests := []struct { + name string + word string + input string + beforeCorrectNumber int + afterCorrectNumber int + result bool + }{ + {name: "nomal", word: "bear", input: "bear", beforeCorrectNumber: 1, afterCorrectNumber: 2, result: true}, + {name: "blank", word: "cat", input: "", beforeCorrectNumber: 1, afterCorrectNumber: 1, result: false}, + {name: "incorrect", word: "dog", input: "d", beforeCorrectNumber: 0, afterCorrectNumber: 0, result: false}, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + g.Score.CorrectNumber = test.beforeCorrectNumber + result := g.Judgment(test.word, test.input) + + if result != test.result { + t.Errorf( + "word: %v, input: %v, beforeCorrect: %v, afterCorrect: %v (want: %v, got: %v)", + test.word, + test.input, + test.beforeCorrectNumber, + test.afterCorrectNumber, + test.result, + result, + ) + } + }) + } +} From 0ecabb472361cdf9622d11a153d895a7666af01d Mon Sep 17 00:00:00 2001 From: mi-bear Date: Sun, 4 Aug 2019 22:44:14 +0900 Subject: [PATCH 3/3] add scan error --- kadai3/micchie/typing-game/.gitignore | 1 + kadai3/micchie/typing-game/game/game.go | 11 +++++++---- .../micchie/typing-game/game_test/game_test.go | 16 ++++++++++++++++ kadai3/micchie/typing-game/go.mod | 5 +---- kadai3/micchie/typing-game/go.sum | 2 -- kadai3/micchie/typing-game/main.go | 4 +--- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/kadai3/micchie/typing-game/.gitignore b/kadai3/micchie/typing-game/.gitignore index 4584eaf..9872947 100644 --- a/kadai3/micchie/typing-game/.gitignore +++ b/kadai3/micchie/typing-game/.gitignore @@ -1 +1,2 @@ +.vscode typing-game diff --git a/kadai3/micchie/typing-game/game/game.go b/kadai3/micchie/typing-game/game/game.go index 2e448f9..5ea6954 100644 --- a/kadai3/micchie/typing-game/game/game.go +++ b/kadai3/micchie/typing-game/game/game.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io" + "os" "time" ) @@ -37,7 +38,7 @@ func NewGame(ctx context.Context, w io.Writer, r io.Reader, t time.Duration, wor // Run は TimeLimit に経過時間が達するまで Words をランダムに表示します. // Word と同じ文字列を入力すると, correct!! 異なった文字列を入力すると, incorrect!! と表示されます. -func (g *Game) Run() error { +func (g *Game) Run() { fmt.Fprintln(g.Output, "===== Typing Game Start =====") scan := make(chan string) @@ -47,6 +48,9 @@ func (g *Game) Run() error { for scanner.Scan() { scan <- scanner.Text() } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "input:", err) + } }() for { @@ -61,8 +65,7 @@ func (g *Game) Run() error { g.Score.Count, g.Score.CorrectNumber, )) - return nil - + return } select { @@ -72,7 +75,7 @@ func (g *Game) Run() error { g.TimeLimit, g.Score.CorrectNumber, )) - return nil + return case input := <-scan: switch { case g.Judgment(word, input): diff --git a/kadai3/micchie/typing-game/game_test/game_test.go b/kadai3/micchie/typing-game/game_test/game_test.go index 0de819d..86d0439 100644 --- a/kadai3/micchie/typing-game/game_test/game_test.go +++ b/kadai3/micchie/typing-game/game_test/game_test.go @@ -2,11 +2,27 @@ package game_test import ( "testing" + "time" "github.com/gopherdojo/dojo6/kadai3/micchie/typing-game/game" ) func TestGame_Run(t *testing.T) { + g := &game.Game{} + g.TimeLimit = 5 * time.Second + g.Words = []string{ + "bear", + "bear", + } + + ch := make(chan string) + go func() { + time.Sleep(2 * time.Second) + ch <- "bear" + time.Sleep(2 * time.Second) + ch <- "beer" + }() + } func TestGame_Judgment(t *testing.T) { diff --git a/kadai3/micchie/typing-game/go.mod b/kadai3/micchie/typing-game/go.mod index e290609..2f7f993 100644 --- a/kadai3/micchie/typing-game/go.mod +++ b/kadai3/micchie/typing-game/go.mod @@ -2,7 +2,4 @@ module github.com/gopherdojo/dojo6/kadai3/micchie/typing-game go 1.12 -require ( - github.com/jinzhu/configor v1.1.1 - github.com/pkg/errors v0.8.1 -) +require github.com/jinzhu/configor v1.1.1 diff --git a/kadai3/micchie/typing-game/go.sum b/kadai3/micchie/typing-game/go.sum index 623197a..226e66d 100644 --- a/kadai3/micchie/typing-game/go.sum +++ b/kadai3/micchie/typing-game/go.sum @@ -2,8 +2,6 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/jinzhu/configor v1.1.1 h1:gntDP+ffGhs7aJ0u8JvjCDts2OsxsI7bnz3q+jC+hSY= github.com/jinzhu/configor v1.1.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/kadai3/micchie/typing-game/main.go b/kadai3/micchie/typing-game/main.go index 20025f8..66ded73 100644 --- a/kadai3/micchie/typing-game/main.go +++ b/kadai3/micchie/typing-game/main.go @@ -28,9 +28,7 @@ func main() { shuffle(list) g := game.NewGame(ctx, os.Stdout, os.Stdin, t, list) - if err := g.Run(); err != nil { - os.Exit(0) - } + g.Run() } func shuffle(list []string) {