Newer
Older
CGTrack / Assets / Oculus / Platform / Samples / VrHoops / Scripts / LeaderboardManager.cs
namespace Oculus.Platform.Samples.VrHoops
{
	using UnityEngine;
	using System.Collections.Generic;
	using Oculus.Platform;
	using Oculus.Platform.Models;

	// Coordinates updating leaderboard scores and polling for leaderboard updates.
	public class LeaderboardManager
	{
		// API NAME for the leaderboard where we store how many matches the user has won
		private const string MOST_MATCHES_WON = "MOST_MATCHES_WON";

		// API NAME for the leaderboard where we store the user's match score
		private const string HIGHEST_MATCH_SCORE = "HIGHEST_MATCH_SCORE";

		// the top number of entries to query
		private const int TOP_N_COUNT = 5;

		// how often to poll the service for leaderboard updates
		private const float LEADERBOARD_POLL_FREQ = 30.0f;

		// the next time to check for leaderboard updates
		private float m_nextCheckTime;

		// cache to hold most-wins leaderboard entries as they come in
		private volatile SortedDictionary<int, LeaderboardEntry> m_mostWins;

		// whether we've found the local user's entry yet
		private bool m_foundLocalUserMostWinsEntry;

		// number of times the local user has won
		private long m_numWins;

		// callback to deliver the most-wins leaderboard entries
		private OnMostWinsLeaderboardUpdated m_mostWinsCallback;

		// cache to hold high-score leaderboard entries as they come in
		private volatile SortedDictionary<int, LeaderboardEntry> m_highScores;

		// whether we've found the local user's entry yet
		private bool m_foundLocalUserHighScore;

		// callback to deliver the high-scores leaderboard entries
		private OnHighScoreLeaderboardUpdated m_highScoreCallback;

		public void CheckForUpdates()
		{
			if (Time.time >= m_nextCheckTime &&
				PlatformManager.CurrentState == PlatformManager.State.WAITING_TO_PRACTICE_OR_MATCHMAKE)
			{
				m_nextCheckTime = Time.time + LEADERBOARD_POLL_FREQ;

				QueryMostWinsLeaderboard();
				QueryHighScoreLeaderboard();
			}
		}

		#region Most Wins Leaderboard

		public delegate void OnMostWinsLeaderboardUpdated(SortedDictionary<int, LeaderboardEntry> entries);

		public OnMostWinsLeaderboardUpdated MostWinsLeaderboardUpdatedCallback
		{
			set { m_mostWinsCallback = value; }
		}

		void QueryMostWinsLeaderboard()
		{
			// if a query is already in progress, don't start a new one.
			if (m_mostWins != null)
				return;

			m_mostWins = new SortedDictionary<int, LeaderboardEntry>();
			m_foundLocalUserMostWinsEntry = false;

			Leaderboards.GetEntries(MOST_MATCHES_WON, TOP_N_COUNT, LeaderboardFilterType.None,
				LeaderboardStartAt.Top).OnComplete(MostWinsGetEntriesCallback);
		}

		void MostWinsGetEntriesCallback(Message<LeaderboardEntryList> msg)
		{
			if (!msg.IsError)
			{
				foreach (LeaderboardEntry entry in msg.Data)
				{
					m_mostWins[entry.Rank] = entry;

					if (entry.User.ID == PlatformManager.MyID)
					{
						m_foundLocalUserMostWinsEntry = true;
						m_numWins = entry.Score;
					}
				}

				// results might be paged for large requests
				if (msg.Data.HasNextPage)
				{
					Leaderboards.GetNextEntries(msg.Data).OnComplete(MostWinsGetEntriesCallback);
					return;
				}

				// if local user not in the top, get their position specifically
				if (!m_foundLocalUserMostWinsEntry)
				{
					Leaderboards.GetEntries(MOST_MATCHES_WON, 1, LeaderboardFilterType.None,
						LeaderboardStartAt.CenteredOnViewer).OnComplete(MostWinsGetEntriesCallback);
					return;
				}
			}
			// else an error is returned if the local player isn't ranked - we can ignore that

			if (m_mostWinsCallback != null)
			{
				m_mostWinsCallback(m_mostWins);
			}
			m_mostWins = null;
		}

		#endregion

		#region Highest Score Board

		public delegate void OnHighScoreLeaderboardUpdated(SortedDictionary<int, LeaderboardEntry> entries);

		public OnHighScoreLeaderboardUpdated HighScoreLeaderboardUpdatedCallback
		{
			set { m_highScoreCallback = value; }
		}

		void QueryHighScoreLeaderboard()
		{
			// if a query is already in progress, don't start a new one.
			if (m_highScores != null)
				return;

			m_highScores = new SortedDictionary<int, LeaderboardEntry>();
			m_foundLocalUserHighScore = false;

			Leaderboards.GetEntries(HIGHEST_MATCH_SCORE, TOP_N_COUNT, LeaderboardFilterType.None,
				LeaderboardStartAt.Top).OnComplete(HighestScoreGetEntriesCallback);
		}

		void HighestScoreGetEntriesCallback(Message<LeaderboardEntryList> msg)
		{
			if (!msg.IsError)
			{
				foreach (LeaderboardEntry entry in msg.Data)
				{
					m_highScores[entry.Rank] = entry;

					if (entry.User.ID == PlatformManager.MyID)
					{
						m_foundLocalUserHighScore = true;
					}
				}

				// results might be paged for large requests
				if (msg.Data.HasNextPage)
				{
					Leaderboards.GetNextEntries(msg.Data).OnComplete(HighestScoreGetEntriesCallback);;
					return;
				}

				// if local user not in the top, get their position specifically
				if (!m_foundLocalUserHighScore)
				{
					Leaderboards.GetEntries(HIGHEST_MATCH_SCORE, 1, LeaderboardFilterType.None,
						LeaderboardStartAt.CenteredOnViewer).OnComplete(HighestScoreGetEntriesCallback);
					return;
				}
			}
			// else an error is returned if the local player isn't ranked - we can ignore that

			if (m_highScoreCallback != null)
			{
				m_highScoreCallback(m_highScores);
			}
			m_highScores = null;
		}

		#endregion

		// submit the local player's match score to the leaderboard service
		public void SubmitMatchScores(bool wonMatch, uint score)
		{
			if (wonMatch)
			{
				m_numWins += 1;
				Leaderboards.WriteEntry(MOST_MATCHES_WON, m_numWins);
			}

			if (score > 0)
			{
				Leaderboards.WriteEntry(HIGHEST_MATCH_SCORE, score);
			}
		}
	}
}