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.
|
|
|
|
|
|
2017-08-31 23:26:22 -07:00
|
|
|
package web
|
2014-06-05 23:09:03 -07:00
|
|
|
|
|
|
|
|
import (
|
2015-04-01 14:19:14 -07:00
|
|
|
"bytes"
|
2015-04-01 22:43:39 -07:00
|
|
|
"fmt"
|
2021-05-16 11:00:29 -07:00
|
|
|
"github.com/Team254/cheesy-arena-lite/model"
|
2014-08-15 22:47:12 -07:00
|
|
|
"github.com/dchest/uniuri"
|
2014-06-05 23:09:03 -07:00
|
|
|
"github.com/gorilla/mux"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
2015-04-01 22:43:39 -07:00
|
|
|
"time"
|
2014-06-05 23:09:03 -07:00
|
|
|
)
|
|
|
|
|
|
2014-08-15 22:47:12 -07:00
|
|
|
const wpaKeyLength = 8
|
|
|
|
|
|
2014-06-05 23:09:03 -07:00
|
|
|
// Shows the team list.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamsGetHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
web.renderTeams(w, r, false)
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adds teams to the team list.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamsPostHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
if !web.canModifyTeamList() {
|
|
|
|
|
web.renderTeams(w, r, true)
|
2014-06-05 23:09:03 -07:00
|
|
|
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 {
|
2018-09-23 15:51:09 -07:00
|
|
|
team := model.Team{Id: teamNumber}
|
|
|
|
|
if web.arena.EventSettings.TBADownloadEnabled {
|
|
|
|
|
if err := web.populateOfficialTeamInfo(&team); err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err := web.arena.Database.CreateTeam(&team); err != nil {
|
2014-06-05 23:09:03 -07:00
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2018-09-23 15:51:09 -07:00
|
|
|
}
|
|
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Re-downloads the data for all teams from TBA and overwrites any local edits.
|
|
|
|
|
func (web *Web) teamsRefreshHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
teams, err := web.arena.Database.GetAllTeams()
|
|
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, team := range teams {
|
|
|
|
|
if err = web.populateOfficialTeamInfo(&team); err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-05-12 17:49:05 -07:00
|
|
|
if err = web.arena.Database.UpdateTeam(&team); err != nil {
|
2014-06-05 23:09:03 -07:00
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 15:51:09 -07:00
|
|
|
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clears the team list.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamsClearHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
if !web.canModifyTeamList() {
|
|
|
|
|
web.renderTeams(w, r, true)
|
2014-06-05 23:09:03 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
err := web.arena.Database.TruncateTeams()
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shows the page to edit a team's fields.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamEditGetHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-05 23:09:03 -07:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
|
teamId, _ := strconv.Atoi(vars["id"])
|
2017-08-28 20:14:32 -07:00
|
|
|
team, err := web.arena.Database.GetTeamById(teamId)
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if team == nil {
|
|
|
|
|
http.Error(w, fmt.Sprintf("Error: No such team: %d", teamId), 400)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-31 23:26:22 -07:00
|
|
|
template, err := web.parseFiles("templates/edit_team.html", "templates/base.html")
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2014-06-06 21:26:55 -07:00
|
|
|
data := struct {
|
2017-08-23 22:41:56 -07:00
|
|
|
*model.EventSettings
|
|
|
|
|
*model.Team
|
2017-08-28 20:14:32 -07:00
|
|
|
}{web.arena.EventSettings, team}
|
2014-06-06 21:26:55 -07:00
|
|
|
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.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamEditPostHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-05 23:09:03 -07:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
|
teamId, _ := strconv.Atoi(vars["id"])
|
2017-08-28 20:14:32 -07:00
|
|
|
team, err := web.arena.Database.GetTeamById(teamId)
|
2014-06-05 23:09:03 -07:00
|
|
|
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")
|
2014-08-03 16:20:40 -07:00
|
|
|
team.Accomplishments = r.PostFormValue("accomplishments")
|
2017-08-28 20:14:32 -07:00
|
|
|
if web.arena.EventSettings.NetworkSecurityEnabled {
|
2014-08-15 22:47:12 -07:00
|
|
|
team.WpaKey = r.PostFormValue("wpaKey")
|
|
|
|
|
if len(team.WpaKey) < 8 || len(team.WpaKey) > 63 {
|
|
|
|
|
handleWebErr(w, fmt.Errorf("WPA key must be between 8 and 63 characters."))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-21 16:05:44 -07:00
|
|
|
team.HasConnected = r.PostFormValue("hasConnected") == "on"
|
2021-05-12 17:49:05 -07:00
|
|
|
err = web.arena.Database.UpdateTeam(team)
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Removes a team from the team list.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamDeletePostHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
if !web.canModifyTeamList() {
|
|
|
|
|
web.renderTeams(w, r, true)
|
2014-06-05 23:09:03 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
|
teamId, _ := strconv.Atoi(vars["id"])
|
2017-08-28 20:14:32 -07:00
|
|
|
team, err := web.arena.Database.GetTeamById(teamId)
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if team == nil {
|
|
|
|
|
http.Error(w, fmt.Sprintf("Error: No such team: %d", teamId), 400)
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-05-12 17:49:05 -07:00
|
|
|
err = web.arena.Database.DeleteTeam(team.Id)
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|
|
|
|
|
|
2014-07-30 22:55:14 -07:00
|
|
|
// Publishes the team list to the web.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamsPublishHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
err := web.arena.TbaClient.PublishTeams(web.arena.Database)
|
2014-07-30 22:55:14 -07:00
|
|
|
if err != nil {
|
2014-09-05 22:17:12 -07:00
|
|
|
http.Error(w, "Failed to publish teams: "+err.Error(), 500)
|
2014-07-30 22:55:14 -07:00
|
|
|
return
|
|
|
|
|
}
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-07-30 22:55:14 -07:00
|
|
|
}
|
|
|
|
|
|
2014-08-15 22:47:12 -07:00
|
|
|
// Generates random WPA keys and saves them to the team models.
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) teamsGenerateWpaKeysHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if !web.userIsAdmin(w, r) {
|
2015-08-22 23:33:38 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-15 22:47:12 -07:00
|
|
|
generateAllKeys := false
|
|
|
|
|
if all, ok := r.URL.Query()["all"]; ok {
|
|
|
|
|
generateAllKeys = all[0] == "true"
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
teams, err := web.arena.Database.GetAllTeams()
|
2014-08-15 22:47:12 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for _, team := range teams {
|
|
|
|
|
if len(team.WpaKey) == 0 || generateAllKeys {
|
|
|
|
|
team.WpaKey = uniuri.NewLen(wpaKeyLength)
|
2021-05-12 17:49:05 -07:00
|
|
|
web.arena.Database.UpdateTeam(&team)
|
2014-08-15 22:47:12 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-02 14:08:16 -07:00
|
|
|
http.Redirect(w, r, "/setup/teams", 303)
|
2014-08-15 22:47:12 -07:00
|
|
|
}
|
|
|
|
|
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) renderTeams(w http.ResponseWriter, r *http.Request, showErrorMessage bool) {
|
|
|
|
|
teams, err := web.arena.Database.GetAllTeams()
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-31 23:26:22 -07:00
|
|
|
template, err := web.parseFiles("templates/setup_teams.html", "templates/base.html")
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil {
|
|
|
|
|
handleWebErr(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data := struct {
|
2017-08-23 22:41:56 -07:00
|
|
|
*model.EventSettings
|
|
|
|
|
Teams []model.Team
|
2014-06-05 23:09:03 -07:00
|
|
|
ShowErrorMessage bool
|
2017-08-28 20:14:32 -07:00
|
|
|
}{web.arena.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).
|
2017-08-28 20:14:32 -07:00
|
|
|
func (web *Web) canModifyTeamList() bool {
|
|
|
|
|
matches, err := web.arena.Database.GetMatchesByType("qualification")
|
2014-06-05 23:09:03 -07:00
|
|
|
if err != nil || len(matches) > 0 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the data for the given team number.
|
2018-09-23 15:51:09 -07:00
|
|
|
func (web *Web) populateOfficialTeamInfo(team *model.Team) error {
|
|
|
|
|
tbaTeam, err := web.arena.TbaClient.GetTeam(team.Id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2015-04-01 22:43:39 -07:00
|
|
|
|
2018-09-23 15:51:09 -07:00
|
|
|
// Check if the result is valid. If a team is not found, it will just not have its detail fields filled out.
|
|
|
|
|
if tbaTeam.TeamNumber == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2015-04-01 22:43:39 -07:00
|
|
|
|
2018-09-23 15:51:09 -07:00
|
|
|
team.Name = tbaTeam.Name
|
|
|
|
|
team.Nickname = tbaTeam.Nickname
|
|
|
|
|
team.City = tbaTeam.City
|
|
|
|
|
team.StateProv = tbaTeam.StateProv
|
|
|
|
|
team.Country = tbaTeam.Country
|
|
|
|
|
team.RookieYear = tbaTeam.RookieYear
|
|
|
|
|
team.RobotName, err = web.arena.TbaClient.GetRobotName(team.Id, time.Now().Year())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2018-09-18 00:36:25 -07:00
|
|
|
|
2018-09-23 15:51:09 -07:00
|
|
|
// Generate string of recent awards in reverse chronological order.
|
|
|
|
|
recentAwards, err := web.arena.TbaClient.GetTeamAwards(team.Id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
var accomplishmentsBuffer bytes.Buffer
|
|
|
|
|
for i := len(recentAwards) - 1; i >= 0; i-- {
|
|
|
|
|
award := recentAwards[i]
|
|
|
|
|
if time.Now().Year()-award.Year <= 2 {
|
|
|
|
|
accomplishmentsBuffer.WriteString(fmt.Sprintf("<p>%d %s - %s</p>", award.Year, award.EventName,
|
|
|
|
|
award.Name))
|
2015-08-31 22:46:24 -07:00
|
|
|
}
|
2015-04-01 22:43:39 -07:00
|
|
|
}
|
2018-09-23 15:51:09 -07:00
|
|
|
team.Accomplishments = accomplishmentsBuffer.String()
|
|
|
|
|
|
|
|
|
|
// Download and store the team's avatar; if there isn't one, ignore the error.
|
|
|
|
|
web.arena.TbaClient.DownloadTeamAvatar(team.Id, time.Now().Year())
|
2015-04-01 14:19:14 -07:00
|
|
|
|
2018-09-23 15:51:09 -07:00
|
|
|
return nil
|
2014-06-05 23:09:03 -07:00
|
|
|
}
|