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

Make methods #59

Open
wants to merge 3 commits into
base: k-ueki-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
182 changes: 169 additions & 13 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,190 @@ package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)

// いずれ外部APIのインターフェイスDIする
type handlers struct {
func (c *Client) Index(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/available_lotteries")
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()

var lotteries []*Lottery
if err := json.NewDecoder(resp.Body).Decode(&lotteries); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

if err := listTmpl.Execute(w, lotteries); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
}

func (h handlers) listPage() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/available_lotteries")
if err != nil {
func (c *Client) GetPurchasePage(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()

var l Lottery
if err := json.NewDecoder(resp.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

data := struct {
Lottery
Remain int64
}{
Lottery: l,
Remain: l.Num, // TODO: 残りを計算する
}
if err := purchasePageTmpl.Execute(w, data); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
}

func (c *Client) Purchase(w http.ResponseWriter, r *http.Request) {
id := r.FormValue("id")
num, err := strconv.Atoi(r.FormValue("num"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
// TODO: パラメタのバリデーション

resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + id)
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()

var l Lottery
if err := json.NewDecoder(resp.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

var count int
if err := c.DB.QueryRow("SELECT COUNT(*) FROM purchased WHERE lottery_id = ?", l.ID).Scan(&count); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

for i := 1; i <= num; i++ {
const sql = "INSERT INTO purchased(lottery_id, number) values (?,?)"
format := fmt.Sprintf(`%%0%dd`, len(strconv.FormatInt(l.Num-1, 10)))
n := fmt.Sprintf(format, count+i)
if _, err := c.DB.Exec(sql, id, n); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()
}

http.Redirect(w, r, "/purchase_page?id="+l.ID, http.StatusFound)
}

func (c *Client) Result(w http.ResponseWriter, r *http.Request) {
resp1, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/result?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp1.Body.Close()

var result Result
if err := json.NewDecoder(resp1.Body).Decode(&result); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

resp2, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp2.Body.Close()

var l Lottery
if err := json.NewDecoder(resp2.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

var lotteries []*Lottery
if err := json.NewDecoder(resp.Body).Decode(&lotteries); err != nil {
type winner struct {
Prize *Prize
Numbers []string
}

data := struct {
Lottery
Winners map[string]*winner
}{
Lottery: l,
Winners: map[string]*winner{},
}

rows, err := c.DB.Query("SELECT number FROM purchased WHERE lottery_id = ?", l.ID)
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
for rows.Next() {
var number string
if err := rows.Scan(&number); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

if err := listTmpl.Execute(w, lotteries); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
for i := range result.Winners {
for _, n := range result.Winners[i].Numbers {
if number == n {
prizeID := result.Winners[i].PrizeID
if data.Winners[prizeID] == nil {
for _, p := range l.Prizes {
if p.ID == prizeID {
data.Winners[prizeID] = &winner{
Prize: p,
}
}
}
}
data.Winners[prizeID].Numbers = append(data.Winners[prizeID].Numbers, n)
}
}
}
}

if err := resultTmpl.Execute(w, data); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
}
169 changes: 9 additions & 160 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ TODO

import (
"database/sql"
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"strconv"

_ "github.com/mattn/go-sqlite3"
)

type Client struct {
DB *sql.DB
}

func main() {

db, err := sql.Open("sqlite3", "database.db")
Expand All @@ -31,168 +32,16 @@ func main() {
if err := initDB(db); err != nil {
panic(err)
}
h := handlers{}
http.HandleFunc("/", h.listPage())

http.HandleFunc("/purchase_page", func(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()

var l Lottery
if err := json.NewDecoder(resp.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

data := struct {
Lottery
Remain int64
}{
Lottery: l,
Remain: l.Num, // TODO: 残りを計算する
}
if err := purchasePageTmpl.Execute(w, data); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
})

http.HandleFunc("/purchase", func(w http.ResponseWriter, r *http.Request) {
id := r.FormValue("id")
num, err := strconv.Atoi(r.FormValue("num"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
// TODO: パラメタのバリデーション

resp, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + id)
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp.Body.Close()

var l Lottery
if err := json.NewDecoder(resp.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

var count int
if err := db.QueryRow("SELECT COUNT(*) FROM purchased WHERE lottery_id = ?", l.ID).Scan(&count); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

for i := 1; i <= num; i++ {
const sql = "INSERT INTO purchased(lottery_id, number) values (?,?)"
format := fmt.Sprintf(`%%0%dd`, len(strconv.FormatInt(l.Num-1, 10)))
n := fmt.Sprintf(format, count+i)
if _, err := db.Exec(sql, id, n); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
}

http.Redirect(w, r, "/purchase_page?id="+l.ID, http.StatusFound)
})

http.HandleFunc("/result", func(w http.ResponseWriter, r *http.Request) {
resp1, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/result?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp1.Body.Close()

var result Result
if err := json.NewDecoder(resp1.Body).Decode(&result); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

resp2, err := http.Get("https://lottery-dot-tenntenn-samples.appspot.com/lottery?id=" + r.FormValue("id"))
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
defer resp2.Body.Close()

var l Lottery
if err := json.NewDecoder(resp2.Body).Decode(&l); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}

type winner struct {
Prize *Prize
Numbers []string
}
client := Client{DB: db}

data := struct {
Lottery
Winners map[string]*winner
}{
Lottery: l,
Winners: map[string]*winner{},
}
http.HandleFunc("/", client.Index)

rows, err := db.Query("SELECT number FROM purchased WHERE lottery_id = ?", l.ID)
if err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
for rows.Next() {
var number string
if err := rows.Scan(&number); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
http.HandleFunc("/purchase_page", client.GetPurchasePage)

for i := range result.Winners {
for _, n := range result.Winners[i].Numbers {
if number == n {
prizeID := result.Winners[i].PrizeID
if data.Winners[prizeID] == nil {
for _, p := range l.Prizes {
if p.ID == prizeID {
data.Winners[prizeID] = &winner{
Prize: p,
}
}
}
}
data.Winners[prizeID].Numbers = append(data.Winners[prizeID].Numbers, n)
}
}
}
}
http.HandleFunc("/purchase", client.Purchase)

if err := resultTmpl.Execute(w, data); err != nil {
const status = http.StatusInternalServerError
http.Error(w, http.StatusText(status), status)
return
}
})
http.HandleFunc("/result", client.Result)

port := os.Getenv("PORT")
if port == "" {
Expand Down
Binary file added stepupgo2-1
Binary file not shown.