Skip to content

[課題3-1] タイピングゲームを作ろう kadai3-1 #36

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

Open
wants to merge 9 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
38 changes: 38 additions & 0 deletions kadai3-1/nas/simpletype/Makefile
Original file line number Diff line number Diff line change
@@ -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'
70 changes: 70 additions & 0 deletions kadai3-1/nas/simpletype/cli.go
Original file line number Diff line number Diff line change
@@ -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()
}
}
}
}
53 changes: 53 additions & 0 deletions kadai3-1/nas/simpletype/cli_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})

}
}
3 changes: 3 additions & 0 deletions kadai3-1/nas/simpletype/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo7/kadai3-1/nas/simpletype

go 1.13
16 changes: 16 additions & 0 deletions kadai3-1/nas/simpletype/main.go
Original file line number Diff line number Diff line change
@@ -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)
}
28 changes: 28 additions & 0 deletions kadai3-1/nas/simpletype/pkg/exercise/exercise.go
Original file line number Diff line number Diff line change
@@ -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]
}
49 changes: 49 additions & 0 deletions kadai3-1/nas/simpletype/pkg/exercise/exercise_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}