/// <summary> /// Add a new score for the user at the given timestamp (default Now). /// </summary> /// <param name="userId">User ID for whom to add the new score.</param> /// <param name="username">Username to display for the score.</param> /// <param name="score">The score value.</param> /// <param name="timestamp"> /// The timestamp the score was achieved, in Epoch seconds. If <= 0, current time is used. /// </param> public void AddScore(string userId, string username, int score, long timestamp = -1L) { if (timestamp <= 0) { timestamp = DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond; } var scoreOb = new UserScore(userId, username, score, timestamp); var scoreDict = scoreOb.ToDictionary(); addingUserScore = true; var newEntry = dbref.Child(AllScoreDataPath).Push(); newEntry.SetValueAsync(scoreDict).ContinueWith(task => { if (task.Exception != null) { Debug.LogWarning("Exception adding score: " + task.Exception); } if (!task.IsCompleted) { return; } userScoreArgs = new UserScoreArgs { Score = scoreOb }; sendScoreAddedEvent = true; addingUserScore = false; }); }
/// <summary> /// Gets the best of the provided scores. /// </summary> /// <param name="scores"></param> /// <returns>Best of scores, depending on whether lower or higher scores are better.</returns> private UserScore GetBestScore(params UserScore[] scores) { if (scores.Length == 0) { return(null); } UserScore bestScore = null; foreach (var score in scores) { if (bestScore == null) { bestScore = score; } else if (LowestFirst && score.Score < bestScore.Score) { bestScore = score; } else if (!LowestFirst && score.Score > bestScore.Score) { bestScore = score; } } return(bestScore); }
/// <summary> /// Add a new pre-built UserScore to the DB. /// </summary> /// <param name="score">Score to add.</param> /// <returns>Task running to add the score.</returns> public Task <UserScore> AddScore(UserScore score) { var scoreDict = score.ToDictionary(); addingUserScore = true; return(Task.Run(() => { // Waits to ensure the FirebaseLeaderboard is initialized before adding the new score. while (!initialized) { } var newEntry = dbref.Child(AllScoreDataPath).Push(); return newEntry.SetValueAsync(scoreDict).ContinueWith(task => { if (task.Exception != null) { Debug.LogWarning("Exception adding score: " + task.Exception); } if (!task.IsCompleted) { return null; } userScoreArgs = new UserScoreArgs { Score = score }; sendScoreAddedEvent = true; addingUserScore = false; return score; }).Result; })); }
/// <summary> /// Add a new pre-built UserScore to the DB. /// </summary> /// <param name="score">Score to add.</param> /// <returns>Task running to add the score.</returns> public Task <UserScore> AddScore(UserScore score) { var scoreDict = score.ToDictionary(); addingUserScore = true; var newEntry = dbref.Child(AllScoreDataPath).Push(); return(newEntry.SetValueAsync(scoreDict).ContinueWith <UserScore>(task => { if (task.Exception != null) { Debug.LogWarning("Exception adding score: " + task.Exception); } if (!task.IsCompleted) { return null; } userScoreArgs = new UserScoreArgs { Score = score }; sendScoreAddedEvent = true; addingUserScore = false; return score; })); }
// Uploads the time data to the database, and returns the current top time list. public static Task <UserScore> UploadReplay( long time, LevelMap map, ReplayData replay) { // Get a client-generated unique id based on timestamp and random number. string key = FirebaseDatabase.DefaultInstance.RootReference.Push().Key; Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance; string name = (auth.CurrentUser != null && !string.IsNullOrEmpty(auth.CurrentUser.DisplayName)) ? auth.CurrentUser.DisplayName : StringConstants.UploadScoreDefaultName; string userId = (auth.CurrentUser != null && !string.IsNullOrEmpty(auth.CurrentUser.UserId)) ? auth.CurrentUser.UserId : StringConstants.UploadScoreDefaultName; string replayPath = replay != null ? Storage_Replay_Root_Folder + GetPath(map) + key : null; var userScore = new Firebase.Leaderboard.UserScore( userId, name, time, DateTime.Now.Ticks / TimeSpan.TicksPerSecond, new Dictionary <string, object> { { Database_Property_ReplayPath, replayPath } }); UploadConfig config = new UploadConfig() { key = key, storagePath = replayPath, dbRankPath = GetDBRankPath(map) + key, dbSharedReplayPath = GetDBSharedReplayPath(map) + key, shareReplay = replay != null //TODO(chkuang): && GameOption.shareReplay }; if (replay == null) { // Nothing to upload, return user score to upload to leaderboard. return(Task.FromResult(userScore)); } else { return(UploadReplayData(userScore, replay, config) .ContinueWith(task => { if (config.shareReplay) { var dbRef = FirebaseDatabase.DefaultInstance.RootReference; return dbRef.Child(config.dbSharedReplayPath) .SetValueAsync(userScore.ToDictionary()); } else { return null; }; }).ContinueWith(task => userScore)); } }
/// <summary> /// Callback when a score record is added with a score high enough for a spot on the /// leaderboard. /// </summary> private void OnScoreAdded(object sender, ChildChangedEventArgs args) { if (args.Snapshot == null || !args.Snapshot.Exists) { return; } var score = new UserScore(args.Snapshot); // Verify that score is within start/end times, and isn't already in TopScores. if (TopScores.Contains(score)) { return; } if (EndTime > 0 || Interval > 0) { var EndTimeInternal = EndTime > 0 ? EndTime : (DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond); var startTime = Interval > 0 ? EndTimeInternal - Interval : 0; if (score.Timestamp > EndTimeInternal || score.Timestamp < startTime) { return; } } // Don't add if the same user already has a better score. // If the same user has a worse score, remove it. var existingScore = TopScores.Find(s => s.UserID == score.UserID); if (existingScore != null) { var bestScore = GetBestScore(existingScore, score); if (existingScore == bestScore) { return; } TopScores.Remove(existingScore); } if (TopScores.Any(s => s.UserID == score.UserID)) { return; } TopScores.Add(score); if (LowestFirst) { TopScores = TopScores.OrderBy(s => s.Score).Take(ScoresToRetrieve).ToList(); } else { TopScores = TopScores.OrderByDescending(s => s.Score).Take(ScoresToRetrieve).ToList(); } sendUpdateTopScoresEvent = true; }
/// <summary> /// Callback when a score record is removed from the database. /// </summary> private void OnScoreRemoved(object sender, ChildChangedEventArgs args) { var score = new UserScore(args.Snapshot); if (TopScores.Contains(score)) { TopScores.Remove(score); RefreshScores(); } }
/// <summary> /// Add a new score for the user at the given timestamp (default Now). /// </summary> /// <param name="userId">User ID for whom to add the new score.</param> /// <param name="username">Username to display for the score.</param> /// <param name="score">The score value.</param> /// <param name="timestamp"> /// The timestamp the score was achieved, in Epoch seconds. If <= 0, current time is used. /// </param> /// <returns>Task running to add the score.</returns> public Task AddScore(string userId, string username, long score, long timestamp = -1L) { if (timestamp <= 0) { timestamp = DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond; } var scoreOb = new UserScore(userId, username, score, timestamp); return(AddScore(scoreOb)); }
/// <summary> /// Parses a DataSnapshot of score records into UserScore objects, and filters out records /// whose timestamp does not fall between startTS and endTS. /// </summary> /// <param name="snapshot">DataSnapshot record of user scores.</param> /// <param name="startTS">Earliest valid timestamp of a user score to retrieve.</param> /// <param name="endTS">Latest valid timestamp of a user score to retrieve.</param> /// <returns>List of valid UserScore objects.</returns> private List <UserScore> ParseValidUserScoreRecords( DataSnapshot snapshot, long startTS, long endTS) { return(snapshot.Children .Select(scoreRecord => UserScore.CreateScoreFromRecord(scoreRecord)) .Where(score => score != null && score.Timestamp > startTS && score.Timestamp <= endTS) .Reverse() .ToList()); }
/// <summary> /// Callback when a score record is removed from the database. /// </summary> private void OnScoreRemoved(object sender, ChildChangedEventArgs args) { if (args.Snapshot == null || !args.Snapshot.Exists) { return; } var score = new UserScore(args.Snapshot); if (TopScores.Contains(score)) { TopScores.Remove(score); RefreshScores(); } }
/// <summary> /// Add a new score for the user at the given timestamp (default Now). /// </summary> /// <param name="userId">User ID for whom to add the new score.</param> /// <param name="username">Username to display for the score.</param> /// <param name="score">The score value.</param> /// <param name="timestamp"> /// The timestamp the score was achieved, in Epoch seconds. If <= 0, current time is used. /// </param> /// <param name="otherData">Miscellaneous data to store with the score object.</param> /// <returns>Task running to add the score.</returns> public Task AddScore( string userId, string username, long score, long timestamp = -1L, Dictionary <string, object> otherData = null) { if (timestamp <= 0) { timestamp = DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond; } var scoreOb = new UserScore(userId, username, score, timestamp, otherData); return(AddScore(scoreOb)); }