using System; using System.Collections.Generic; using System.Globalization; using UnityEngine; public class LocalPlayerData { /// /// queue of the best online scores, /// used in user rating calculation and accuracy display stats /// public Queue BestOnlineScores = new(30); /// /// last known email used /// public string LastKnownEmail = ""; /// /// last known username used /// public string LastKnownUsername = "Guest"; /// /// queue of the 10 most recent local scores /// public Queue RecentLocalScores = new(10); /// /// queue of the 10 most recent online scores, /// used in user rating calculation and accuracy display stats /// public Queue RecentOnlineScores = new(10); /// /// loads player data from player prefs and database /// public void LoadFromTheWorld(Action callback) { // load user data, possibly from the backend var possibleUser = GameManager.Instance.Backend.GetUser(); var currentKnownEmail = string.Empty; var currentKnownUsername = string.Empty; if (possibleUser != null) { currentKnownEmail = possibleUser.Email; currentKnownUsername = GameManager.Instance.Backend.GetUsername(); } var lastStoredEmail = PlayerPrefs.GetString("LastKnownEmail", ""); var lastStoredUsername = PlayerPrefs.GetString("LastKnownUsername", "Guest"); LastKnownEmail = string.IsNullOrEmpty(currentKnownEmail) ? lastStoredEmail : currentKnownEmail; LastKnownUsername = string.IsNullOrEmpty(currentKnownUsername) ? lastStoredUsername : currentKnownUsername; // load local scores RecentLocalScores.Clear(); for (var idx = 0; idx < 10; idx++) { var timestampRaw = PlayerPrefs.GetString($"RecentLocalScores_{idx}_Timestamp", ""); if (timestampRaw == "") continue; var timestamp = DateTime.TryParseExact(timestampRaw, "s", CultureInfo.InvariantCulture, DateTimeStyles.None, out var t) ? t : DateTime.MinValue; if (timestamp == DateTime.MinValue) continue; var noOfRounds = PlayerPrefs.GetInt($"RecentLocalScores_{idx}_NoOfRounds", -1); var l = PlayerPrefs.GetFloat($"RecentLocalScores_{idx}_AvgLightnessAccuracy", -1f); var c = PlayerPrefs.GetFloat($"RecentLocalScores_{idx}_AvgChromaAccuracy", -1f); var h = PlayerPrefs.GetFloat($"RecentLocalScores_{idx}_AvgHueAccuracy", -1f); // if any of the values are invalid, don't add the score if (noOfRounds < 0 || l < 0 || c < 0 || h < 0) continue; RegisterLocalScore(new Score(timestamp, noOfRounds, l, c, h)); } // load online scores RecentOnlineScores.Clear(); GameManager.Instance.Backend.GetRecentScores((_, recentOnlineScores) => { foreach (var onlineScore in recentOnlineScores) { if (RecentOnlineScores.Count > 10) RecentOnlineScores.Dequeue(); RecentOnlineScores.Enqueue(onlineScore); } Debug.Log( $"loaded lpdata from the world ({LastKnownUsername} <{LastKnownEmail}> with RLS.Count={RecentLocalScores.Count}, ROS.Count={RecentOnlineScores.Count}"); callback(this); }); } /// /// saves player data to player prefs /// public void SaveToTheWorld() { PlayerPrefs.SetString("LastKnownEmail", LastKnownEmail); PlayerPrefs.SetString("LastKnownUsername", LastKnownUsername); var idx = 0; foreach (var score in RecentLocalScores) { PlayerPrefs.SetString($"RecentLocalScores_{idx}_Timestamp", score.Timestamp.ToString("s", CultureInfo.InvariantCulture)); PlayerPrefs.SetInt($"RecentLocalScores_{idx}_NoOfRounds", score.NoOfRounds); PlayerPrefs.SetFloat($"RecentLocalScores_{idx}_AvgLightnessAccuracy", score.AvgLightnessAccuracy); PlayerPrefs.SetFloat($"RecentLocalScores_{idx}_AvgChromaAccuracy", score.AvgChromaAccuracy); PlayerPrefs.SetFloat($"RecentLocalScores_{idx}_AvgHueAccuracy", score.AvgHueAccuracy); idx++; } Debug.Log("saved lpdata to playerprefs"); // online scores are already saved in the backend } /// /// registers a score to the player's local data /// /// the score to register public void RegisterLocalScore(Score score) { if (RecentLocalScores.Count > 10) RecentLocalScores.Dequeue(); RecentLocalScores.Enqueue(score); } public struct Score { /// /// timestamp of the score /// public DateTime Timestamp; /// /// number of rounds played (0-100) /// public int NoOfRounds; /// /// average lightness accuracy across all rounds (0-100) /// public float AvgLightnessAccuracy; /// /// average chroma accuracy across all rounds (0-100) /// public float AvgChromaAccuracy; /// /// average hue accuracy across all rounds (0-100) /// public float AvgHueAccuracy; /// /// constructor for the score struct /// /// timestamp of the score /// number of rounds played (0-100) /// average lightness accuracy across all rounds (0-100) /// average chroma accuracy across all rounds (0-100) /// average hue accuracy across all rounds (0-100) public Score(DateTime timestamp = new(), int noOfRounds = 1, float l = 100.0f, float c = 100.0f, float h = 100.0f) { Timestamp = timestamp; NoOfRounds = noOfRounds; AvgLightnessAccuracy = l; AvgChromaAccuracy = c; AvgHueAccuracy = h; } } }