using System; using UnityEngine; using UnityEngine.UIElements; /// /// singleton for a single source of truth game state and flow management /// public class GameManager : MonoBehaviour { /// /// singleton pattern: define instance field for accessing the singleton elsewhere /// public static GameManager Instance; /// /// ui manager object for handling ui state and flow /// public UIManager ui; /// /// the local player data object for storing player data /// private LocalPlayerData _localPlayerData; /// /// backend object for handling communication with the firebase backend /// public Backend Backend; /// /// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances /// private void Awake() { // check if instance hasn't been set yet if (Instance == null) { Debug.Log("awake as singleton instance, setting self as the forever-alive instance"); Instance = this; DontDestroyOnLoad(gameObject); } // check if instance is already set and it's not this instance else if (Instance != null && Instance != this) { Debug.Log("awake as non-singleton instance, destroying self"); Destroy(gameObject); } } private void Start() { // load the local player data and refresh the ui _localPlayerData = new LocalPlayerData(); _localPlayerData.LoadFromTheWorld(); PopulateFields(); try { RenderFromPlayerData(); } catch (Exception) { // TODO: remove this once the bug is fixed Debug.LogWarning("handling known exception, remove this once the bug is fixed"); } // register a callback to refresh the ui when the player signs in Backend.RegisterOnSignInCallback(_ => { Debug.Log("sign in callback, refreshing GameManager-controlled SideView UI"); _localPlayerData.LoadFromTheWorld(); PopulateFields(); RenderFromPlayerData(); }); } /// /// called when the game object is enabled, initialises variables /// private void OnEnable() { Backend = new Backend(); Backend.Initialise(); ui = UIManager.Instance; } /// /// called when the application is quitting, saves the local player data /// private void OnApplicationQuit() { Debug.Log("running deferred cleanup/save functions"); Backend.Cleanup(); _localPlayerData.SaveToTheWorld(); } /// /// populate the fields with the given username and email, used by GameManager after local player data is loaded /// public void PopulateFields() { Debug.Log( $"populating AccountView fields with lkUsername={_localPlayerData.LastKnownUsername} and lkEmail={_localPlayerData.LastKnownEmail}"); ui.UI.Q("UsernameField").value = _localPlayerData.LastKnownUsername; ui.UI.Q("EmailField").value = _localPlayerData.LastKnownEmail; } /// /// function to update the ui with the latest data /// private void RenderFromPlayerData() { // calculate averages from both recent local scores and online scores var totalLightnessAcc = 0f; var totalChromaAcc = 0f; var totalHueAcc = 0f; var totalRounds = 0; // average out all the scores we have to get a stable-ish average foreach (var localScore in _localPlayerData.RecentLocalScores) { totalLightnessAcc += localScore.AvgLightnessAccuracy; totalChromaAcc += localScore.AvgChromaAccuracy; totalHueAcc += localScore.AvgHueAccuracy; totalRounds += localScore.NoOfRounds; } foreach (var onlineScore in _localPlayerData.RecentOnlineScores) { totalLightnessAcc += onlineScore.AvgLightnessAccuracy; totalChromaAcc += onlineScore.AvgChromaAccuracy; totalHueAcc += onlineScore.AvgHueAccuracy; totalRounds += onlineScore.NoOfRounds; } foreach (var onlineScore in _localPlayerData.BestOnlineScores) { totalLightnessAcc += onlineScore.AvgLightnessAccuracy; totalChromaAcc += onlineScore.AvgChromaAccuracy; totalHueAcc += onlineScore.AvgHueAccuracy; totalRounds += onlineScore.NoOfRounds; } Debug.Log($"tL={totalLightnessAcc} tC={totalChromaAcc} tH={totalHueAcc} tR={totalRounds}"); if (totalRounds == 0) totalRounds = 1; var lightnessAcc = totalLightnessAcc / totalRounds; var chromaAcc = totalChromaAcc / totalRounds; var hueAcc = totalHueAcc / totalRounds; var playerText = Backend.IsSignedIn ? _localPlayerData.LastKnownUsername : $"{_localPlayerData.LastKnownUsername} (Not Signed In)"; // finally, set the labels ui.UI.Q