From f964669cc6827c229fc5c17ded6cd9a717ae4090 Mon Sep 17 00:00:00 2001 From: ShintaNakama Date: Mon, 23 Sep 2019 03:19:22 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E5=8B=95=E3=81=8F=E5=BD=A2=E3=81=BE?= =?UTF-8?q?=E3=81=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ README.md | 18 +++------- kadai1/.gitkeep | 0 kadai3-1/shinta/main.go | 62 ++++++++++++++++++++++++++++++++ kadai3-1/shinta/typing/typing.go | 28 +++++++++++++++ 5 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 .gitignore delete mode 100644 kadai1/.gitkeep create mode 100644 kadai3-1/shinta/main.go create mode 100644 kadai3-1/shinta/typing/typing.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e529828 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +testdata + diff --git a/README.md b/README.md index f19aaef..9722074 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,8 @@ -# dojo7 -#7 Gopher道場用のリポジトリです -connpass: https://gopherdojo.connpass.com/event/142892/ +# 課題3 -## 課題の提出方法 - -1回目の課題を提出する場合は次のようにコードを書いて下さい。 - -* ブランチ名を`kadai1-tenntenn`のようにする -* `kadai1/tenntenn`のようにディレクトリを作る -* READMEに説明や文章による課題の回答を書く -* PRを送る - -※FBには時間がかかる可能性があります。 +## タイピングゲームを作ろう +- [x] 標準出力に英単語を出す(出すものは自由) +- [x] 標準入力から1行受け取る +- [x] 制限時間内に何問解けたか表示する diff --git a/kadai1/.gitkeep b/kadai1/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/kadai3-1/shinta/main.go b/kadai3-1/shinta/main.go new file mode 100644 index 0000000..8eec8a4 --- /dev/null +++ b/kadai3-1/shinta/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "os" + "time" + + "github.com/gopherdojo/dojo7/kadai3-1/shinta/typing" +) + +const timeLimit = 5 + +type Typing interface { + ShowText() string + Judge(input string) bool +} + +func main() { + problems := []string{"apple", "bake", "cup", "dog", "egg", "fight", "green", "hoge", "idea", "japan"} + typing := typing.Redy(problems) + chInput := inputRoutine(os.Stdin) + chFinish := time.After(time.Duration(timeLimit) * time.Second) + + execute(chInput, chFinish, os.Stdout, typing) +} + +func execute(chInput <-chan string, chFinish <-chan time.Time, stdout io.Writer, t Typing) { + + score := 0 + for i := 0; ; i++ { + fmt.Fprintf(stdout, "[%03d]: %v\n", i, t.ShowText()) + fmt.Fprint(stdout, "type>>") + select { + case inText := <-chInput: + if t.Judge(inText) { + score++ + fmt.Fprintln(stdout, "Correct!") + } else { + fmt.Fprintln(stdout, "Miss!") + } + case <-chFinish: + fmt.Fprintln(stdout, "\nTime's up!!") + fmt.Fprintf(stdout, "You Scored: %v\n", score) + return + } + } +} + +func inputRoutine(r io.Reader) <-chan string { + ch := make(chan string) + + go func() { + s := bufio.NewScanner(r) + for s.Scan() { + ch <- s.Text() + } + }() + + return ch +} diff --git a/kadai3-1/shinta/typing/typing.go b/kadai3-1/shinta/typing/typing.go new file mode 100644 index 0000000..08b2bb5 --- /dev/null +++ b/kadai3-1/shinta/typing/typing.go @@ -0,0 +1,28 @@ +package typing + +import ( + "math/rand" + "time" +) + +type Typing struct { + wordList []string + nextWord string +} + +func Redy(prolems []string) *Typing { + rand.Seed(time.Now().UnixNano()) + return &Typing{ + wordList: prolems, + } +} + +func (t *Typing) ShowText() string { + i := rand.Int() % len(t.wordList) + t.nextWord = t.wordList[i] + return t.nextWord +} + +func (t *Typing) Judge(inText string) bool { + return inText == t.nextWord +} From 6b5b82944ac602b53c6105ac91f2cafe605c2af8 Mon Sep 17 00:00:00 2001 From: ShintaNakama Date: Mon, 23 Sep 2019 16:27:28 +0900 Subject: [PATCH 2/3] =?UTF-8?q?test=E3=82=82=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-1/shinta/export_test.go | 4 ++ kadai3-1/shinta/go.mod | 3 ++ kadai3-1/shinta/go.sum | 1 + kadai3-1/shinta/main.go | 6 ++- kadai3-1/shinta/main_mock_test.go | 44 +++++++++++++++ kadai3-1/shinta/main_test.go | 77 +++++++++++++++++++++++++++ kadai3-1/shinta/typing/typing.go | 7 ++- kadai3-1/shinta/typing/typing_test.go | 46 ++++++++++++++++ 8 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 kadai3-1/shinta/export_test.go create mode 100644 kadai3-1/shinta/go.mod create mode 100644 kadai3-1/shinta/go.sum create mode 100644 kadai3-1/shinta/main_mock_test.go create mode 100644 kadai3-1/shinta/main_test.go create mode 100644 kadai3-1/shinta/typing/typing_test.go diff --git a/kadai3-1/shinta/export_test.go b/kadai3-1/shinta/export_test.go new file mode 100644 index 0000000..5d70d0f --- /dev/null +++ b/kadai3-1/shinta/export_test.go @@ -0,0 +1,4 @@ +package main + +var Execute = execute +var InputRoutine = inputRoutine diff --git a/kadai3-1/shinta/go.mod b/kadai3-1/shinta/go.mod new file mode 100644 index 0000000..f56eb14 --- /dev/null +++ b/kadai3-1/shinta/go.mod @@ -0,0 +1,3 @@ +module github.com/gopherdojo/dojo7/kadai3-1/shinta + +go 1.12 diff --git a/kadai3-1/shinta/go.sum b/kadai3-1/shinta/go.sum new file mode 100644 index 0000000..5726ce0 --- /dev/null +++ b/kadai3-1/shinta/go.sum @@ -0,0 +1 @@ +github.com/gopherdojo/dojo7 v0.0.0-20190903074013-69385d40c994 h1:UbdhtSFDdFiSYOb/TkEmlRIUFQRrBlKOzVDY3+SXaSw= diff --git a/kadai3-1/shinta/main.go b/kadai3-1/shinta/main.go index 8eec8a4..d995334 100644 --- a/kadai3-1/shinta/main.go +++ b/kadai3-1/shinta/main.go @@ -12,6 +12,10 @@ import ( const timeLimit = 5 +/* +Typing displays the English word in question with the showtext method. +Compare with the value entered in the judge method. +*/ type Typing interface { ShowText() string Judge(input string) bool @@ -29,7 +33,7 @@ func main() { func execute(chInput <-chan string, chFinish <-chan time.Time, stdout io.Writer, t Typing) { score := 0 - for i := 0; ; i++ { + for i := 1; ; i++ { fmt.Fprintf(stdout, "[%03d]: %v\n", i, t.ShowText()) fmt.Fprint(stdout, "type>>") select { diff --git a/kadai3-1/shinta/main_mock_test.go b/kadai3-1/shinta/main_mock_test.go new file mode 100644 index 0000000..4676029 --- /dev/null +++ b/kadai3-1/shinta/main_mock_test.go @@ -0,0 +1,44 @@ +package main_test + +import ( + "io" +) + +//Stdin +type StdinMock struct { + i int + input []string +} + +func (stdin *StdinMock) Read(p []byte) (n int, err error) { + if stdin.i >= len(stdin.input) { + return 0, io.EOF + } + b := []byte(stdin.input[stdin.i] + "\n") //Scanが回るようにLF追加 + copy(p, b) + stdin.i++ + return len(b), nil +} + +//Stdout +type StdoutMock struct { + output []string +} + +func (stdout *StdoutMock) Write(p []byte) (n int, err error) { + str := string(p) + stdout.output = append(stdout.output, str) + return len(str), nil +} + +//Typing +type TypingMock struct { +} + +func (typ *TypingMock) ShowText() string { + return "FOO" +} + +func (typ *TypingMock) Judge(input string) bool { + return "FOO" == input +} diff --git a/kadai3-1/shinta/main_test.go b/kadai3-1/shinta/main_test.go new file mode 100644 index 0000000..7bc7ff5 --- /dev/null +++ b/kadai3-1/shinta/main_test.go @@ -0,0 +1,77 @@ +package main_test + +import ( + "bytes" + "testing" + "time" + + main "github.com/gopherdojo/dojo7/kadai3-1/shinta" +) + +func TestInputRoutine(t *testing.T) { + input := []string{"foo", "bar", "baz", "qux"} + stdin := &StdinMock{ + i: 0, + input: input, + } + + ch := main.InputRoutine(stdin) + + for _, expected := range input { + actual := <-ch + if actual != expected { + t.Errorf("expected:%v, actual:%v", expected, actual) + } + } +} + +func TestExecute(t *testing.T) { + chInput := make(chan string, 3) + chFinish := make(chan time.Time, 1) + + scenario := []struct { + inputText string + time time.Time + }{ + { + inputText: "FOO", + }, + { + inputText: "BAR", + }, + { + inputText: "FOO", + }, + { + time: time.Now(), + }, + } + + buf := bytes.NewBufferString("") + typ := &TypingMock{} + + go func() { + for _, s := range scenario { + time.Sleep(100 * time.Millisecond) + if s.inputText != "" { + chInput <- s.inputText + } + if !s.time.IsZero() { + chFinish <- s.time + } + } + }() + main.Execute(chInput, chFinish, buf, typ) + + expected := []byte("" + + "[001]: FOO\n" + "type>>" + "Correct!\n" + + "[002]: FOO\n" + "type>>" + "Miss!\n" + + "[003]: FOO\n" + "type>>" + "Correct!\n" + + "[004]: FOO\n" + "type>>" + + "\nTime's up!!\n" + + "You Scored: 2\n") + + if bytes.Compare(buf.Bytes(), expected) != 0 { + t.Errorf("[expected]:\n%s\n[actual]:\n%s", expected, buf.Bytes()) + } +} diff --git a/kadai3-1/shinta/typing/typing.go b/kadai3-1/shinta/typing/typing.go index 08b2bb5..765cbbe 100644 --- a/kadai3-1/shinta/typing/typing.go +++ b/kadai3-1/shinta/typing/typing.go @@ -5,24 +5,29 @@ import ( "time" ) +// Typing represents a list of English words and a single word extracted from it. type Typing struct { wordList []string nextWord string } +// Redy function is a constructor for typing struct. func Redy(prolems []string) *Typing { + // 乱数の初期化 rand.Seed(time.Now().UnixNano()) return &Typing{ wordList: prolems, } } +// ShowText method returns one English word randomly from the English word list. func (t *Typing) ShowText() string { - i := rand.Int() % len(t.wordList) + i := rand.Intn(len(t.wordList)) t.nextWord = t.wordList[i] return t.nextWord } +// Judge method determines whether the sent word and the nextText of the typing structure are the same func (t *Typing) Judge(inText string) bool { return inText == t.nextWord } diff --git a/kadai3-1/shinta/typing/typing_test.go b/kadai3-1/shinta/typing/typing_test.go new file mode 100644 index 0000000..da7dae5 --- /dev/null +++ b/kadai3-1/shinta/typing/typing_test.go @@ -0,0 +1,46 @@ +package typing_test + +import ( + "testing" + + "github.com/gopherdojo/dojo7/kadai3-1/shinta/typing" +) + +var problems = []string{"apple", "bake", "cup", "dog", "egg", "fight", "green", "hoge", "idea", "japan"} + +func includes(s string) bool { + for _, v := range problems { + if v == s { + return true + } + } + return false +} + +func TestShowText(t *testing.T) { + typ := typing.Redy(problems) + for i := 0; i < len(problems); i++ { + txt := typ.ShowText() + if !includes(txt) { + t.Errorf("actual: %v\n", txt) + } + } +} + +func TestJudge(t *testing.T) { + typ := typing.Redy(problems) + txt := typ.ShowText() + + if !typ.Judge(txt) { + t.Errorf("Judge() must be true") + } +} + +func TestJudgeFailed(t *testing.T) { + typ := typing.Redy(problems) + typ.ShowText() + + if typ.Judge("TTT") { + t.Errorf("Judge() must be false") + } +} From 4b7253f6b007c6943af8bcf889ef088bd960880f Mon Sep 17 00:00:00 2001 From: ShintaNakama Date: Mon, 23 Sep 2019 23:03:54 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai3-1/shinta/main_test.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/kadai3-1/shinta/main_test.go b/kadai3-1/shinta/main_test.go index 7bc7ff5..8a50283 100644 --- a/kadai3-1/shinta/main_test.go +++ b/kadai3-1/shinta/main_test.go @@ -9,12 +9,12 @@ import ( ) func TestInputRoutine(t *testing.T) { - input := []string{"foo", "bar", "baz", "qux"} + input := []string{"apple", "bake", "cup", "dog"} + // StdinMockのinputに、標準入力で送信されたと仮定した文字列が入る stdin := &StdinMock{ i: 0, input: input, } - ch := main.InputRoutine(stdin) for _, expected := range input { @@ -34,19 +34,20 @@ func TestExecute(t *testing.T) { time time.Time }{ { - inputText: "FOO", + inputText: "apple", }, { - inputText: "BAR", + inputText: "bbaak", }, { - inputText: "FOO", + inputText: "cup", }, { time: time.Now(), }, } + // 新しく文字列を格納するbufferを確保 buf := bytes.NewBufferString("") typ := &TypingMock{} @@ -64,13 +65,14 @@ func TestExecute(t *testing.T) { main.Execute(chInput, chFinish, buf, typ) expected := []byte("" + - "[001]: FOO\n" + "type>>" + "Correct!\n" + - "[002]: FOO\n" + "type>>" + "Miss!\n" + - "[003]: FOO\n" + "type>>" + "Correct!\n" + - "[004]: FOO\n" + "type>>" + + "[001]: apple\n" + "type>>" + "Correct!\n" + + "[002]: bake\n" + "type>>" + "Miss!\n" + + "[003]: cup\n" + "type>>" + "Correct!\n" + + "[004]: dog\n" + "type>>" + "\nTime's up!!\n" + "You Scored: 2\n") + // byteスライスの比較、a == bの場合は0を返す if bytes.Compare(buf.Bytes(), expected) != 0 { t.Errorf("[expected]:\n%s\n[actual]:\n%s", expected, buf.Bytes()) }