Files
cheesy-arena-lite/setup_teams.go

252 lines
5.8 KiB
Go
Raw Normal View History

2014-06-05 23:09:03 -07:00
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
//
// Web routes for configuring the team list.
package main
import (
"encoding/csv"
"fmt"
"github.com/gorilla/mux"
"html"
"html/template"
"io"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"strings"
)
var officialTeamInfoUrl = "https://my.usfirst.org/frc/scoring/index.lasso?page=teamlist"
var officialTeamInfo map[int][]string
// Shows the team list.
func TeamsGetHandler(w http.ResponseWriter, r *http.Request) {
renderTeams(w, r, false)
}
// Adds teams to the team list.
func TeamsPostHandler(w http.ResponseWriter, r *http.Request) {
if !canModifyTeamList() {
renderTeams(w, r, true)
return
}
var teamNumbers []int
for _, teamNumberString := range strings.Split(r.PostFormValue("teamNumbers"), "\r\n") {
teamNumber, err := strconv.Atoi(teamNumberString)
if err == nil {
teamNumbers = append(teamNumbers, teamNumber)
}
}
for _, teamNumber := range teamNumbers {
team, err := getOfficialTeamInfo(teamNumber)
if err != nil {
handleWebErr(w, err)
return
}
err = db.CreateTeam(team)
if err != nil {
handleWebErr(w, err)
return
}
}
2014-06-07 02:02:12 -07:00
http.Redirect(w, r, "/setup/teams", 302)
2014-06-05 23:09:03 -07:00
}
// Clears the team list.
func TeamsClearHandler(w http.ResponseWriter, r *http.Request) {
if !canModifyTeamList() {
renderTeams(w, r, true)
return
}
err := db.TruncateTeams()
if err != nil {
handleWebErr(w, err)
return
}
2014-06-07 02:02:12 -07:00
http.Redirect(w, r, "/setup/teams", 302)
2014-06-05 23:09:03 -07:00
}
// Shows the page to edit a team's fields.
func TeamEditGetHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
teamId, _ := strconv.Atoi(vars["id"])
team, err := db.GetTeamById(teamId)
if err != nil {
handleWebErr(w, err)
return
}
if team == nil {
http.Error(w, fmt.Sprintf("Error: No such team: %d", teamId), 400)
return
}
template, err := template.ParseFiles("templates/edit_team.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
return
}
2014-06-06 21:26:55 -07:00
data := struct {
*EventSettings
*Team
}{eventSettings, team}
err = template.ExecuteTemplate(w, "base", data)
2014-06-05 23:09:03 -07:00
if err != nil {
handleWebErr(w, err)
return
}
}
// Updates a team's fields.
func TeamEditPostHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
teamId, _ := strconv.Atoi(vars["id"])
team, err := db.GetTeamById(teamId)
if err != nil {
handleWebErr(w, err)
return
}
if team == nil {
http.Error(w, fmt.Sprintf("Error: No such team: %d", teamId), 400)
return
}
team.Name = r.PostFormValue("name")
team.Nickname = r.PostFormValue("nickname")
team.City = r.PostFormValue("city")
team.StateProv = r.PostFormValue("stateProv")
team.Country = r.PostFormValue("country")
2014-06-06 21:26:55 -07:00
team.RookieYear, _ = strconv.Atoi(r.PostFormValue("rookieYear"))
2014-06-05 23:09:03 -07:00
team.RobotName = r.PostFormValue("robotName")
err = db.SaveTeam(team)
if err != nil {
handleWebErr(w, err)
return
}
2014-06-07 02:02:12 -07:00
http.Redirect(w, r, "/setup/teams", 302)
2014-06-05 23:09:03 -07:00
}
// Removes a team from the team list.
func TeamDeletePostHandler(w http.ResponseWriter, r *http.Request) {
if !canModifyTeamList() {
renderTeams(w, r, true)
return
}
vars := mux.Vars(r)
teamId, _ := strconv.Atoi(vars["id"])
team, err := db.GetTeamById(teamId)
if err != nil {
handleWebErr(w, err)
return
}
if team == nil {
http.Error(w, fmt.Sprintf("Error: No such team: %d", teamId), 400)
return
}
err = db.DeleteTeam(team)
if err != nil {
handleWebErr(w, err)
return
}
2014-06-07 02:02:12 -07:00
http.Redirect(w, r, "/setup/teams", 302)
2014-06-05 23:09:03 -07:00
}
2014-07-30 22:55:14 -07:00
// Publishes the team list to the web.
func TeamsPublishHandler(w http.ResponseWriter, r *http.Request) {
err := PublishTeams()
if err != nil {
handleWebErr(w, err)
return
}
http.Redirect(w, r, "/setup/teams", 302)
}
2014-06-05 23:09:03 -07:00
func renderTeams(w http.ResponseWriter, r *http.Request, showErrorMessage bool) {
teams, err := db.GetAllTeams()
if err != nil {
handleWebErr(w, err)
return
}
template, err := template.ParseFiles("templates/teams.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
return
}
data := struct {
2014-06-06 21:26:55 -07:00
*EventSettings
2014-06-05 23:09:03 -07:00
Teams []Team
ShowErrorMessage bool
2014-06-06 21:26:55 -07:00
}{eventSettings, teams, showErrorMessage}
2014-06-05 23:09:03 -07:00
err = template.ExecuteTemplate(w, "base", data)
if err != nil {
handleWebErr(w, err)
return
}
}
// Returns true if it is safe to change the team list (i.e. no matches/results exist yet).
func canModifyTeamList() bool {
matches, err := db.GetMatchesByType("qualification")
if err != nil || len(matches) > 0 {
return false
}
return true
}
// Returns the data for the given team number.
func getOfficialTeamInfo(teamId int) (*Team, error) {
if officialTeamInfo == nil {
// Download all team info from the FIRST website if it is not cached.
resp, err := http.Get(officialTeamInfoUrl)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
re := regexp.MustCompile("(?s).*<PRE>(.*)</PRE>.*")
teamsCsv := re.FindStringSubmatch(string(body))[1]
reader := csv.NewReader(strings.NewReader(teamsCsv))
reader.Comma = '\t'
reader.FieldsPerRecord = -1
officialTeamInfo = make(map[int][]string)
reader.Read() // Ignore header line.
for {
fields, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
teamNumber, err := strconv.Atoi(fields[1])
if err != nil {
return nil, err
}
officialTeamInfo[teamNumber] = fields
}
}
teamData, ok := officialTeamInfo[teamId]
var team Team
if ok {
rookieYear, _ := strconv.Atoi(teamData[8])
team = Team{teamId, html.UnescapeString(teamData[2]), html.UnescapeString(teamData[7]),
html.UnescapeString(teamData[4]), html.UnescapeString(teamData[5]), html.UnescapeString(teamData[6]),
rookieYear, html.UnescapeString(teamData[9])}
} else {
// If no team data exists, just fill in the team number.
team = Team{Id: teamId}
}
return &team, nil
}