mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 21:56:50 -04:00
Add publishing of match video split times to STEMtv.
This commit is contained in:
@@ -26,7 +26,9 @@ CREATE TABLE event_settings (
|
||||
reddefenselightsaddress VARCHAR(255),
|
||||
bluegoallightsaddress VARCHAR(255),
|
||||
bluedefenselightsaddress VARCHAR(255),
|
||||
initialtowerstrength int
|
||||
initialtowerstrength int,
|
||||
stemtvpublishingenabled bool,
|
||||
stemtveventcode VARCHAR(16)
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
|
||||
const elimMatchSpacingSec = 600
|
||||
|
||||
var elimRoundNames = map[int]string{1: "F", 2: "SF", 4: "QF", 8: "EF"}
|
||||
|
||||
// Incrementally creates any elimination matches that can be created, based on the results of alliance
|
||||
// selection or prior elimination rounds. Returns the winning alliance once it has been determined.
|
||||
func (database *Database) UpdateEliminationSchedule(startTime time.Time) ([]AllianceTeam, error) {
|
||||
@@ -49,7 +51,7 @@ func (database *Database) buildEliminationMatchSet(round int, group int, numAlli
|
||||
if numAlliances < 2 {
|
||||
return []AllianceTeam{}, fmt.Errorf("Must have at least 2 alliances")
|
||||
}
|
||||
roundName, ok := map[int]string{1: "F", 2: "SF", 4: "QF", 8: "EF"}[round]
|
||||
roundName, ok := elimRoundNames[round]
|
||||
if !ok {
|
||||
return []AllianceTeam{}, fmt.Errorf("Round of depth %d is not supported", round*2)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ type EventSettings struct {
|
||||
BlueGoalLightsAddress string
|
||||
BlueDefenseLightsAddress string
|
||||
InitialTowerStrength int
|
||||
StemTvPublishingEnabled bool
|
||||
StemTvEventCode string
|
||||
}
|
||||
|
||||
const eventSettingsId = 0
|
||||
|
||||
11
match.go
11
match.go
@@ -6,6 +6,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -112,3 +113,13 @@ func (match *Match) CapitalizedType() string {
|
||||
}
|
||||
return strings.ToUpper(match.Type[0:1]) + match.Type[1:]
|
||||
}
|
||||
|
||||
func (match *Match) TbaCode() string {
|
||||
if match.Type == "qualification" {
|
||||
return fmt.Sprintf("qm%s", match.DisplayName)
|
||||
} else if match.Type == "elimination" {
|
||||
return fmt.Sprintf("%s%dm%d", strings.ToLower(elimRoundNames[match.ElimRound]), match.ElimGroup,
|
||||
match.ElimInstance)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -170,6 +170,16 @@ func MatchPlayShowResultHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}()
|
||||
}
|
||||
|
||||
if eventSettings.StemTvPublishingEnabled && match.Type != "practice" {
|
||||
// Publish asynchronously to STEMtv.
|
||||
go func() {
|
||||
err = PublishMatchVideoSplit(match, time.Now())
|
||||
if err != nil {
|
||||
log.Printf("Failed to publish match video split to STEMtv: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/match_play", 302)
|
||||
}
|
||||
|
||||
|
||||
@@ -122,9 +122,11 @@ func TestMatchPlayShowResult(t *testing.T) {
|
||||
assert.Equal(t, match.Id, mainArena.savedMatch.Id)
|
||||
assert.Equal(t, match.Id, mainArena.savedMatchResult.MatchId)
|
||||
|
||||
// Verify TBA publishing by checking the log for the expected failure messages.
|
||||
// Verify TBA and STEMtv publishing by checking the log for the expected failure messages.
|
||||
tbaBaseUrl = "fakeurl"
|
||||
stemTvBaseUrl = "fakeurl"
|
||||
eventSettings.TbaPublishingEnabled = true
|
||||
eventSettings.StemTvPublishingEnabled = true
|
||||
var writer bytes.Buffer
|
||||
log.SetOutput(&writer)
|
||||
recorder = getHttpResponse(fmt.Sprintf("/match_play/%d/show_result", match.Id))
|
||||
@@ -132,6 +134,7 @@ func TestMatchPlayShowResult(t *testing.T) {
|
||||
time.Sleep(time.Millisecond * 10) // Allow some time for the asynchronous publishing to happen.
|
||||
assert.Contains(t, writer.String(), "Failed to publish matches")
|
||||
assert.Contains(t, writer.String(), "Failed to publish rankings")
|
||||
assert.Contains(t, writer.String(), "Failed to publish match video split to STEMtv")
|
||||
}
|
||||
|
||||
func TestMatchPlayErrors(t *testing.T) {
|
||||
|
||||
@@ -122,3 +122,18 @@ func TestGetMatchesByType(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(matches))
|
||||
}
|
||||
|
||||
func TestTbaCode(t *testing.T) {
|
||||
match := Match{Type: "practice", DisplayName: "3"}
|
||||
assert.Equal(t, "", match.TbaCode())
|
||||
match = Match{Type: "qualification", DisplayName: "26"}
|
||||
assert.Equal(t, "qm26", match.TbaCode())
|
||||
match = Match{Type: "elimination", DisplayName: "EF2-1", ElimRound: 8, ElimGroup: 2, ElimInstance: 1}
|
||||
assert.Equal(t, "ef2m1", match.TbaCode())
|
||||
match = Match{Type: "elimination", DisplayName: "QF3-2", ElimRound: 4, ElimGroup: 3, ElimInstance: 2}
|
||||
assert.Equal(t, "qf3m2", match.TbaCode())
|
||||
match = Match{Type: "elimination", DisplayName: "SF1-3", ElimRound: 2, ElimGroup: 1, ElimInstance: 3}
|
||||
assert.Equal(t, "sf1m3", match.TbaCode())
|
||||
match = Match{Type: "elimination", DisplayName: "F2", ElimRound: 1, ElimGroup: 1, ElimInstance: 2}
|
||||
assert.Equal(t, "f1m2", match.TbaCode())
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ func SettingsPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
eventSettings.TbaEventCode = r.PostFormValue("tbaEventCode")
|
||||
eventSettings.TbaSecretId = r.PostFormValue("tbaSecretId")
|
||||
eventSettings.TbaSecret = r.PostFormValue("tbaSecret")
|
||||
eventSettings.StemTvPublishingEnabled = r.PostFormValue("stemTvPublishingEnabled") == "on"
|
||||
eventSettings.StemTvEventCode = r.PostFormValue("stemTvEventCode")
|
||||
eventSettings.NetworkSecurityEnabled = r.PostFormValue("networkSecurityEnabled") == "on"
|
||||
eventSettings.ApAddress = r.PostFormValue("apAddress")
|
||||
eventSettings.ApUsername = r.PostFormValue("apUsername")
|
||||
|
||||
27
stemtv.go
Normal file
27
stemtv.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2016 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
//
|
||||
// Methods for publishing match video split information to STEMtv.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
preMatchPaddingSec = 5
|
||||
postScoreDisplayPaddingSec = 10
|
||||
)
|
||||
|
||||
var stemTvBaseUrl = "http://stemtv.io"
|
||||
|
||||
func PublishMatchVideoSplit(match *Match, scoreDisplayTime time.Time) error {
|
||||
url := fmt.Sprintf("%s/event/api/v1.0/%s/%s/split/%d,%d", stemTvBaseUrl, eventSettings.StemTvEventCode,
|
||||
match.TbaCode(), match.StartedAt.Unix()-preMatchPaddingSec,
|
||||
scoreDisplayTime.Unix()+postScoreDisplayPaddingSec)
|
||||
_, err := http.Get(url)
|
||||
return err
|
||||
}
|
||||
35
stemtv_test.go
Normal file
35
stemtv_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2016 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"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPublishMatchVideoSplit(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
var err error
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
eventSettings.StemTvEventCode = "my_event_code"
|
||||
|
||||
// Mock the STEMtv server.
|
||||
stemTvServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, "/event/api/v1.0/my_event_code/qm254/split/981187501,981187690", r.URL.String())
|
||||
}))
|
||||
defer stemTvServer.Close()
|
||||
stemTvBaseUrl = stemTvServer.URL
|
||||
|
||||
matchStartedTime, _ := time.Parse("2006-01-02 15:04:05 -0700", "2001-02-03 04:05:06 -0400")
|
||||
match := &Match{Type: "qualification", DisplayName: "254", StartedAt: matchStartedTime}
|
||||
scoreDisplayTime, _ := time.Parse("2006-01-02 15:04:05 -0700", "2001-02-03 04:08:00 -0400")
|
||||
assert.Nil(t, PublishMatchVideoSplit(match, scoreDisplayTime))
|
||||
}
|
||||
@@ -128,6 +128,19 @@
|
||||
<input type="text" class="form-control" name="tbaSecret" value="{{.TbaSecret}}">
|
||||
</div>
|
||||
</div>
|
||||
<p>Contact STEMtv to obtain an event code.</p>
|
||||
<div class="form-group">
|
||||
<label class="col-lg-7 control-label">Enable STEMtv publishing</label>
|
||||
<div class="col-lg-1 checkbox">
|
||||
<input type="checkbox" name="stemTvPublishingEnabled"{{if .StemTvPublishingEnabled}} checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-lg-5 control-label">STEMtv Event Code</label>
|
||||
<div class="col-lg-7">
|
||||
<input type="text" class="form-control" name="stemTvEventCode" value="{{.StemTvEventCode}}">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Authentication</legend>
|
||||
|
||||
Reference in New Issue
Block a user