~ethanmad/bouts.app

ref: 29bebc9c35a12467b436acd64f326f99972cc6f8 bouts.app/controllers/seeding.go -rw-r--r-- 3.1 KiB
29bebc9c — Ethan Madison models/seeding: Add support for IDs 1 year, 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package controllers

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"git.sr.ht/~ethanmad/bouts.app/models"
	"git.sr.ht/~ethanmad/bouts.app/views"
	"github.com/gorilla/mux"
)

// NewSeeding returns a *Seeding, for use as a SeedingController (e.g., for routing).
func NewSeeding(ss models.SeedingService, r *mux.Router) *Seeding {
	return &Seeding{
		r:       r,
		NewView: views.NewView("app", "seeding/new"),
		ss:      ss,
	}
}

// Seeding holds all services needed to build seedings and a mux.Router.
type Seeding struct {
	r       *mux.Router
	NewView *views.View
	ss      models.SeedingService
}

// New renders the NewView.
//
// GET /seeding/new
func (s *Seeding) New(w http.ResponseWriter, r *http.Request) {
	var (
		vd   views.Data
		form SeedingForm
	)
	form.CategoryOptions = models.Categories
	form.PluralityOptions = models.Pluralities
	vd.Yield = form
	s.NewView.Render(w, r, vd)
}

// SeedingForm holds and maps data from the new seeding form.
type SeedingForm struct {
	Category         models.Category  `schema:"category"`
	Plurality        models.Plurality `schema:"plurality"`
	CategoryOptions  [6]models.Category
	PluralityOptions [2]models.Plurality
}

// Create is used to process the new seeding form when a user tries to create a new seeding.
//
// POST /seeding
func (s *Seeding) Create(w http.ResponseWriter, r *http.Request) {
	var form SeedingForm
	if err := parseForm(r, &form); err != nil {
		views.RedirectAlert(w, r, "/seeding/new", http.StatusFound, *views.NewAlertErr(err))
		return
	}
	seeding, err := s.ss.Create(form.Category, form.Plurality)
	if err != nil {
		views.RedirectAlert(w, r, "/seeding/new", http.StatusFound, *views.NewAlertErr(err))
		return
	}
	// Create csv.Writer with underlying bytes.Buffer io.Writer.
	// Data will be written to and buffered in cw, then flushed to b, and later written to w.
	b := &bytes.Buffer{}
	cw := csv.NewWriter(b)

	cw.Write([]string{seeding.Plurality.String(), seeding.Category.String(), "", ""})

	switch seeding.Plurality {
	case models.Individuals:
		cw.Write([]string{"rank", "name", "schoolName", "elo"})
		for i := range seeding.Names {
			rank := strconv.Itoa(i + 1)
			name := seeding.Names[i]
			schoolName := seeding.SchoolNames[i]
			elo := strconv.Itoa(seeding.Elos[i])
			cw.Write([]string{rank, name, schoolName, elo})
		}
	case models.Squads:
		cw.Write([]string{"rank", "schoolName", "elo"})
		for i := range seeding.SchoolNames {
			rank := strconv.Itoa(i + 1)
			schoolName := seeding.SchoolNames[i]
			elo := strconv.Itoa(seeding.Elos[i])
			cw.Write([]string{rank, schoolName, elo})
		}
	default:
		views.RedirectAlert(w, r, "/seeding/new", http.StatusFound, *views.NewAlertErr(models.ErrPluralityInvalid))
		return
	}
	// Flush buffered data to underylying io.Writer.
	cw.Flush()

	fname := fmt.Sprintf("attachment;filename=%s_%s_%v.csv", seeding.Plurality.ID(), seeding.Category.ID(), time.Now().Format("2006-01-02T15-04-05"))
	fname = strings.ReplaceAll(fname, " ", "_")

	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", fname)
	w.Write(b.Bytes())
}