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

tsuchinaga / 課題3 #23

Open
wants to merge 2 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 kadai3-1/tsuchinaga/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
*.iml
20 changes: 20 additions & 0 deletions kadai3-1/tsuchinaga/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 課題3-1 tsuchinaga

## タイピングゲームを作ろう
* 標準出力に英単語を出す(出すものは自由)
* 標準入力から1行受け取る
* 制限時間内に何問解けたか表示する

### ヒント
* 制限時間にはtime.After関数を用いる
* context.WithTimeoutでもよい
* select構文を用いる
* 制限時間と入力を同時に待つ

## TODO
* [x] タイピングゲームができる
* [x] ランダムなアルファベットが3~6文字表示される
* [x] 標準入力にて解答を受け付ける
* [x] 表示と入力を繰り返す
* [x] 状態にかかわらず15秒で終了する
* [x] 終了時に、表示と入力の一致回数を表示する
3 changes: 3 additions & 0 deletions kadai3-1/tsuchinaga/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo8/kadai3-1/tsuchinaga

go 1.14
34 changes: 34 additions & 0 deletions kadai3-1/tsuchinaga/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"bufio"
"os"
"time"

"github.com/gopherdojo/dojo8/kadai3-1/tsuchinaga/typinggame"
)

func main() {
bs := bufio.NewScanner(os.Stdin)
bs.Split(bufio.ScanLines)

g := typinggame.New(time.Now().UnixNano())

tCh := time.After(15 * time.Second)
for {
iCh := make(chan string)
go func() {
println(g.Next())
bs.Scan()
iCh <- bs.Text()
}()

select {
case ans := <-iCh:
g.Answer(ans)
case _ = <-tCh:
println("\nResult", g.Result())
return
}
}
}
57 changes: 57 additions & 0 deletions kadai3-1/tsuchinaga/typinggame/typinggame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package typinggame

import (
"math/rand"
"sync"
)

// New - 新しいタイピンゲームの生成
func New(seed int64) Game {
return &game{
r: rand.New(rand.NewSource(seed)),
}
}

// Game - ゲームのinterface
type Game interface {
Next() string
Answer(ans string)
Result() int
}

// game - ゲーム
type game struct {
r *rand.Rand // 乱数
q string // 問題
pass int // 正答数
mutex sync.Mutex
}

// Next - 次の問題
func (g *game) Next() string {
g.mutex.Lock()
defer g.mutex.Unlock()

g.q = ""
n := g.r.Intn(4) + 3
for i := 0; i < n; i++ {
g.q += string('a' + g.r.Intn(24))
}
return g.q
}

// Answer - 回答入力
func (g *game) Answer(ans string) {
g.mutex.Lock()
defer g.mutex.Unlock()

if g.q == ans {
g.pass++
}
}

func (g *game) Result() int {
g.mutex.Lock()
defer g.mutex.Unlock()
return g.pass
}
114 changes: 114 additions & 0 deletions kadai3-1/tsuchinaga/typinggame/typinggame_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package typinggame

import (
"math/rand"
"testing"
)

func Test_game_Next(t *testing.T) {
t.Parallel()
type fields struct {
r *rand.Rand
q string
pass int
}
tests := []struct {
name string
fields fields
want string
}{
{name: "randの値が98の場合は3文字", fields: fields{r: rand.New(rand.NewSource(98))}, want: "nnn"},
{name: "randの値が99の場合は4文字", fields: fields{r: rand.New(rand.NewSource(99))}, want: "hsso"},
{name: "randの値が83の場合は5文字", fields: fields{r: rand.New(rand.NewSource(83))}, want: "jdree"},
{name: "randの値が79の場合は6文字", fields: fields{r: rand.New(rand.NewSource(79))}, want: "wqtjme"},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
g := &game{}

// ロックのテスト
g.mutex.Lock()
go func() {
defer g.mutex.Unlock()
g.r = tt.fields.r
}()

if got := g.Next(); got != tt.want {
t.Errorf("Next() = %v, want %v", got, tt.want)
}
})
}
}

func Test_game_Answer(t *testing.T) {
t.Parallel()

type fields struct {
q string
pass int
}
type args struct {
ans string
}
tests := []struct {
name string
fields fields
args args
want int
}{
{name: "qとansが一致している場合にpassが加算される", fields: fields{q: "foo", pass: 3}, args: args{ans: "foo"}, want: 4},
{name: "qとansが一致していない場合はpassは変わらない", fields: fields{q: "foo", pass: 3}, args: args{ans: "foo"}, want: 4},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
g := &game{}

// ロックのテスト
g.mutex.Lock()
go func() {
defer g.mutex.Unlock()
g.q = tt.fields.q
g.pass = tt.fields.pass
}()

g.Answer(tt.args.ans)
if g.pass != tt.want {
t.Errorf("game.pass = %v, want %v", g.pass, tt.want)
}
})
}
}

func Test_game_Result(t *testing.T) {
t.Parallel()
type fields struct {
pass int
}
tests := []struct {
name string
fields fields
want int
}{
{name: "passが0なら0が返される", fields: fields{pass: 0}, want: 0},
{name: "passが3なら3が返される", fields: fields{pass: 3}, want: 3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := &game{}

// ロックのテスト
g.mutex.Lock()
go func() {
defer g.mutex.Unlock()
g.pass = tt.fields.pass
}()
if got := g.Result(); got != tt.want {
t.Errorf("Result() = %v, want %v", got, tt.want)
}
})
}
}
19 changes: 19 additions & 0 deletions kadai3-2/tsuchinaga/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 課題3-2 tsuchinaga

## 分割ダウンロードを行う
* Rangeアクセスを用いる
* いくつかのゴルーチンでダウンロードしてマージする
* エラー処理を工夫する
* golang.org/x/sync/errgourpパッケージなどを使ってみる
* キャンセルが発生した場合の実装を行う

## TODO
* [x] 分割ダウンロードを行なう
* [x] ダウンロードするファイルをURLで指定できる
* [x] ダウンロードするファイルを指定していなかったらエラー
* [x] ダウンロードするファイルのURLが存在しなかったらエラー
* [x] 指定されたURLを分割してダウンロードできる
* [x] 指定範囲をダウンロードする
* [x] ダウンロードした結果をマージしてファイルに出力する
* [x] 並列ダウンロードしているうち、ひとつでも失敗したらエラーを出して終了
* [x] SIGINTをキャッチして中断することができる
Loading