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 / 課題4 #25

Open
wants to merge 1 commit 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
17 changes: 17 additions & 0 deletions kadai4/tsuchinaga/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 課題4 tsuchinaga

## おみくじAPIを作ってみよう

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

## TODO
* [x] おみじくの結果をJSONで返すWebAPIをつくる
* [x] サーバを立てる
* [x] サーバのポートを標準出力に出す
* [x] `/fortune` でおみくじの結果をJSONで返す
* [x] おみくじの結果をつくる
* [x] 1/1~1/3の期間は全て大吉
* [x] 1/1~1/3以外の期間はランダム
* [x] テストのために、日時を外から注入できるようにする
15 changes: 15 additions & 0 deletions kadai4/tsuchinaga/clock/clock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package clock

import "time"

func New() Clock { return &clock{} }

type Clock interface {
Now() time.Time
}

type clock struct{}

func (c *clock) Now() time.Time {
return time.Now()
}
24 changes: 24 additions & 0 deletions kadai4/tsuchinaga/clock/clock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package clock

import (
"reflect"
"testing"
"time"
)

func Test_clock_Now(t *testing.T) {
c := &clock{}
got := c.Now()
now := time.Now()
if got.After(now) {
t.Errorf("Now() = %v, want before %v", got, now)
}
}

func TestNew(t *testing.T) {
want := &clock{}
got := New()
if !reflect.DeepEqual(got, want) {
t.Errorf("New() = %v, want %v", got, want)
}
}
55 changes: 55 additions & 0 deletions kadai4/tsuchinaga/fortune/fortune.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package fortune

import (
"math/rand"
"time"
)

// Foredoom - 吉凶
type Foredoom string

const (
ForedoomDaikichi Foredoom = "大吉"
ForedoomKichi Foredoom = "吉"
ForedoomChukichi Foredoom = "中吉"
ForedoomShokichi Foredoom = "小吉"
ForedoomKyou Foredoom = "凶"
)

var foredooms = []Foredoom{ForedoomDaikichi, ForedoomKichi, ForedoomChukichi, ForedoomShokichi, ForedoomKyou}

// Paper - 結果の載ってる紙
type Paper struct {
No int `json:"no"` // おみくじ番号 [1,100]
Foredoom Foredoom `json:"foredoom"` // 吉凶
Wish Foredoom `json:"wish"` // 願望
Health Foredoom `json:"health"` // 健康
Business Foredoom `json:"business"` // 仕事
Love Foredoom `json:"love"` // 恋愛
Study Foredoom `json:"study"` // 勉強
}

func Get(now time.Time) Paper {
if now.Month() == 1 && now.Day() <= 3 {
return Paper{
No: now.Day(),
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}
}

r := rand.New(rand.NewSource(now.UnixNano()))
return Paper{
No: r.Intn(100) + 1,
Foredoom: foredooms[r.Intn(5)],
Wish: foredooms[r.Intn(5)],
Health: foredooms[r.Intn(5)],
Business: foredooms[r.Intn(5)],
Love: foredooms[r.Intn(5)],
Study: foredooms[r.Intn(5)],
}
}
111 changes: 111 additions & 0 deletions kadai4/tsuchinaga/fortune/fortune_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package fortune

import (
"reflect"
"testing"
"time"
)

func TestGet(t *testing.T) {
tests := []struct {
name string
arg time.Time
want Paper
}{
{name: "2020/01/01 00:00:00は1番で全部大吉",
arg: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
want: Paper{
No: 1,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2020/01/01 23:59:59は1番で全部大吉",
arg: time.Date(2020, 1, 1, 23, 59, 59, 0, time.Local),
want: Paper{
No: 1,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2020/01/02は2番で全部大吉",
arg: time.Date(2020, 1, 2, 0, 0, 0, 0, time.Local),
want: Paper{
No: 2,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2020/01/03は3番で全部大吉",
arg: time.Date(2020, 1, 3, 0, 0, 0, 0, time.Local),
want: Paper{
No: 3,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2030/01/01は1番で全部大吉",
arg: time.Date(2030, 1, 1, 0, 0, 0, 0, time.Local),
want: Paper{
No: 1,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2040/01/01は1番で全部大吉",
arg: time.Date(2040, 1, 1, 0, 0, 0, 0, time.Local),
want: Paper{
No: 1,
Foredoom: ForedoomDaikichi,
Wish: ForedoomDaikichi,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomDaikichi,
}},
{name: "2020/01/04 00:00:00はランダム",
arg: time.Date(2020, 1, 4, 0, 0, 0, 0, time.Local),
want: Paper{
No: 30,
Foredoom: ForedoomChukichi,
Wish: ForedoomKyou,
Health: ForedoomDaikichi,
Business: ForedoomDaikichi,
Love: ForedoomDaikichi,
Study: ForedoomKyou,
}},
{name: "2020/01/04 00:00:01はランダム",
arg: time.Date(2020, 1, 4, 0, 0, 1, 0, time.Local),
want: Paper{
No: 53,
Foredoom: ForedoomKichi,
Wish: ForedoomShokichi,
Health: ForedoomShokichi,
Business: ForedoomKyou,
Love: ForedoomKyou,
Study: ForedoomKichi,
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Get(tt.arg); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Get() = %v, want %v", got, tt.want)
}
})
}
}
3 changes: 3 additions & 0 deletions kadai4/tsuchinaga/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo8/kadai4/tsuchinaga

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

import (
"fmt"
"log"
"os"
"time"

"github.com/gopherdojo/dojo8/kadai4/tsuchinaga/clock"

"github.com/gopherdojo/dojo8/kadai4/tsuchinaga/server"
)

func main() {
serv := server.New(clock.New())
go func() {
if err := serv.Run(); err != nil {
log.Println(err)
os.Exit(2)
}
}()

for {
time.Sleep(100 * time.Millisecond)
if serv.GetAddr() != "" {
fmt.Printf("server started at %s\n", serv.GetAddr())
break
}
}
<-make(chan error)
}
64 changes: 64 additions & 0 deletions kadai4/tsuchinaga/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package server

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

"github.com/gopherdojo/dojo8/kadai4/tsuchinaga/clock"

"github.com/gopherdojo/dojo8/kadai4/tsuchinaga/fortune"
)

func New(clock clock.Clock) Server {
return &server{clock: clock}
}

type Server interface {
GetAddr() string
Run() error
Stop(ctx context.Context) error
}

type server struct {
addr string
serv *http.Server
clock clock.Clock
}

func (s *server) GetAddr() string {
return s.addr
}

func (s *server) Run() error {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
defer ln.Close()
s.addr = ln.Addr().String()

mux := http.NewServeMux()
mux.HandleFunc("/fortune", s.FortuneHandler)
s.serv = &http.Server{Handler: mux}
return s.serv.Serve(ln)
}

func (s *server) Stop(ctx context.Context) error {
if s.serv != nil {
return s.serv.Shutdown(ctx)
}
return nil
}

func (s *server) FortuneHandler(w http.ResponseWriter, _ *http.Request) {
res, err := json.Marshal(fortune.Get(s.clock.Now()))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(res)
}
Loading