diff --git a/font b/font new file mode 120000 index 0000000..1efa7b1 --- /dev/null +++ b/font @@ -0,0 +1 @@ +../../../code.google.com/p/gofpdf/font \ No newline at end of file diff --git a/main.go b/main.go index e0151a3..e13cecb 100644 --- a/main.go +++ b/main.go @@ -4,15 +4,17 @@ package main import ( - "fmt" "log" "math/rand" "time" ) +var db *Database + func main() { rand.Seed(time.Now().UnixNano()) - fmt.Println("Cheesy Arena") + db, _ = OpenDatabase("test.db") + ServeWebInterface() } func checkErr(err error) { diff --git a/reports.go b/reports.go new file mode 100644 index 0000000..3749e29 --- /dev/null +++ b/reports.go @@ -0,0 +1,74 @@ +// Copyright 2014 Team 254. All Rights Reserved. +// Author: pat@patfairbank.com (Patrick Fairbank) +// +// Web handlers for generating CSV and PDF reports. + +package main + +import ( + "code.google.com/p/gofpdf" + "fmt" + "net/http" + "strconv" + "text/template" +) + +func TeamsCsvReportHandler(w http.ResponseWriter, r *http.Request) { + teams, err := db.GetAllTeams() + if err != nil { + handleWebErr(w, err) + return + } + + w.Header().Set("Content-Type", "text/plain") + template, err := template.ParseFiles("templates/teams.csv") + if err != nil { + handleWebErr(w, err) + return + } + err = template.Execute(w, teams) + if err != nil { + handleWebErr(w, err) + return + } +} + +func TeamsPdfReportHandler(w http.ResponseWriter, r *http.Request) { + teams, err := db.GetAllTeams() + if err != nil { + handleWebErr(w, err) + return + } + eventSettings, err := db.GetEventSettings() + if err != nil { + handleWebErr(w, err) + return + } + + colWidths := map[string]float64{"Id": 12, "Name": 80, "Location": 80, "RookieYear": 23} + rowHeight := 6.5 + + pdf := gofpdf.New("P", "mm", "Letter", "font") + pdf.AddPage() + pdf.SetFont("Arial", "B", 10) + pdf.SetFillColor(220, 220, 220) + pdf.CellFormat(195, rowHeight, "Team List - "+eventSettings.Name, "", 1, "C", false, 0, "") + pdf.CellFormat(colWidths["Id"], rowHeight, "Team", "1", 0, "C", true, 0, "") + pdf.CellFormat(colWidths["Name"], rowHeight, "Name", "1", 0, "C", true, 0, "") + pdf.CellFormat(colWidths["Location"], rowHeight, "Location", "1", 0, "C", true, 0, "") + pdf.CellFormat(colWidths["RookieYear"], rowHeight, "Rookie Year", "1", 1, "C", true, 0, "") + pdf.SetFont("Arial", "", 10) + for _, team := range teams { + pdf.CellFormat(colWidths["Id"], rowHeight, strconv.Itoa(team.Id), "1", 0, "L", false, 0, "") + pdf.CellFormat(colWidths["Name"], rowHeight, team.Nickname, "1", 0, "L", false, 0, "") + location := fmt.Sprintf("%s, %s, %s", team.City, team.StateProv, team.Country) + pdf.CellFormat(colWidths["Location"], rowHeight, location, "1", 0, "L", false, 0, "") + pdf.CellFormat(colWidths["RookieYear"], rowHeight, strconv.Itoa(team.RookieYear), "1", 1, "L", false, 0, "") + } + w.Header().Set("Content-Type", "application/pdf") + err = pdf.Output(w) + if err != nil { + handleWebErr(w, err) + return + } +} diff --git a/reports_test.go b/reports_test.go new file mode 100644 index 0000000..ab73213 --- /dev/null +++ b/reports_test.go @@ -0,0 +1,49 @@ +// Copyright 2014 Team 254. All Rights Reserved. +// Author: pat@patfairbank.com (Patrick Fairbank) + +package main + +import ( + "github.com/stretchr/testify/assert" + "net/http" + "net/http/httptest" + "testing" +) + +func TestTeamsCsvReport(t *testing.T) { + clearDb() + defer clearDb() + db, _ = OpenDatabase(testDbPath) + team1 := Team{254, "NASA", "The Cheesy Poofs", "San Jose", "CA", "USA", 1999, "Barrage"} + team2 := Team{1114, "GM", "Simbotics", "St. Catharines", "ON", "Canada", 2003, "Simbot Evolution"} + db.CreateTeam(&team1) + db.CreateTeam(&team2) + + recorder := getHttpResponse("/reports/csv/teams") + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "text/plain", recorder.HeaderMap["Content-Type"][0]) + expectedBody := "Number,Name,Nickname,City,StateProv,Country,RookieYear,RobotName\n254,\"NASA\"," + + "\"The Cheesy Poofs\",\"San Jose\",\"CA\",\"USA\",1999,\"Barrage\"\n1114,\"GM\",\"Simbotics\"," + + "\"St. Catharines\",\"ON\",\"Canada\",2003,\"Simbot Evolution\"\n\n" + assert.Equal(t, expectedBody, recorder.Body.String()) +} + +func TestTeamsPdfReport(t *testing.T) { + clearDb() + defer clearDb() + db, _ = OpenDatabase(testDbPath) + team1 := Team{254, "NASA", "The Cheesy Poofs", "San Jose", "CA", "USA", 1999, "Barrage"} + db.CreateTeam(&team1) + + // Can't really parse the PDF content and check it, so just check that what's sent back is a PDF. + recorder := getHttpResponse("/reports/pdf/teams") + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "application/pdf", recorder.HeaderMap["Content-Type"][0]) +} + +func getHttpResponse(path string) *httptest.ResponseRecorder { + recorder := httptest.NewRecorder() + req, _ := http.NewRequest("GET", path, nil) + newHandler().ServeHTTP(recorder, req) + return recorder +} diff --git a/templates/teams.csv b/templates/teams.csv new file mode 100644 index 0000000..30ac3be --- /dev/null +++ b/templates/teams.csv @@ -0,0 +1,3 @@ +Number,Name,Nickname,City,StateProv,Country,RookieYear,RobotName +{{range $team := .}}{{$team.Id}},"{{$team.Name}}","{{$team.Nickname}}","{{$team.City}}","{{$team.StateProv}}","{{$team.Country}}",{{$team.RookieYear}},"{{$team.RobotName}}" +{{end}} diff --git a/web.go b/web.go new file mode 100644 index 0000000..1b70318 --- /dev/null +++ b/web.go @@ -0,0 +1,32 @@ +// Copyright 2014 Team 254. All Rights Reserved. +// Author: pat@patfairbank.com (Patrick Fairbank) +// +// Configuration and functions for the event server web interface. + +package main + +import ( + "fmt" + "github.com/gorilla/mux" + "log" + "net/http" +) + +const httpPort = 8080 + +func ServeWebInterface() { + http.Handle("/", newHandler()) + log.Printf("Serving HTTP requests on port %d", httpPort) + http.ListenAndServe(fmt.Sprintf(":%d", httpPort), nil) +} + +func newHandler() http.Handler { + router := mux.NewRouter() + router.HandleFunc("/reports/csv/teams", TeamsCsvReportHandler) + router.HandleFunc("/reports/pdf/teams", TeamsPdfReportHandler) + return router +} + +func handleWebErr(w http.ResponseWriter, err error) { + http.Error(w, "Internal server error: "+err.Error(), 500) +}