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

Kadai3-1: lfcd85 #28

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions kadai3-1/lfcd85/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin/typinggame
12 changes: 12 additions & 0 deletions kadai3-1/lfcd85/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
build: cmd/*.go typinggame/*.go words/*.go
GO111MODULE=on go build -o bin/typinggame cmd/main.go

fmt:
go fmt ./...
go vet ./...

check:
GO111MODULE=on go test ./... -v

coverage:
GO111MODULE=on go test ./... -cover
41 changes: 41 additions & 0 deletions kadai3-1/lfcd85/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Typing Game

An implementation for the typing game, kadai3-1 of Gopherdojo #5. The standard library packages for Golang are the words for typing.

Gopher道場 #5 課題3-1 `タイピングゲームを作ろう` の実装です。Go言語の標準ライブラリのパッケージ名がタイピング対象の単語になっています。

## Installation

```bash
$ make build
```

## Usage

The game starts after executing the command below. Let's type the shown package name. Your score will be shown after reaching to the time limit and finishing the game.

下記のコマンドを実行するとゲームが開始します。表示されたパッケージ名をタイプしてください。制限時間に達するとゲームが終了し、スコアが表示されます。

```bash
$ bin/typinggame
Let's type the standard package names! ( Time limit: 30s )
> hash/fnv
hash/fnv
hash/fnv ... OK! current score: 1

> debug
d
d ... NG: try again.
> debug

30s has passed: you correctly typed 1 package(s)!
```

The time limit can be set by `-t` option. Default value is 30 sec.

制限時間は `-t` オプションで変更可能です。デフォルトは30秒です。

```bash
$ bin/typinggame -t 10
Let's type the standard package names! ( Time limit: 10s )
```
Empty file added kadai3-1/lfcd85/bin/.gitkeep
Empty file.
32 changes: 32 additions & 0 deletions kadai3-1/lfcd85/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"flag"
"fmt"
"time"

"github.com/gopherdojo/dojo5/kadai3-1/lfcd85/typinggame"
"github.com/gopherdojo/dojo5/kadai3-1/lfcd85/words"
)

const path = "./testdata/go_standard_library.txt"

func main() {
timeLimit := flag.Int("t", 30, "Time limit of the game (sec)")
flag.Parse()

words, err := words.Import(path)
if err != nil {
fmt.Println("error:", err)
return
}
g := typinggame.Game{
Words: words,
TimeLimit: time.Duration(*timeLimit) * time.Second,
}

if err := typinggame.Execute(g); err != nil {
fmt.Println("error:", err)
return
}
}
5 changes: 5 additions & 0 deletions kadai3-1/lfcd85/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/gopherdojo/dojo5/kadai3-1/lfcd85

go 1.12

require github.com/hashicorp/go-multierror v1.0.0
4 changes: 4 additions & 0 deletions kadai3-1/lfcd85/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
3 changes: 3 additions & 0 deletions kadai3-1/lfcd85/testdata/abc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
a
b
c
154 changes: 154 additions & 0 deletions kadai3-1/lfcd85/testdata/go_standard_library.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
archive
archive/tar
archive/zip
bufio
builtin
bytes
compress
compress/bzip2
compress/flate
compress/gzip
compress/lzw
compress/zlib
container
container/heap
container/list
container/ring
context
crypto
crypto/aes
crypto/cipher
crypto/des
crypto/dsa
crypto/ecdsa
crypto/elliptic
crypto/hmac
crypto/md5
crypto/rand
crypto/rc4
crypto/rsa
crypto/sha1
crypto/sha256
crypto/sha512
crypto/subtle
crypto/tls
crypto/x509
crypto/x509/pkix
database
database/sql
database/sql/driver
debug
debug/dwarf
debug/elf
debug/gosym
debug/macho
debug/pe
debug/plan9obj
encoding
encoding/ascii85
encoding/asn1
encoding/base32
encoding/base64
encoding/binary
encoding/csv
encoding/gob
encoding/hex
encoding/json
encoding/pem
encoding/xml
errors
expvar
flag
fmt
go
go/ast
go/build
go/constant
go/doc
go/format
go/importer
go/parser
go/printer
go/scanner
go/token
go/types
hash
hash/adler32
hash/crc32
hash/crc64
hash/fnv
html
html/template
image
image/color
image/color/palette
image/draw
image/gif
image/jpeg
image/png
index
index/suffixarray
io
io/ioutil
log
log/syslog
math
math/big
math/bits
math/cmplx
math/rand
mime
mime/multipart
mime/quotedprintable
net
net/http
net/http/cgi
net/http/cookiejar
net/http/fcgi
net/http/httptest
net/http/httptrace
net/http/httputil
net/http/pprof
net/mail
net/rpc
net/rpc/jsonrpc
net/smtp
net/textproto
net/url
os
os/exec
os/signal
os/user
path
path/filepath
plugin
reflect
regexp
regexp/syntax
runtime
runtime/cgo
runtime/debug
runtime/msan
runtime/pprof
runtime/race
runtime/trace
sort
strconv
strings
sync
sync/atomic
syscall
syscall/js
testing
testing/iotest
testing/quick
text
text/scanner
text/tabwriter
text/template
text/template/parse
time
unicode
unicode/utf16
unicode/utf8
unsafe
3 changes: 3 additions & 0 deletions kadai3-1/lfcd85/typinggame/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package typinggame

var ExportGameRun = (*Game).run
81 changes: 81 additions & 0 deletions kadai3-1/lfcd85/typinggame/typinggame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package typinggame

import (
"bufio"
"context"
"fmt"
"io"
"math/rand"
"os"
"time"

"github.com/hashicorp/go-multierror"
)

// Words stores a slice of words which is used for the game.
type Words []string

// Game struct holds the words and the time limits of the game.
type Game struct {
Words Words
TimeLimit time.Duration
}

// Execute starts the game using standard input and output.
func Execute(g Game) error {
err := g.run(inputChannel(os.Stdin), os.Stdout)
return err
}

func (g *Game) run(ch <-chan string, w io.Writer) error {
var result error

bc := context.Background()
ctx, cancel := context.WithTimeout(bc, g.TimeLimit)
defer cancel()

result = printWithMultiErr(w, result, "Let's type the standard package names! ( Time limit:", g.TimeLimit, ")")

var score int
rand.Seed(time.Now().UnixNano())
word := g.Words[rand.Intn(len(g.Words))]
LOOP:
for {
result = printWithMultiErr(w, result, ">", word)
select {
case input := <-ch:
if input == word {
score++
result = printWithMultiErr(w, result, input, "... OK! current score:", score)
word = g.Words[rand.Intn(len(g.Words))]
} else {
result = printWithMultiErr(w, result, input, "... NG: try again.")
}
case <-ctx.Done():
result = printWithMultiErr(w, result)
result = printWithMultiErr(w, result, g.TimeLimit, "has passed: you correctly typed", score, "package(s)!")
break LOOP
}
}

return result
}

func inputChannel(r io.Reader) <-chan string {
ch := make(chan string)

go func() {
s := bufio.NewScanner(r)
for s.Scan() {
ch <- s.Text()
}
}()
return ch
}

func printWithMultiErr(w io.Writer, result error, a ...interface{}) error {
if _, err := fmt.Fprintln(w, a...); err != nil {
result = multierror.Append(result, err)
}
return result
}
Loading