diff --git a/kadai4/annkara/README.md b/kadai4/annkara/README.md new file mode 100644 index 0000000..9ebc042 --- /dev/null +++ b/kadai4/annkara/README.md @@ -0,0 +1,22 @@ +# 課題4 + +## おみくじプログラム + +* サイコロを転がし、出た目によって運勢を占うプログラム + * 6 : 大吉 + * 5,4 : 中吉 + * 3,2 : 吉 + * 1 : 凶 + +## Webアプリ化してみよう + +* HTTPサーバを作成する +* リクエストが来たらおみくじの結果を返す +* 乱数の種は1回だけ初期化する + * HTTPサーバを起動する前に初期化する + +## おみくじAPIを作ってみよう + +* JSON形式でおみくじの結果を返す +* 正月(1/1-1/3)だけ大吉にする +* ハンドラのテストを書いてみる diff --git a/kadai4/annkara/cmd/omikuji/main.go b/kadai4/annkara/cmd/omikuji/main.go new file mode 100644 index 0000000..859c668 --- /dev/null +++ b/kadai4/annkara/cmd/omikuji/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "net/http" + "math/rand" + "time" + + "github.com/dojo6/kadai4/annkara/pkg/omikuji" +) + +func main() { + n := time.Now().UnixNano() + rand.Seed(n) + + http.HandleFunc("/", omikuji.Handler) + http.ListenAndServe(":8080", nil) +} diff --git a/kadai4/annkara/omikuji_test/omikuij_test.go b/kadai4/annkara/omikuji_test/omikuij_test.go new file mode 100644 index 0000000..dea22d7 --- /dev/null +++ b/kadai4/annkara/omikuji_test/omikuij_test.go @@ -0,0 +1,118 @@ +package omikuji_test + +import ( + "io/ioutil" + "math/rand" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/dojo6/kadai4/annkara/pkg/omikuji" +) + +type result struct { + r1 bool + r2 bool + r3 bool + r4 bool + r5 bool + r6 bool +} + +func (r *result) finished() bool { + return r.r1 && r.r2 && r.r3 && r.r4 && r.r5 && r.r6 +} + +func TestOmikuji(t *testing.T) { + n := time.Now().UnixNano() + rand.Seed(n) + + r := result{} + for { + + if r.finished() { + return + } + + me, unsei := omikuji.Hiku(time.Now()) + switch me { + case 6: + r.r6 = true + if unsei != "大吉" { + t.Errorf("me: %d, expected: %v, actual: %v", me, "大吉", unsei) + } + case 5, 4: + if me == 5 { + r.r5 = true + } else { + r.r4 = true + } + if unsei != "中吉" { + t.Errorf("me: %d, expected: %v, actual: %v", me, "中吉", unsei) + } + case 3, 2: + if me == 3 { + r.r3 = true + } else { + r.r2 = true + } + if unsei != "小吉" { + t.Errorf("me: %d, expected: %v, actual: %v", me, "小吉", unsei) + } + case 1: + r.r1 = true + if unsei != "凶" { + t.Errorf("me: %d, expected: %v, actual: %v", me, "凶", unsei) + } + default: + t.Fatalf("Invalid value %d", me) + } + } +} + +func TestOmikujiInShogatsu(t *testing.T) { + + tests := []struct { + desc string + date time.Time + expected string + }{ + { + desc: "1月1日", + date: time.Date(2019, time.January, 1, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, { + desc: "1月2日", + date: time.Date(2019, time.January, 2, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, { + desc: "1月3日", + date: time.Date(2019, time.January, 3, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, + } + + for _, test := range tests { + _, unsei := omikuji.Hiku(test.date) + if unsei != test.expected { + t.Errorf("Unexpected Unsei: expected %s, actual %s", test.expected, unsei) + } + } +} + +func TestHandler(t *testing.T) { + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + omikuji.Handler(w, r) + wr := w.Result() + defer wr.Body.Close() + + if wr.StatusCode != http.StatusOK { + t.Fatal("unexpecete status code") + } + _, err := ioutil.ReadAll(wr.Body) + if err != nil { + t.Fatalf("unexpected error") + } +} diff --git a/kadai4/annkara/pkg/omikuji/omikuji.go b/kadai4/annkara/pkg/omikuji/omikuji.go new file mode 100644 index 0000000..a16ddd3 --- /dev/null +++ b/kadai4/annkara/pkg/omikuji/omikuji.go @@ -0,0 +1,60 @@ +package omikuji + +import ( + "encoding/json" + "math/rand" + "net/http" + "time" +) + +// Omikuji Result +type Omikuji struct { + Me int `json:"me"` + Unsei string `json:"unsei"` +} + +// Hiku a omikuji +func Hiku(t time.Time) (int, string) { + + if shogatsu(t) { + return 0, "大吉" + } + + me := rand.Intn(7) + var unsei string + switch me { + case 6: + unsei = "大吉" + case 5, 4: + unsei = "中吉" + case 3, 2: + unsei = "小吉" + case 1: + unsei = "凶" + default: + return Hiku(t) + } + return me, unsei +} + +func shogatsu(t time.Time) bool { + + if t.Month() == time.January { + if (t.Day() == 1) || (t.Day() == 2) || (t.Day() == 3) { + return true + } + } + + return false +} + +// Handler provides Omikuji Handler +func Handler(w http.ResponseWriter, r *http.Request) { + me, unsei := Hiku(time.Now()) + o := &Omikuji{Me: me, Unsei: unsei} + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + if err := json.NewEncoder(w).Encode(o); err != nil { + http.Error(w, "Omikuji Error", http.StatusInternalServerError) + } +}