mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-10 06:06:47 -04:00
230 lines
5.6 KiB
Go
230 lines
5.6 KiB
Go
// Copyright 2014 Team 254. All Rights Reserved.
|
|
// Author: pat@patfairbank.com (Patrick Fairbank)
|
|
//
|
|
// Web routes for controlling match play.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/gorilla/mux"
|
|
"html/template"
|
|
"math/rand"
|
|
"net/http"
|
|
"sort"
|
|
"strconv"
|
|
)
|
|
|
|
type MatchPlayListItem struct {
|
|
Id int
|
|
DisplayName string
|
|
Time string
|
|
Status string
|
|
ColorClass string
|
|
}
|
|
|
|
type MatchPlayList []MatchPlayListItem
|
|
|
|
// Global var to hold the current active tournament so that its matches are displayed by default.
|
|
var currentMatchType string
|
|
|
|
var currentMatch *Match
|
|
|
|
// Shows the match play control interface.
|
|
func MatchPlayHandler(w http.ResponseWriter, r *http.Request) {
|
|
practiceMatches, err := buildMatchPlayList("practice")
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
qualificationMatches, err := buildMatchPlayList("qualification")
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
eliminationMatches, err := buildMatchPlayList("elimination")
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
|
|
template, err := template.ParseFiles("templates/match_play.html", "templates/base.html")
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
matchesByType := map[string]MatchPlayList{"practice": practiceMatches,
|
|
"qualification": qualificationMatches, "elimination": eliminationMatches}
|
|
if currentMatchType == "" {
|
|
currentMatchType = "practice"
|
|
}
|
|
if currentMatch == nil {
|
|
currentMatch = new(Match)
|
|
}
|
|
data := struct {
|
|
*EventSettings
|
|
MatchesByType map[string]MatchPlayList
|
|
CurrentMatchType string
|
|
Match *Match
|
|
}{eventSettings, matchesByType, currentMatchType, currentMatch}
|
|
err = template.ExecuteTemplate(w, "base", data)
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func MatchPlayQueueHandler(w http.ResponseWriter, r *http.Request) {
|
|
vars := mux.Vars(r)
|
|
matchId, _ := strconv.Atoi(vars["matchId"])
|
|
match, err := db.GetMatchById(matchId)
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
if match == nil {
|
|
handleWebErr(w, fmt.Errorf("Invalid match ID %d.", matchId))
|
|
return
|
|
}
|
|
|
|
// TODO(pat): Disallow if there is a match currently being played or there are uncommitted results.
|
|
currentMatch = match
|
|
currentMatchType = match.Type
|
|
|
|
http.Redirect(w, r, "/match_play", 302)
|
|
}
|
|
|
|
func MatchPlayFakeResultHandler(w http.ResponseWriter, r *http.Request) {
|
|
vars := mux.Vars(r)
|
|
matchId, _ := strconv.Atoi(vars["matchId"])
|
|
match, err := db.GetMatchById(matchId)
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
if match == nil {
|
|
handleWebErr(w, fmt.Errorf("Invalid match ID %d.", matchId))
|
|
return
|
|
}
|
|
matchResult := MatchResult{MatchId: match.Id, RedFouls: []Foul{}, BlueFouls: []Foul{Foul{17, "G22", 23.5, true}},
|
|
Cards: Cards{[]int{17}, []int{8}}}
|
|
matchResult.RedScore = randomScore()
|
|
matchResult.BlueScore = randomScore()
|
|
err = CommitMatchScore(match, &matchResult)
|
|
if err != nil {
|
|
handleWebErr(w, err)
|
|
return
|
|
}
|
|
currentMatchType = match.Type
|
|
|
|
http.Redirect(w, r, "/match_play", 302)
|
|
}
|
|
|
|
func CommitMatchScore(match *Match, matchResult *MatchResult) error {
|
|
if matchResult.PlayNumber == 0 {
|
|
// Determine the play number for this new match result.
|
|
prevMatchResult, err := db.GetMatchResultForMatch(match.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if prevMatchResult != nil {
|
|
matchResult.PlayNumber = prevMatchResult.PlayNumber + 1
|
|
} else {
|
|
matchResult.PlayNumber = 1
|
|
}
|
|
|
|
// Save the match result record to the database.
|
|
err = db.CreateMatchResult(matchResult)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
// We are updating a match result record that already exists.
|
|
err := db.SaveMatchResult(matchResult)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Update and save the match record to the database.
|
|
match.Status = "complete"
|
|
redScore := matchResult.RedScoreSummary()
|
|
blueScore := matchResult.BlueScoreSummary()
|
|
if redScore.Score > blueScore.Score {
|
|
match.Winner = "R"
|
|
} else if redScore.Score < blueScore.Score {
|
|
match.Winner = "B"
|
|
} else {
|
|
match.Winner = "T"
|
|
}
|
|
err := db.SaveMatch(match)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Recalculate all the rankings.
|
|
err = db.CalculateRankings()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (list MatchPlayList) Len() int {
|
|
return len(list)
|
|
}
|
|
|
|
func (list MatchPlayList) Less(i, j int) bool {
|
|
return list[i].Status != "complete" && list[j].Status == "complete"
|
|
}
|
|
|
|
func (list MatchPlayList) Swap(i, j int) {
|
|
list[i], list[j] = list[j], list[i]
|
|
}
|
|
|
|
func buildMatchPlayList(matchType string) (MatchPlayList, error) {
|
|
matches, err := db.GetMatchesByType(matchType)
|
|
if err != nil {
|
|
return MatchPlayList{}, err
|
|
}
|
|
|
|
prefix := ""
|
|
if matchType == "practice" {
|
|
prefix = "P"
|
|
} else if matchType == "qualification" {
|
|
prefix = "Q"
|
|
}
|
|
matchPlayList := make(MatchPlayList, len(matches))
|
|
for i, match := range matches {
|
|
matchPlayList[i].Id = match.Id
|
|
matchPlayList[i].DisplayName = prefix + match.DisplayName
|
|
matchPlayList[i].Time = match.Time.Format("3:04 PM")
|
|
matchPlayList[i].Status = match.Status
|
|
switch match.Winner {
|
|
case "R":
|
|
matchPlayList[i].ColorClass = "danger"
|
|
case "B":
|
|
matchPlayList[i].ColorClass = "info"
|
|
case "T":
|
|
matchPlayList[i].ColorClass = "warning"
|
|
default:
|
|
matchPlayList[i].ColorClass = ""
|
|
}
|
|
if currentMatch != nil && matchPlayList[i].Id == currentMatch.Id {
|
|
matchPlayList[i].ColorClass = "success"
|
|
}
|
|
}
|
|
|
|
// Sort the list to put all completed matches at the bottom.
|
|
sort.Stable(matchPlayList)
|
|
|
|
return matchPlayList, nil
|
|
}
|
|
|
|
func randomScore() Score {
|
|
cycle := Cycle{rand.Intn(3) + 1, rand.Intn(2) == 1, rand.Intn(2) == 1, rand.Intn(2) == 1, rand.Intn(2) == 1,
|
|
rand.Intn(2) == 1}
|
|
return Score{rand.Intn(4), rand.Intn(4), rand.Intn(4), rand.Intn(4), rand.Intn(4), 0, 0, []Cycle{cycle}}
|
|
}
|