using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Timers; namespace TELTest { public class Scoreboard { public Scoreboard(string fileName) { FileName = fileName; if (File.Exists(fileName)) { ReloadAllScores(); } t.Interval = 15000; t.Elapsed += this.T_Elapsed; t.AutoReset = false; } private void T_Elapsed(Object sender, ElapsedEventArgs e) { Save(); } public string FileName { get; } private readonly object _lock = new object(); private void ReloadAllScores() { string[] lines = null; lock (_lock) lines = File.ReadAllLines(FileName); lock (m_Entries) foreach (var item in lines) { var i = ScoreboardEntry.Deserialize(item); if (i.Name != null) m_Entries.Add(i); } } public void Save() { lock (_lock) { File.WriteAllLines(FileName, m_Entries.Select(x=>x.Serialize())); } } public void Add(ScoreboardEntry entry) { lock (m_Entries) m_Entries.Add(entry); t.Stop(); t.Start(); } public ScoreboardEntry[] Highscore(int count = 15) { lock(m_Entries) return m_Entries.OrderBy(x => -x.Value).ToList().GetRange(0, count < m_Entries.Count ? count : m_Entries.Count).ToArray(); } public ScoreboardEntry[] Lowscore(int count = 15) { lock (m_Entries) return m_Entries.OrderBy(x => x.Value).ToList().GetRange(0, count < m_Entries.Count ? count : m_Entries.Count).ToArray(); } System.Timers.Timer t = new System.Timers.Timer(); private List m_Entries = new List(); public IReadOnlyList Entries { get { return m_Entries; } } public struct ScoreboardEntry { public ScoreboardEntry(string name, int value) { this.Date = DateTime.Now; this.Name = name; this.Value = value; } public DateTime Date; public string Name; public int Value; const char SEP_CHAR = '|'; public string Serialize() { return Name + SEP_CHAR + Value + SEP_CHAR + Date.ToString("O", System.Globalization.CultureInfo.InvariantCulture); } public static ScoreboardEntry Deserialize(string str) { if (str.IndexOf(SEP_CHAR) == -1) return default; string[] s = str.Split(SEP_CHAR); string name = s[0]; int value = int.MinValue; DateTime dt = DateTime.MinValue; if (int.TryParse(s[1], out int p)) { value = p; } if (s.Length > 2) { dt = DateTime.ParseExact(s[2], "O", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind); } return new ScoreboardEntry(name, value) { Date = dt }; } } public static Scoreboard Of(string name) { lock (Scoreboards) { if (!Directory.Exists("Hiscores")) lock (_dirLock) Directory.CreateDirectory("Hiscores"); if (Scoreboards.ContainsKey(name)) return Scoreboards[name]; Scoreboard s = new Scoreboard(System.IO.Path.Combine("Hiscores", name + ".txt")); Scoreboards.Add(name, s); return s; } } private static object _dirLock = new object(); public static Dictionary Scoreboards { get; set; } = new Dictionary(); } }