mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 21:56:50 -04:00
Implement bracket audience display for double-elimination.
This commit is contained in:
71
web/api.go
71
web/api.go
@@ -34,6 +34,19 @@ type RankingWithNickname struct {
|
||||
Nickname string
|
||||
}
|
||||
|
||||
type allianceMatchup struct {
|
||||
Round int
|
||||
Group int
|
||||
DisplayName string
|
||||
RedAllianceSource string
|
||||
BlueAllianceSource string
|
||||
RedAlliance *model.Alliance
|
||||
BlueAlliance *model.Alliance
|
||||
IsActive bool
|
||||
SeriesLeader string
|
||||
SeriesStatus string
|
||||
}
|
||||
|
||||
// Generates a JSON dump of the matches and results.
|
||||
func (web *Web) matchesApiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
@@ -211,3 +224,61 @@ func (web *Web) teamAvatarsApiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
http.ServeFile(w, r, avatarPath)
|
||||
}
|
||||
|
||||
func (web *Web) bracketSvgApiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
alliances, err := web.arena.Database.GetAllAlliances()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
activeMatch := web.arena.SavedMatch
|
||||
|
||||
matchups := make(map[string]*allianceMatchup)
|
||||
if web.arena.PlayoffBracket != nil {
|
||||
for _, matchup := range web.arena.PlayoffBracket.GetAllMatchups() {
|
||||
allianceMatchup := allianceMatchup{
|
||||
Round: matchup.Round,
|
||||
Group: matchup.Group,
|
||||
DisplayName: matchup.LongDisplayName(),
|
||||
RedAllianceSource: matchup.RedAllianceSourceDisplayName(),
|
||||
BlueAllianceSource: matchup.BlueAllianceSourceDisplayName(),
|
||||
}
|
||||
if matchup.RedAllianceId > 0 {
|
||||
if len(alliances) > 0 {
|
||||
allianceMatchup.RedAlliance = &alliances[matchup.RedAllianceId-1]
|
||||
} else {
|
||||
allianceMatchup.RedAlliance = &model.Alliance{Id: matchup.RedAllianceId}
|
||||
}
|
||||
}
|
||||
if matchup.BlueAllianceId > 0 {
|
||||
if len(alliances) > 0 {
|
||||
allianceMatchup.BlueAlliance = &alliances[matchup.BlueAllianceId-1]
|
||||
} else {
|
||||
allianceMatchup.BlueAlliance = &model.Alliance{Id: matchup.BlueAllianceId}
|
||||
}
|
||||
}
|
||||
if activeMatch != nil {
|
||||
allianceMatchup.IsActive = activeMatch.ElimRound == matchup.Round &&
|
||||
activeMatch.ElimGroup == matchup.Group
|
||||
}
|
||||
allianceMatchup.SeriesLeader, allianceMatchup.SeriesStatus = matchup.StatusText()
|
||||
matchups[fmt.Sprintf("%d_%d", matchup.Round, matchup.Group)] = &allianceMatchup
|
||||
}
|
||||
}
|
||||
|
||||
template, err := web.parseFiles("templates/bracket.svg")
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
data := struct {
|
||||
*model.EventSettings
|
||||
Matchups map[string]*allianceMatchup
|
||||
}{web.arena.EventSettings, matchups}
|
||||
w.Header().Set("Content-Type", "image/svg+xml")
|
||||
err = template.ExecuteTemplate(w, "bracket", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/Team254/cheesy-arena-lite/game"
|
||||
"github.com/Team254/cheesy-arena-lite/model"
|
||||
"github.com/Team254/cheesy-arena-lite/tournament"
|
||||
"github.com/Team254/cheesy-arena-lite/websocket"
|
||||
gorillawebsocket "github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -31,7 +32,7 @@ func TestMatchesApi(t *testing.T) {
|
||||
|
||||
recorder := web.getHttpResponse("/api/matches/qualification")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.HeaderMap["Content-Type"][0])
|
||||
assert.Equal(t, "application/json", recorder.Header()["Content-Type"][0])
|
||||
var matchesData []MatchWithResult
|
||||
err := json.Unmarshal([]byte(recorder.Body.String()), &matchesData)
|
||||
assert.Nil(t, err)
|
||||
@@ -49,7 +50,7 @@ func TestRankingsApi(t *testing.T) {
|
||||
// Test that empty rankings produces an empty array.
|
||||
recorder := web.getHttpResponse("/api/rankings")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.HeaderMap["Content-Type"][0])
|
||||
assert.Equal(t, "application/json", recorder.Header()["Content-Type"][0])
|
||||
rankingsData := struct {
|
||||
Rankings []RankingWithNickname
|
||||
TeamNicknames map[string]string
|
||||
@@ -71,7 +72,7 @@ func TestRankingsApi(t *testing.T) {
|
||||
|
||||
recorder = web.getHttpResponse("/api/rankings")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.HeaderMap["Content-Type"][0])
|
||||
assert.Equal(t, "application/json", recorder.Header()["Content-Type"][0])
|
||||
err = json.Unmarshal([]byte(recorder.Body.String()), &rankingsData)
|
||||
assert.Nil(t, err)
|
||||
if assert.Equal(t, 2, len(rankingsData.Rankings)) {
|
||||
@@ -91,7 +92,7 @@ func TestSponsorSlidesApi(t *testing.T) {
|
||||
|
||||
recorder := web.getHttpResponse("/api/sponsor_slides")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.HeaderMap["Content-Type"][0])
|
||||
assert.Equal(t, "application/json", recorder.Header()["Content-Type"][0])
|
||||
var sponsorSlides []model.SponsorSlide
|
||||
err := json.Unmarshal([]byte(recorder.Body.String()), &sponsorSlides)
|
||||
assert.Nil(t, err)
|
||||
@@ -108,7 +109,7 @@ func TestAlliancesApi(t *testing.T) {
|
||||
|
||||
recorder := web.getHttpResponse("/api/alliances")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.HeaderMap["Content-Type"][0])
|
||||
assert.Equal(t, "application/json", recorder.Header()["Content-Type"][0])
|
||||
var alliances []model.Alliance
|
||||
err := json.Unmarshal([]byte(recorder.Body.String()), &alliances)
|
||||
assert.Nil(t, err)
|
||||
@@ -143,3 +144,15 @@ func TestArenaWebsocketApi(t *testing.T) {
|
||||
readWebsocketType(t, ws, "matchLoad")
|
||||
readWebsocketType(t, ws, "matchTime")
|
||||
}
|
||||
|
||||
func TestBracketSvgApiDoubleElimination(t *testing.T) {
|
||||
web := setupTestWeb(t)
|
||||
web.arena.EventSettings.ElimType = "double"
|
||||
tournament.CreateTestAlliances(web.arena.Database, 8)
|
||||
web.arena.CreatePlayoffBracket()
|
||||
|
||||
recorder := web.getHttpResponse("/api/bracket/svg")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "image/svg+xml", recorder.Header()["Content-Type"][0])
|
||||
assert.Contains(t, recorder.Body.String(), "Best-of-3")
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func TestMatchReviewEditExistingResult(t *testing.T) {
|
||||
matchResult.MatchType = match.Type
|
||||
assert.Nil(t, web.arena.Database.CreateMatchResult(matchResult))
|
||||
tournament.CreateTestAlliances(web.arena.Database, 2)
|
||||
web.arena.EventSettings.NumElimAlliances = 2
|
||||
web.arena.CreatePlayoffBracket()
|
||||
|
||||
recorder := web.getHttpResponse("/match_review")
|
||||
@@ -86,6 +87,7 @@ func TestMatchReviewCreateNewResult(t *testing.T) {
|
||||
Red2: 1002, Red3: 1003, Blue1: 1004, Blue2: 1005, Blue3: 1006, ElimRedAlliance: 1, ElimBlueAlliance: 2}
|
||||
web.arena.Database.CreateMatch(&match)
|
||||
tournament.CreateTestAlliances(web.arena.Database, 2)
|
||||
web.arena.EventSettings.NumElimAlliances = 2
|
||||
web.arena.CreatePlayoffBracket()
|
||||
|
||||
recorder := web.getHttpResponse("/match_review")
|
||||
|
||||
@@ -115,6 +115,7 @@ func (web *Web) newHandler() http.Handler {
|
||||
router.HandleFunc("/alliance_selection/start", web.allianceSelectionStartHandler).Methods("POST")
|
||||
router.HandleFunc("/api/alliances", web.alliancesApiHandler).Methods("GET")
|
||||
router.HandleFunc("/api/arena/websocket", web.arenaWebsocketApiHandler).Methods("GET")
|
||||
router.HandleFunc("/api/bracket/svg", web.bracketSvgApiHandler).Methods("GET")
|
||||
router.HandleFunc("/api/matches/{type}", web.matchesApiHandler).Methods("GET")
|
||||
router.HandleFunc("/api/rankings", web.rankingsApiHandler).Methods("GET")
|
||||
router.HandleFunc("/api/scores", web.getScoresHandler).Methods("GET")
|
||||
|
||||
Reference in New Issue
Block a user