Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kadai 3-1 shinta #34

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
testdata

18 changes: 5 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -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] 制限時間内に何問解けたか表示する

Empty file removed kadai1/.gitkeep
Empty file.
4 changes: 4 additions & 0 deletions kadai3-1/shinta/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package main

var Execute = execute
var InputRoutine = inputRoutine
3 changes: 3 additions & 0 deletions kadai3-1/shinta/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo7/kadai3-1/shinta

go 1.12
1 change: 1 addition & 0 deletions kadai3-1/shinta/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github.com/gopherdojo/dojo7 v0.0.0-20190903074013-69385d40c994 h1:UbdhtSFDdFiSYOb/TkEmlRIUFQRrBlKOzVDY3+SXaSw=
66 changes: 66 additions & 0 deletions kadai3-1/shinta/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package main

import (
"bufio"
"fmt"
"io"
"os"
"time"

"github.com/gopherdojo/dojo7/kadai3-1/shinta/typing"
)

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
}

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ゼロ値

for i := 1; ; 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() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

タイムアウトした場合のこのゴールーチンの終了は?

s := bufio.NewScanner(r)
for s.Scan() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラー処理

ch <- s.Text()
}
}()

return ch
}
44 changes: 44 additions & 0 deletions kadai3-1/shinta/main_mock_test.go
Original file line number Diff line number Diff line change
@@ -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
}
79 changes: 79 additions & 0 deletions kadai3-1/shinta/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main_test

import (
"bytes"
"testing"
"time"

main "github.com/gopherdojo/dojo7/kadai3-1/shinta"
)

func TestInputRoutine(t *testing.T) {
input := []string{"apple", "bake", "cup", "dog"}
// StdinMockのinputに、標準入力で送信されたと仮定した文字列が入る
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: "apple",
},
{
inputText: "bbaak",
},
{
inputText: "cup",
},
{
time: time.Now(),
},
}

// 新しく文字列を格納するbufferを確保
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]: 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())
}
}
33 changes: 33 additions & 0 deletions kadai3-1/shinta/typing/typing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package typing

import (
"math/rand"
"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.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
}
46 changes: 46 additions & 0 deletions kadai3-1/shinta/typing/typing_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
}