Modified score view UI

Change-Id: Ida827b3de35ffc96e30de7ff723e08a69d3419c1
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 7feaee2..e7ae256 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -20,8 +20,8 @@
 )
 
 const (
-	// animationFrameCounter is the number of frames it will take to complete any animation
-	animationFrameCounter = 100
+	// animationFrameCount is the number of frames it will take to complete any animation
+	animationFrameCount = 100
 	// animRotationScaler is the speed at which an image rotates, if rotation is involved in an animation
 	animRotationScaler = .15
 )
@@ -234,15 +234,15 @@
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if iteration < animationFrameCounter {
+		if iteration < animationFrameCount {
 			curXY := animImage.GetCurrent()
 			curDim := animImage.GetDimensions()
-			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
-			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCount)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCount)
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animImage.Move(newVec, dimVec, eng)
-		} else if iteration == animationFrameCounter {
+		} else if iteration == animationFrameCount {
 			animImage.Move(endPos, endDim, eng)
 			c <- true
 		}
@@ -256,15 +256,15 @@
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if iteration < animationFrameCounter {
+		if iteration < animationFrameCount {
 			curXY := animImage.GetCurrent()
 			curDim := animImage.GetDimensions()
-			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
-			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCount)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCount)
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animImage.Move(newVec, dimVec, eng)
-		} else if iteration == animationFrameCounter {
+		} else if iteration == animationFrameCount {
 			animImage.Move(endPos, endDim, eng)
 		}
 	})
@@ -277,15 +277,15 @@
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if iteration < animationFrameCounter {
+		if iteration < animationFrameCount {
 			curXY := animCard.GetCurrent()
 			curDim := animCard.GetDimensions()
-			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
-			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCount)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCount)
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animCard.Move(newVec, dimVec, eng)
-		} else if iteration == animationFrameCounter {
+		} else if iteration == animationFrameCount {
 			animCard.Move(endPos, endDim, eng)
 			c <- true
 		}
@@ -299,15 +299,15 @@
 	iteration := 0
 	node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
 		iteration++
-		if iteration < animationFrameCounter {
+		if iteration < animationFrameCount {
 			curXY := animCard.GetCurrent()
 			curDim := animCard.GetDimensions()
-			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCounter)
-			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCounter)
+			XYStep := endPos.MinusVec(startPos).DividedBy(animationFrameCount)
+			dimStep := endDim.MinusVec(startDim).DividedBy(animationFrameCount)
 			newVec := curXY.PlusVec(XYStep)
 			dimVec := curDim.PlusVec(dimStep)
 			animCard.Move(newVec, dimVec, eng)
-		} else if iteration == animationFrameCounter {
+		} else if iteration == animationFrameCount {
 			animCard.Move(endPos, endDim, eng)
 		}
 	})
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index c9a09b3..4c45f81 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -246,35 +246,73 @@
 }
 
 // Score View: Shows current player standings at the end of every round, including the end of the game
-func LoadScoreView(winners []int, u *uistate.UIState) {
+func LoadScoreView(roundScores, winners []int, u *uistate.UIState) {
 	u.CurView = uistate.Score
 	resetImgs(u)
 	resetScene(u)
-	// adding score text
-	textImgs := make([]*staticimg.StaticImg, 0)
-	center := coords.MakeVec(u.WindowSize.X/2, u.WindowSize.Y/4)
+	addHeader(u)
+	top := u.CardDim.Y
 	scaler := float32(4)
-	maxWidthBanner := u.WindowSize.X - 2*u.Padding
-	maxWidthScores := u.WindowSize.X / 2
-	if len(winners) == 0 {
-		textImgs = texture.MakeStringImgCenterAlign("Current Standings", "", "", true, center, scaler, maxWidthBanner, u)
-	} else {
-		str := "Game over! Congratulations " + u.CurTable.GetPlayers()[winners[0]].GetName()
-		for i := 1; i < len(winners); i++ {
-			str += " and " + u.CurTable.GetPlayers()[winners[i]].GetName()
-		}
-		str += "!"
-		textImgs = texture.MakeStringImgCenterAlign(str, "", "", true, center, scaler, maxWidthBanner, u)
-	}
-	left := coords.MakeVec(u.WindowSize.X/4, center.Y+40)
+	maxWidth := u.WindowSize.X / 4
+	totalScores := make([]int, 0)
 	for _, p := range u.CurTable.GetPlayers() {
-		str := p.GetName() + ": " + strconv.Itoa(p.GetScore())
-		newTextImgs := texture.MakeStringImgLeftAlign(str, "", "", true, left, scaler, maxWidthScores, u)
-		textImgs = append(textImgs, newTextImgs...)
-		left = coords.MakeVec(left.X, left.Y+30)
+		totalScores = append(totalScores, p.GetScore())
 	}
-	for _, img := range textImgs {
-		u.BackgroundImgs = append(u.BackgroundImgs, img)
+	maxRoundScore := maxInt(roundScores)
+	maxTotalScore := maxInt(totalScores)
+	// adding score text
+	center := coords.MakeVec(u.WindowSize.X/4, top)
+	u.BackgroundImgs = append(u.BackgroundImgs,
+		texture.MakeStringImgCenterAlign("Score:", "", "", true, center, scaler, maxWidth, u)...)
+	// adding game text
+	center = coords.MakeVec(u.WindowSize.X/2, top)
+	u.BackgroundImgs = append(u.BackgroundImgs,
+		texture.MakeStringImgCenterAlign("Round", "", "", true, center, scaler, maxWidth, u)...)
+	// adding total text
+	center = coords.MakeVec(3*u.WindowSize.X/4, top)
+	u.BackgroundImgs = append(u.BackgroundImgs,
+		texture.MakeStringImgCenterAlign("Total", "", "", true, center, scaler, maxWidth, u)...)
+	// adding player info
+	rowHeight := u.WindowSize.Y / 5
+	for i, p := range u.CurTable.GetPlayers() {
+		var color string
+		// blue divider
+		dividerImage := u.Texs["blue.png"]
+		dividerDim := coords.MakeVec(u.WindowSize.X, u.Padding/2)
+		dividerPos := coords.MakeVec(0, top+(float32(i)+.5)*rowHeight)
+		u.BackgroundImgs = append(u.BackgroundImgs,
+			texture.MakeImgWithoutAlt(dividerImage, dividerPos, dividerDim, u.Eng, u.Scene))
+		// player icon
+		playerIconImage := p.GetImage()
+		playerIconDim := coords.MakeVec(rowHeight/2, rowHeight/2)
+		playerIconPos := coords.MakeVec(u.WindowSize.X/4-playerIconDim.X/2, top+(float32(i)+.5)*rowHeight+3*u.Padding)
+		u.BackgroundImgs = append(u.BackgroundImgs,
+			texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, playerIconDim, u.Eng, u.Scene))
+		// player name
+		name := p.GetName()
+		center = coords.MakeVec(playerIconPos.X+playerIconDim.X/2, playerIconPos.Y+playerIconDim.Y)
+		u.BackgroundImgs = append(u.BackgroundImgs,
+			texture.MakeStringImgCenterAlign(name, "", "", true, center, scaler, maxWidth, u)...)
+		// player round score
+		roundScore := roundScores[i]
+		if roundScore == maxRoundScore {
+			color = "Red"
+		} else {
+			color = ""
+		}
+		center = coords.MakeVec(u.WindowSize.X/2, playerIconPos.Y+playerIconDim.Y/2)
+		u.BackgroundImgs = append(u.BackgroundImgs,
+			texture.MakeStringImgCenterAlign(strconv.Itoa(roundScore), color, color, true, center, scaler, maxWidth, u)...)
+		// player total score
+		totalScore := p.GetScore()
+		if totalScore == maxTotalScore {
+			color = "Red"
+		} else {
+			color = ""
+		}
+		center = coords.MakeVec(3*u.WindowSize.X/4, playerIconPos.Y+playerIconDim.Y/2)
+		u.BackgroundImgs = append(u.BackgroundImgs,
+			texture.MakeStringImgCenterAlign(strconv.Itoa(totalScore), color, color, true, center, scaler, maxWidth, u)...)
 	}
 	// adding play button to move to next round
 	pressedImg := u.Texs["playPressed.png"]
@@ -627,3 +665,14 @@
 	u.Buttons = append(u.Buttons,
 		texture.MakeImgWithoutAlt(debugPassImage, debugPassPos, buttonDim, u.Eng, u.Scene))
 }
+
+// Helper function that returns the largest int in a non-negative int array (not index of largest int)
+func maxInt(array []int) int {
+	max := 0
+	for _, num := range array {
+		if num > max {
+			max = num
+		}
+	}
+	return max
+}
diff --git a/go/src/hearts/logic/table/table.go b/go/src/hearts/logic/table/table.go
index c3a8f4d..ae70f94 100644
--- a/go/src/hearts/logic/table/table.go
+++ b/go/src/hearts/logic/table/table.go
@@ -245,9 +245,9 @@
 	return false, highestIndex
 }
 
-// Updates each player's score with the score of the current round
+// Returns the score of the current round
 // Accounts for a player possibly shooting the moon
-func (t *Table) ScoreRound() {
+func (t *Table) ScoreRound() []int {
 	allPoints := 26
 	roundScores := make([]int, len(t.players))
 	shotMoon := false
@@ -268,7 +268,11 @@
 			}
 		}
 	}
-	// sending scores to players
+	return roundScores
+}
+
+// Adds the scores of the current round to the players total scores
+func (t *Table) UpdatePlayerScores(roundScores []int) {
 	for i := 0; i < len(t.players); i++ {
 		t.players[i].UpdateScore(roundScores[i])
 	}
@@ -285,9 +289,11 @@
 	return allHands
 }
 
-// Returns empty array if the game hasn't been won yet, array containing all playerIndices of the winners if it has
-func (t *Table) EndRound() []int {
-	t.ScoreRound()
+// Returns an array of the current round's scores, and an array of the game winners
+// The winners array is empty if the game hasn't been won yet, contains all playerIndices of the winners if it has
+func (t *Table) EndRound() ([]int, []int) {
+	roundScores := t.ScoreRound()
+	t.UpdatePlayerScores(roundScores)
 	lowestScore := -1
 	winningPlayers := make([]int, 0)
 	winTriggered := false
@@ -308,7 +314,7 @@
 			}
 		}
 	}
-	return winningPlayers
+	return roundScores, winningPlayers
 }
 
 // Resets stats for a new round of the game
diff --git a/go/src/hearts/syncbase/watch/watch.go b/go/src/hearts/syncbase/watch/watch.go
index b8e0713..c1e99ff 100644
--- a/go/src/hearts/syncbase/watch/watch.go
+++ b/go/src/hearts/syncbase/watch/watch.go
@@ -93,6 +93,8 @@
 		}
 	} else if u.CurView == uistate.Take && u.CurPlayerIndex == receivingPlayer {
 		view.LoadTakeView(u)
+	} else if u.CurView == uistate.Play && u.CurTable.AllDonePassing() {
+		view.LoadPlayView(u)
 	}
 }
 
@@ -110,14 +112,16 @@
 	}
 	if p.HasTwoOfClubs() {
 		u.CurTable.SetFirstPlayer(p.GetPlayerIndex())
+		// UI
+		if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
+			view.LoadPlayView(u)
+		}
 	}
 	// UI
 	if u.CurView == uistate.Table {
 		for i, c := range passed {
 			reposition.AnimateTableCardTake(c, i, u.CurTable.GetPlayers()[playerInt])
 		}
-	} else if u.CurPlayerIndex == playerInt {
-		//view.LoadPassOrTakeOrPlay(u)
 	}
 }
 
@@ -143,9 +147,10 @@
 	if trickOver {
 		roundOver, recipient = u.CurTable.SendTrick()
 	}
+	var roundScores []int
 	var winners []int
 	if roundOver {
-		winners = u.CurTable.EndRound()
+		roundScores, winners = u.CurTable.EndRound()
 	}
 	// UI
 	if u.CurView == uistate.Table {
@@ -168,7 +173,7 @@
 		}
 	} else if u.CurView == uistate.Play {
 		if roundOver {
-			view.LoadScoreView(winners, u)
+			view.LoadScoreView(roundScores, winners, u)
 		} else if u.CurPlayerIndex != playerInt {
 			view.LoadPlayView(u)
 		}