Enabled editing of match results before committing.

This commit is contained in:
Patrick Fairbank
2015-08-19 22:35:04 -07:00
parent 874aeb44e8
commit d35ffaca13
9 changed files with 67 additions and 37 deletions

View File

@@ -460,7 +460,7 @@ func TestSubstituteTeam(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, 107, mainArena.currentMatch.Red1)
assert.Equal(t, 107, mainArena.AllianceStations["R1"].team.Id)
CommitMatchScore(mainArena.currentMatch, &MatchResult{MatchId: mainArena.currentMatch.Id})
CommitMatchScore(mainArena.currentMatch, &MatchResult{MatchId: mainArena.currentMatch.Id}, false)
match2, _ := db.GetMatchById(match.Id)
assert.Equal(t, 107, match2.Red1)

View File

@@ -407,7 +407,7 @@ func MatchPlayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
}
// Saves the given match and result to the database, supplanting any previous result for the match.
func CommitMatchScore(match *Match, matchResult *MatchResult) error {
func CommitMatchScore(match *Match, matchResult *MatchResult, loadToShowBuffer bool) error {
if matchResult.RedScore.CoopertitionSet != matchResult.BlueScore.CoopertitionSet ||
matchResult.RedScore.CoopertitionStack != matchResult.BlueScore.CoopertitionStack {
// Don't accept the score if the red and blue co-opertition points don't match up.
@@ -423,10 +423,12 @@ func CommitMatchScore(match *Match, matchResult *MatchResult) error {
matchResult.CorrectEliminationScore()
}
// Store the result in the buffer to be shown in the audience display.
mainArena.savedMatch = match
mainArena.savedMatchResult = matchResult
mainArena.scorePostedNotifier.Notify(nil)
if loadToShowBuffer {
// Store the result in the buffer to be shown in the audience display.
mainArena.savedMatch = match
mainArena.savedMatchResult = matchResult
mainArena.scorePostedNotifier.Notify(nil)
}
if match.Type == "test" {
// Do nothing since this is a test match and doesn't exist in the database.
@@ -520,12 +522,15 @@ func CommitMatchScore(match *Match, matchResult *MatchResult) error {
return nil
}
// Saves the realtime result as the final score for the match currently loaded into the arena.
func CommitCurrentMatchScore() error {
matchResult := MatchResult{MatchId: mainArena.currentMatch.Id,
func GetCurrentMatchResult() *MatchResult {
return &MatchResult{MatchId: mainArena.currentMatch.Id,
RedScore: mainArena.redRealtimeScore.CurrentScore, BlueScore: mainArena.blueRealtimeScore.CurrentScore,
RedCards: mainArena.redRealtimeScore.Cards, BlueCards: mainArena.blueRealtimeScore.Cards}
return CommitMatchScore(mainArena.currentMatch, &matchResult)
}
// Saves the realtime result as the final score for the match currently loaded into the arena.
func CommitCurrentMatchScore() error {
return CommitMatchScore(mainArena.currentMatch, GetCurrentMatchResult(), true)
}
// Helper function to implement the required interface for Sort.

View File

@@ -149,7 +149,7 @@ func TestCommitMatch(t *testing.T) {
// Committing test match should do nothing.
match := &Match{Id: 0, Type: "test", Red1: 101, Red2: 102, Red3: 103, Blue1: 104, Blue2: 105, Blue3: 106}
err = CommitMatchScore(match, &MatchResult{MatchId: match.Id})
err = CommitMatchScore(match, &MatchResult{MatchId: match.Id}, false)
assert.Nil(t, err)
matchResult, err := db.GetMatchResultForMatch(match.Id)
assert.Nil(t, err)
@@ -160,19 +160,19 @@ func TestCommitMatch(t *testing.T) {
match.Type = "qualification"
db.CreateMatch(match)
matchResult = &MatchResult{MatchId: match.Id, BlueScore: Score{AutoRobotSet: true}}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 1, matchResult.PlayNumber)
match, _ = db.GetMatchById(1)
assert.Equal(t, "B", match.Winner)
matchResult = &MatchResult{MatchId: match.Id, RedScore: Score{AutoRobotSet: true}}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 2, matchResult.PlayNumber)
match, _ = db.GetMatchById(1)
assert.Equal(t, "R", match.Winner)
matchResult = &MatchResult{MatchId: match.Id}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 3, matchResult.PlayNumber)
match, _ = db.GetMatchById(1)
@@ -183,7 +183,7 @@ func TestCommitMatch(t *testing.T) {
eventSettings.TbaPublishingEnabled = true
var writer bytes.Buffer
log.SetOutput(&writer)
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
time.Sleep(time.Millisecond * 10) // Allow some time for the asynchronous publishing to happen.
assert.Contains(t, writer.String(), "Failed to publish matches")
@@ -203,13 +203,13 @@ func TestCommitEliminationTie(t *testing.T) {
match := &Match{Id: 0, Type: "qualification", Red1: 1, Red2: 2, Red3: 3, Blue1: 4, Blue2: 5, Blue3: 6}
db.CreateMatch(match)
matchResult := &MatchResult{MatchId: match.Id, RedScore: Score{AutoToteSet: true, Fouls: []Foul{Foul{}}}}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
match, _ = db.GetMatchById(1)
assert.Equal(t, "T", match.Winner)
match.Type = "elimination"
db.SaveMatch(match)
CommitMatchScore(match, matchResult)
CommitMatchScore(match, matchResult, false)
match, _ = db.GetMatchById(1)
assert.Equal(t, "T", match.Winner) // No elimination tiebreakers in 2015.
}
@@ -230,21 +230,21 @@ func TestCommitCards(t *testing.T) {
match := &Match{Id: 0, Type: "qualification", Red1: 1, Red2: 2, Red3: 3, Blue1: 4, Blue2: 5, Blue3: 6}
db.CreateMatch(match)
matchResult := &MatchResult{MatchId: match.Id, BlueCards: map[string]string{"5": "yellow"}}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
team, _ = db.GetTeamById(5)
assert.True(t, team.YellowCard)
// Check that editing a match result removes a yellow card from a team.
matchResult = &MatchResult{MatchId: match.Id}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
team, _ = db.GetTeamById(5)
assert.False(t, team.YellowCard)
// Check that a red card causes a yellow card to stick with a team.
matchResult = &MatchResult{MatchId: match.Id, BlueCards: map[string]string{"5": "red"}}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
team, _ = db.GetTeamById(5)
assert.True(t, team.YellowCard)
@@ -255,7 +255,7 @@ func TestCommitCards(t *testing.T) {
db.SaveMatch(match)
*matchResult = buildTestMatchResult(match.Id, 10)
matchResult.RedCards = map[string]string{"1": "red"}
err = CommitMatchScore(match, matchResult)
err = CommitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 0, matchResult.RedScoreSummary().Score)
assert.Equal(t, 104, matchResult.BlueScoreSummary().Score)

View File

@@ -66,7 +66,7 @@ func MatchReviewHandler(w http.ResponseWriter, r *http.Request) {
// Shows the page to edit the results for a match.
func MatchReviewEditGetHandler(w http.ResponseWriter, r *http.Request) {
match, matchResult, err := getMatchResultFromRequest(r)
match, matchResult, _, err := getMatchResultFromRequest(r)
if err != nil {
handleWebErr(w, err)
return
@@ -96,7 +96,7 @@ func MatchReviewEditGetHandler(w http.ResponseWriter, r *http.Request) {
// Updates the results for a match.
func MatchReviewEditPostHandler(w http.ResponseWriter, r *http.Request) {
match, matchResult, err := getMatchResultFromRequest(r)
match, matchResult, isCurrent, err := getMatchResultFromRequest(r)
if err != nil {
handleWebErr(w, err)
return
@@ -114,36 +114,52 @@ func MatchReviewEditPostHandler(w http.ResponseWriter, r *http.Request) {
return
}
err = CommitMatchScore(match, matchResult)
if err != nil {
handleWebErr(w, err)
return
}
if isCurrent {
// If editing the current match, just save it back to memory.
mainArena.redRealtimeScore.CurrentScore = matchResult.RedScore
mainArena.blueRealtimeScore.CurrentScore = matchResult.BlueScore
mainArena.redRealtimeScore.Cards = matchResult.RedCards
mainArena.blueRealtimeScore.Cards = matchResult.BlueCards
http.Redirect(w, r, "/match_review", 302)
http.Redirect(w, r, "/match_play", 302)
} else {
err = CommitMatchScore(match, matchResult, false)
if err != nil {
handleWebErr(w, err)
return
}
http.Redirect(w, r, "/match_review", 302)
}
}
// Load the match result for the match referenced in the HTTP query string.
func getMatchResultFromRequest(r *http.Request) (*Match, *MatchResult, error) {
func getMatchResultFromRequest(r *http.Request) (*Match, *MatchResult, bool, error) {
vars := mux.Vars(r)
// If editing the current match, get it from memory instead of the DB.
if vars["matchId"] == "current" {
return mainArena.currentMatch, GetCurrentMatchResult(), true, nil
}
matchId, _ := strconv.Atoi(vars["matchId"])
match, err := db.GetMatchById(matchId)
if err != nil {
return nil, nil, err
return nil, nil, false, err
}
if match == nil {
return nil, nil, fmt.Errorf("Error: No such match: %d", matchId)
return nil, nil, false, fmt.Errorf("Error: No such match: %d", matchId)
}
matchResult, err := db.GetMatchResultForMatch(matchId)
if err != nil {
return nil, nil, err
return nil, nil, false, err
}
if matchResult == nil {
// We're scoring a match that hasn't been played yet, but that's okay.
matchResult = NewMatchResult()
}
return match, matchResult, nil
return match, matchResult, false, nil
}
// Constructs the list of matches to display in the match review interface.

View File

@@ -74,7 +74,8 @@
background-color: #fc0;
}
.btn-match-play {
width: 165px;
width: 150px;
font-size: 16px;
}
.label-scoring {
background-color: #e66;

View File

@@ -106,6 +106,7 @@ var handleStatus = function(data) {
$("#abortMatch").prop("disabled", true);
$("#commitResults").prop("disabled", true);
$("#discardResults").prop("disabled", true);
$("#editResults").prop("disabled", true);
break;
case "START_MATCH":
case "AUTO_PERIOD":
@@ -116,12 +117,14 @@ var handleStatus = function(data) {
$("#abortMatch").prop("disabled", false);
$("#commitResults").prop("disabled", true);
$("#discardResults").prop("disabled", true);
$("#editResults").prop("disabled", true);
break;
case "POST_MATCH":
$("#startMatch").prop("disabled", true);
$("#abortMatch").prop("disabled", true);
$("#commitResults").prop("disabled", false);
$("#discardResults").prop("disabled", false);
$("#editResults").prop("disabled", false);
break;
}
};

View File

@@ -83,7 +83,7 @@ var updateResults = function(alliance) {
var prefix = alliance + "Stack" + i;
var stack = {Totes: parseInt(formData[prefix + "Totes"]),
Container: formData[prefix + "Container"] == "on",
Noodle: formData[prefix + "Litter"] == "on"}
Litter: formData[prefix + "Litter"] == "on"}
result.score.Stacks.push(stack);
}

View File

@@ -8,7 +8,7 @@
{{define "body"}}
<div class="row">
<div class="well">
<form class="form-horizontal" action="/match_review/{{.Match.Id}}/edit" method="POST">
<form class="form-horizontal" method="POST">
<fieldset>
<legend>Edit Match {{.Match.DisplayName}} Results</legend>
<div class="col-lg-6" id="redScore"></div>

View File

@@ -102,6 +102,11 @@
onclick="$('#confirmDiscardResults').modal('show');" disabled>
Discard Results
</button>
<a href="/match_review/current/edit">
<button type="button" id="editResults" class="btn btn-default btn-lg btn-match-play" disabled>
Edit Results
</button>
</a>
</div>
<br />
<div class="row">