Update TBA publishing for 2016.

This commit is contained in:
Patrick Fairbank
2016-08-14 18:59:24 -07:00
parent 3d35cbb0ac
commit 1358ae6b83
3 changed files with 173 additions and 97 deletions

View File

@@ -170,6 +170,7 @@ func getMatchResultFromRequest(r *http.Request) (*Match, *MatchResult, bool, err
if matchResult == nil {
// We're scoring a match that hasn't been played yet, but that's okay.
matchResult = NewMatchResult()
matchResult.MatchType = match.Type
}
return match, matchResult, false, nil

144
tba.go
View File

@@ -28,22 +28,41 @@ var tbaEventNames = make(map[string]string)
// MODELS
type TbaMatch struct {
CompLevel string `json:"comp_level"`
SetNumber int `json:"set_number"`
MatchNumber int `json:"match_number"`
Alliances map[string]interface{} `json:"alliances"`
ScoreBreakdown map[string]TbaScoreBreakdown `json:"score_breakdown"`
TimeString string `json:"time_string"`
TimeUtc string `json:"time_utc"`
CompLevel string `json:"comp_level"`
SetNumber int `json:"set_number"`
MatchNumber int `json:"match_number"`
Alliances map[string]interface{} `json:"alliances"`
ScoreBreakdown map[string]*TbaScoreBreakdown `json:"score_breakdown"`
TimeString string `json:"time_string"`
TimeUtc string `json:"time_utc"`
}
type TbaScoreBreakdown struct {
Coopertition int `json:"coopertition_points"`
Auto int `json:"auto_points"`
Container int `json:"container_points"`
Tote int `json:"tote_points"`
Litter int `json:"litter_points"`
Foul int `json:"foul_points"`
TeleopBouldersLow int `json:"teleopBouldersLow"`
TeleopBouldersHigh int `json:"teleopBouldersHigh"`
TeleopTowerCaptured bool `json:"teleopTowerCaptured"`
TeleopDefensesBreached bool `json:"teleopDefensesBreached"`
Position1Crossings int `json:"position1crossings"`
Position2 string `json:"position2"`
Position2Crossings int `json:"position2crossings"`
Position3 string `json:"position3"`
Position3Crossings int `json:"position3crossings"`
Position4 string `json:"position4"`
Position4Crossings int `json:"position4crossings"`
Position5 string `json:"position5"`
Position5Crossings int `json:"position5crossings"`
AutoPoints int `json:"autoPoints"`
AutoReachPoints int `json:"autoReachPoints"`
AutoCrossingPoints int `json:"autoCrossingPoints"`
AutoBoulderPoints int `json:"autoBoulderPoints"`
TeleopCrossingPoints int `json:"teleopCrossingPoints"`
TeleopBoulderPoints int `json:"teleopBoulderPoints"`
TeleopChallengePoints int `json:"teleopChallengePoints"`
TeleopScalePoints int `json:"teleopScalePoints"`
BreachPoints int `json:"breachPoints"`
CapturePoints int `json:"capturePoints"`
FoulPoints int `json:"foulPoints"`
TotalPoints int `json:"totalPoints"`
}
type TbaRanking struct {
@@ -51,9 +70,10 @@ type TbaRanking struct {
Rank int `json:"rank"`
RP int `json:"RP"`
Auto int `json:"Auto"`
ScaleChallenge int `json:"ScaleChallenge"`
ScaleChallenge int `json:"Scale/Challenge"`
Goal int `json:"Goal"`
Defense int `json:"Defense"`
WinLossTie string `json:"W-L-T"`
Dqs int `json:"dqs"`
Played int `json:"played"`
}
@@ -240,30 +260,21 @@ func PublishMatches() error {
getTbaTeam(match.Red3)}, "score": nil}
blueAlliance := map[string]interface{}{"teams": []string{getTbaTeam(match.Blue1), getTbaTeam(match.Blue2),
getTbaTeam(match.Blue3)}, "score": nil}
var scoreBreakdown map[string]TbaScoreBreakdown
var scoreBreakdown map[string]*TbaScoreBreakdown
// Fill in scores if the match has been played.
if match.Status == "complete" {
// TODO(patrick): Implement for 2016.
/*
matchResult, err := db.GetMatchResultForMatch(match.Id)
if err != nil {
return err
}
if matchResult != nil {
redScoreSummary := matchResult.RedScoreSummary()
blueScoreSummary := matchResult.BlueScoreSummary()
redAlliance["score"] = redScoreSummary.Score
blueAlliance["score"] = blueScoreSummary.Score
scoreBreakdown = make(map[string]TbaScoreBreakdown)
scoreBreakdown["red"] = TbaScoreBreakdown{redScoreSummary.CoopertitionPoints,
redScoreSummary.AutoPoints, redScoreSummary.ContainerPoints, redScoreSummary.TotePoints,
redScoreSummary.LitterPoints, redScoreSummary.FoulPoints}
scoreBreakdown["blue"] = TbaScoreBreakdown{blueScoreSummary.CoopertitionPoints,
blueScoreSummary.AutoPoints, blueScoreSummary.ContainerPoints, blueScoreSummary.TotePoints,
blueScoreSummary.LitterPoints, blueScoreSummary.FoulPoints}
}
*/
matchResult, err := db.GetMatchResultForMatch(match.Id)
if err != nil {
return err
}
if matchResult != nil {
scoreBreakdown = make(map[string]*TbaScoreBreakdown)
scoreBreakdown["red"] = createTbaScoringBreakdown(&match, matchResult, "red")
scoreBreakdown["blue"] = createTbaScoringBreakdown(&match, matchResult, "blue")
redAlliance["score"] = scoreBreakdown["red"].TotalPoints
blueAlliance["score"] = scoreBreakdown["blue"].TotalPoints
}
}
tbaMatches[i] = TbaMatch{"qm", 0, matchNumber, map[string]interface{}{"red": redAlliance,
@@ -300,12 +311,13 @@ func PublishRankings() error {
}
// Build a JSON object of TBA-format rankings.
breakdowns := []string{"RP", "Auto", "Scale/Challenge", "Goal", "Defense"}
breakdowns := []string{"RP", "Auto", "Scale/Challenge", "Goal", "Defense", "W-L-T"}
tbaRankings := make([]TbaRanking, len(rankings))
for i, ranking := range rankings {
tbaRankings[i] = TbaRanking{getTbaTeam(ranking.TeamId), ranking.Rank, ranking.RankingPoints,
ranking.AutoPoints, ranking.ScaleChallengePoints, ranking.GoalPoints, ranking.DefensePoints,
ranking.Disqualifications, ranking.Played}
fmt.Sprintf("%d-%d-%d", ranking.Wins, ranking.Losses, ranking.Ties), ranking.Disqualifications,
ranking.Played}
}
jsonBody, err := json.Marshal(map[string]interface{}{"breakdowns": breakdowns, "rankings": tbaRankings})
if err != nil {
@@ -402,3 +414,61 @@ func getTbaRequest(url string) (*http.Response, error) {
req.Header.Set("X-TBA-App-Id", "cheesy-arena:cheesy-fms:v0.1")
return client.Do(req)
}
func createTbaScoringBreakdown(match *Match, matchResult *MatchResult, alliance string) *TbaScoreBreakdown {
tbaDefenseNames := map[string]string{"CDF": "A_ChevalDeFrise", "M": "B_Moat", "R": "B_Ramparts",
"RW": "D_RockWall", "RT": "D_RoughTerrain"}
var score *Score
var opponentScore *Score
var scoreSummary *ScoreSummary
var breakdown TbaScoreBreakdown
if alliance == "red" {
score = &matchResult.RedScore
opponentScore = &matchResult.BlueScore
scoreSummary = matchResult.RedScoreSummary()
breakdown.Position2 = tbaDefenseNames[match.RedDefense2]
breakdown.Position3 = tbaDefenseNames[match.RedDefense3]
breakdown.Position4 = tbaDefenseNames[match.RedDefense4]
breakdown.Position5 = tbaDefenseNames[match.RedDefense5]
} else {
score = &matchResult.BlueScore
opponentScore = &matchResult.RedScore
scoreSummary = matchResult.BlueScoreSummary()
breakdown.Position2 = tbaDefenseNames[match.BlueDefense2]
breakdown.Position3 = tbaDefenseNames[match.BlueDefense3]
breakdown.Position4 = tbaDefenseNames[match.BlueDefense4]
breakdown.Position5 = tbaDefenseNames[match.BlueDefense5]
}
breakdown.TeleopBouldersLow = score.LowGoals
breakdown.TeleopBouldersHigh = score.HighGoals
breakdown.TeleopTowerCaptured = scoreSummary.Captured
breakdown.TeleopDefensesBreached = scoreSummary.Breached
breakdown.Position1Crossings = score.AutoDefensesCrossed[0] + score.DefensesCrossed[0]
breakdown.Position2Crossings = score.AutoDefensesCrossed[1] + score.DefensesCrossed[1]
breakdown.Position3Crossings = score.AutoDefensesCrossed[2] + score.DefensesCrossed[2]
breakdown.Position4Crossings = score.AutoDefensesCrossed[3] + score.DefensesCrossed[3]
breakdown.Position5Crossings = score.AutoDefensesCrossed[4] + score.DefensesCrossed[4]
breakdown.AutoPoints = scoreSummary.AutoPoints
breakdown.AutoReachPoints = 2 * score.AutoDefensesReached
for _, crossings := range score.AutoDefensesCrossed {
breakdown.AutoCrossingPoints += 10 * crossings
}
breakdown.AutoBoulderPoints = 5*score.AutoLowGoals + 10*score.AutoHighGoals
for _, crossings := range score.DefensesCrossed {
breakdown.TeleopCrossingPoints += 5 * crossings
}
breakdown.TeleopBoulderPoints = 2*score.LowGoals + 5*score.HighGoals
breakdown.TeleopChallengePoints = 5 * score.Challenges
breakdown.TeleopScalePoints = 15 * score.Scales
if match.Type == "elimination" {
if scoreSummary.Breached {
breakdown.BreachPoints = 20
}
if scoreSummary.Captured {
breakdown.CapturePoints = 25
}
}
breakdown.FoulPoints = 5 * len(opponentScore.Fouls)
breakdown.TotalPoints = scoreSummary.Score
return &breakdown
}

View File

@@ -9,6 +9,7 @@ import (
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestPublishTeams(t *testing.T) {
@@ -41,73 +42,77 @@ func TestPublishTeams(t *testing.T) {
}
func TestPublishMatches(t *testing.T) {
// TODO(patrick): Update for 2016.
/*
clearDb()
defer clearDb()
var err error
db, err = OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
eventSettings, _ = db.GetEventSettings()
match1 := Match{Type: "qualification", DisplayName: "2", Time: time.Unix(600, 0), Red1: 7, Red2: 8, Red3: 9,
Blue1: 10, Blue2: 11, Blue3: 12, Status: "complete"}
match2 := Match{Type: "elimination", DisplayName: "SF2-2", ElimRound: 2, ElimGroup: 2, ElimInstance: 2}
db.CreateMatch(&match1)
db.CreateMatch(&match2)
matchResult1 := buildTestMatchResult(match1.Id, 1)
db.CreateMatchResult(&matchResult1)
clearDb()
defer clearDb()
var err error
db, err = OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
eventSettings, _ = db.GetEventSettings()
match1 := Match{Type: "qualification", DisplayName: "2", Time: time.Unix(600, 0), Red1: 7, Red2: 8, Red3: 9,
Blue1: 10, Blue2: 11, Blue3: 12, Status: "complete"}
match2 := Match{Type: "elimination", DisplayName: "SF2-2", ElimRound: 2, ElimGroup: 2, ElimInstance: 2}
db.CreateMatch(&match1)
db.CreateMatch(&match2)
matchResult1 := buildTestMatchResult(match1.Id, 1)
db.CreateMatchResult(&matchResult1)
// Mock the TBA server.
tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var reader bytes.Buffer
reader.ReadFrom(r.Body)
assert.Equal(t, "[{\"comp_level\":\"qm\",\"set_number\":0,\"match_number\":2,\"alliances\":{\"blue\""+
":{\"score\":104,\"teams\":[\"frc10\",\"frc11\",\"frc12\"]},\"red\":{\"score\":92,\"teams\":[\"f"+
"rc7\",\"frc8\",\"frc9\"]}},\"score_breakdown\":{\"blue\":{\"coopertition_points\":40,\"auto_poi"+
"nts\":10,\"container_points\":24,\"tote_points\":24,\"litter_points\":6,\"foul_points\":0},\"re"+
"d\":{\"coopertition_points\":40,\"auto_points\":28,\"container_points\":24,\"tote_points\":12,"+
"\"litter_points\":6,\"foul_points\":18}},\"time_string\":\"4:10 PM\",\"time_utc\":\"1970-01-01T"+
"00:10:00\"},{\"comp_level\":\"sf\",\"set_number\":2,\"match_number\":2,\"alliances\":{\"blue\":"+
"{\"score\":null,\"teams\":[\"frc0\",\"frc0\",\"frc0\"]},\"red\":{\"score\":null,\"teams\":[\"fr"+
"c0\",\"frc0\",\"frc0\"]}},\"score_breakdown\":null,\"time_string\":\"4:00 PM\",\"time_utc\":\"0"+
"001-01-01T00:00:00\"}]", reader.String())
}))
defer tbaServer.Close()
tbaBaseUrl = tbaServer.URL
// Mock the TBA server.
tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var reader bytes.Buffer
reader.ReadFrom(r.Body)
assert.Equal(t, "[{\"comp_level\":\"qm\",\"set_number\":0,\"match_number\":2,\"alliances\":{\"blue"+
"\":{\"score\":113,\"teams\":[\"frc10\",\"frc11\",\"frc12\"]},\"red\":{\"score\":156,\"teams\":"+
"[\"frc7\",\"frc8\",\"frc9\"]}},\"score_breakdown\":{\"blue\":{\"teleopBouldersLow\":3,\"teleop"+
"BouldersHigh\":4,\"teleopTowerCaptured\":false,\"teleopDefensesBreached\":false,\"position1cro"+
"ssings\":1,\"position2\":\"\",\"position2crossings\":2,\"position3\":\"\",\"position3crossings"+
"\":0,\"position4\":\"\",\"position4crossings\":0,\"position5\":\"\",\"position5crossings\":1,"+
"\"autoPoints\":22,\"autoReachPoints\":2,\"autoCrossingPoints\":10,\"autoBoulderPoints\":10,\"t"+
"eleopCrossingPoints\":15,\"teleopBoulderPoints\":26,\"teleopChallengePoints\":5,\"teleopScaleP"+
"oints\":30,\"breachPoints\":0,\"capturePoints\":0,\"foulPoints\":15,\"totalPoints\":113},\"red"+
"\":{\"teleopBouldersLow\":3,\"teleopBouldersHigh\":11,\"teleopTowerCaptured\":false,\"teleopDe"+
"fensesBreached\":true,\"position1crossings\":2,\"position2\":\"\",\"position2crossings\":2,\"p"+
"osition3\":\"\",\"position3crossings\":2,\"position4\":\"\",\"position4crossings\":2,\"positio"+
"n5\":\"\",\"position5crossings\":1,\"autoPoints\":55,\"autoReachPoints\":0,\"autoCrossingPoint"+
"s\":30,\"autoBoulderPoints\":25,\"teleopCrossingPoints\":30,\"teleopBoulderPoints\":61,\"teleo"+
"pChallengePoints\":10,\"teleopScalePoints\":0,\"breachPoints\":0,\"capturePoints\":0,\"foulPoi"+
"nts\":0,\"totalPoints\":156}},\"time_string\":\"4:10 PM\",\"time_utc\":\"1970-01-01T00:10:00\""+
"},{\"comp_level\":\"sf\",\"set_number\":2,\"match_number\":2,\"alliances\":{\"blue\":{\"score"+
"\":null,\"teams\":[\"frc0\",\"frc0\",\"frc0\"]},\"red\":{\"score\":null,\"teams\":[\"frc0\",\""+
"frc0\",\"frc0\"]}},\"score_breakdown\":null,\"time_string\":\"4:00 PM\",\"time_utc\":\"0001-01"+
"-01T00:00:00\"}]", reader.String())
}))
defer tbaServer.Close()
tbaBaseUrl = tbaServer.URL
assert.Nil(t, PublishMatches())
*/
assert.Nil(t, PublishMatches())
}
func TestPublishRankings(t *testing.T) {
// TODO(patrick): Update for 2016.
/*
clearDb()
defer clearDb()
var err error
db, err = OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
eventSettings, _ = db.GetEventSettings()
db.CreateRanking(&Ranking{1114, 2, 20, 625, 90, 554, 10, 0.254, 0, 10})
db.CreateRanking(&Ranking{254, 1, 20, 625, 90, 554, 10, 0.254, 0, 10})
clearDb()
defer clearDb()
var err error
db, err = OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
eventSettings, _ = db.GetEventSettings()
db.CreateRanking(&Ranking{1114, 2, 20, 625, 90, 554, 10, 0.254, 3, 2, 1, 0, 10})
db.CreateRanking(&Ranking{254, 1, 20, 625, 90, 554, 10, 0.254, 1, 2, 3, 0, 10})
// Mock the TBA server.
tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var reader bytes.Buffer
reader.ReadFrom(r.Body)
assert.Equal(t, "{\"breakdowns\":[\"QA\",\"Coopertition\",\"Auto\",\"Container\",\"Tote\","+
"\"Litter\"],\"rankings\":[{\"team_key\":\"frc254\",\"rank\":1,\"QA\":20,\"Coopertition\":1100,"+
"\"Auto\":625,\"Container\":90,\"Tote\":554,\"Litter\":10,\"dqs\":0,\"played\":10},"+
"{\"team_key\":\"frc1114\",\"rank\":2,\"QA\":20,\"Coopertition\":1100,\"Auto\":625,"+
"\"Container\":90,\"Tote\":554,\"Litter\":10,\"dqs\":0,\"played\":10}]}", reader.String())
}))
defer tbaServer.Close()
tbaBaseUrl = tbaServer.URL
// Mock the TBA server.
tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var reader bytes.Buffer
reader.ReadFrom(r.Body)
assert.Equal(t, "{\"breakdowns\":[\"RP\",\"Auto\",\"Scale/Challenge\",\"Goal\",\"Defense\",\"W-L-T"+
"\"],\"rankings\":[{\"team_key\":\"frc254\",\"rank\":1,\"RP\":20,\"Auto\":625,\"Scale/Challenge"+
"\":90,\"Goal\":554,\"Defense\":10,\"W-L-T\":\"1-2-3\",\"dqs\":0,\"played\":10},{\"team_key\":"+
"\"frc1114\",\"rank\":2,\"RP\":20,\"Auto\":625,\"Scale/Challenge\":90,\"Goal\":554,\"Defense\":"+
"10,\"W-L-T\":\"3-2-1\",\"dqs\":0,\"played\":10}]}", reader.String())
}))
defer tbaServer.Close()
tbaBaseUrl = tbaServer.URL
assert.Nil(t, PublishRankings())
*/
assert.Nil(t, PublishRankings())
}
func TestPublishAlliances(t *testing.T) {