Fixing bug with unset card.Initial().
Allowing for restart without restarting syncbase

Change-Id: I2859abf6b720e0cce1f6460d1787729dd9e4e736
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 926cf13..cd72e9c 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -278,6 +278,7 @@
 }
 
 func AnimateInSplit(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)
@@ -322,6 +323,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)
@@ -570,3 +572,10 @@
 		return
 	}
 }
+
+func ResetAnims(u *uistate.UIState) {
+	for _, ch := range u.AnimChans {
+		ch <- true
+	}
+	u.AnimChans = make([]chan bool, 0)
+}
diff --git a/go/src/hearts/img/uistate/uistate.go b/go/src/hearts/img/uistate/uistate.go
index 75fff63..392a00f 100644
--- a/go/src/hearts/img/uistate/uistate.go
+++ b/go/src/hearts/img/uistate/uistate.go
@@ -84,6 +84,7 @@
 	Overlap          *coords.Vec
 	Padding          float32
 	CurView          View                     // the screen currently being shown to the user
+	ViewOnTouch      View                     // the view at the beginning of a touch action
 	CurTable         *table.Table             // the table of the current game
 	Done             bool                     // true if the app has been quit
 	Texs             map[string]sprite.SubTex // map of all loaded images
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index 87a4a2b..a325a4c 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -29,7 +29,7 @@
 func LoadArrangeView(u *uistate.UIState) {
 	u.CurView = uistate.Arrange
 	<-time.After(1 * time.Second)
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addHeader(u)
@@ -63,7 +63,7 @@
 // Waiting view: Displays the word "Waiting". To be displayed when players are waiting for a new round to be dealt
 // TODO(emshack): Integrate this with Arrange view and Score view so that a separate screen is not necessary
 func LoadWaitingView(u *uistate.UIState) {
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	center := u.WindowSize.DividedBy(2)
@@ -78,7 +78,7 @@
 // Discovery view: Displays a menu of possible games to join
 func LoadDiscoveryView(discChan chan []string, u *uistate.UIState) {
 	u.CurView = uistate.Discovery
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	newGameImg := u.Texs["NewGame.png"]
@@ -101,7 +101,7 @@
 // Table View: Displays the table. Intended for public devices
 func LoadTableView(u *uistate.UIState) {
 	u.CurView = uistate.Table
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	scaler := float32(6)
@@ -124,6 +124,7 @@
 	dropCard := u.CurTable.GetTrick()[0]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.Cards = append(u.Cards, dropCard)
 	}
@@ -141,6 +142,7 @@
 	dropCard = u.CurTable.GetTrick()[1]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.Cards = append(u.Cards, dropCard)
 	}
@@ -158,6 +160,7 @@
 	dropCard = u.CurTable.GetTrick()[2]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.Cards = append(u.Cards, dropCard)
 	}
@@ -175,6 +178,7 @@
 	dropCard = u.CurTable.GetTrick()[3]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.Cards = append(u.Cards, dropCard)
 	}
@@ -313,6 +317,7 @@
 				texture.PopulateCardImage(c, u)
 				c.SetBackDisplay(u.Eng)
 				pos := reposition.DetermineTablePassPosition(c, i, p.GetPlayerIndex(), u)
+				c.SetInitial(pos)
 				c.Move(pos, u.TableCardDim, u.Eng)
 				u.TableCards = append(u.TableCards, c)
 			}
@@ -340,7 +345,7 @@
 // Score View: Shows current player standings at the end of every round, including the end of the game
 func LoadScoreView(roundScores, winners []int, u *uistate.UIState) {
 	u.CurView = uistate.Score
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addHeader(u)
@@ -352,7 +357,7 @@
 // Pass View: Shows player's hand and allows them to pass cards
 func LoadPassView(u *uistate.UIState) {
 	u.CurView = uistate.Pass
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addHeader(u)
@@ -367,7 +372,7 @@
 // Take View: Shows player's hand and allows them to take the cards that have been passed to them
 func LoadTakeView(u *uistate.UIState) {
 	u.CurView = uistate.Take
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addHeader(u)
@@ -384,7 +389,7 @@
 // Play View: Shows player's hand and allows them to play cards
 func LoadPlayView(u *uistate.UIState) {
 	u.CurView = uistate.Play
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addPlaySlot(u)
@@ -408,7 +413,7 @@
 
 func LoadSplitView(reloading bool, u *uistate.UIState) {
 	u.CurView = uistate.Split
-	resetAnims(u)
+	reposition.ResetAnims(u)
 	resetImgs(u)
 	resetScene(u)
 	addPlayHeader(getTurnText(u), !reloading, u)
@@ -503,6 +508,7 @@
 	dropCard := u.CurTable.GetTrick()[u.CurPlayerIndex]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
@@ -523,6 +529,7 @@
 	dropCard = u.CurTable.GetTrick()[(u.CurPlayerIndex+1)%len(u.CurTable.GetPlayers())]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
@@ -543,6 +550,7 @@
 	dropCard = u.CurTable.GetTrick()[(u.CurPlayerIndex+2)%len(u.CurTable.GetPlayers())]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
@@ -563,6 +571,7 @@
 	dropCard = u.CurTable.GetTrick()[(u.CurPlayerIndex+3)%len(u.CurTable.GetPlayers())]
 	if dropCard != nil {
 		texture.PopulateCardImage(dropCard, u)
+		dropCard.SetInitial(dropTargetPos)
 		dropCard.Move(dropTargetPos, dropTargetDimensions, u.Eng)
 		u.TableCards = append(u.TableCards, dropCard)
 	}
@@ -1081,13 +1090,6 @@
 	})
 }
 
-func resetAnims(u *uistate.UIState) {
-	for _, ch := range u.AnimChans {
-		ch <- true
-	}
-	u.AnimChans = make([]chan bool, 0)
-}
-
 func addDebugBar(u *uistate.UIState) {
 	buttonDim := u.CardDim
 	debugTableImage := u.Texs["BakuSquare.png"]
diff --git a/go/src/hearts/sync/client.go b/go/src/hearts/sync/client.go
index f7bc1f4..c126c7c 100644
--- a/go/src/hearts/sync/client.go
+++ b/go/src/hearts/sync/client.go
@@ -84,6 +84,15 @@
 	return db.Watch(u.Ctx, tableName, prefix, resumeMarker)
 }
 
+// Returns a scanstream of the data in the table
+func ScanData(tableName, prefix string, u *uistate.UIState) nosql.ScanStream {
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
+	table := db.Table(tableName)
+	rowRange := nosql.Range(prefix, "")
+	return table.Scan(u.Ctx, rowRange)
+}
+
 // Joins gamelog syncgroup
 func JoinLogSyncgroup(ch chan bool, logName string, u *uistate.UIState) {
 	fmt.Println("Joining gamelog syncgroup")
diff --git a/go/src/hearts/sync/server.go b/go/src/hearts/sync/server.go
index 9acb8c7..155830d 100644
--- a/go/src/hearts/sync/server.go
+++ b/go/src/hearts/sync/server.go
@@ -119,6 +119,7 @@
 	u.IsOwner = true
 	// Generate random gameID information to advertise this game
 	gameID := rand.Intn(1000000)
+	u.GameID = gameID
 	gameMap := make(map[string]interface{})
 	gameMap["type"] = "Hearts"
 	gameMap["playerNumber"] = 0
@@ -139,7 +140,7 @@
 		"Resolve": allAccess,
 		"Debug":   allAccess,
 	}
-	logPref := wire.TableRow{LogName, ""}
+	logPref := wire.TableRow{LogName, fmt.Sprintf("%d", u.GameID)}
 	logPrefs := []wire.TableRow{logPref}
 	tables := []string{MountPoint + "/croupier"}
 	logSpec := wire.SyncgroupSpec{
@@ -156,10 +157,16 @@
 	err = logSG.Create(u.Ctx, logSpec, myInfoCreator)
 	if err != nil {
 		fmt.Println("SYNCGROUP CREATE ERROR: ", err)
-		ch <- ""
+		fmt.Println("JOINING INSTEAD...")
+		_, err2 := logSG.Join(u.Ctx, myInfoCreator)
+		if err2 != nil {
+			fmt.Println("SYNCGROUP JOIN ERROR: ", err2)
+			ch <- ""
+		} else {
+			ch <- logSGName
+		}
 	} else {
 		fmt.Println("Syncgroup created")
-		u.GameID = gameID
 		go UpdateGame(u)
 		ch <- logSGName
 	}
@@ -194,7 +201,14 @@
 	err := settingsSG.Create(u.Ctx, settingsSpec, myInfoCreator)
 	if err != nil {
 		fmt.Println("SYNCGROUP CREATE ERROR: ", err)
-		ch <- ""
+		fmt.Println("JOINING INSTEAD...")
+		_, err2 := settingsSG.Join(u.Ctx, myInfoCreator)
+		if err2 != nil {
+			fmt.Println("SYNCGROUP JOIN ERROR: ", err2)
+			ch <- ""
+		} else {
+			ch <- settingsSGName
+		}
 	} else {
 		fmt.Println("Syncgroup created")
 		ch <- settingsSGName
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index 5e1ebcc..cf72edd 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -8,16 +8,16 @@
 
 const (
 	// switch back to my mountpoint with the following code:
-	//MountPoint = "users/emshack@google.com"
-	MountPoint        = "/192.168.86.254:8101"
-	UserID            = 2222
+	MountPoint = "users/emshack@google.com"
+	//MountPoint        = "/192.168.86.254:8101"
+	UserID            = 4444
 	UserColor         = 16777215
-	UserAvatar        = "player1.jpeg"
-	UserName          = "Bob"
-	SBName            = "syncbase1"
+	UserAvatar        = "player3.jpeg"
+	UserName          = "Dan"
+	SBName            = "syncbase3"
 	AppName           = "app"
 	DbName            = "db"
 	LogName           = "games"
 	SettingsName      = "table_settings"
-	CroupierInterface = "CroupierSettingsAndGame"
+	CroupierInterface = "CroupierSettingsAndGameEmily"
 )
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index cb4effe..9cc2e87 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -24,6 +24,19 @@
 )
 
 func UpdateSettings(u *uistate.UIState) {
+	scanner := ScanData(SettingsName, "users", u)
+	for {
+		if updateExists := scanner.Advance(); updateExists {
+			key := scanner.Key()
+			var value []byte
+			if err := scanner.Value(&value); err != nil {
+				fmt.Println("Value error:", err)
+			}
+			handleSettingsUpdate(key, value, u)
+		} else {
+			break
+		}
+	}
 	stream, err := WatchData(SettingsName, "users", u)
 	if err != nil {
 		fmt.Println("WatchData error:", err)
@@ -32,42 +45,46 @@
 		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)
 				}
-				var valueMap map[string]interface{}
-				err := json.Unmarshal(value, &valueMap)
-				if err != nil {
-					fmt.Println("Unmarshal error:", err)
-				}
-				key := c.Row
-				userID, _ := strconv.Atoi(strings.Split(key, "/")[1])
-				u.UserData[userID] = valueMap
-				for _, v := range u.PlayerData {
-					if v == userID {
-						switch u.CurView {
-						case uistate.Arrange:
-							view.LoadArrangeView(u)
-						case uistate.Table:
-							view.LoadTableView(u)
-						case uistate.Pass:
-							view.LoadPassView(u)
-						case uistate.Take:
-							view.LoadTakeView(u)
-						case uistate.Play:
-							view.LoadPlayView(u)
-						case uistate.Split:
-							view.LoadSplitView(true, u)
-						}
-					}
-				}
+				handleSettingsUpdate(key, value, u)
 			} else {
 				fmt.Println("Unexpected ChangeType: ", c.ChangeType)
 			}
 		}
 	}
-} 
+}
+
+func handleSettingsUpdate(key string, value []byte, u *uistate.UIState) {
+	var valueMap map[string]interface{}
+	err := json.Unmarshal(value, &valueMap)
+	if err != nil {
+		fmt.Println("Unmarshal error:", err)
+	}
+	userID, _ := strconv.Atoi(strings.Split(key, "/")[1])
+	u.UserData[userID] = valueMap
+	for _, v := range u.PlayerData {
+		if v == userID {
+			switch u.CurView {
+			case uistate.Arrange:
+				view.LoadArrangeView(u)
+			case uistate.Table:
+				view.LoadTableView(u)
+			case uistate.Pass:
+				view.LoadPassView(u)
+			case uistate.Take:
+				view.LoadTakeView(u)
+			case uistate.Play:
+				view.LoadPlayView(u)
+			case uistate.Split:
+				view.LoadSplitView(true, u)
+			}
+		}
+	}
+}
 
 func UpdateGame(u *uistate.UIState) {
 	stream, err := WatchData(LogName, fmt.Sprintf("%d", u.GameID), u)
@@ -87,8 +104,6 @@
 				valueStr := string(value)
 				fmt.Println(key, valueStr)
 				keyType := strings.Split(key, "/")[1]
-				gameID := strings.Split(key, "/")[0]
-				fmt.Println("GAME ID:", gameID)
 				switch keyType {
 				case "log":
 					updateType := strings.Split(valueStr, "|")[0]
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index 0b4dc27..9283e23 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -22,6 +22,11 @@
 )
 
 func OnTouch(t touch.Event, u *uistate.UIState) {
+	if t.Type == touch.TypeBegin {
+		u.ViewOnTouch = u.CurView
+	} else if u.CurView != u.ViewOnTouch {
+		return
+	}
 	switch u.CurView {
 	case uistate.Discovery:
 		switch t.Type {
@@ -459,16 +464,10 @@
 			removeCardFromTarget(c, u)
 			// add card back to hand
 			reposition.ResetCardPosition(c, u.Eng)
-			reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
-		} else {
-			reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
 		}
 	} else {
-		// check to see if card was removed from a drop target
-		removeCardFromTarget(c, u)
 		// add card back to hand
 		reposition.ResetCardPosition(c, u.Eng)
-		reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
 	}
 }