Skip to content

Kadai4 gosagawa #66

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 15 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions kadai4/gosagawa/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bin/*
!.gitkeep

17 changes: 17 additions & 0 deletions kadai4/gosagawa/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
VERSION=1.0.0
TARGETS_NOVENDOR=$(shell go list ./... | grep -v /vendor/)

all: bin/main

bin/main: main.go
go build -o bin/main main.go

fmt:
@echo ./... | xargs go fmt

check:
go test -v -cover ./...

clean:
rm -rf bin/*

38 changes: 38 additions & 0 deletions kadai4/gosagawa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# kadai4

- おみくじAPIを作ってみよう
- JSON形式でおみくじの結果を返す
- 正月(1/1-1/3)だけ大吉にする
- ハンドラのテストを書いてみる

#install

```shell
$ make
```

#usage

- 実行するとポート8080でサーバが起動されます。
```shell
$ bin/main
```

- アクセスすると、その日のおみくじ結果を返します。
```shell
$ curl "http://127.0.0.1:8080/"
{"result":"吉"}
```

- パラメータでdateを指定すると、その日のおみくじ結果を確認できます。
```shell
$ curl "http://127.0.0.1:8080/?date=2019-01-02"
{"result":"大吉"}
```

#test

```shell
$ make check
```

Empty file added kadai4/gosagawa/bin/.gitkeep
Empty file.
38 changes: 38 additions & 0 deletions kadai4/gosagawa/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"encoding/json"
"log"
"net/http"

"github.com/gopherdojo/dojo3/kadai4/gosagawa/omikuzi"
)

//OmikuziResult おみくじの実行結果
type OmikuziResult struct {
Result string `json:"result"`
}

func main() {
http.HandleFunc("/", handler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Println("Error:", err)
}
}

func handler(w http.ResponseWriter, r *http.Request) {

date := r.FormValue("date")
var data *OmikuziResult
if date == "" {
data = &OmikuziResult{Result: omikuzi.Draw()}
} else {
data = &OmikuziResult{Result: omikuzi.DrawByDate(date)}
}

w.Header().Set("Content-Type", "application/json; charset=utf-8")
if err := json.NewEncoder(w).Encode(data); err != nil {
log.Println("Error:", err)
}
}
47 changes: 47 additions & 0 deletions kadai4/gosagawa/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)

func TestHandler(t *testing.T) {

cases := []struct {
name string
date string
isResultFixed bool
result string
}{
{name: "normal", date: ""},
{name: "shogatsu_12/31", date: "2018-12-31"},
{name: "shogatsu_1/1", date: "2019-01-01", isResultFixed: true, result: "大吉"},
{name: "shogatsu_1/2", date: "2019-01-02", isResultFixed: true, result: "大吉"},
{name: "shogatsu_1/3", date: "2019-01-03", isResultFixed: true, result: "大吉"},
{name: "shogatsu_1/4", date: "2019-01-04"},
}

for _, v := range cases {
t.Run(v.name, func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/?date="+v.date, nil)
handler(w, r)
rw := w.Result()
defer rw.Body.Close()
if rw.StatusCode != http.StatusOK {
t.Fatal("unexpected status code")
}
var or OmikuziResult
dec := json.NewDecoder(rw.Body)
if err := dec.Decode(&or); err != nil {
t.Fatal(err)
}

if v.isResultFixed && or.Result != v.result {
t.Errorf("expected %v but %v ", v.result, or.Result)
}
})
}
}
121 changes: 121 additions & 0 deletions kadai4/gosagawa/omikuzi/omikuzi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package omikuzi

import (
"log"
"math/rand"
"time"
)

//Fortune おみくじ結果
type Fortune string

//RandomGenerater ランダム生成器
type RandomGenerater interface {
Get() int
}

//OmikuziPattern おみくじ結果配列
var OmikuziPattern []Fortune

const (
//Daikichi 大吉
Daikichi Fortune = "大吉"

//Chukichi 中吉
Chukichi Fortune = "中吉"

//Kichi 吉
Kichi Fortune = "吉"

//Kyo 凶
Kyo Fortune = "凶"
)

//TimeLayout 日付レイアウト
const TimeLayout = "2006-01-02"

//Omikuzi おみくじ構造体
type Omikuzi struct {
RandomGenerater RandomGenerater
Time time.Time
OmikuziPattern []Fortune
}

//Draw おみくじを引く
func (o *Omikuzi) Draw() Fortune {
m := int(o.Time.Month())
d := o.Time.Day()

var r Fortune
if isShogatsu(m, d) {
r = Daikichi
} else {
r = o.OmikuziPattern[o.RandomGenerater.Get()]
}
return r
}

func isShogatsu(m int, d int) bool {
if m == 1 && d >= 1 && d <= 3 {
return true
}
return false
}

func init() {
OmikuziPattern = []Fortune{
Kyo,
Kichi,
Kichi,
Chukichi,
Chukichi,
Daikichi,
}
}

//Draw おみくじを引く
func Draw() string {

now := time.Now()

//XXX 1日で結果を固定するように当日の00:00を取得するためフォーマット化し、
//またtime.Timeに戻してている。
//別のいいやり方がないか検討していた。
timeFormated := now.Format(TimeLayout)
targetTime, err := time.Parse(TimeLayout, timeFormated)
if err != nil {
log.Println("error:", err)
}

o := Omikuzi{
RandomGenerater: &random{TargetTime: targetTime},
Time: targetTime,
OmikuziPattern: OmikuziPattern,
}
return string(o.Draw())
}

//DrawByDate 日付でおみくじを引く
func DrawByDate(targetDate string) string {

targetTime, err := time.Parse(TimeLayout, targetDate)
if err != nil {
log.Println("error:", err)
}

o := Omikuzi{
RandomGenerater: &random{TargetTime: targetTime},
Time: targetTime,
OmikuziPattern: OmikuziPattern,
}
return string(o.Draw())
}

type random struct {
TargetTime time.Time
}

func (r *random) Get() int {
rand.Seed(r.TargetTime.Unix())
return rand.Intn(len(OmikuziPattern))
}
58 changes: 58 additions & 0 deletions kadai4/gosagawa/omikuzi/omikuzi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package omikuzi

import (
"log"
"testing"
"time"
)

func TestDraw(t *testing.T) {
cases := []struct {
name string
date string
index int
result Fortune
}{
{name: "normal_0", date: "2018-09-01", index: 0, result: Kyo},
{name: "normal_1", date: "2018-09-01", index: 1, result: Kichi},
{name: "normal_2", date: "2018-09-01", index: 2, result: Kichi},
{name: "normal_3", date: "2018-09-01", index: 3, result: Chukichi},
{name: "normal_4", date: "2018-09-01", index: 4, result: Chukichi},
{name: "normal_5", date: "2018-09-01", index: 5, result: Daikichi},
{name: "shogatsu_12/31", date: "2018-12-31", index: 0, result: Kyo},
{name: "shogatsu_1/1", date: "2019-01-01", index: 0, result: Daikichi},
{name: "shogatsu_1/2", date: "2019-01-02", index: 0, result: Daikichi},
{name: "shogatsu_1/3", date: "2019-01-03", index: 0, result: Daikichi},
{name: "shogatsu_1/4", date: "2019-01-04", index: 0, result: Kyo},
}
layout := "2006-01-02"
for _, v := range cases {
t.Run(v.name, func(t *testing.T) {
time, err := time.Parse(layout, v.date)
if err != nil {
log.Fatal(err)
}
o := Omikuzi{
RandomGenerater: &TestRandom{index: v.index},
Time: time,
OmikuziPattern: OmikuziPattern,
}
result := o.Draw()
if result != v.result {
t.Errorf("expected %v but %v ", v.result, result)
}
})
}
}

func getTestRandomGenerater(index int) {

}

type TestRandom struct {
index int
}

func (r *TestRandom) Get() int {
return r.index
}