diff --git a/match_result.go b/match_result.go index ae46479..ecb3f10 100644 --- a/match_result.go +++ b/match_result.go @@ -67,6 +67,16 @@ type Cards struct { RedCardTeamIds []int } +type ScoreSummary struct { + AutoPoints int + AssistPoints int + TrussCatchPoints int + GoalPoints int + TeleopPoints int + FoulPoints int + Score int +} + func (database *Database) CreateMatchResult(matchResult *MatchResult) error { matchResultDb, err := matchResult.serialize() if err != nil { @@ -119,6 +129,57 @@ func (database *Database) TruncateMatchResults() error { return database.matchResultMap.TruncateTables() } +// Calculates and returns the summary fields used for ranking and display for the red alliance. +func (matchResult *MatchResult) RedScoreSummary() *ScoreSummary { + return scoreSummary(&matchResult.RedScore, &matchResult.BlueFouls) +} + +// Calculates and returns the summary fields used for ranking and display for the blue alliance. +func (matchResult *MatchResult) BlueScoreSummary() *ScoreSummary { + return scoreSummary(&matchResult.BlueScore, &matchResult.RedFouls) +} + +// Calculates and returns the summary fields used for ranking and display. +func scoreSummary(score *Score, opponentFouls *Fouls) *ScoreSummary { + summary := new(ScoreSummary) + + // Calculate autonomous score. + summary.AutoPoints = 5*score.AutoMobilityBonuses + 20*score.AutoHighHot + 15*score.AutoHigh + + 11*score.AutoLowHot + 6*score.AutoLow + + // Calculate teleop score. + summary.GoalPoints = 10*score.AutoClearHigh + 1*score.AutoClearLow + for _, cycle := range score.Cycles { + if cycle.Truss { + summary.TrussCatchPoints += 10 + if cycle.Catch { + summary.TrussCatchPoints += 10 + } + } + if cycle.ScoredHigh { + summary.GoalPoints += 10 + } else if cycle.ScoredLow { + summary.GoalPoints += 1 + } + if cycle.ScoredHigh || cycle.ScoredLow { + if cycle.Assists == 2 { + summary.AssistPoints += 10 + } else if cycle.Assists == 3 { + summary.AssistPoints += 30 + } + } + } + + // Calculate foul score. + summary.FoulPoints = 20*len(opponentFouls.Fouls) + 50*len(opponentFouls.TechFouls) + + // Fill in summed values. + summary.TeleopPoints = summary.AssistPoints + summary.TrussCatchPoints + summary.GoalPoints + summary.Score = summary.AutoPoints + summary.TeleopPoints + summary.FoulPoints + + return summary +} + // Converts the nested struct MatchResult to the DB version that has JSON fields. func (matchResult *MatchResult) serialize() (*MatchResultDb, error) { matchResultDb := MatchResultDb{Id: matchResult.Id, MatchId: matchResult.MatchId, PlayNumber: matchResult.PlayNumber} diff --git a/match_result_test.go b/match_result_test.go index 51d9991..8772eda 100644 --- a/match_result_test.go +++ b/match_result_test.go @@ -80,6 +80,73 @@ func TestGetMatchResultForMatch(t *testing.T) { assert.Equal(t, matchResult2, *matchResult4) } +func TestCycleScores(t *testing.T) { + matchResult := MatchResult{} + matchResult.RedScore.Cycles = []Cycle{Cycle{}} + assert.Equal(t, 0, matchResult.RedScoreSummary().Score) + cycle := &matchResult.RedScore.Cycles[0] + + *cycle = Cycle{Assists: 3, Truss: false, Catch: false, ScoredHigh: false, ScoredLow: false, DeadBall: true} + assert.Equal(t, 0, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: true, Catch: false, ScoredHigh: false, ScoredLow: false, DeadBall: true} + assert.Equal(t, 10, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: false, Catch: true, ScoredHigh: false, ScoredLow: false, DeadBall: true} + assert.Equal(t, 0, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: true, Catch: true, ScoredHigh: false, ScoredLow: false, DeadBall: true} + assert.Equal(t, 20, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 0, Truss: false, Catch: false, ScoredHigh: true, ScoredLow: false, DeadBall: false} + assert.Equal(t, 10, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 1, Truss: false, Catch: false, ScoredHigh: true, ScoredLow: false, DeadBall: false} + assert.Equal(t, 10, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 2, Truss: false, Catch: false, ScoredHigh: true, ScoredLow: false, DeadBall: false} + assert.Equal(t, 20, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: false, Catch: true, ScoredHigh: true, ScoredLow: false, DeadBall: false} + assert.Equal(t, 40, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 1, Truss: false, Catch: false, ScoredHigh: false, ScoredLow: true, DeadBall: false} + assert.Equal(t, 1, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 2, Truss: false, Catch: true, ScoredHigh: false, ScoredLow: true, DeadBall: false} + assert.Equal(t, 11, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: false, Catch: false, ScoredHigh: false, ScoredLow: true, DeadBall: false} + assert.Equal(t, 31, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: true, Catch: true, ScoredHigh: false, ScoredLow: true, DeadBall: false} + assert.Equal(t, 51, matchResult.RedScoreSummary().Score) + + *cycle = Cycle{Assists: 3, Truss: true, Catch: true, ScoredHigh: true, ScoredLow: true, DeadBall: false} + assert.Equal(t, 60, matchResult.RedScoreSummary().Score) +} + +func TestScoreSummary(t *testing.T) { + matchResult := buildTestMatchResult(1, 1) + redSummary := matchResult.RedScoreSummary() + assert.Equal(t, 164, redSummary.AutoPoints) + assert.Equal(t, 40, redSummary.AssistPoints) + assert.Equal(t, 30, redSummary.TrussCatchPoints) + assert.Equal(t, 78, redSummary.GoalPoints) + assert.Equal(t, 148, redSummary.TeleopPoints) + assert.Equal(t, 0, redSummary.FoulPoints) + assert.Equal(t, 312, redSummary.Score) + + blueSummary := matchResult.BlueScoreSummary() + assert.Equal(t, 292, blueSummary.AutoPoints) + assert.Equal(t, 90, blueSummary.AssistPoints) + assert.Equal(t, 70, blueSummary.TrussCatchPoints) + assert.Equal(t, 51, blueSummary.GoalPoints) + assert.Equal(t, 211, blueSummary.TeleopPoints) + assert.Equal(t, 90, blueSummary.FoulPoints) + assert.Equal(t, 593, blueSummary.Score) +} + func buildTestMatchResult(matchId int, playNumber int) MatchResult { cycle1 := Cycle{3, true, true, true, false, false} cycle2 := Cycle{2, false, false, false, true, false}