mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 21:56:50 -04:00
Merge branch 'master' of https://github.com/Team254/cheesy-arena
This commit is contained in:
69
arena.go
69
arena.go
@@ -12,8 +12,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
arenaLoopPeriodMs = 10
|
||||
dsPacketPeriodMs = 250
|
||||
arenaLoopPeriodMs = 10
|
||||
dsPacketPeriodMs = 250
|
||||
matchEndScoreDwellSec = 3
|
||||
)
|
||||
|
||||
// Progression of match states.
|
||||
@@ -56,30 +57,34 @@ type RealtimeScore struct {
|
||||
}
|
||||
|
||||
type Arena struct {
|
||||
AllianceStations map[string]*AllianceStation
|
||||
MatchState int
|
||||
CanStartMatch bool
|
||||
matchTiming MatchTiming
|
||||
currentMatch *Match
|
||||
redRealtimeScore *RealtimeScore
|
||||
blueRealtimeScore *RealtimeScore
|
||||
matchStartTime time.Time
|
||||
lastDsPacketTime time.Time
|
||||
matchStateNotifier *Notifier
|
||||
matchTimeNotifier *Notifier
|
||||
robotStatusNotifier *Notifier
|
||||
matchLoadTeamsNotifier *Notifier
|
||||
scoringStatusNotifier *Notifier
|
||||
realtimeScoreNotifier *Notifier
|
||||
scorePostedNotifier *Notifier
|
||||
audienceDisplayNotifier *Notifier
|
||||
playSoundNotifier *Notifier
|
||||
audienceDisplayScreen string
|
||||
allianceStationDisplays map[string]string
|
||||
lastMatchState int
|
||||
lastMatchTimeSec float64
|
||||
savedMatch *Match
|
||||
savedMatchResult *MatchResult
|
||||
AllianceStations map[string]*AllianceStation
|
||||
MatchState int
|
||||
CanStartMatch bool
|
||||
matchTiming MatchTiming
|
||||
currentMatch *Match
|
||||
redRealtimeScore *RealtimeScore
|
||||
blueRealtimeScore *RealtimeScore
|
||||
matchStartTime time.Time
|
||||
lastDsPacketTime time.Time
|
||||
matchStateNotifier *Notifier
|
||||
matchTimeNotifier *Notifier
|
||||
robotStatusNotifier *Notifier
|
||||
matchLoadTeamsNotifier *Notifier
|
||||
scoringStatusNotifier *Notifier
|
||||
realtimeScoreNotifier *Notifier
|
||||
scorePostedNotifier *Notifier
|
||||
audienceDisplayNotifier *Notifier
|
||||
playSoundNotifier *Notifier
|
||||
allianceStationDisplayNotifier *Notifier
|
||||
allianceSelectionNotifier *Notifier
|
||||
lowerThirdNotifier *Notifier
|
||||
audienceDisplayScreen string
|
||||
allianceStationDisplays map[string]string
|
||||
allianceStationDisplayScreen string
|
||||
lastMatchState int
|
||||
lastMatchTimeSec float64
|
||||
savedMatch *Match
|
||||
savedMatchResult *MatchResult
|
||||
}
|
||||
|
||||
var mainArena Arena // Named thusly to avoid polluting the global namespace with something more generic.
|
||||
@@ -108,6 +113,9 @@ func (arena *Arena) Setup() {
|
||||
arena.scorePostedNotifier = NewNotifier()
|
||||
arena.audienceDisplayNotifier = NewNotifier()
|
||||
arena.playSoundNotifier = NewNotifier()
|
||||
arena.allianceStationDisplayNotifier = NewNotifier()
|
||||
arena.allianceSelectionNotifier = NewNotifier()
|
||||
arena.lowerThirdNotifier = NewNotifier()
|
||||
|
||||
// Load empty match as current.
|
||||
arena.MatchState = PRE_MATCH
|
||||
@@ -120,6 +128,7 @@ func (arena *Arena) Setup() {
|
||||
arena.savedMatch = &Match{}
|
||||
arena.savedMatchResult = &MatchResult{}
|
||||
arena.allianceStationDisplays = make(map[string]string)
|
||||
arena.allianceStationDisplayScreen = "blank"
|
||||
}
|
||||
|
||||
// Loads a team into an alliance station, cleaning up the previous team there if there is one.
|
||||
@@ -402,8 +411,12 @@ func (arena *Arena) Update() {
|
||||
auto = false
|
||||
enabled = false
|
||||
sendDsPacket = true
|
||||
arena.audienceDisplayScreen = "blank"
|
||||
arena.audienceDisplayNotifier.Notify(nil)
|
||||
go func() {
|
||||
// Leave the scores on the screen briefly at the end of the match.
|
||||
time.Sleep(time.Second * matchEndScoreDwellSec)
|
||||
arena.audienceDisplayScreen = "blank"
|
||||
arena.audienceDisplayNotifier.Notify(nil)
|
||||
}()
|
||||
arena.playSoundNotifier.Notify("match-end")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type Database struct {
|
||||
rankingMap *modl.DbMap
|
||||
teamMap *modl.DbMap
|
||||
allianceTeamMap *modl.DbMap
|
||||
lowerThirdMap *modl.DbMap
|
||||
}
|
||||
|
||||
// Opens the SQLite database at the given path, creating it if it doesn't exist, and runs any pending
|
||||
@@ -75,4 +76,7 @@ func (database *Database) mapTables() {
|
||||
|
||||
database.allianceTeamMap = modl.NewDbMap(database.db, dialect)
|
||||
database.allianceTeamMap.AddTableWithName(AllianceTeam{}, "alliance_teams").SetKeys(true, "Id")
|
||||
|
||||
database.lowerThirdMap = modl.NewDbMap(database.db, dialect)
|
||||
database.lowerThirdMap.AddTableWithName(LowerThird{}, "lower_thirds").SetKeys(true, "Id")
|
||||
}
|
||||
|
||||
9
db/migrations/20140811222034_CreateLowerThirds.sql
Normal file
9
db/migrations/20140811222034_CreateLowerThirds.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE lower_thirds (
|
||||
id INTEGER PRIMARY KEY,
|
||||
toptext VARCHAR(255),
|
||||
bottomtext VARCHAR(255)
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE lower_thirds;
|
||||
50
displays.go
50
displays.go
@@ -60,6 +60,10 @@ func AudienceDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(scorePostedListener)
|
||||
playSoundListener := mainArena.playSoundNotifier.Listen()
|
||||
defer close(playSoundListener)
|
||||
allianceSelectionListener := mainArena.allianceSelectionNotifier.Listen()
|
||||
defer close(allianceSelectionListener)
|
||||
lowerThirdListener := mainArena.lowerThirdNotifier.Listen()
|
||||
defer close(lowerThirdListener)
|
||||
|
||||
// Send the various notifications immediately upon connection.
|
||||
var data interface{}
|
||||
@@ -113,6 +117,11 @@ func AudienceDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
return
|
||||
}
|
||||
err = websocket.Write("allianceSelection", cachedAlliances)
|
||||
if err != nil {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Spin off a goroutine to listen for notifications and pass them on through the websocket.
|
||||
go func() {
|
||||
@@ -173,6 +182,18 @@ func AudienceDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
messageType = "playSound"
|
||||
message = sound
|
||||
case _, ok := <-allianceSelectionListener:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
messageType = "allianceSelection"
|
||||
message = cachedAlliances
|
||||
case lowerThird, ok := <-lowerThirdListener:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
messageType = "lowerThird"
|
||||
message = lowerThird
|
||||
}
|
||||
err = websocket.Write(messageType, message)
|
||||
if err != nil {
|
||||
@@ -772,9 +793,14 @@ func AllianceStationDisplayHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
displayId := ""
|
||||
if _, ok := r.URL.Query()["displayId"]; ok {
|
||||
displayId = r.URL.Query()["displayId"][0]
|
||||
}
|
||||
data := struct {
|
||||
*EventSettings
|
||||
}{eventSettings}
|
||||
DisplayId string
|
||||
}{eventSettings, displayId}
|
||||
err = template.ExecuteTemplate(w, "alliance_station_display.html", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
@@ -797,10 +823,13 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
|
||||
station = ""
|
||||
mainArena.allianceStationDisplays[displayId] = station
|
||||
}
|
||||
defer delete(mainArena.allianceStationDisplays, displayId)
|
||||
|
||||
allianceStationDisplayListener := mainArena.allianceStationDisplayNotifier.Listen()
|
||||
defer close(allianceStationDisplayListener)
|
||||
matchLoadTeamsListener := mainArena.matchLoadTeamsNotifier.Listen()
|
||||
defer close(matchLoadTeamsListener)
|
||||
robotStatusListener := mainArena.robotStatusNotifier.Listen()
|
||||
defer close(robotStatusListener)
|
||||
matchTimeListener := mainArena.matchTimeNotifier.Listen()
|
||||
defer close(matchTimeListener)
|
||||
realtimeScoreListener := mainArena.realtimeScoreNotifier.Listen()
|
||||
@@ -808,6 +837,11 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// Send the various notifications immediately upon connection.
|
||||
var data interface{}
|
||||
err = websocket.Write("setAllianceStationDisplay", mainArena.allianceStationDisplayScreen)
|
||||
if err != nil {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
return
|
||||
}
|
||||
err = websocket.Write("matchTiming", mainArena.matchTiming)
|
||||
if err != nil {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
@@ -851,6 +885,12 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
|
||||
var messageType string
|
||||
var message interface{}
|
||||
select {
|
||||
case _, ok := <-allianceStationDisplayListener:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
messageType = "setAllianceStationDisplay"
|
||||
message = mainArena.allianceStationDisplayScreen
|
||||
case _, ok := <-matchLoadTeamsListener:
|
||||
if !ok {
|
||||
return
|
||||
@@ -864,6 +904,12 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
|
||||
"R2": mainArena.AllianceStations["R2"].team, "R3": mainArena.AllianceStations["R3"].team,
|
||||
"B1": mainArena.AllianceStations["B1"].team, "B2": mainArena.AllianceStations["B2"].team,
|
||||
"B3": mainArena.AllianceStations["B3"].team}}
|
||||
case _, ok := <-robotStatusListener:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
messageType = "status"
|
||||
message = mainArena
|
||||
case matchTimeSec, ok := <-matchTimeListener:
|
||||
if !ok {
|
||||
return
|
||||
|
||||
46
lower_third.go
Normal file
46
lower_third.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
//
|
||||
// Model and datastore CRUD methods for the text on a lower third slide.
|
||||
|
||||
package main
|
||||
|
||||
type LowerThird struct {
|
||||
Id int
|
||||
TopText string
|
||||
BottomText string
|
||||
}
|
||||
|
||||
func (database *Database) CreateLowerThird(lowerThird *LowerThird) error {
|
||||
return database.lowerThirdMap.Insert(lowerThird)
|
||||
}
|
||||
|
||||
func (database *Database) GetLowerThirdById(id int) (*LowerThird, error) {
|
||||
lowerThird := new(LowerThird)
|
||||
err := database.lowerThirdMap.Get(lowerThird, id)
|
||||
if err != nil && err.Error() == "sql: no rows in result set" {
|
||||
lowerThird = nil
|
||||
err = nil
|
||||
}
|
||||
return lowerThird, err
|
||||
}
|
||||
|
||||
func (database *Database) SaveLowerThird(lowerThird *LowerThird) error {
|
||||
_, err := database.lowerThirdMap.Update(lowerThird)
|
||||
return err
|
||||
}
|
||||
|
||||
func (database *Database) DeleteLowerThird(lowerThird *LowerThird) error {
|
||||
_, err := database.lowerThirdMap.Delete(lowerThird)
|
||||
return err
|
||||
}
|
||||
|
||||
func (database *Database) TruncateLowerThirds() error {
|
||||
return database.lowerThirdMap.TruncateTables()
|
||||
}
|
||||
|
||||
func (database *Database) GetAllLowerThirds() ([]LowerThird, error) {
|
||||
var lowerThirds []LowerThird
|
||||
err := database.teamMap.Select(&lowerThirds, "SELECT * FROM lower_thirds ORDER BY id")
|
||||
return lowerThirds, err
|
||||
}
|
||||
@@ -161,6 +161,8 @@ func MatchPlayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(audienceDisplayListener)
|
||||
scoringStatusListener := mainArena.scoringStatusNotifier.Listen()
|
||||
defer close(scoringStatusListener)
|
||||
allianceStationDisplayListener := mainArena.allianceStationDisplayNotifier.Listen()
|
||||
defer close(allianceStationDisplayListener)
|
||||
|
||||
// Send the various notifications immediately upon connection.
|
||||
var data interface{}
|
||||
@@ -196,6 +198,11 @@ func MatchPlayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
return
|
||||
}
|
||||
err = websocket.Write("setAllianceStationDisplay", mainArena.allianceStationDisplayScreen)
|
||||
if err != nil {
|
||||
log.Printf("Websocket error: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Spin off a goroutine to listen for notifications and pass them on through the websocket.
|
||||
go func() {
|
||||
@@ -232,6 +239,12 @@ func MatchPlayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
BlueScoreReady bool
|
||||
}{mainArena.redRealtimeScore.FoulsCommitted && mainArena.blueRealtimeScore.FoulsCommitted,
|
||||
mainArena.redRealtimeScore.TeleopCommitted, mainArena.blueRealtimeScore.TeleopCommitted}
|
||||
case _, ok := <-allianceStationDisplayListener:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
messageType = "setAllianceStationDisplay"
|
||||
message = mainArena.allianceStationDisplayScreen
|
||||
}
|
||||
err = websocket.Write(messageType, message)
|
||||
if err != nil {
|
||||
@@ -340,6 +353,15 @@ func MatchPlayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
mainArena.audienceDisplayScreen = screen
|
||||
mainArena.audienceDisplayNotifier.Notify(nil)
|
||||
continue
|
||||
case "setAllianceStationDisplay":
|
||||
screen, ok := data.(string)
|
||||
if !ok {
|
||||
websocket.WriteError(fmt.Sprintf("Failed to parse '%s' message.", messageType))
|
||||
continue
|
||||
}
|
||||
mainArena.allianceStationDisplayScreen = screen
|
||||
mainArena.allianceStationDisplayNotifier.Notify(nil)
|
||||
continue
|
||||
default:
|
||||
websocket.WriteError(fmt.Sprintf("Invalid message type '%s'.", messageType))
|
||||
continue
|
||||
|
||||
@@ -72,6 +72,8 @@ func AllianceSelectionPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainArena.allianceSelectionNotifier.Notify(nil)
|
||||
http.Redirect(w, r, "/setup/alliance_selection", 302)
|
||||
}
|
||||
|
||||
@@ -109,6 +111,8 @@ func AllianceSelectionStartHandler(w http.ResponseWriter, r *http.Request) {
|
||||
for i, ranking := range rankings {
|
||||
cachedRankedTeams[i] = &RankedTeam{i + 1, ranking.TeamId, false}
|
||||
}
|
||||
|
||||
mainArena.allianceSelectionNotifier.Notify(nil)
|
||||
http.Redirect(w, r, "/setup/alliance_selection", 302)
|
||||
}
|
||||
|
||||
@@ -121,6 +125,7 @@ func AllianceSelectionResetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
cachedAlliances = [][]*AllianceTeam{}
|
||||
cachedRankedTeams = []*RankedTeam{}
|
||||
mainArena.allianceSelectionNotifier.Notify(nil)
|
||||
http.Redirect(w, r, "/setup/alliance_selection", 302)
|
||||
}
|
||||
|
||||
|
||||
78
setup_lower_thirds.go
Normal file
78
setup_lower_thirds.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
//
|
||||
// Web routes for managing lower thirds.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Shows the lower third configuration page.
|
||||
func LowerThirdsGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
template, err := template.ParseFiles("templates/lower_thirds.html", "templates/base.html")
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
lowerThirds, err := db.GetAllLowerThirds()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
data := struct {
|
||||
*EventSettings
|
||||
LowerThirds []LowerThird
|
||||
}{eventSettings, lowerThirds}
|
||||
err = template.ExecuteTemplate(w, "base", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Saves the new or modified lower third to the database and triggers showing it on the audience display.
|
||||
func LowerThirdsPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
lowerThirdId, _ := strconv.Atoi(r.PostFormValue("id"))
|
||||
lowerThird, err := db.GetLowerThirdById(lowerThirdId)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
if r.PostFormValue("action") == "delete" {
|
||||
err := db.DeleteLowerThird(lowerThird)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Save the lower third even if the show or hide buttons were clicked.
|
||||
if lowerThird == nil {
|
||||
lowerThird = &LowerThird{TopText: r.PostFormValue("topText"),
|
||||
BottomText: r.PostFormValue("bottomText")}
|
||||
err = db.CreateLowerThird(lowerThird)
|
||||
} else {
|
||||
lowerThird.TopText = r.PostFormValue("topText")
|
||||
lowerThird.BottomText = r.PostFormValue("bottomText")
|
||||
err = db.SaveLowerThird(lowerThird)
|
||||
}
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if r.PostFormValue("action") == "show" {
|
||||
mainArena.lowerThirdNotifier.Notify(lowerThird)
|
||||
mainArena.audienceDisplayScreen = "lowerThird"
|
||||
mainArena.audienceDisplayNotifier.Notify(nil)
|
||||
} else if r.PostFormValue("action") == "hide" {
|
||||
mainArena.audienceDisplayScreen = "blank"
|
||||
mainArena.audienceDisplayNotifier.Notify(nil)
|
||||
}
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/setup/lower_thirds", 302)
|
||||
}
|
||||
@@ -8,28 +8,60 @@ body {
|
||||
background-color: #000;
|
||||
font-family: "FuturaLTBold";
|
||||
}
|
||||
#match {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#displayId {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto auto;
|
||||
height: 1px;
|
||||
line-height: 1px;
|
||||
text-align: center;
|
||||
color: #ff0;
|
||||
font-size: 500px;
|
||||
}
|
||||
#teamId {
|
||||
position: absolute;
|
||||
top: 7%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 500px;
|
||||
line-height: 500px;
|
||||
text-align: center;
|
||||
margin: 50px 0px;
|
||||
color: #fff;
|
||||
}
|
||||
#teamName {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
height: 200px;
|
||||
line-height: 200px;
|
||||
text-align: center;
|
||||
font-family: "FuturaLT";
|
||||
font-size: 120px;
|
||||
}
|
||||
[data-alliance=R] {
|
||||
color: #f00;
|
||||
}
|
||||
[data-alliance=B] {
|
||||
color: #00f;
|
||||
}
|
||||
.match-info {
|
||||
color: #fff;
|
||||
}
|
||||
#matchInfo {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
height: 200px;
|
||||
line-height: 200px;
|
||||
text-align: center;
|
||||
font-size: 190px;
|
||||
color: #fff;
|
||||
}
|
||||
#redScore {
|
||||
color: #f00;
|
||||
@@ -37,3 +69,21 @@ body {
|
||||
#blueScore {
|
||||
color: #00f;
|
||||
}
|
||||
#logo {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 90%;
|
||||
margin: auto auto;
|
||||
}
|
||||
[data-alliance=R], [data-status=R] {
|
||||
background-color: #f00;
|
||||
}
|
||||
[data-alliance=B], [data-status=B] {
|
||||
background-color: #00f;
|
||||
}
|
||||
[data-status=bypass] {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ html {
|
||||
overflow: hidden;
|
||||
}
|
||||
#centering {
|
||||
position: absolute; left: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -340px;
|
||||
}
|
||||
#matchOverlay {
|
||||
@@ -275,3 +276,61 @@ html {
|
||||
font-size: 28px;
|
||||
color: #fff;
|
||||
}
|
||||
#allianceSelectionCentering {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
display: table;
|
||||
}
|
||||
#allianceSelection {
|
||||
position: relative;
|
||||
left: -50%;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#allianceSelectionTable {
|
||||
background-color: #006;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
font-family: "FuturaLTBold";
|
||||
font-size: 70px;
|
||||
}
|
||||
.alliance-cell {
|
||||
padding: 0px 40px;
|
||||
font-family: "FuturaLT";
|
||||
color: #999;
|
||||
}
|
||||
.selection-cell {
|
||||
width: 250px;
|
||||
color: #fff;
|
||||
}
|
||||
#lowerThird {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: -1000px;
|
||||
bottom: 100px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
color: #000;
|
||||
font-size: 30px;
|
||||
width: 800px;
|
||||
height: 87px;
|
||||
}
|
||||
#lowerThirdLogo {
|
||||
margin: 20px;
|
||||
height: 45px;
|
||||
float: left;
|
||||
}
|
||||
#lowerThirdTop {
|
||||
display: none;
|
||||
font-family: "FuturaLTBold";
|
||||
}
|
||||
#lowerThirdBottom {
|
||||
display: none;
|
||||
font-family: "FuturaLT";
|
||||
}
|
||||
#lowerThirdSingle {
|
||||
display: none;
|
||||
font-family: "FuturaLTBold";
|
||||
line-height: 87px;
|
||||
}
|
||||
@@ -88,3 +88,6 @@
|
||||
.scoring-message {
|
||||
color: #f00;
|
||||
}
|
||||
.btn-lower-third {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ body {
|
||||
background: -webkit-linear-gradient(top, #003375 1%, #3C679D 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -webkit-linear-gradient(top, #003375 1%, #3C679D 100%); /* Chrome10+,Safari5.1+ */
|
||||
background-repeat: no-repeat;
|
||||
font-family: sans-serif;
|
||||
font-family: "FuturaLT";
|
||||
}
|
||||
#column {
|
||||
width: 80%;
|
||||
@@ -26,7 +26,7 @@ body {
|
||||
padding: 20px 0px;
|
||||
line-height: 50px;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
font-family: "FuturaLTBold";
|
||||
color: #fff;
|
||||
}
|
||||
#logo {
|
||||
|
||||
BIN
static/img/logo-black.png
Normal file
BIN
static/img/logo-black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
static/img/logo-colored.png
Normal file
BIN
static/img/logo-colored.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -3,11 +3,27 @@
|
||||
//
|
||||
// Client-side methods for the alliance station display.
|
||||
|
||||
// A unique id to differentiate this station's display from its peers.
|
||||
var displayId;
|
||||
var allianceStation = "";
|
||||
var blinkInterval;
|
||||
var websocket;
|
||||
|
||||
var handleSetAllianceStationDisplay = function(targetScreen) {
|
||||
switch (targetScreen) {
|
||||
case "logo":
|
||||
$("#match").hide();
|
||||
$("#logo").show();
|
||||
break;
|
||||
case "blank":
|
||||
$("#match").hide();
|
||||
$("#logo").hide();
|
||||
break;
|
||||
case "match":
|
||||
$("#match").show();
|
||||
$("#logo").hide();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
var handleSetMatch = function(data) {
|
||||
if (allianceStation != "" && data.AllianceStation == "") {
|
||||
// The client knows better what display this should be; let the server know.
|
||||
@@ -22,22 +38,49 @@ var handleSetMatch = function(data) {
|
||||
if (team == null) {
|
||||
$("#teamId").text("");
|
||||
$("#teamName").text("");
|
||||
$("#teamName").attr("data-alliance", "");
|
||||
} else {
|
||||
$("#teamId").attr("data-alliance", allianceStation[0]);
|
||||
$("#teamName").attr("data-alliance", allianceStation[0]);
|
||||
$("#teamId").text(data.Teams[allianceStation].Id);
|
||||
$("#teamName").text(data.Teams[allianceStation].Nickname);
|
||||
}
|
||||
$("#displayIdRow").hide();
|
||||
$("#teamIdRow").show();
|
||||
$("#teamNameRow").show();
|
||||
$("#displayId").hide();
|
||||
$("#teamId").show();
|
||||
$("#teamName").show();
|
||||
} else {
|
||||
// Show the display ID so that someone can assign it to a station from the configuration interface.
|
||||
$("#teamId").text("");
|
||||
$("#teamName").text("");
|
||||
$("#displayIdRow").show();
|
||||
$("#teamIdRow").hide();
|
||||
$("#teamNameRow").hide();
|
||||
$("#displayId").show();
|
||||
$("#teamId").hide();
|
||||
$("#teamName").hide();
|
||||
}
|
||||
};
|
||||
|
||||
var handleStatus = function(data) {
|
||||
stationStatus = data.AllianceStations[allianceStation];
|
||||
var blink = false;
|
||||
if (stationStatus.Bypass) {
|
||||
$("#match").attr("data-status", "bypass");
|
||||
} else if (stationStatus.DsConn) {
|
||||
if (!stationStatus.DsConn.DriverStationStatus.DsLinked) {
|
||||
$("#match").attr("data-status", allianceStation[0]);
|
||||
} else if (!stationStatus.DsConn.DriverStationStatus.RobotLinked) {
|
||||
blink = true;
|
||||
if (!blinkInterval) {
|
||||
blinkInterval = setInterval(function() {
|
||||
var status = $("#match").attr("data-status");
|
||||
$("#match").attr("data-status", (status == "") ? allianceStation[0] : "");
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$("#match").attr("data-status", "");
|
||||
}
|
||||
|
||||
if (!blink && blinkInterval) {
|
||||
clearInterval(blinkInterval);
|
||||
blinkInterval = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,11 +94,11 @@ var handleMatchTime = function(data) {
|
||||
$("#matchTime").text(countdownString);
|
||||
|
||||
if (matchState == "PRE_MATCH" || matchState == "POST_MATCH") {
|
||||
$("#teamNameRow").show();
|
||||
$("#matchInfoRow").hide();
|
||||
$("#teamName").show();
|
||||
$("#matchInfo").hide();
|
||||
} else {
|
||||
$("#teamNameRow").hide();
|
||||
$("#matchInfoRow").show();
|
||||
$("#teamName").hide();
|
||||
$("#matchInfo").show();
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -66,12 +109,17 @@ var handleRealtimeScore = function(data) {
|
||||
};
|
||||
|
||||
$(function() {
|
||||
displayId = Math.floor(Math.random() * 10000);
|
||||
if (displayId == "") {
|
||||
displayId = Math.floor(Math.random() * 10000);
|
||||
window.location = "/displays/alliance_station?displayId=" + displayId;
|
||||
}
|
||||
$("#displayId").text(displayId);
|
||||
|
||||
// Set up the websocket back to the server.
|
||||
websocket = new CheesyWebsocket("/displays/alliance_station/websocket?displayId=" + displayId, {
|
||||
setAllianceStationDisplay: function(event) { handleSetAllianceStationDisplay(event.data); },
|
||||
setMatch: function(event) { handleSetMatch(event.data); },
|
||||
status: function(event) { handleStatus(event.data); },
|
||||
matchTiming: function(event) { handleMatchTiming(event.data); },
|
||||
matchTime: function(event) { handleMatchTime(event.data); },
|
||||
realtimeScore: function(event) { handleRealtimeScore(event.data); }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
var websocket;
|
||||
var transitionMap;
|
||||
var currentScreen = "blank";
|
||||
var allianceSelectionTemplate = Handlebars.compile($("#allianceSelectionTemplate").html());
|
||||
|
||||
var handleSetAudienceDisplay = function(targetScreen) {
|
||||
if (targetScreen == currentScreen) {
|
||||
@@ -87,6 +88,30 @@ var handlePlaySound = function(sound) {
|
||||
$("#" + sound)[0].play();
|
||||
};
|
||||
|
||||
var handleAllianceSelection = function(alliances) {
|
||||
if (alliances) {
|
||||
$.each(alliances, function(k, v) {
|
||||
v.Index = k + 1;
|
||||
});
|
||||
$("#allianceSelection").html(allianceSelectionTemplate(alliances));
|
||||
}
|
||||
};
|
||||
|
||||
var handleLowerThird = function(data) {
|
||||
if (data.BottomText == "") {
|
||||
$("#lowerThirdTop").hide();
|
||||
$("#lowerThirdBottom").hide();
|
||||
$("#lowerThirdSingle").text(data.TopText);
|
||||
$("#lowerThirdSingle").show();
|
||||
} else {
|
||||
$("#lowerThirdSingle").hide();
|
||||
$("#lowerThirdTop").text(data.TopText);
|
||||
$("#lowerThirdBottom").text(data.BottomText);
|
||||
$("#lowerThirdTop").show();
|
||||
$("#lowerThirdBottom").show();
|
||||
}
|
||||
};
|
||||
|
||||
var transitionBlankToIntro = function(callback) {
|
||||
$("#centering").transition({queue: false, bottom: "0px"}, 500, "ease", function() {
|
||||
$(".teams").transition({queue: false, width: "75px"}, 100, "linear", function() {
|
||||
@@ -209,6 +234,34 @@ var transitionScoreToBlank = function(callback) {
|
||||
});
|
||||
}
|
||||
|
||||
var transitionBlankToAllianceSelection = function(callback) {
|
||||
$("#allianceSelectionCentering").show();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
var transitionAllianceSelectionToBlank = function(callback) {
|
||||
$("#allianceSelectionCentering").hide();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
var transitionBlankToLowerThird = function(callback) {
|
||||
$("#lowerThird").show();
|
||||
$("#lowerThird").transition({queue: false, left: "150px"}, 750, "ease", callback);
|
||||
};
|
||||
|
||||
var transitionLowerThirdToBlank = function(callback) {
|
||||
$("#lowerThird").transition({queue: false, left: "-1000px"}, 1000, "ease", function() {
|
||||
$("#lowerThird").hide();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$(function() {
|
||||
// Set up the websocket back to the server.
|
||||
websocket = new CheesyWebsocket("/displays/audience/websocket", {
|
||||
@@ -218,7 +271,9 @@ $(function() {
|
||||
matchTime: function(event) { handleMatchTime(event.data); },
|
||||
realtimeScore: function(event) { handleRealtimeScore(event.data); },
|
||||
setFinalScore: function(event) { handleSetFinalScore(event.data); },
|
||||
playSound: function(event) { handlePlaySound(event.data); }
|
||||
playSound: function(event) { handlePlaySound(event.data); },
|
||||
allianceSelection: function(event) { handleAllianceSelection(event.data); },
|
||||
lowerThird: function(event) { handleLowerThird(event.data); }
|
||||
});
|
||||
|
||||
// Map how to transition from one screen to another. Missing links between screens indicate that first we
|
||||
@@ -228,7 +283,9 @@ $(function() {
|
||||
intro: transitionBlankToIntro,
|
||||
match: transitionBlankToInMatch,
|
||||
score: transitionBlankToScore,
|
||||
logo: transitionBlankToLogo
|
||||
logo: transitionBlankToLogo,
|
||||
allianceSelection: transitionBlankToAllianceSelection,
|
||||
lowerThird: transitionBlankToLowerThird
|
||||
},
|
||||
intro: {
|
||||
blank: transitionIntroToBlank,
|
||||
@@ -245,6 +302,12 @@ $(function() {
|
||||
logo: {
|
||||
blank: transitionLogoToBlank,
|
||||
score: transitionLogoToScore
|
||||
},
|
||||
allianceSelection: {
|
||||
blank: transitionAllianceSelectionToBlank
|
||||
},
|
||||
lowerThird: {
|
||||
blank: transitionLowerThirdToBlank
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -34,6 +34,10 @@ var setAudienceDisplay = function() {
|
||||
websocket.send("setAudienceDisplay", $("input[name=audienceDisplay]:checked").val());
|
||||
};
|
||||
|
||||
var setAllianceStationDisplay = function() {
|
||||
websocket.send("setAllianceStationDisplay", $("input[name=allianceStationDisplay]:checked").val());
|
||||
};
|
||||
|
||||
var confirmCommit = function(isReplay) {
|
||||
if (isReplay || !scoreIsReady) {
|
||||
// Show the appropriate message(s) in the confirmation dialog.
|
||||
@@ -108,6 +112,7 @@ var handleMatchTime = function(data) {
|
||||
};
|
||||
|
||||
var handleSetAudienceDisplay = function(data) {
|
||||
$("input[name=audienceDisplay]:checked").prop("checked", false);
|
||||
$("input[name=audienceDisplay][value=" + data + "]").prop("checked", true);
|
||||
};
|
||||
|
||||
@@ -118,6 +123,11 @@ var handleScoringStatus = function(data) {
|
||||
$("#blueScoreStatus").attr("data-ready", data.BlueScoreReady);
|
||||
};
|
||||
|
||||
var handleSetAllianceStationDisplay = function(data) {
|
||||
$("input[name=allianceStationDisplay]:checked").prop("checked", false);
|
||||
$("input[name=allianceStationDisplay][value=" + data + "]").prop("checked", true);
|
||||
};
|
||||
|
||||
$(function() {
|
||||
// Activate tooltips above the status headers.
|
||||
$("[data-toggle=tooltip]").tooltip({"placement": "top"});
|
||||
@@ -128,6 +138,7 @@ $(function() {
|
||||
matchTiming: function(event) { handleMatchTiming(event.data); },
|
||||
matchTime: function(event) { handleMatchTime(event.data); },
|
||||
setAudienceDisplay: function(event) { handleSetAudienceDisplay(event.data); },
|
||||
scoringStatus: function(event) { handleScoringStatus(event.data); }
|
||||
scoringStatus: function(event) { handleScoringStatus(event.data); },
|
||||
setAllianceStationDisplay: function(event) { handleSetAllianceStationDisplay(event.data); }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,20 +8,21 @@
|
||||
<link rel="stylesheet" href="/static/css/alliance_station_display.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="row" id="displayIdRow" style="display: none;">>
|
||||
<div class="col-lg-12 text-center" id="displayId">1718</div>
|
||||
</div>
|
||||
<div class="row" id="teamIdRow" style="display: none;">>
|
||||
<div class="col-lg-12 text-center" id="teamId">254</div>
|
||||
</div>
|
||||
<div class="row" id="teamNameRow" style="display: none;">
|
||||
<div class="col-lg-12 text-center" id="teamName">Buchanan Bird Brains</div>
|
||||
</div>
|
||||
<div class="row" id="matchInfoRow" style="display: none;">
|
||||
<div class="col-lg-4 text-center match-info" id="redScore"></div>
|
||||
<div class="col-lg-4 text-center match-info" id="matchTime"></div>
|
||||
<div class="col-lg-4 text-center match-info" id="blueScore"></div>
|
||||
<div id="displayId" style="display: none;"></div>
|
||||
<div id="match" style="display: none;">
|
||||
<div id="teamId" style="display: none;"></div>
|
||||
<div id="teamName" style="display: none;"></div>
|
||||
<div class="row" id="matchInfo" style="display: none;">
|
||||
<div class="col-lg-4 text-center" id="redScore"></div>
|
||||
<div class="col-lg-4 text-center" id="matchTime"></div>
|
||||
<div class="col-lg-4 text-center" id="blueScore"></div>
|
||||
</div>
|
||||
</div>
|
||||
<img id="logo" src="/static/img/logo-black.png" style="display: none;"/>
|
||||
<script>
|
||||
// A unique id to differentiate this station's display from its peers.
|
||||
var displayId = "{{.DisplayId}}";
|
||||
</script>
|
||||
<script src="/static/js/lib/jquery.min.js"></script>
|
||||
<script src="/static/js/lib/jquery.json-2.4.min.js"></script>
|
||||
<script src="/static/js/lib/jquery.websocket-0.0.1.js"></script>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center" id="matchCircle">
|
||||
<img id="logo" src="/static/img/logo-min.svg"</img>
|
||||
<img id="logo" src="/static/img/logo-min.svg" />
|
||||
<div id="matchTime"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="blinds right center-blank"></div>
|
||||
<div class="blinds left background"></div>
|
||||
<div id="blindsCenter">
|
||||
<img id="blindsLogo" src="/static/img/logo-min.svg"</img>
|
||||
<img id="blindsLogo" src="/static/img/logo-min.svg" />
|
||||
</div>
|
||||
<div class="blinds left center-blank"></div>
|
||||
<div id="finalScore">
|
||||
@@ -98,6 +98,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="allianceSelectionCentering" style="display: none;">
|
||||
<div id="allianceSelection"></div>
|
||||
</div>
|
||||
<div id="lowerThird">
|
||||
<img id="lowerThirdLogo" src="/static/img/logo-min.svg" />
|
||||
<div id="lowerThirdTop"></div>
|
||||
<div id="lowerThirdBottom"></div>
|
||||
<div id="lowerThirdSingle"></div>
|
||||
</div>
|
||||
<script id="allianceSelectionTemplate" type="text/x-handlebars-template">
|
||||
<table id="allianceSelectionTable">
|
||||
{{"{{#each this}}"}}
|
||||
<tr>
|
||||
<td class="alliance-cell">{{"{{Index}}"}}</td>
|
||||
{{"{{#each this}}"}}
|
||||
<td class="selection-cell">{{"{{#if TeamId}}"}}{{"{{TeamId}}"}}{{"{{/if}}"}}</td>
|
||||
{{"{{/each}}"}}
|
||||
</tr>
|
||||
{{"{{/each}}"}}
|
||||
</table>
|
||||
</script>
|
||||
<audio id="match-start" src="/static/audio/match_start.wav" type="audio/wav" preload="auto" />
|
||||
<audio id="match-end" src="/static/audio/match_end.wav" type="audio/wav" preload="auto" />
|
||||
<audio id="match-abort" src="/static/audio/match_abort.mp3" type="audio/mp3" preload="auto" />
|
||||
@@ -107,6 +128,7 @@
|
||||
<script src="/static/js/lib/jquery.json-2.4.min.js"></script>
|
||||
<script src="/static/js/lib/jquery.websocket-0.0.1.js"></script>
|
||||
<script src="/static/js/lib/jquery.transit.min.js"></script>
|
||||
<script src="/static/js/lib/handlebars-1.3.0.js"></script>
|
||||
<script src="/static/js/cheesy-websocket.js"></script>
|
||||
<script src="/static/js/match_timing.js"></script>
|
||||
<script src="/static/js/audience_display.js"></script>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<li><a href="/setup/teams">Team List</a></li>
|
||||
<li><a href="/setup/schedule">Match Scheduling</a></li>
|
||||
<li><a href="/setup/alliance_selection">Alliance Selection</a></li>
|
||||
<li><a href="/setup/lower_thirds">Lower Thirds</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
|
||||
43
templates/lower_thirds.html
Normal file
43
templates/lower_thirds.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{{define "title"}}Lower Thirds{{end}}
|
||||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-lg-offset-3">
|
||||
<div class="well">
|
||||
<legend>Lower Thirds</legend>
|
||||
{{range $lowerThird := .LowerThirds}}
|
||||
<form class="form-horizontal" action="/setup/lower_thirds" method="POST">
|
||||
<div class="form-group">
|
||||
<div class="col-lg-7">
|
||||
<input type="hidden" name="id" value="{{$lowerThird.Id}}" />
|
||||
<input type="text" class="form-control" name="topText" value="{{$lowerThird.TopText}}"
|
||||
placeholder="Top Text"/>
|
||||
<input type="text" class="form-control" name="bottomText" value="{{$lowerThird.BottomText}}"
|
||||
placeholder="Bottom Text"/>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<button type="submit" class="btn btn-info btn-lower-third" name="action" value="save">Save</button>
|
||||
<button type="submit" class="btn btn-success btn-lower-third" name="action" value="show">Show</button>
|
||||
<br />
|
||||
<button type="submit" class="btn btn-primary btn-lower-third" name="action" value="delete">Delete</button>
|
||||
<button type="submit" class="btn btn-default btn-lower-third" name="action" value="hide">Hide</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{end}}
|
||||
<form class="form-horizontal" action="/setup/lower_thirds" method="POST">
|
||||
<div class="form-group">
|
||||
<div class="col-lg-7">
|
||||
<input type="text" class="form-control" name="topText" placeholder="Top or Solo Text" />
|
||||
<input type="text" class="form-control" name="bottomText" placeholder="Bottom Text" />
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<button type="submit" class="btn btn-info btn-lower-third" name="action" value="save">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}
|
||||
{{end}}
|
||||
@@ -97,8 +97,8 @@
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-lg-6 well">
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-9 well">
|
||||
<div class="col-lg-4">
|
||||
Audience Display
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
@@ -126,14 +126,43 @@
|
||||
<input type="radio" name="audienceDisplay" value="logo" onclick="setAudienceDisplay();">Logo
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="audienceDisplay" value="allianceSelection"
|
||||
onclick="setAudienceDisplay();">Alliance Selection
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-4">
|
||||
<p>Scoring Status</p>
|
||||
<p><span class="label label-scoring" id="refereeScoreStatus">Referee</span><br />
|
||||
<span class="label label-scoring" id="redScoreStatus">Red Scoring</span><br />
|
||||
<span class="label label-scoring" id="blueScoreStatus">Blue Scoring</span></p>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
Alliance Station Display
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="allianceStationDisplay" value="blank"
|
||||
onclick="setAllianceStationDisplay();">Blank
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="allianceStationDisplay" value="match"
|
||||
onclick="setAllianceStationDisplay();">Match
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="allianceStationDisplay" value="logo"
|
||||
onclick="setAllianceStationDisplay();">Logo
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
<title>Pit Display - {{.EventSettings.Name}} - Cheesy Arena </title>
|
||||
<link rel="shortcut icon" href="/static/img/favicon32.png">
|
||||
<link rel="stylesheet" href="/static/css/lib/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/static/css/cheesy-arena.css" />
|
||||
<link rel="stylesheet" href="/static/css/pit_display.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="column">
|
||||
<div id="titlebar">
|
||||
<div class="pull-left">TEAM STANDINGS</div>
|
||||
<div class="pull-right"><img id="logo" src="/static/img/logo.png"></div>
|
||||
<div class="pull-right"><img id="logo" src="/static/img/logo-colored.png"></div>
|
||||
<div> </div>
|
||||
</div>
|
||||
<div id="standings">
|
||||
|
||||
2
web.go
2
web.go
@@ -123,6 +123,8 @@ func newHandler() http.Handler {
|
||||
router.HandleFunc("/setup/alliance_selection/finalize", AllianceSelectionFinalizeHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/field", FieldGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/field", FieldPostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/lower_thirds", LowerThirdsGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/lower_thirds", LowerThirdsPostHandler).Methods("POST")
|
||||
router.HandleFunc("/match_play", MatchPlayHandler).Methods("GET")
|
||||
router.HandleFunc("/match_play/{matchId}/load", MatchPlayLoadHandler).Methods("GET")
|
||||
router.HandleFunc("/match_play/{matchId}/show_result", MatchPlayShowResultHandler).Methods("GET")
|
||||
|
||||
Reference in New Issue
Block a user