Getting ready for user evaluation

Change-Id: I8924cbfcf0a7a1e1b15bcb2a11f74a38f6dd368c
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index a86da1f..926cf13 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -214,18 +214,15 @@
 	passedCards := u.CurTable.GetPlayers()[u.CurPlayerIndex].GetPassedTo()
 	for _, i := range imgs {
 		dims := i.GetDimensions()
-		var to *coords.Vec
-		if passedCards == nil {
-			to = coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
-		} else {
-			to = coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
-		}
+		to := coords.MakeVec(i.GetCurrent().X, i.GetCurrent().Y+u.WindowSize.Y)
 		AnimateImageNoChannel(i, to, dims, u)
 	}
-	for _, c := range passedCards {
-		dims := c.GetDimensions()
-		to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y+u.WindowSize.Y)
-		animateCardNoChannel(c, to, dims, u)
+	if !u.SequentialPhases || u.CurTable.AllDonePassing() {
+		for _, c := range passedCards {
+			dims := c.GetDimensions()
+			to := coords.MakeVec(c.GetCurrent().X, c.GetCurrent().Y+u.WindowSize.Y)
+			animateCardNoChannel(c, to, dims, u)
+		}
 	}
 }
 
diff --git a/go/src/hearts/img/uistate/uistate.go b/go/src/hearts/img/uistate/uistate.go
index 10497df..75fff63 100644
--- a/go/src/hearts/img/uistate/uistate.go
+++ b/go/src/hearts/img/uistate/uistate.go
@@ -128,11 +128,12 @@
 		Padding:          float32(5),
 		CurView:          None,
 		Done:             false,
-		Debug:            true,
+		Debug:            false,
 		SequentialPhases: true,
 		UserData:         make(map[int]map[string]interface{}),
 		PlayerData:       make(map[int]int),
 		AnimChans:        make([]chan bool, 0),
+		CurPlayerIndex:   -1,
 	}
 }
 
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index 3977bcc..87a4a2b 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -34,7 +34,7 @@
 	resetScene(u)
 	addHeader(u)
 	watchImg := u.Texs["WatchSpot.png"]
-	arrangeBlockLength := u.WindowSize.X - 4*u.Padding - u.CardDim.X
+	arrangeBlockLength := u.WindowSize.X - 4*u.Padding
 	if u.WindowSize.Y < u.WindowSize.X {
 		arrangeBlockLength = u.WindowSize.Y - u.CardDim.Y
 	}
@@ -50,6 +50,14 @@
 	// table
 	watchPos := coords.MakeVec((u.WindowSize.X-arrangeDim.X)/2, (u.WindowSize.Y+arrangeBlockLength)/2-2*arrangeDim.Y-4*u.Padding)
 	u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(watchImg, watchPos, arrangeDim, u))
+	if u.IsOwner {
+		startImg := u.Texs["StartBlue.png"]
+		startAlt := u.Texs["StartGray.png"]
+		startDim := coords.MakeVec(2*u.CardDim.X, u.CardDim.Y)
+		startPos := u.WindowSize.MinusVec(startDim).Minus(u.BottomPadding)
+		display := u.CurTable.AllReadyForNewRound()
+		u.Buttons = append(u.Buttons, texture.MakeImgWithAlt(startImg, startAlt, startPos, startDim, display, u))
+	}
 }
 
 // Waiting view: Displays the word "Waiting". To be displayed when players are waiting for a new round to be dealt
@@ -652,7 +660,7 @@
 	altColor := "LBlue"
 	center := coords.MakeVec(u.WindowSize.X/2, u.TopPadding+5)
 	scaler := float32(3)
-	maxWidth := grayBarDim.X
+	maxWidth := grayBarDim.X - 2*u.Padding
 	nameImgs := texture.MakeStringImgCenterAlign(name, color, altColor, true, center, scaler, maxWidth, u)
 	u.Other = append(u.Other, nameImgs...)
 }
@@ -695,7 +703,7 @@
 	awaitingAltColor := "None"
 	center := coords.MakeVec(u.WindowSize.X/2, 20-u.WindowSize.Y)
 	scaler := float32(3)
-	maxWidth := grayBarDim.X
+	maxWidth := grayBarDim.X - 2*u.Padding
 	u.Other = append(u.Other,
 		texture.MakeStringImgCenterAlign(name, color, nameAltColor, display, center, scaler, maxWidth, u)...)
 	center = coords.MakeVec(center.X, center.Y+30)
diff --git a/go/src/hearts/main.go b/go/src/hearts/main.go
index b82a34e..8526f23 100644
--- a/go/src/hearts/main.go
+++ b/go/src/hearts/main.go
@@ -21,10 +21,7 @@
 	"hearts/img/uistate"
 	"hearts/img/view"
 	"hearts/logic/table"
-	"hearts/syncbase/client"
-	"hearts/syncbase/server"
-	"hearts/syncbase/util"
-	"hearts/syncbase/watch"
+	"hearts/sync"
 	"hearts/touchhandler"
 
 	"golang.org/x/mobile/app"
@@ -89,7 +86,7 @@
 	ctx, shutdown := v23.Init()
 	u.Shutdown = shutdown
 	u.Ctx = ctx
-	u.Service = syncbase.NewService(util.MountPoint + "/croupier/" + util.SBName)
+	u.Service = syncbase.NewService(sync.MountPoint + "/croupier/" + sync.SBName)
 	namespace := v23.GetNamespace(u.Ctx)
 	allAccess := access.AccessList{In: []security.BlessingPattern{"..."}}
 	permissions := access.Permissions{
@@ -99,23 +96,26 @@
 		"Resolve": allAccess,
 		"Debug":   allAccess,
 	}
-	namespace.SetPermissions(u.Ctx, util.MountPoint, permissions, "")
-	namespace.SetPermissions(u.Ctx, util.MountPoint+"/croupier", permissions, "")
+	namespace.SetPermissions(u.Ctx, sync.MountPoint, permissions, "")
+	namespace.SetPermissions(u.Ctx, sync.MountPoint+"/croupier", permissions, "")
 	u.Service.SetPermissions(u.Ctx, permissions, "")
 	u.Images = glutil.NewImages(glctx)
-	fps = debug.NewFPS(u.Images)
+	if u.Debug {
+		fps = debug.NewFPS(u.Images)
+	}
 	u.Eng = glsprite.Engine(u.Images)
 	u.Texs = texture.LoadTextures(u.Eng)
 	u.CurTable = table.InitializeGame(u.NumPlayers, u.Texs)
-	server.CreateTables(u)
+	sync.CreateTables(u)
 	// Create watch stream to update game state based on Syncbase updates
-	go watch.UpdateGame(u)
-	go watch.UpdateSettings(u)
+	go sync.UpdateSettings(u)
 }
 
 func onStop(u *uistate.UIState) {
 	u.Eng.Release()
-	fps.Release()
+	if u.Debug {
+		fps.Release()
+	}
 	u.Images.Release()
 	u.Done = true
 	u.Shutdown()
@@ -125,12 +125,14 @@
 	if u.CurView == uistate.None {
 		discChan := make(chan []string)
 		u.ScanChan = make(chan bool)
-		go client.ScanForSG(discChan, u.Ctx, u.ScanChan)
+		go sync.ScanForSG(discChan, u.Ctx, u.ScanChan)
 		view.LoadDiscoveryView(discChan, u)
 	}
 	glctx.ClearColor(1, 1, 1, 1)
 	glctx.Clear(gl.COLOR_BUFFER_BIT)
 	now := clock.Time(time.Since(u.StartTime) * 60 / time.Second)
 	u.Eng.Render(u.Scene, now, sz)
-	fps.Draw(sz)
+	if u.Debug {
+		fps.Draw(sz)
+	}
 }
diff --git a/go/src/hearts/syncbase/client/main.go b/go/src/hearts/sync/client.go
similarity index 89%
rename from go/src/hearts/syncbase/client/main.go
rename to go/src/hearts/sync/client.go
index 8924dbd..f7bc1f4 100644
--- a/go/src/hearts/syncbase/client/main.go
+++ b/go/src/hearts/sync/client.go
@@ -4,7 +4,7 @@
 
 // client handles pulling data from syncbase. To be fleshed out when discovery is added.
 
-package client
+package sync
 
 import (
 	"fmt"
@@ -12,7 +12,6 @@
 	"strings"
 
 	"hearts/img/uistate"
-	"hearts/syncbase/util"
 
 	"v.io/v23/context"
 	"v.io/v23/discovery"
@@ -60,7 +59,7 @@
 		found := u.Value
 		instances[string(found.Service.InstanceId)] = found.Service.InstanceName
 		fmt.Printf("Discovered %q: Instance=%x, Interface=%q, Addrs=%v\n", found.Service.InstanceName, found.Service.InstanceId, found.Service.InterfaceName, found.Service.Addrs)
-		if found.Service.InterfaceName == util.CroupierInterface {
+		if found.Service.InterfaceName == CroupierInterface {
 			return []string{found.Service.Attrs["settings_sgname"], found.Service.Addrs[0]}
 		}
 	case discovery.UpdateLost:
@@ -77,7 +76,7 @@
 
 // Returns a watchstream of the data in the table
 func WatchData(tableName, prefix string, u *uistate.UIState) (nosql.WatchStream, error) {
-	db := u.Service.App(util.AppName).NoSQLDatabase(util.DbName, nil)
+	db := u.Service.App(AppName).NoSQLDatabase(DbName, nil)
 	resumeMarker, err := db.GetResumeMarker(u.Ctx)
 	if err != nil {
 		fmt.Println("RESUMEMARKER ERR: ", err)
@@ -89,8 +88,8 @@
 func JoinLogSyncgroup(ch chan bool, logName string, u *uistate.UIState) {
 	fmt.Println("Joining gamelog syncgroup")
 	u.IsOwner = false
-	app := u.Service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
 	logSg := db.Syncgroup(logName)
 	myInfoJoiner := wire.SyncgroupMemberInfo{8, false}
 	_, err := logSg.Join(u.Ctx, myInfoJoiner)
@@ -103,6 +102,7 @@
 		tmp := strings.Split(logName, "-")
 		gameID, _ := strconv.Atoi(tmp[len(tmp)-1])
 		u.GameID = gameID
+		go UpdateGame(u)
 		ch <- true
 	}
 }
@@ -110,8 +110,8 @@
 // Joins player settings syncgroup
 func JoinSettingsSyncgroup(ch chan bool, settingsName string, u *uistate.UIState) {
 	fmt.Println("Joining user settings syncgroup")
-	app := u.Service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
 	settingsSg := db.Syncgroup(settingsName)
 	myInfoJoiner := wire.SyncgroupMemberInfo{8, false}
 	_, err := settingsSg.Join(u.Ctx, myInfoJoiner)
@@ -125,8 +125,8 @@
 }
 
 func NumInSG(logName string, u *uistate.UIState) int {
-	app := u.Service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
 	sg := db.Syncgroup(logName)
 	members, err := sg.GetMembers(u.Ctx)
 	if err != nil {
diff --git a/go/src/hearts/syncbase/gamelog/logWriter.go b/go/src/hearts/sync/logWriter.go
similarity index 89%
rename from go/src/hearts/syncbase/gamelog/logWriter.go
rename to go/src/hearts/sync/logWriter.go
index 92e51ab..3e575e8 100644
--- a/go/src/hearts/syncbase/gamelog/logWriter.go
+++ b/go/src/hearts/sync/logWriter.go
@@ -5,7 +5,7 @@
 // gamelog handles creating the appropriately formatted key and value strings to write to the game log in syncbase
 // a description of the log syntax can be found here: https://docs.google.com/document/d/1uZc9EQ2-F6CjJjGkj7VWvJNFklKGsFGQSVHtpEiJUlQ
 
-package gamelog
+package sync
 
 import (
 	"fmt"
@@ -14,8 +14,6 @@
 
 	"hearts/img/uistate"
 	"hearts/logic/card"
-	"hearts/syncbase/server"
-	"hearts/syncbase/util"
 
 	"v.io/v23/context"
 	"v.io/v23/syncbase"
@@ -90,16 +88,22 @@
 }
 
 func LogPlayerNum(u *uistate.UIState) bool {
-	key := strconv.Itoa(u.GameID) + "/players/" + strconv.Itoa(util.UserID) + "/player_number"
+	key := fmt.Sprintf("%d/players/%d/player_number", u.GameID, UserID)
 	value := strconv.Itoa(u.CurPlayerIndex)
 	return logKeyValue(u.Service, u.Ctx, key, value)
 }
 
 func LogSettingsName(name string, u *uistate.UIState) bool {
-	key := strconv.Itoa(u.GameID) + "/players/" + strconv.Itoa(util.UserID) + "/settings_sg"
+	key := fmt.Sprintf("%d/players/%d/settings_sg", u.GameID, UserID)
 	return logKeyValue(u.Service, u.Ctx, key, name)
 }
 
+func LogGameStart(u *uistate.UIState) bool {
+	key := fmt.Sprintf("%d/status", u.GameID)
+	value := "RUNNING"
+	return logKeyValue(u.Service, u.Ctx, key, value)
+}
+
 // Note: The syntax replicates the way Croupier in Dart/Flutter writes keys.
 func getKey(playerId int, u *uistate.UIState) string {
 	t := time.Now().UnixNano() / 1000000
@@ -108,5 +112,5 @@
 }
 
 func logKeyValue(service syncbase.Service, ctx *context.T, key, value string) bool {
-	return server.AddKeyValue(service, ctx, key, value)
+	return AddKeyValue(service, ctx, key, value)
 }
diff --git a/go/src/hearts/syncbase/server/main.go b/go/src/hearts/sync/server.go
similarity index 80%
rename from go/src/hearts/syncbase/server/main.go
rename to go/src/hearts/sync/server.go
index 6291fd1..9acb8c7 100644
--- a/go/src/hearts/syncbase/server/main.go
+++ b/go/src/hearts/sync/server.go
@@ -4,7 +4,7 @@
 
 // server handles advertising (to be fleshed out when discovery is added), and all local syncbase updates
 
-package server
+package sync
 
 import (
 	"encoding/json"
@@ -12,7 +12,6 @@
 	"math/rand"
 
 	"hearts/img/uistate"
-	"hearts/syncbase/util"
 
 	"v.io/v23/context"
 	"v.io/v23/discovery"
@@ -36,7 +35,7 @@
 	discoveryService := ldiscovery.NewWithPlugins([]ldiscovery.Plugin{mdns})
 	gameService := discovery.Service{
 		InstanceName:  "A sample game service",
-		InterfaceName: util.CroupierInterface,
+		InterfaceName: CroupierInterface,
 		Attrs:         map[string]string{"settings_sgname": settingsAddress, "game_start_data": gameStartData},
 		Addrs:         []string{logAddress},
 	}
@@ -53,9 +52,9 @@
 
 // Puts key and value into the syncbase gamelog table
 func AddKeyValue(service syncbase.Service, ctx *context.T, key, value string) bool {
-	app := service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
-	table := db.Table(util.LogName)
+	app := service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
+	table := db.Table(LogName)
 	valueByte := []byte(value)
 	err := table.Put(ctx, key, valueByte)
 	if err != nil {
@@ -68,7 +67,7 @@
 // Creates an app, db, game log table and game settings table in syncbase if they don't already exist
 // Adds appropriate data to settings table
 func CreateTables(u *uistate.UIState) {
-	app := u.Service.App(util.AppName)
+	app := u.Service.App(AppName)
 	if isThere, err := app.Exists(u.Ctx); err != nil {
 		fmt.Println("APP EXISTS ERROR: ", err)
 	} else if !isThere {
@@ -76,7 +75,7 @@
 			fmt.Println("APP ERROR: ", err)
 		}
 	}
-	db := app.NoSQLDatabase(util.DbName, nil)
+	db := app.NoSQLDatabase(DbName, nil)
 	if isThere, err := db.Exists(u.Ctx); err != nil {
 		fmt.Println("DB EXISTS ERROR: ", err)
 	} else if !isThere {
@@ -84,7 +83,7 @@
 			fmt.Println("DB ERROR: ", err)
 		}
 	}
-	logTable := db.Table(util.LogName)
+	logTable := db.Table(LogName)
 	if isThere, err := logTable.Exists(u.Ctx); err != nil {
 		fmt.Println("TABLE EXISTS ERROR: ", err)
 	} else if !isThere {
@@ -92,7 +91,7 @@
 			fmt.Println("TABLE ERROR: ", err)
 		}
 	}
-	settingsTable := db.Table(util.SettingsName)
+	settingsTable := db.Table(SettingsName)
 	if isThere, err := settingsTable.Exists(u.Ctx); err != nil {
 		fmt.Println("TABLE EXISTS ERROR: ", err)
 	} else if !isThere {
@@ -102,16 +101,16 @@
 	}
 	// Add user settings data to represent this player
 	settingsMap := make(map[string]interface{})
-	settingsMap["userID"] = util.UserID
-	settingsMap["avatar"] = util.UserAvatar
-	settingsMap["name"] = util.UserName
-	settingsMap["color"] = util.UserColor
-	u.UserData[util.UserID] = settingsMap
+	settingsMap["userID"] = UserID
+	settingsMap["avatar"] = UserAvatar
+	settingsMap["name"] = UserName
+	settingsMap["color"] = UserColor
+	u.UserData[UserID] = settingsMap
 	value, err := json.Marshal(settingsMap)
 	if err != nil {
 		fmt.Println("WE HAVE A HUGE PROBLEM:", err)
 	}
-	settingsTable.Put(u.Ctx, fmt.Sprintf("users/%d/settings", util.UserID), value)
+	settingsTable.Put(u.Ctx, fmt.Sprintf("users/%d/settings", UserID), value)
 }
 
 // Creates a new gamelog syncgroup
@@ -124,14 +123,14 @@
 	gameMap["type"] = "Hearts"
 	gameMap["playerNumber"] = 0
 	gameMap["gameID"] = gameID
-	gameMap["ownerID"] = util.UserID
+	gameMap["ownerID"] = UserID
 	value, err := json.Marshal(gameMap)
 	if err != nil {
 		fmt.Println("WE HAVE A HUGE PROBLEM:", err)
 	}
 	ch <- string(value)
 	// Create gamelog syncgroup
-	logSGName := fmt.Sprintf("%s/croupier/%s/%%%%sync/gaming-%d", util.MountPoint, util.SBName, gameID)
+	logSGName := fmt.Sprintf("%s/croupier/%s/%%%%sync/gaming-%d", MountPoint, SBName, gameID)
 	allAccess := access.AccessList{In: []security.BlessingPattern{"..."}}
 	permissions := access.Permissions{
 		"Admin":   allAccess,
@@ -140,9 +139,9 @@
 		"Resolve": allAccess,
 		"Debug":   allAccess,
 	}
-	logPref := wire.TableRow{util.LogName, ""}
+	logPref := wire.TableRow{LogName, ""}
 	logPrefs := []wire.TableRow{logPref}
-	tables := []string{util.MountPoint + "/croupier"}
+	tables := []string{MountPoint + "/croupier"}
 	logSpec := wire.SyncgroupSpec{
 		Description: "croupier syncgroup",
 		Perms:       permissions,
@@ -151,8 +150,8 @@
 		IsPrivate:   false,
 	}
 	myInfoCreator := wire.SyncgroupMemberInfo{8, true}
-	app := u.Service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
 	logSG := db.Syncgroup(logSGName)
 	err = logSG.Create(u.Ctx, logSpec, myInfoCreator)
 	if err != nil {
@@ -161,6 +160,7 @@
 	} else {
 		fmt.Println("Syncgroup created")
 		u.GameID = gameID
+		go UpdateGame(u)
 		ch <- logSGName
 	}
 }
@@ -176,12 +176,12 @@
 		"Resolve": allAccess,
 		"Debug":   allAccess,
 	}
-	tables := []string{util.MountPoint + "/croupier"}
+	tables := []string{MountPoint + "/croupier"}
 	myInfoCreator := wire.SyncgroupMemberInfo{8, true}
-	app := u.Service.App(util.AppName)
-	db := app.NoSQLDatabase(util.DbName, nil)
-	settingsSGName := fmt.Sprintf("%s/croupier/%s/%%%%sync/discovery-%d", util.MountPoint, util.SBName, util.UserID)
-	settingsPref := wire.TableRow{util.SettingsName, fmt.Sprintf("users/%d", util.UserID)}
+	app := u.Service.App(AppName)
+	db := app.NoSQLDatabase(DbName, nil)
+	settingsSGName := fmt.Sprintf("%s/croupier/%s/%%%%sync/discovery-%d", MountPoint, SBName, UserID)
+	settingsPref := wire.TableRow{SettingsName, fmt.Sprintf("users/%d", UserID)}
 	settingsPrefs := []wire.TableRow{settingsPref}
 	settingsSpec := wire.SyncgroupSpec{
 		Description: "croupier syncgroup",
diff --git a/go/src/hearts/syncbase/util/util.go b/go/src/hearts/sync/util.go
similarity index 68%
rename from go/src/hearts/syncbase/util/util.go
rename to go/src/hearts/sync/util.go
index bb4413e..5e1ebcc 100644
--- a/go/src/hearts/syncbase/util/util.go
+++ b/go/src/hearts/sync/util.go
@@ -4,17 +4,17 @@
 
 // util.go stores constants relevant to the syncbase hierarchy
 
-package util
+package sync
 
 const (
 	// switch back to my mountpoint with the following code:
-	MountPoint = "users/emshack@google.com"
-	//MountPoint        = "/192.168.86.254:8101"
-	UserID            = 23876
+	//MountPoint = "users/emshack@google.com"
+	MountPoint        = "/192.168.86.254:8101"
+	UserID            = 2222
 	UserColor         = 16777215
-	UserAvatar        = "player0.jpeg"
-	UserName          = "Ewen"
-	SBName            = "syncbase"
+	UserAvatar        = "player1.jpeg"
+	UserName          = "Bob"
+	SBName            = "syncbase1"
 	AppName           = "app"
 	DbName            = "db"
 	LogName           = "games"
diff --git a/go/src/hearts/syncbase/watch/watch.go b/go/src/hearts/sync/watch.go
similarity index 86%
rename from go/src/hearts/syncbase/watch/watch.go
rename to go/src/hearts/sync/watch.go
index aacb706..cb4effe 100644
--- a/go/src/hearts/syncbase/watch/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -7,7 +7,7 @@
 // the syncgroup and updating the game state and UI display as a result
 // of any changes that come along.
 
-package watch
+package sync
 
 import (
 	"encoding/json"
@@ -17,9 +17,6 @@
 	"hearts/img/uistate"
 	"hearts/img/view"
 	"hearts/logic/card"
-	"hearts/syncbase/client"
-	"hearts/syncbase/gamelog"
-	"hearts/syncbase/util"
 	"strconv"
 	"strings"
 	"time"
@@ -27,7 +24,7 @@
 )
 
 func UpdateSettings(u *uistate.UIState) {
-	stream, err := client.WatchData(util.SettingsName, "users", u)
+	stream, err := WatchData(SettingsName, "users", u)
 	if err != nil {
 		fmt.Println("WatchData error:", err)
 	}
@@ -47,15 +44,34 @@
 				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)
+						}
+					}
+				}
 			} else {
 				fmt.Println("Unexpected ChangeType: ", c.ChangeType)
 			}
 		}
 	}
-}
+} 
 
 func UpdateGame(u *uistate.UIState) {
-	stream, err := client.WatchData(util.LogName, "", u)
+	stream, err := WatchData(LogName, fmt.Sprintf("%d", u.GameID), u)
+	fmt.Println("STARTING WATCH FOR GAME", u.GameID)
 	if err != nil {
 		fmt.Println("WatchData error:", err)
 	}
@@ -69,21 +85,23 @@
 					fmt.Println("Value error:", err)
 				}
 				valueStr := string(value)
-				fmt.Println(valueStr)
+				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]
 					switch updateType {
-					case gamelog.Deal:
+					case Deal:
 						onDeal(valueStr, u)
-					case gamelog.Pass:
+					case Pass:
 						onPass(valueStr, u)
-					case gamelog.Take:
+					case Take:
 						onTake(valueStr, u)
-					case gamelog.Play:
+					case Play:
 						onPlay(valueStr, u)
-					case gamelog.Ready:
+					case Ready:
 						onReady(valueStr, u)
 					}
 				case "players":
@@ -106,14 +124,14 @@
 	userID, _ := strconv.Atoi(strings.Split(key, "/")[2])
 	playerNum, _ := strconv.Atoi(value)
 	u.PlayerData[playerNum] = userID
-	if u.CurView == uistate.Arrange && !u.CurTable.AllReadyForNewRound() {
+	if u.CurView == uistate.Arrange {
 		view.LoadArrangeView(u)
 	}
 }
 
 func onSettings(key, value string, u *uistate.UIState) {
 	joinDone := make(chan bool)
-	go client.JoinSettingsSyncgroup(joinDone, value, u)
+	go JoinSettingsSyncgroup(joinDone, value, u)
 	<-joinDone
 }
 
@@ -307,18 +325,24 @@
 	// logic
 	playerInt, _ := parsePlayerAndCards(value, u)
 	u.CurTable.GetPlayers()[playerInt].SetDoneScoring(true)
-	if u.CurTable.AllReadyForNewRound() && u.IsOwner {
-		newHands := u.CurTable.Deal()
-		success := gamelog.LogDeal(u, u.CurPlayerIndex, newHands)
-		for !success {
-			success = gamelog.LogDeal(u, u.CurPlayerIndex, newHands)
-		}
-	}
 	// UI
-	if u.CurTable.AllReadyForNewRound() {
-		if u.SGChan != nil {
-			u.SGChan <- true
-			u.SGChan = nil
+	if u.CurTable.AllReadyForNewRound() && u.IsOwner {
+		if u.CurView == uistate.Arrange {
+			b := u.Buttons[5]
+			if !b.GetDisplayingImage() {
+				u.Eng.SetSubTex(b.GetNode(), b.GetImage())
+				b.SetDisplayingImage(true)
+			}
+			if u.SGChan != nil {
+				u.SGChan <- true
+				u.SGChan = nil
+			}
+		} else if u.CurView == uistate.Score {
+			newHands := u.CurTable.Deal()
+			successDeal := LogDeal(u, u.CurPlayerIndex, newHands)
+			for !successDeal {
+				successDeal = LogDeal(u, u.CurPlayerIndex, newHands)
+			}
 		}
 	}
 }
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index 7f48b97..0b4dc27 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -18,9 +18,7 @@
 	"hearts/img/uistate"
 	"hearts/img/view"
 	"hearts/logic/card"
-	"hearts/syncbase/client"
-	"hearts/syncbase/gamelog"
-	"hearts/syncbase/server"
+	"hearts/sync"
 )
 
 func OnTouch(t touch.Event, u *uistate.UIState) {
@@ -108,17 +106,17 @@
 		if buttonList[0] == u.Buttons[0] {
 			logCh := make(chan string)
 			settingsCh := make(chan string)
-			go server.CreateLogSyncgroup(logCh, u)
-			go server.CreateSettingsSyncgroup(settingsCh, u)
+			go sync.CreateLogSyncgroup(logCh, u)
+			go sync.CreateSettingsSyncgroup(settingsCh, u)
 			gameStartData := <-logCh
 			logName := <-logCh
 			settingsName := <-settingsCh
 			if logName != "" && settingsName != "" {
-				gamelog.LogSettingsName(settingsName, u)
+				sync.LogSettingsName(settingsName, u)
 				u.ScanChan <- true
 				u.ScanChan = nil
 				u.SGChan = make(chan bool)
-				go server.Advertise(logName, settingsName, gameStartData, u.SGChan, u.Ctx)
+				go sync.Advertise(logName, settingsName, gameStartData, u.SGChan, u.Ctx)
 				view.LoadArrangeView(u)
 			}
 		} else {
@@ -128,15 +126,15 @@
 					joinSettingsDone := make(chan bool)
 					settingsAddr := b.GetInfo()[0]
 					logAddr := b.GetInfo()[1]
-					go client.JoinLogSyncgroup(joinLogDone, logAddr, u)
-					go client.JoinSettingsSyncgroup(joinSettingsDone, settingsAddr, u)
+					go sync.JoinLogSyncgroup(joinLogDone, logAddr, u)
+					go sync.JoinSettingsSyncgroup(joinSettingsDone, settingsAddr, u)
 					<-joinSettingsDone
 					if success := <-joinLogDone; success {
 						settingsCh := make(chan string)
-						go server.CreateSettingsSyncgroup(settingsCh, u)
+						go sync.CreateSettingsSyncgroup(settingsCh, u)
 						sgName := <-settingsCh
 						if sgName != "" {
-							gamelog.LogSettingsName(sgName, u)
+							sync.LogSettingsName(sgName, u)
 						}
 						u.ScanChan <- true
 						u.ScanChan = nil
@@ -150,24 +148,32 @@
 	}
 }
 
-// If players cannot sit in more than one spot, replace the line 5 ahead of this one with the following line:
-// if len(buttonList) > 0 && u.PlayerData[u.CurPlayerIndex] == 0 {
-
 func beginClickArrange(t touch.Event, u *uistate.UIState) {
 	buttonList := findClickedButton(t, u)
 	if len(buttonList) > 0 {
 		for i, b := range u.Buttons {
 			if buttonList[0] == b {
-				u.CurPlayerIndex = i
+				if i == 5 {
+					if b.GetDisplayingImage() {
+						successStart := sync.LogGameStart(u)
+						for !successStart {
+							successStart = sync.LogGameStart(u)
+						}
+						newHands := u.CurTable.Deal()
+						successDeal := sync.LogDeal(u, u.CurPlayerIndex, newHands)
+						for !successDeal {
+							successDeal = sync.LogDeal(u, u.CurPlayerIndex, newHands)
+						}
+					}
+				} else if u.CurPlayerIndex < 0 {
+					u.CurPlayerIndex = i
+					if u.CurPlayerIndex >= 0 && u.CurPlayerIndex < u.NumPlayers {
+						sync.LogReady(u)
+					}
+					sync.LogPlayerNum(u)
+				}
 			}
 		}
-		if u.CurPlayerIndex >= 0 && u.CurPlayerIndex < u.NumPlayers {
-			gamelog.LogReady(u)
-		}
-		gamelog.LogPlayerNum(u)
-		if !u.CurTable.AllReadyForNewRound() {
-			view.LoadWaitingView(u)
-		}
 	}
 }
 
@@ -469,9 +475,9 @@
 func beginClickScore(t touch.Event, u *uistate.UIState) {
 	buttonList := findClickedButton(t, u)
 	if len(buttonList) > 0 {
-		success := gamelog.LogReady(u)
+		success := sync.LogReady(u)
 		for !success {
-			gamelog.LogReady(u)
+			sync.LogReady(u)
 		}
 		view.LoadWaitingView(u)
 	}
@@ -515,9 +521,9 @@
 	if !u.CurTable.ValidPass(cardsPassed) || u.CurTable.GetPlayers()[playerId].GetDonePassing() {
 		return false
 	}
-	success := gamelog.LogPass(u, cardsPassed)
+	success := sync.LogPass(u, cardsPassed)
 	for !success {
-		success = gamelog.LogPass(u, cardsPassed)
+		success = sync.LogPass(u, cardsPassed)
 	}
 	// UI component
 	pullTab := u.Buttons[0]
@@ -541,9 +547,9 @@
 	if len(passedCards) != 3 {
 		return false
 	}
-	success := gamelog.LogTake(u)
+	success := sync.LogTake(u)
 	for !success {
-		success = gamelog.LogTake(u)
+		success = sync.LogTake(u)
 	}
 	reposition.AnimateHandCardTake(ch, u.Other, u)
 	return true
@@ -572,9 +578,9 @@
 		return err
 	}
 	u.DropTargets[0].SetCardHere(nil)
-	success := gamelog.LogPlay(u, c)
+	success := sync.LogPlay(u, c)
 	for !success {
-		success = gamelog.LogPlay(u, c)
+		success = sync.LogPlay(u, c)
 	}
 	// no animation when in split view
 	if u.CurView == uistate.Play {