Fixing case where two players sit in the same spot before syncing

Change-Id: I48086533308146efdf327117783e897ebb8189df
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index d4503e0..4f32f36 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -322,6 +322,7 @@
 }
 
 func AnimateOutSplit(ch chan bool, u *uistate.UIState) {
+	ResetAnims(u)
 	topOfBanner := u.WindowSize.Y - 4*u.CardDim.Y - 5*u.Padding - u.BottomPadding - 40
 	tableImgs := make([]*staticimg.StaticImg, 0)
 	bannerImgs := make([]*staticimg.StaticImg, 0)
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index 41dd84c..95e9231 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -409,6 +409,7 @@
 // Play View: Shows player's hand and allows them to play cards
 func LoadPlayView(u *uistate.UIState) {
 	u.CurView = uistate.Play
+	fmt.Println("In play view")
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
@@ -433,6 +434,7 @@
 
 func LoadSplitView(reloading bool, u *uistate.UIState) {
 	u.CurView = uistate.Split
+	fmt.Println("In split view")
 	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index f5a77b1..1e4f12e 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -8,13 +8,13 @@
 
 const (
 	// switch back to my mountpoint with the following code:
-	MountPoint = "users/emshack@google.com"
-	//MountPoint        = "/192.168.86.254:8101"
-	UserID            = 4444
+	//MountPoint = "users/emshack@google.com"
+	MountPoint        = "/192.168.86.254:8101"
+	UserID            = 2222
 	UserColor         = 16777215
-	UserAvatar        = "player3.jpeg"
-	UserName          = "D"
-	SBName            = "syncbase3"
+	UserAvatar        = "player1.jpeg"
+	UserName          = "Bob"
+	SBName            = "syncbase"
 	AppName           = "app"
 	DbName            = "db"
 	LogName           = "games"
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index 3cf301b..985c91f 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -17,6 +17,7 @@
 	"hearts/img/uistate"
 	"hearts/img/view"
 	"hearts/logic/card"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -96,50 +97,58 @@
 	if err != nil {
 		fmt.Println("WatchData error:", err)
 	}
+	updateBlock := make([]nosql.WatchChange, 0)
 	for {
 		if updateExists := stream.Advance(); updateExists {
 			c := stream.Change()
-			if c.ChangeType == nosql.PutChange {
-				key := c.Row
-				var value []byte
-				if err := c.Value(&value); err != nil {
-					fmt.Println("Value error:", err)
-				}
-				handleGameUpdate(key, value, u)
-			} else {
-				fmt.Println("Unexpected ChangeType: ", c.ChangeType)
+			updateBlock = append(updateBlock, c)
+			if !c.Continued {
+				sort.Sort(updateSorter(updateBlock))
+				handleGameUpdate(updateBlock, u)
+				updateBlock = make([]nosql.WatchChange, 0)
 			}
 		}
 	}
 }
 
-func handleGameUpdate(key string, value []byte, u *uistate.UIState) {
-	valueStr := string(value)
-	fmt.Println(key, valueStr)
-	keyType := strings.Split(key, "/")[1]
-	switch keyType {
-	case "log":
-		updateType := strings.Split(valueStr, "|")[0]
-		switch updateType {
-		case Deal:
-			onDeal(valueStr, u)
-		case Pass:
-			onPass(valueStr, u)
-		case Take:
-			onTake(valueStr, u)
-		case Play:
-			onPlay(valueStr, u)
-		case Ready:
-			onReady(valueStr, u)
-		}
-	case "players":
-		switch strings.Split(key, "/")[3] {
-		case "player_number":
-			onPlayerNum(key, valueStr, u)
-		case "settings_sg":
-			onSettings(key, valueStr, u)
-		}
+func handleGameUpdate(changes []nosql.WatchChange, u *uistate.UIState) {
+	for _, c := range changes {
+		if c.ChangeType == nosql.PutChange {
+			key := c.Row
+			var value []byte
+			if err := c.Value(&value); err != nil {
+				fmt.Println("Value error:", err)
+			}
+			valueStr := string(value)
+			fmt.Println(key, valueStr)
+			keyType := strings.Split(key, "/")[1]
+			switch keyType {
+			case "log":
+				updateType := strings.Split(valueStr, "|")[0]
+				switch updateType {
+				case Deal:
+					onDeal(valueStr, u)
+				case Pass:
+					onPass(valueStr, u)
+				case Take:
+					onTake(valueStr, u)
+				case Play:
+					onPlay(valueStr, u)
+				case Ready:
+					onReady(valueStr, u)
+				}
+			case "players":
+				switch strings.Split(key, "/")[3] {
+				case "player_number":
+					onPlayerNum(key, valueStr, u)
+				case "settings_sg":
+					onSettings(key, valueStr, u)
+				}
 
+			}
+		} else {
+			fmt.Println("Unexpected ChangeType: ", c.ChangeType)
+		}
 	}
 }
 
@@ -147,6 +156,9 @@
 	userID, _ := strconv.Atoi(strings.Split(key, "/")[2])
 	playerNum, _ := strconv.Atoi(value)
 	u.PlayerData[playerNum] = userID
+	if playerNum == u.CurPlayerIndex && userID != UserID {
+		u.CurPlayerIndex = -1
+	}
 	if u.CurView == uistate.Arrange {
 		view.LoadArrangeView(u)
 	}
@@ -384,3 +396,33 @@
 	}
 	return playerInt, curCards
 }
+
+// Used to sort an array of watch changes
+type updateSorter []nosql.WatchChange
+
+// Returns the length of the array
+func (us updateSorter) Len() int {
+	return len(us)
+}
+
+// Swaps the positions of two changes in the array
+func (us updateSorter) Swap(i, j int) {
+	us[i], us[j] = us[j], us[i]
+}
+
+// Compares two changes-- one card is less than another if it has an earlier timestamp
+func (us updateSorter) Less(i, j int) bool {
+	iKey := us[i].Row
+	jKey := us[j].Row
+	itmp := strings.Split(iKey, "/")
+	if len(itmp) < 3 {
+		return true
+	}
+	iTime := itmp[2]
+	jtmp := strings.Split(jKey, "/")
+	if len(jtmp) < 3 {
+		return false
+	}
+	jTime := jtmp[2]
+	return iTime < jTime
+}
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index 65918e7..bf2c271 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -178,7 +178,7 @@
 			}
 		} else {
 			for key, button := range u.Buttons {
-				if b == button {
+				if b == button && u.CurPlayerIndex < 0 {
 					if key == "joinTable" {
 						u.CurPlayerIndex = 4
 						sync.LogPlayerNum(u)