/* If you want to trim down the number of highscores, then call * KeepSomeHighscores() and pass in a filter that returns TRUE for * the highscores you want to keep. If you pass in NULL, a default * filter that keeps about half the highscores will be used. This * algorithm automatically keeps all highscores that are younger * than a week. It's appropriate to call this function after you've * first loaded highscores in your game, for example. */ public void KeepSomeHighscores(HighscoreFilter toKeep) { Random r = new System.Random(); DateTime now = DateTime.Now; List <Highscore> keepers = new List <Highscore>(); lock (highscores) { foreach (Highscore hs in highscores) { if (toKeep == null) { /* highscores from the last week are kept */ double threshold = 0; /* highscores older than a week have a 2:3 chance */ if (hs.Date.Ticks < now.Ticks - 10000000L * 60L * 60L * 24L * 7L) { threshold = 0.333f; } /* highscores older than 13 weeks (approx 3 months) have a higher * chance of going away. */ if (hs.Date.Ticks < now.Ticks - 10000000L * 60L * 60L * 24L * 7L * 13L) { threshold = 0.75f; } if (r.NextDouble() >= threshold) { keepers.Add(hs); } } else { if (toKeep(hs)) { keepers.Add(hs); } } } highscores.Clear(); highscores.AddRange(keepers); } if (HighscoresChanged != null) { HighscoresChanged(this, EventArgs.Empty); } }
/* Given all highscores, return the set of scores that fulfills the given * query filter predicate. */ public IEnumerable <Highscore> QueryHighscores(HighscoreFilter filter) { // Painfully, I have to create a copy, because the array // may be separately modified by the worker thread, and I // can't hold the lock while yield returning Highscore[] hslist; lock (highscores) { hslist = highscores.ToArray(); } foreach (Highscore hs in hslist) { if (filter(hs)) { yield return(hs); } } }