game: fiddle around with execution order
generally found - Awake -> init - OnEnable -> init + register callbacks - Start -> do anything that might call a callback
This commit is contained in:
parent
e8091632c4
commit
872f3f263e
|
@ -78,22 +78,11 @@ public class AccountUI : MonoBehaviour
|
|||
/// </summary>
|
||||
private Button _usernameUpdateButton;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
GameManager.Instance.Backend.RegisterOnSignInCallback(OnSignInCallback);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (state == State.UnassociatedState) throw new Exception("unreachable state");
|
||||
|
||||
// GameManager.Instance.Backend.RegisterOnSignInCallback(OnSignInCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// function to subscribe button events to their respective functions
|
||||
/// function called when the object is enabled,
|
||||
/// subscribes button events to their respective functions
|
||||
/// </summary>
|
||||
public void OnEnable()
|
||||
private void OnEnable()
|
||||
{
|
||||
var ui = GetComponent<UIDocument>().rootVisualElement;
|
||||
|
||||
|
@ -121,17 +110,18 @@ public void OnEnable()
|
|||
_secondaryActionButton.clicked += OnSecondaryActionButtonClick;
|
||||
|
||||
TransitionStateTo(State.NotSignedIn);
|
||||
}
|
||||
|
||||
private void OnSignInCallback(FirebaseUser user)
|
||||
{
|
||||
Debug.Log("sign in account ui callback");
|
||||
|
||||
var username = GameManager.Instance.Backend.GetUsername();
|
||||
_usernameField.value = username;
|
||||
_emailField.value = GameManager.Instance.Backend.GetUser().Email;
|
||||
_passwordField.value = "";
|
||||
_header.text = $"Signed in as {username}";
|
||||
if (state == State.UnassociatedState) throw new Exception("unreachable state");
|
||||
GameManager.Instance.Backend.RegisterOnSignInCallback(_ =>
|
||||
{
|
||||
Debug.Log("post-authentication callback, updating AccountView fields");
|
||||
var username = GameManager.Instance.Backend.GetUsername();
|
||||
_header.text = $"Signed in as {username}";
|
||||
_passwordField.value = "";
|
||||
_usernameField.value = username;
|
||||
_emailField.value = GameManager.Instance.Backend.GetUser().Email;
|
||||
});
|
||||
GameManager.Instance.RegisterOnLocalPlayerDataChangeCallback(PopulateFields);
|
||||
}
|
||||
|
||||
private void TransitionStateTo(State newState, bool keepAccompanyingText = false)
|
||||
|
@ -619,6 +609,18 @@ private void OnSecondaryActionButtonClick()
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// populate the fields with the given username and email,
|
||||
/// used as a callback to when local player data is changed
|
||||
/// </summary>
|
||||
public void PopulateFields(LocalPlayerData data)
|
||||
{
|
||||
Debug.Log(
|
||||
$"populating AccountView fields with lkUsername={data.LastKnownUsername} and lkEmail={data.LastKnownEmail}");
|
||||
_usernameField.value = data.LastKnownUsername;
|
||||
_emailField.value = data.LastKnownEmail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// state of the account view
|
||||
/// </summary>
|
||||
|
|
|
@ -4,7 +4,7 @@ MonoImporter:
|
|||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
executionOrder: -10
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
|
|
@ -60,12 +60,18 @@ public enum UserAccountDetailTargetEnum
|
|||
/// <summary>
|
||||
/// callback functions to be invoked when the user signs in
|
||||
/// </summary>
|
||||
private readonly List<Action<FirebaseUser>> _onSignInCallback = new();
|
||||
private readonly List<Action<FirebaseUser>> _onSignInCallbacks = new();
|
||||
|
||||
/// <summary>
|
||||
/// callback functions to be invoked when the user signs out
|
||||
/// </summary>
|
||||
private readonly List<Action> _onSignOutCallback = new();
|
||||
private readonly List<Action> _onSignOutCallbacks = new();
|
||||
|
||||
/// <summary>
|
||||
/// callback functions to be invoked when the user signs in
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private readonly List<Action<FirebaseConnectionStatus>> _onConnectionStatusChangedCallbacks = new ();
|
||||
|
||||
/// <summary>
|
||||
/// the firebase authentication object
|
||||
|
@ -100,9 +106,9 @@ public enum UserAccountDetailTargetEnum
|
|||
/// <summary>
|
||||
/// variable initialisation function
|
||||
/// </summary>
|
||||
public void Initialise()
|
||||
public void Initialise(Action<FirebaseConnectionStatus> callback)
|
||||
{
|
||||
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
|
||||
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
|
||||
{
|
||||
// cher is this robust enough
|
||||
switch (task.Result)
|
||||
|
@ -112,6 +118,7 @@ public void Initialise()
|
|||
_auth.StateChanged += AuthStateChanged;
|
||||
_db = FirebaseDatabase.DefaultInstance.RootReference;
|
||||
Status = FirebaseConnectionStatus.Connected;
|
||||
callback(Status);
|
||||
break;
|
||||
|
||||
case DependencyStatus.UnavailableDisabled:
|
||||
|
@ -119,21 +126,25 @@ public void Initialise()
|
|||
case DependencyStatus.UnavilableMissing:
|
||||
case DependencyStatus.UnavailablePermission:
|
||||
Status = FirebaseConnectionStatus.ExternalError;
|
||||
callback(Status);
|
||||
break;
|
||||
|
||||
case DependencyStatus.UnavailableUpdating:
|
||||
Status = FirebaseConnectionStatus.Updating;
|
||||
RetryInitialiseAfterDelay();
|
||||
callback(Status);
|
||||
RetryInitialiseAfterDelay(callback);
|
||||
break;
|
||||
|
||||
case DependencyStatus.UnavailableUpdaterequired:
|
||||
Status = FirebaseConnectionStatus.UpdateRequired;
|
||||
callback(Status);
|
||||
break;
|
||||
|
||||
case DependencyStatus.UnavailableOther:
|
||||
default:
|
||||
Status = FirebaseConnectionStatus.InternalError;
|
||||
Debug.LogError("firebase ??? blew up or something," + task.Result);
|
||||
callback(Status);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -146,8 +157,8 @@ public void Initialise()
|
|||
/// </summary>
|
||||
private void FireOnSignInCallbacks()
|
||||
{
|
||||
Debug.Log($"firing on sign in callbacks ({_onSignInCallback.Count})");
|
||||
foreach (var callback in _onSignInCallback)
|
||||
Debug.Log($"firing OnSignInCallbacks ({_onSignInCallbacks.Count})");
|
||||
foreach (var callback in _onSignInCallbacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -155,18 +166,18 @@ private void FireOnSignInCallbacks()
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
Debug.LogError($"error invoking OnSignInCallback: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// function to fire all on sign out callbacks
|
||||
/// function to fire all on sign-out callbacks
|
||||
/// </summary>
|
||||
private void FireOnSignOutCallbacks()
|
||||
{
|
||||
Debug.Log($"firing on sign out callbacks ({_onSignOutCallback.Count})");
|
||||
foreach (var callback in _onSignOutCallback)
|
||||
Debug.Log($"firing OnSignOutCallbacks ({_onSignOutCallbacks.Count})");
|
||||
foreach (var callback in _onSignOutCallbacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -174,7 +185,7 @@ private void FireOnSignOutCallbacks()
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
Debug.LogError($"error invoking OnSignOutCallback: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,10 +193,10 @@ private void FireOnSignOutCallbacks()
|
|||
/// <summary>
|
||||
/// async function to retry initialisation after a delay
|
||||
/// </summary>
|
||||
private async void RetryInitialiseAfterDelay()
|
||||
private async void RetryInitialiseAfterDelay(Action<FirebaseConnectionStatus> callback)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(10));
|
||||
Initialise();
|
||||
Initialise(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -235,25 +246,24 @@ private void AuthStateChanged(object sender, EventArgs eventArgs)
|
|||
/// <param name="callback">callback function that takes in a <c>FirebaseUser</c> object</param>
|
||||
public void RegisterOnSignInCallback(Action<FirebaseUser> callback)
|
||||
{
|
||||
Debug.Log("registering on sign in callback");
|
||||
_onSignInCallback.Add(callback);
|
||||
_onSignInCallbacks.Add(callback);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// function to register a callback for when the user signs out
|
||||
// /// </summary>
|
||||
// /// <param name="callback">callback function</param>
|
||||
// public void RegisterOnSignOutCallback(Action callback)
|
||||
// {
|
||||
// _onSignOutCallback.Add(callback);
|
||||
// }
|
||||
/// <summary>
|
||||
/// function to register a callback for when the user signs out
|
||||
/// </summary>
|
||||
/// <param name="callback">callback function</param>
|
||||
public void RegisterOnSignOutCallback(Action callback)
|
||||
{
|
||||
_onSignOutCallbacks.Add(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// abstraction function to authenticate the user
|
||||
/// </summary>
|
||||
/// <param name="email">email string</param>
|
||||
/// <param name="password">user raw password string</param>
|
||||
/// <param name="callback">callback function that takes in an AuthenticationResult argument</param>
|
||||
/// <param name="callback">callback function that takes in an <c>AuthenticationResult</c> enum</param>
|
||||
/// <param name="registerUser">whether to treat authentication as registration</param>
|
||||
/// <param name="registeringUsername">username string if registering</param>
|
||||
public void AuthenticateUser(
|
||||
|
@ -472,8 +482,7 @@ public void ForgotPassword(string email, Action<bool> callback)
|
|||
/// abstraction function to get the user's recent scores from the database
|
||||
/// </summary>
|
||||
/// <param name="callback">
|
||||
/// callback function that takes in a DatabaseTransactionResult and List of LocalPlayerData.Score
|
||||
/// argument
|
||||
/// callback function that takes in a <c>DatabaseTransactionResult</c> enum and a <c>List<LocalPlayerData.Score></c>
|
||||
/// </param>
|
||||
public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerData.Score>> callback)
|
||||
{
|
||||
|
@ -485,7 +494,7 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
|||
/// abstraction function to submit a score to the database
|
||||
/// </summary>
|
||||
/// <param name="score">score</param>
|
||||
/// <param name="callback">callback function that takes in one DatabaseTransactionResult argument</param>
|
||||
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum </param>
|
||||
public void SubmitScore(
|
||||
LocalPlayerData.Score score,
|
||||
Action<DatabaseTransactionResult> callback)
|
||||
|
@ -497,7 +506,7 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
|||
/// abstraction function to get and calculate the user's rating from the database
|
||||
/// calculation is done locally, call UpdateUserRating to update the user's rating in the database
|
||||
/// </summary>
|
||||
/// <param name="callback">callback function that takes in a DatabaseTransactionResult and float (user rating) argument</param>
|
||||
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum and a user rating <c>float</c></param>
|
||||
public void CalculateUserRating(
|
||||
Action<DatabaseTransactionResult, float> callback)
|
||||
{
|
||||
|
@ -508,7 +517,7 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
|||
/// abstraction function to update the user's rating in the database
|
||||
/// </summary>
|
||||
/// <param name="newRating">new user rating value as a float</param>
|
||||
/// <param name="callback">callback function that takes in one DatabaseTransactionResult argument</param>
|
||||
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum </param>
|
||||
public void UpdateUserRating(
|
||||
float newRating,
|
||||
Action<DatabaseTransactionResult> callback)
|
||||
|
@ -520,7 +529,7 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
|||
/// abstraction function to get the leaderboard from the database
|
||||
/// </summary>
|
||||
/// <param name="callback">
|
||||
/// callback function that takes in a DatabaseTransactionResult and LeaderboardEntry[] argument
|
||||
/// callback function that takes in a <c>DatabaseTransactionResult</c> enum and a <c>List<LeaderboardEntry></c>
|
||||
/// </param>
|
||||
public void GetLeaderboard(
|
||||
Action<DatabaseTransactionResult, LeaderboardEntry[]> callback)
|
||||
|
@ -533,7 +542,7 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
|||
/// </summary>
|
||||
/// <param name="target">the target account detail to update</param>
|
||||
/// <param name="newValue">the new value for the target account detail</param>
|
||||
/// <param name="callback">callback function that takes in one DatabaseTransactionResult argument</param>
|
||||
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">thrown when the target is not a valid UserAccountDetailTargetEnum</exception>
|
||||
public void UpdateUserAccountDetail(
|
||||
UserAccountDetailTargetEnum target,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
|
@ -20,7 +21,17 @@ public class GameManager : MonoBehaviour
|
|||
/// <summary>
|
||||
/// the local player data object for storing player data
|
||||
/// </summary>
|
||||
private LocalPlayerData _localPlayerData;
|
||||
private LocalPlayerData _data;
|
||||
|
||||
/// <summary>
|
||||
/// read-only property for accessing the local player data outside of this class
|
||||
/// </summary>
|
||||
public LocalPlayerData Data => _data;
|
||||
|
||||
/// <summary>
|
||||
/// list of callbacks to call when the local player data changes
|
||||
/// </summary>
|
||||
private readonly List<Action<LocalPlayerData>> _onLocalPlayerDataChangeCallbacks = new List<Action<LocalPlayerData>>();
|
||||
|
||||
/// <summary>
|
||||
/// backend object for handling communication with the firebase backend
|
||||
|
@ -47,40 +58,55 @@ private void Awake()
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called when the game object is enabled, initialises variables
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
Backend = new Backend();
|
||||
Backend.Initialise();
|
||||
ui = UIManager.Instance;
|
||||
|
||||
// load the local player data and refresh the ui
|
||||
_data = new LocalPlayerData();
|
||||
|
||||
Backend = new Backend();
|
||||
Backend.Initialise(status =>
|
||||
{
|
||||
Debug.Log("initialised backend, setting connection status text");
|
||||
|
||||
ui.UI.Q<Label>("ConnectionStatusText").text = status switch
|
||||
{
|
||||
Backend.FirebaseConnectionStatus.Connected => "Status: Connected",
|
||||
Backend.FirebaseConnectionStatus.Updating => "Status: Updating... (Retrying in a bit!)",
|
||||
Backend.FirebaseConnectionStatus.NotConnected => "Status: Disconnected",
|
||||
Backend.FirebaseConnectionStatus.UpdateRequired =>
|
||||
"Status: Disconnected (Device Component Update Required)",
|
||||
Backend.FirebaseConnectionStatus.ExternalError => "Status: Disconnected (External/Device Error)",
|
||||
Backend.FirebaseConnectionStatus.InternalError => "Status: Disconnected (Internal Error)",
|
||||
_ => "Status: Disconnected (unknown fcs state, this is unreachable and a bug)"
|
||||
};
|
||||
|
||||
if (status == Backend.FirebaseConnectionStatus.Connected) return;
|
||||
|
||||
// if we're not connected, hide any online 'features'
|
||||
ui.UI.Q<Button>("LeaderboardButton").style.display = DisplayStyle.None;
|
||||
ui.UI.Q<Button>("AccountButton").style.display = DisplayStyle.None;
|
||||
});
|
||||
|
||||
// register a callback to refresh the ui when the player signs in
|
||||
Backend.RegisterOnSignInCallback(_ =>
|
||||
{
|
||||
Debug.Log("sign in callback, refreshing GameManager-controlled SideView UI");
|
||||
_data.LoadFromTheWorld(FireLocalPlayerDataChangeCallbacks);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// load in stuff
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
Debug.Log("GameManager starts here");
|
||||
_data.LoadFromTheWorld(FireLocalPlayerDataChangeCallbacks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -90,76 +116,35 @@ private void OnApplicationQuit()
|
|||
{
|
||||
Debug.Log("running deferred cleanup/save functions");
|
||||
Backend.Cleanup();
|
||||
_localPlayerData.SaveToTheWorld();
|
||||
_data.SaveToTheWorld();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// populate the fields with the given username and email, used by GameManager after local player data is loaded
|
||||
/// function to register a callback to be called when the local player data changes
|
||||
/// </summary>
|
||||
public void PopulateFields()
|
||||
/// <param name="callback">callback function that takes a <c>LocalPlayerData</c> object</param>
|
||||
public void RegisterOnLocalPlayerDataChangeCallback(Action<LocalPlayerData> callback)
|
||||
{
|
||||
Debug.Log(
|
||||
$"populating AccountView fields with lkUsername={_localPlayerData.LastKnownUsername} and lkEmail={_localPlayerData.LastKnownEmail}");
|
||||
ui.UI.Q<TextField>("UsernameField").value = _localPlayerData.LastKnownUsername;
|
||||
ui.UI.Q<TextField>("EmailField").value = _localPlayerData.LastKnownEmail;
|
||||
_onLocalPlayerDataChangeCallbacks.Add(callback);
|
||||
Debug.Log($"registering LocalPlayerDataChangeCallback ({_onLocalPlayerDataChangeCallbacks.Count})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// function to update the ui with the latest data
|
||||
/// function to fire all local player data change callbacks
|
||||
/// </summary>
|
||||
private void RenderFromPlayerData()
|
||||
private void FireLocalPlayerDataChangeCallbacks(LocalPlayerData data)
|
||||
{
|
||||
// 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)
|
||||
Debug.Log($"firing LocalPlayerDataChangeCallbacks ({_onLocalPlayerDataChangeCallbacks.Count})");
|
||||
foreach (var callback in _onLocalPlayerDataChangeCallbacks)
|
||||
{
|
||||
totalLightnessAcc += localScore.AvgLightnessAccuracy;
|
||||
totalChromaAcc += localScore.AvgChromaAccuracy;
|
||||
totalHueAcc += localScore.AvgHueAccuracy;
|
||||
totalRounds += localScore.NoOfRounds;
|
||||
try
|
||||
{
|
||||
callback.Invoke(data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"error invoking LocalPlayerDataChangeCallback: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
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<Label>("PlayerText").text = playerText;
|
||||
ui.UI.Q<Label>("LightnessAccuracyText").text = $"{lightnessAcc:F}";
|
||||
ui.UI.Q<Label>("ChromaAccuracyText").text = $"{chromaAcc:F}";
|
||||
ui.UI.Q<Label>("HueAccuracyText").text = $"{hueAcc:F}";
|
||||
|
||||
// and set the player rating, but after we get it from the backend
|
||||
// (god I LOVE async (I am LYING out of my teeth))
|
||||
Backend.CalculateUserRating((dtr, rating) =>
|
||||
{
|
||||
if (dtr != Backend.DatabaseTransactionResult.Ok) return;
|
||||
ui.UI.Q<Label>("RatingText").text = $"{rating:F}";
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ MonoImporter:
|
|||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -10
|
||||
executionOrder: -50
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
|
|
@ -35,7 +35,7 @@ public class LocalPlayerData
|
|||
/// <summary>
|
||||
/// loads player data from player prefs and database
|
||||
/// </summary>
|
||||
public void LoadFromTheWorld()
|
||||
public void LoadFromTheWorld(Action<LocalPlayerData> callback)
|
||||
{
|
||||
// load user data, possibly from the backend
|
||||
var possibleUser = GameManager.Instance.Backend.GetUser();
|
||||
|
@ -91,7 +91,8 @@ public void LoadFromTheWorld()
|
|||
}
|
||||
|
||||
Debug.Log(
|
||||
$"loaded lpdata from the world ({LastKnownUsername} <{LastKnownEmail}> with RLS.Count={RecentLocalScores.Count}), ROS.Count={RecentOnlineScores.Count}");
|
||||
$"loaded lpdata from the world ({LastKnownUsername} <{LastKnownEmail}> with RLS.Count={RecentLocalScores.Count}, ROS.Count={RecentOnlineScores.Count}");
|
||||
callback(this);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
|
@ -21,6 +22,36 @@ public class SideViewUI : MonoBehaviour
|
|||
/// </summary>
|
||||
private Button _playButton;
|
||||
|
||||
/// <summary>
|
||||
/// connection status label for showing the connection status
|
||||
/// </summary>
|
||||
private Label _connectionStatusLabel;
|
||||
|
||||
/// <summary>
|
||||
/// text label for showing the player's known name
|
||||
/// </summary>
|
||||
private Label _playerText;
|
||||
|
||||
/// <summary>
|
||||
/// text label for showing the player's rating
|
||||
/// </summary>
|
||||
private Label _ratingText;
|
||||
|
||||
/// <summary>
|
||||
/// text label for showing the player's stable-ish lightness accuracy
|
||||
/// </summary>
|
||||
private Label _lightnessAccuracyText;
|
||||
|
||||
/// <summary>
|
||||
/// text label for showing the player's stable-ish chroma accuracy
|
||||
/// </summary>
|
||||
private Label _chromaAccuracyText;
|
||||
|
||||
/// <summary>
|
||||
/// text label for showing the player's stable-ish hue accuracy
|
||||
/// </summary>
|
||||
private Label _hueAccuracyText;
|
||||
|
||||
/// <summary>
|
||||
/// function to subscribe button events to their respective functions
|
||||
/// </summary>
|
||||
|
@ -36,6 +67,21 @@ private void OnEnable()
|
|||
|
||||
_accountButton = ui.Q<Button>("AccountButton");
|
||||
_accountButton.clicked += OnAccountButtonClicked;
|
||||
|
||||
_connectionStatusLabel = ui.Q<Label>("ConnectionStatusLabel");
|
||||
|
||||
_playerText = ui.Q<Label>("PlayerText");
|
||||
_ratingText = ui.Q<Label>("RatingText");
|
||||
|
||||
_lightnessAccuracyText = ui.Q<Label>("LightnessAccuracyText");
|
||||
_chromaAccuracyText = ui.Q<Label>("ChromaAccuracyText");
|
||||
_hueAccuracyText = ui.Q<Label>("HueAccuracyText");
|
||||
|
||||
GameManager.Instance.Backend.RegisterOnSignOutCallback(() =>
|
||||
{
|
||||
RenderFromPlayerData(GameManager.Instance.Data);
|
||||
});
|
||||
GameManager.Instance.RegisterOnLocalPlayerDataChangeCallback(RenderFromPlayerData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,4 +107,65 @@ private static void OnAccountButtonClicked()
|
|||
{
|
||||
GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.AccountView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// function to update the ui with the latest data
|
||||
/// </summary>
|
||||
private void RenderFromPlayerData(LocalPlayerData data)
|
||||
{
|
||||
// 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 data.RecentLocalScores)
|
||||
{
|
||||
totalLightnessAcc += localScore.AvgLightnessAccuracy;
|
||||
totalChromaAcc += localScore.AvgChromaAccuracy;
|
||||
totalHueAcc += localScore.AvgHueAccuracy;
|
||||
totalRounds += localScore.NoOfRounds;
|
||||
}
|
||||
|
||||
foreach (var onlineScore in data.RecentOnlineScores)
|
||||
{
|
||||
totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
|
||||
totalChromaAcc += onlineScore.AvgChromaAccuracy;
|
||||
totalHueAcc += onlineScore.AvgHueAccuracy;
|
||||
totalRounds += onlineScore.NoOfRounds;
|
||||
}
|
||||
|
||||
foreach (var onlineScore in data.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 = GameManager.Instance.Backend.IsSignedIn
|
||||
? data.LastKnownUsername
|
||||
: $"{data.LastKnownUsername} (Not Signed In)";
|
||||
|
||||
// finally, set the labels
|
||||
_playerText.text = playerText;
|
||||
_lightnessAccuracyText.text = $"{lightnessAcc:F}";
|
||||
_chromaAccuracyText.text = $"{chromaAcc:F}";
|
||||
_hueAccuracyText.text = $"{hueAcc:F}";
|
||||
|
||||
// and set the player rating, but after we get it from the backend
|
||||
// (god I LOVE async (I am LYING out of my teeth))
|
||||
GameManager.Instance.Backend.CalculateUserRating((dtr, rating) =>
|
||||
{
|
||||
if (dtr != Backend.DatabaseTransactionResult.Ok) return;
|
||||
_ratingText.text = $"{rating:F}";
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ MonoImporter:
|
|||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
executionOrder: -20
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
|
|
@ -4,7 +4,7 @@ MonoImporter:
|
|||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -15
|
||||
executionOrder: -60
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
|
Reference in a new issue