Added match result model.

This commit is contained in:
Patrick Fairbank
2014-05-26 20:16:36 -07:00
parent a4d461c795
commit df2eaa7bb3
5 changed files with 285 additions and 1 deletions

View File

@@ -19,6 +19,7 @@ type Database struct {
db *sql.DB
eventSettingsMap *modl.DbMap
matchMap *modl.DbMap
matchResultMap *modl.DbMap
teamMap *modl.DbMap
}
@@ -61,6 +62,9 @@ func (database *Database) mapTables() {
database.matchMap = modl.NewDbMap(database.db, dialect)
database.matchMap.AddTableWithName(Match{}, "matches").SetKeys(true, "Id")
database.matchResultMap = modl.NewDbMap(database.db, dialect)
database.matchResultMap.AddTableWithName(MatchResultDb{}, "match_results").SetKeys(true, "Id")
database.teamMap = modl.NewDbMap(database.db, dialect)
database.teamMap.AddTableWithName(Team{}, "teams").SetKeys(false, "Id")
}

View File

@@ -21,4 +21,4 @@ CREATE TABLE matches (
);
-- +goose Down
DROP TABLE event_settings;
DROP TABLE matches;

View File

@@ -0,0 +1,14 @@
-- +goose Up
CREATE TABLE match_results (
id INTEGER PRIMARY KEY,
matchid int,
playnumber int,
redscorejson text,
bluescorejson text,
redfoulsjson text,
bluefoulsjson text,
cardsjson text
);
-- +goose Down
DROP TABLE match_results;

171
match_result.go Normal file
View File

@@ -0,0 +1,171 @@
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
//
// Model and datastore CRUD methods for the results (score and fouls) from a match at an event.
package main
import (
"encoding/json"
)
type MatchResult struct {
Id int
MatchId int
PlayNumber int
RedScore Score
BlueScore Score
RedFouls Fouls
BlueFouls Fouls
Cards Cards
}
type MatchResultDb struct {
Id int
MatchId int
PlayNumber int
RedScoreJson string
BlueScoreJson string
RedFoulsJson string
BlueFoulsJson string
CardsJson string
}
type Score struct {
AutoMobilityBonuses int
AutoHighHot int
AutoHigh int
AutoLowHot int
AutoLow int
AutoClearHigh int
AutoClearLow int
Cycles []Cycle
}
type Cycle struct {
Assists int
Truss bool
Catch bool
ScoredHigh bool
ScoredLow bool
DeadBall bool
}
type Fouls struct {
Fouls []Foul
TechFouls []Foul
}
type Foul struct {
TeamId int
Rule string
TimeInMatchSec float32
}
type Cards struct {
YellowCardTeamIds []int
RedCardTeamIds []int
}
func (database *Database) CreateMatchResult(matchResult *MatchResult) error {
matchResultDb, err := matchResult.serialize()
if err != nil {
return err
}
err = database.matchResultMap.Insert(matchResultDb)
if err != nil {
return err
}
matchResult.Id = matchResultDb.Id
return nil
}
func (database *Database) GetMatchResultForMatch(matchId int) (*MatchResult, error) {
var matchResults []MatchResultDb
query := "SELECT * FROM match_results WHERE matchid = ? ORDER BY playnumber DESC LIMIT 1"
err := database.matchResultMap.Select(&matchResults, query, matchId)
if err != nil {
return nil, err
}
if len(matchResults) == 0 {
return nil, nil
}
matchResult, err := matchResults[0].deserialize()
if err != nil {
return nil, err
}
return matchResult, err
}
func (database *Database) SaveMatchResult(matchResult *MatchResult) error {
matchResultDb, err := matchResult.serialize()
if err != nil {
return err
}
_, err = database.matchResultMap.Update(matchResultDb)
return err
}
func (database *Database) DeleteMatchResult(matchResult *MatchResult) error {
matchResultDb, err := matchResult.serialize()
if err != nil {
return err
}
_, err = database.matchResultMap.Delete(matchResultDb)
return err
}
func (database *Database) TruncateMatchResults() error {
return database.matchResultMap.TruncateTables()
}
// 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}
if err := serializeHelper(&matchResultDb.RedScoreJson, matchResult.RedScore); err != nil {
return nil, err
}
if err := serializeHelper(&matchResultDb.BlueScoreJson, matchResult.BlueScore); err != nil {
return nil, err
}
if err := serializeHelper(&matchResultDb.RedFoulsJson, matchResult.RedFouls); err != nil {
return nil, err
}
if err := serializeHelper(&matchResultDb.BlueFoulsJson, matchResult.BlueFouls); err != nil {
return nil, err
}
if err := serializeHelper(&matchResultDb.CardsJson, matchResult.Cards); err != nil {
return nil, err
}
return &matchResultDb, nil
}
func serializeHelper(target *string, source interface{}) error {
bytes, err := json.Marshal(source)
if err != nil {
return err
}
*target = string(bytes)
return nil
}
// Converts the DB MatchResult with JSON fields to the nested struct version.
func (matchResultDb *MatchResultDb) deserialize() (*MatchResult, error) {
matchResult := MatchResult{Id: matchResultDb.Id, MatchId: matchResultDb.MatchId, PlayNumber: matchResultDb.PlayNumber}
if err := json.Unmarshal([]byte(matchResultDb.RedScoreJson), &matchResult.RedScore); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(matchResultDb.BlueScoreJson), &matchResult.BlueScore); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(matchResultDb.RedFoulsJson), &matchResult.RedFouls); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(matchResultDb.BlueFoulsJson), &matchResult.BlueFouls); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(matchResultDb.CardsJson), &matchResult.Cards); err != nil {
return nil, err
}
return &matchResult, nil
}

95
match_result_test.go Normal file
View File

@@ -0,0 +1,95 @@
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
package main
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestGetNonexistentMatchResult(t *testing.T) {
clearDb()
defer clearDb()
db, err := OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
match, err := db.GetMatchResultForMatch(1114)
assert.Nil(t, err)
assert.Nil(t, match)
}
func TestMatchResultCrud(t *testing.T) {
clearDb()
defer clearDb()
db, err := OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
matchResult := buildTestMatchResult(254, 5)
db.CreateMatchResult(&matchResult)
matchResult2, err := db.GetMatchResultForMatch(254)
assert.Nil(t, err)
assert.Equal(t, matchResult, *matchResult2)
matchResult.BlueScore.Cycles[0].Truss = !matchResult.BlueScore.Cycles[0].Truss
db.SaveMatchResult(&matchResult)
matchResult2, err = db.GetMatchResultForMatch(254)
assert.Nil(t, err)
assert.Equal(t, matchResult, *matchResult2)
db.DeleteMatchResult(&matchResult)
matchResult2, err = db.GetMatchResultForMatch(254)
assert.Nil(t, err)
assert.Nil(t, matchResult2)
}
func TestTruncateMatchResults(t *testing.T) {
clearDb()
defer clearDb()
db, err := OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
matchResult := buildTestMatchResult(254, 1)
db.CreateMatchResult(&matchResult)
db.TruncateMatchResults()
matchResult2, err := db.GetMatchResultForMatch(254)
assert.Nil(t, err)
assert.Nil(t, matchResult2)
}
func TestGetMatchResultForMatch(t *testing.T) {
clearDb()
defer clearDb()
db, err := OpenDatabase(testDbPath)
assert.Nil(t, err)
defer db.Close()
matchResult := buildTestMatchResult(254, 2)
db.CreateMatchResult(&matchResult)
matchResult2 := buildTestMatchResult(254, 5)
db.CreateMatchResult(&matchResult2)
matchResult3 := buildTestMatchResult(254, 4)
db.CreateMatchResult(&matchResult3)
// Should return the match result with the highest play number (i.e. the most recent).
matchResult4, err := db.GetMatchResultForMatch(254)
assert.Nil(t, err)
assert.Equal(t, matchResult2, *matchResult4)
}
func buildTestMatchResult(matchId int, playNumber int) MatchResult {
cycle1 := Cycle{3, true, true, true, false, false}
cycle2 := Cycle{2, false, false, false, true, false}
cycle3 := Cycle{1, true, false, false, false, true}
fouls := Fouls{[]Foul{Foul{25, "G22", 25.2}, Foul{25, "G18", 150}}, []Foul{Foul{1868, "G20", 0}}}
matchResult := MatchResult{MatchId: matchId, PlayNumber: playNumber}
matchResult.RedScore = Score{1, 2, 3, 4, 5, 6, 7, []Cycle{cycle1, cycle2, cycle3}}
matchResult.BlueScore = Score{7, 6, 5, 4, 3, 2, 1, []Cycle{cycle3, cycle1, cycle1, cycle1}}
matchResult.RedFouls = fouls
matchResult.BlueFouls = Fouls{}
matchResult.Cards = Cards{[]int{1868}, []int{}}
return matchResult
}