From d331d998c07f1f2be084cf6f164d5f25ac583692 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 10 Feb 2018 00:26:38 -0600 Subject: [PATCH] Stats thread safe Cleaned up WebService class and shutdown reimped stats and topstats moved things out of stats into main code --- Admin/Manager.cs | 37 +- Admin/Server.cs | 40 +- Admin/ServerConfigurationGenerator.cs | 14 +- Admin/WebService.cs | 17 +- Admin/config/messages.cfg | 3 +- Admin/lib/SharedLibrary.dll | Bin 150528 -> 153600 bytes Plugins/SimpleStats/Chat/ChatDatabase.cs | 188 -------- Plugins/SimpleStats/Chat/ChatHistory.cs | 16 - Plugins/SimpleStats/Chat/ChatHistoryPage.cs | 89 ---- Plugins/SimpleStats/Commands/ResetStats.cs | 40 ++ Plugins/SimpleStats/Commands/TopStats.cs | 43 ++ Plugins/SimpleStats/Commands/ViewStats.cs | 72 ++++ Plugins/SimpleStats/Helpers/StatManager.cs | 93 ++-- .../Helpers/ThreadSafeStatsService.cs | 29 ++ Plugins/SimpleStats/Models/EFClientMessage.cs | 25 ++ .../SimpleStats/Pages/ClientMessageJson.cs | 44 ++ Plugins/SimpleStats/Pages/ClientMessages.cs | 30 ++ Plugins/SimpleStats/Pages/LiveStats.cs | 30 ++ .../{StatsPage.cs => Pages/LiveStatsJson.cs} | 38 +- Plugins/SimpleStats/Pages/WordCloudJson.cs | 32 ++ Plugins/SimpleStats/Plugin.cs | 32 +- Plugins/SimpleStats/StatsPlugin.csproj | 15 +- Plugins/SimpleStats/TrustedGroupCommands.cs | 44 -- Plugins/SimpleStats/_Plugin.cs | 406 +----------------- SharedLibrary/Commands/NativeCommands.cs | 56 ++- SharedLibrary/Database/DatabaseContext.cs | 2 +- SharedLibrary/Helpers/AsyncStatus.cs | 10 +- SharedLibrary/RCON.cs | 129 +++--- SharedLibrary/ServerConfiguration.cs | 1 + SharedLibrary/Services/GenericRepository.cs | 18 +- SharedLibrary/WebService.cs | 2 +- 31 files changed, 668 insertions(+), 927 deletions(-) delete mode 100644 Plugins/SimpleStats/Chat/ChatDatabase.cs delete mode 100644 Plugins/SimpleStats/Chat/ChatHistory.cs delete mode 100644 Plugins/SimpleStats/Chat/ChatHistoryPage.cs create mode 100644 Plugins/SimpleStats/Commands/ResetStats.cs create mode 100644 Plugins/SimpleStats/Commands/TopStats.cs create mode 100644 Plugins/SimpleStats/Commands/ViewStats.cs create mode 100644 Plugins/SimpleStats/Helpers/ThreadSafeStatsService.cs create mode 100644 Plugins/SimpleStats/Models/EFClientMessage.cs create mode 100644 Plugins/SimpleStats/Pages/ClientMessageJson.cs create mode 100644 Plugins/SimpleStats/Pages/ClientMessages.cs create mode 100644 Plugins/SimpleStats/Pages/LiveStats.cs rename Plugins/SimpleStats/{StatsPage.cs => Pages/LiveStatsJson.cs} (66%) create mode 100644 Plugins/SimpleStats/Pages/WordCloudJson.cs delete mode 100644 Plugins/SimpleStats/TrustedGroupCommands.cs diff --git a/Admin/Manager.cs b/Admin/Manager.cs index 7a9cc8b94..d4b5d9201 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -28,7 +28,7 @@ namespace IW4MAdmin List TaskStatuses; List Commands; List MessageTokens; - Kayak.IScheduler webServiceTask; + WebService WebSvc; Thread WebThread; ClientService ClientSvc; AliasService AliasSvc; @@ -70,14 +70,8 @@ namespace IW4MAdmin { #region WEBSERVICE SharedLibrary.WebService.Init(); - webServiceTask = WebService.GetScheduler(); - - WebThread = new Thread(webServiceTask.Start) - { - Name = "Web Thread" - }; - - WebThread.Start(); + WebSvc = new WebService(); + WebSvc.StartScheduler(); #endregion #region PLUGINS @@ -182,6 +176,7 @@ namespace IW4MAdmin Commands.Add(new CPlugins()); Commands.Add(new CIP()); Commands.Add(new CMask()); + Commands.Add(new CPruneAdmins()); foreach (Command C in SharedLibrary.Plugins.PluginImporter.ActiveCommands) Commands.Add(C); @@ -192,19 +187,22 @@ namespace IW4MAdmin public void Start() { - while (Running) + while (Running || TaskStatuses.Count > 0) { for (int i = 0; i < TaskStatuses.Count; i++) { var Status = TaskStatuses[i]; + + // remove the task when we want to quit and last run has finished + if (!Running) + { + TaskStatuses.RemoveAt(i); + continue; + } + + // task is read to be rerun if (Status.RequestedTask == null || Status.RequestedTask.Status == TaskStatus.RanToCompletion) { - if (Status.ElapsedMillisecondsTime() > 60000) - { - Logger.WriteWarning($"Task took longer than 60 seconds to complete, killing"); - //Status.RequestedTask. - } - Status.Update(new Task(() => { return (Status.Dependant as Server).ProcessUpdatesAsync(Status.GetToken()).Result; })); if (Status.RunAverage > 1000 + UPDATE_FREQUENCY) Logger.WriteWarning($"Update task average execution is longer than desired for {(Status.Dependant as Server)} [{Status.RunAverage}ms]"); @@ -218,13 +216,16 @@ namespace IW4MAdmin S.Broadcast("^1IW4MAdmin going offline!"); #endif _servers.Clear(); - WebThread.Abort(); - webServiceTask.Stop(); + WebSvc.WebScheduler.Stop(); + WebSvc.SchedulerThread.Join(); } public void Stop() { + // tell threads it's time to stop + foreach (var status in TaskStatuses) + status.TokenSrc.Cancel(); Running = false; } diff --git a/Admin/Server.cs b/Admin/Server.cs index 601050d04..015b138ad 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -15,11 +15,13 @@ namespace IW4MAdmin { public class IW4MServer : Server { + private CancellationToken cts; + public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { } public override int GetHashCode() { - return Math.Abs(IP.GetHashCode() + Port); + return Math.Abs($"{IP}:{Port.ToString()}".GetHashCode()); } override public async Task AddPlayer(Player polledPlayer) { @@ -32,7 +34,7 @@ namespace IW4MAdmin if (Players[polledPlayer.ClientNumber] != null && Players[polledPlayer.ClientNumber].NetworkId == polledPlayer.NetworkId) { - // update their ping + // update their ping & score Players[polledPlayer.ClientNumber].Ping = polledPlayer.Ping; Players[polledPlayer.ClientNumber].Score = polledPlayer.Score; return true; @@ -117,6 +119,17 @@ namespace IW4MAdmin Players[player.ClientNumber] = player; Logger.WriteInfo($"Client {player} connecting..."); + // give trusted rank + if (Config.AllowTrustedRank && + player.TotalConnectionTime / 60.0 >= 2880 && + player.Level < Player.Permission.Trusted && + player.Level != Player.Permission.Flagged) + { + player.Level = Player.Permission.Trusted; + await player.Tell("Congratulations, you are now a ^5trusted ^7player! Type ^5!help ^7to view new commands."); + await player.Tell("You earned this by playing for ^53 ^7full days!"); + } + await ExecuteEvent(new Event(Event.GType.Connect, "", player, null, this)); // if (NewPlayer.Level > Player.Permission.Moderator) @@ -261,7 +274,9 @@ namespace IW4MAdmin E.Target = matchingPlayers.First(); E.Data = Regex.Replace(E.Data, $"\"{E.Target.Name}\"", "", RegexOptions.IgnoreCase).Trim(); - if (E.Data.ToLower().Trim() == E.Target.Name.ToLower().Trim()) + if ((E.Data.ToLower().Trim() == E.Target.Name.ToLower().Trim() || + E.Data == String.Empty) && + C.RequiresTarget) { await E.Origin.Tell($"Not enough arguments supplied!"); await E.Origin.Tell(C.Syntax); @@ -284,8 +299,11 @@ namespace IW4MAdmin { E.Target = matchingPlayers.First(); E.Data = Regex.Replace(E.Data, $"{E.Target.Name}", "", RegexOptions.IgnoreCase).Trim(); + E.Data = Regex.Replace(E.Data, $"{Args[0]}", "", RegexOptions.IgnoreCase).Trim(); - if (E.Data.Trim() == E.Target.Name.ToLower().Trim()) + if ((E.Data.Trim() == E.Target.Name.ToLower().Trim() || + E.Data == String.Empty) && + C.RequiresTarget) { await E.Origin.Tell($"Not enough arguments supplied!"); await E.Origin.Tell(C.Syntax); @@ -316,6 +334,9 @@ namespace IW4MAdmin try #endif { + if (cts.IsCancellationRequested) + break; + await P.OnEventAsync(E, this); } #if !DEBUG @@ -362,6 +383,7 @@ namespace IW4MAdmin override public async Task ProcessUpdatesAsync(CancellationToken cts) { + this.cts = cts; #if DEBUG == false try #endif @@ -400,7 +422,12 @@ namespace IW4MAdmin if ((DateTime.Now - tickTime).TotalMilliseconds >= 1000) { foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins) + { + if (cts.IsCancellationRequested) + break; + await Plugin.OnTickAsync(this); + } tickTime = DateTime.Now; } @@ -459,6 +486,11 @@ namespace IW4MAdmin } oldLines = lines; l_size = LogFile.Length(); + if (!((ApplicationManager)Manager).Running) + { + foreach (var plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins) + await plugin.OnUnloadAsync(); + } return true; } #if DEBUG == false diff --git a/Admin/ServerConfigurationGenerator.cs b/Admin/ServerConfigurationGenerator.cs index f5abeb256..c888bdc62 100644 --- a/Admin/ServerConfigurationGenerator.cs +++ b/Admin/ServerConfigurationGenerator.cs @@ -16,6 +16,7 @@ namespace IW4MAdmin int Port = 0; string Password; bool AllowMultipleOwners; + bool AllowTrustedRank; while (IP == String.Empty) { @@ -53,7 +54,18 @@ namespace IW4MAdmin Console.Write("Allow multiple owners? [y/n]: "); AllowMultipleOwners = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - var config = new ServerConfiguration() { IP = IP, Password = Password, Port = Port, AllowMultipleOwners = AllowMultipleOwners }; + Console.Write("Allow trusted rank? [y/n]: "); + AllowTrustedRank = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + var config = new ServerConfiguration() + { + IP = IP, + Password = Password, + Port = Port, + AllowMultipleOwners = AllowMultipleOwners, + AllowTrustedRank = AllowTrustedRank + }; + config.Write(); Console.Write("Configuration saved, add another? [y/n]:"); diff --git a/Admin/WebService.cs b/Admin/WebService.cs index 036c0bfca..6d1189391 100644 --- a/Admin/WebService.cs +++ b/Admin/WebService.cs @@ -19,12 +19,14 @@ namespace IW4MAdmin { public class WebService { - public static IServer webService; + public IServer WebServer { get; private set; } + public IScheduler WebScheduler { get; private set; } + public Thread SchedulerThread { get; private set; } - public static IScheduler GetScheduler() + public void StartScheduler() { - var webScheduler = Kayak.KayakScheduler.Factory.Create(new Scheduler()); - webService = KayakServer.Factory.CreateHttp(new Request(), webScheduler); + WebScheduler = KayakScheduler.Factory.Create(new Scheduler()); + WebServer = KayakServer.Factory.CreateHttp(new Request(), WebScheduler); SharedLibrary.WebService.PageList.Add(new Pages()); SharedLibrary.WebService.PageList.Add(new Homepage()); @@ -40,13 +42,14 @@ namespace IW4MAdmin SharedLibrary.WebService.PageList.Add(new AdminsJSON()); SharedLibrary.WebService.PageList.Add(new Admins()); - Thread scheduleThread = new Thread(() => { ScheduleThreadStart(webScheduler, webService); }) + SchedulerThread = new Thread(() => { + ScheduleThreadStart(WebScheduler, WebServer); + }) { Name = "Web Service Thread" }; - scheduleThread.Start(); - return webScheduler; + SchedulerThread.Start(); } private static void ScheduleThreadStart(IScheduler S, IServer ss) diff --git a/Admin/config/messages.cfg b/Admin/config/messages.cfg index eef2903ee..c72ab1b78 100644 --- a/Admin/config/messages.cfg +++ b/Admin/config/messages.cfg @@ -1,7 +1,8 @@ 60 +Over ^5{{TOTALPLAYTIME}} ^7man hours have been played on this server! This server uses ^5IW4M Admin v{{VERSION}} ^7get it at ^5raidmax.org/IW4MAdmin ^5IW4M Admin ^7sees ^5YOU! This server has harvested the information of ^5{{TOTALPLAYERS}} ^7players! Cheaters are ^1unwelcome ^7 on this server Did you know 8/10 people agree with unverified statistics? -^5{{TOTALKILLS}} ^7innocent people having been murdered in this server! \ No newline at end of file +^5{{TOTALKILLS}} ^7innocent people have been murdered in this server! \ No newline at end of file diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index 0a35b3e5b6d4ecd82c87df43885ad914c4b32e22..0552f463b1d0e593a250961684612c34e5b3c0a9 100644 GIT binary patch literal 153600 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 z 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 literal 150528 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

{1pn4;=?HRqdQcS=~@ZEY>4kQh&Q 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

25VD#%0lld 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 F{{S!`fL8zj diff --git a/Plugins/SimpleStats/Chat/ChatDatabase.cs b/Plugins/SimpleStats/Chat/ChatDatabase.cs deleted file mode 100644 index e3089b5b0..000000000 --- a/Plugins/SimpleStats/Chat/ChatDatabase.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using SharedLibrary; -using System.IO; -using System.Data; - -namespace StatsPlugin -{ - public class ChatDatabase : _Database - { - private string[] CommonWords = new string[] { "for", -"with", -"from", -"about", -"your", -"just", -"into", -"over", -"after", -"that", -"not", -"you", -"this", -"but", -"his", -"they", -"then", -"her", -"she", -"will", -"one", -"all", -"would", -"there", -"their", -"have", -"say", -"get", -"make", -"know", -"take", -"see", -"come", -"think", -"look", -"want", -"can", -"was", -"give", -"use", -"find", -"tell", -"ask", -"work", -"seem", -"feel", -"try", -"leave", -"call", -"good", -"new", -"first", -"last", -"long", -"great", -"little", -"own", -"other", -"old", -"right", -"big", -"high", -"small", -"large", -"next", -"early", -"young", -"important", -"few", -"public", -"same", -"able", -"the", -"and", -"that", -"than", -"have", -"this", -"one", -"would", - "yeah", - "yah", - "why", - "who" , - "when", - "where", - }; - - public ChatDatabase(string FN, SharedLibrary.Interfaces.ILogger logger) : base(FN, logger) - { - } - - public override void Init() - { - if (!File.Exists(FileName)) - { - string createChatHistory = @"CREATE TABLE `CHATHISTORY` ( - `ClientID` INTEGER NOT NULL, - `Message` TEXT NOT NULL, - `ServerID` INTEGER NOT NULL, - `TimeSent` TEXT NOT NULL - );"; - - ExecuteNonQuery(createChatHistory); - - string createChatStats = @"CREATE TABLE `WORDSTATS` ( - `Word` TEXT NOT NULL, - `Count` INTEGER NOT NULL DEFAULT 1, - PRIMARY KEY(`Word`) - );"; - - ExecuteNonQuery(createChatStats); - } - } - - private List GetChatHistoryFromQuery(DataTable dt) - { - return dt.Select().Select(q => new ChatHistory() - { - ClientID = Convert.ToInt32(q["ClientID"].ToString()), - Message = q["Message"].ToString(), - ServerID = Convert.ToInt32(q["ServerID"].ToString()), - TimeSent = DateTime.Parse(q["TimeSent"].ToString()) - }) - .ToList(); - } - - public List GetChatForPlayer(int clientID) - { - var queryResult = GetDataTable("CHATHISTORY", new KeyValuePair("ClientID", clientID)); - return GetChatHistoryFromQuery(queryResult); - } - - public List GetChatForServer(int serverID) - { - var queryResult = GetDataTable("CHATHISTORY", new KeyValuePair("ServerID", serverID)); - return GetChatHistoryFromQuery(queryResult); - } - - public void AddChatHistory(int clientID, int serverID, string message) - { - if (message.Length < 3) - return; - - var chat = new Dictionary() - { - { "ClientID", clientID }, - { "ServerID", serverID }, - { "Message", message}, - { "TimeSent", DateTime.UtcNow } - }; - - Insert("CHATHISTORY", chat); - - var eachWord = message.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) - .Where (word => word.Length >= 3) - .Where(word => CommonWords.FirstOrDefault(c => c == word.ToLower()) == null) - .ToList(); - - foreach (string _word in eachWord) - { - string word = _word.ToLower(); - Insert("WORDSTATS", new Dictionary() { { "Word", word } }, true); - UpdateIncrement("WORDSTATS", "Count", new Dictionary() { { "Count", 1 } }, new KeyValuePair("Word", word)); - } - } - - public KeyValuePair[] GetWords() - { - var result = GetDataTable("SELECT * FROM WORDSTATS ORDER BY Count desc LIMIT 200"); - return result.Select().Select(w => new KeyValuePair(w["Word"].ToString(), Convert.ToInt32(w["Count"].ToString()))).ToArray(); - } - } -} diff --git a/Plugins/SimpleStats/Chat/ChatHistory.cs b/Plugins/SimpleStats/Chat/ChatHistory.cs deleted file mode 100644 index 46563b003..000000000 --- a/Plugins/SimpleStats/Chat/ChatHistory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StatsPlugin -{ - public class ChatHistory - { - public int ClientID { get; set; } - public string Message { get; set; } - public int ServerID { get; set; } - public DateTime TimeSent { get; set; } - } -} diff --git a/Plugins/SimpleStats/Chat/ChatHistoryPage.cs b/Plugins/SimpleStats/Chat/ChatHistoryPage.cs deleted file mode 100644 index 6dd91c1fb..000000000 --- a/Plugins/SimpleStats/Chat/ChatHistoryPage.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using SharedLibrary; -using System.Collections.Specialized; - -namespace StatsPlugin.Chat -{ - public class ChatPage : HTMLPage - { - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - StringBuilder S = new StringBuilder(); - S.Append(LoadHeader()); - - IFile chat = new IFile("webfront\\chat.html"); - S.Append(chat.GetText()); - chat.Close(); - - S.Append(LoadFooter()); - - return S.ToString(); - } - - public override string GetName() => "Word Cloud"; - public override string GetPath() => "/chat"; - } - - public class WordCloudJSON : IPage - { - public string GetName() => "Word Cloud JSON"; - public string GetPath() => "/_words"; - public string GetContentType() => "application/json"; - public bool Visible() => false; - - public HttpResponse GetPage(NameValueCollection querySet, IDictionary headers) - { - - HttpResponse resp = new HttpResponse() - { - contentType = GetContentType(), - content = Stats.ChatDB.GetWords().Select(w => new - { - Word = w.Key, - Count = w.Value - }) - .OrderByDescending(x => x.Count) - .ToArray(), - - additionalHeaders = new Dictionary() - }; - - return resp; - } - } - - public class ClientChatJSON : IPage - { - public string GetName() => "Client Chat JSON"; - public string GetPath() => "/_clientchat"; - public string GetContentType() => "application/json"; - public bool Visible() => false; - - public HttpResponse GetPage(NameValueCollection querySet, IDictionary headers) - { - int clientID = Convert.ToInt32(querySet["clientid"]); - var name = Stats.ManagerInstance.GetDatabase().GetClient(clientID).Name; - - HttpResponse resp = new HttpResponse() - { - contentType = GetContentType(), - content = Stats.ChatDB.GetChatForPlayer(clientID).ToArray().Select(c => new - { - ClientID = c.ClientID, - ServerID = c.ServerID, - Message = c.Message, - TimeSent = c.TimeSent, - ClientName = name, - }), - additionalHeaders = new Dictionary() - }; - - return resp; - } - } -} diff --git a/Plugins/SimpleStats/Commands/ResetStats.cs b/Plugins/SimpleStats/Commands/ResetStats.cs new file mode 100644 index 000000000..8d41e6f1d --- /dev/null +++ b/Plugins/SimpleStats/Commands/ResetStats.cs @@ -0,0 +1,40 @@ +using SharedLibrary; +using SharedLibrary.Objects; +using StatsPlugin.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Commands +{ + + public class ResetStats : Command + { + public ResetStats() : base("resetstats", "reset your stats to factory-new", "rs", Player.Permission.User, false) { } + + public override async Task ExecuteAsync(Event E) + { + if (E.Origin.ClientNumber >= 0) + { + var svc = new SharedLibrary.Services.GenericRepository(); + var stats = svc.Find(s => s.ClientId == E.Origin.ClientId).First(); + + stats.Deaths = 0; + stats.Kills = 0; + stats.SPM = 0; + stats.Skill = 0; + + // fixme: this doesn't work properly when another context exists + await svc.SaveChangesAsync(); + await E.Origin.Tell("Your stats have been reset"); + } + + else + { + await E.Origin.Tell("You must be connected to a server to reset your stats"); + } + } + } +} diff --git a/Plugins/SimpleStats/Commands/TopStats.cs b/Plugins/SimpleStats/Commands/TopStats.cs new file mode 100644 index 000000000..70e44d3c6 --- /dev/null +++ b/Plugins/SimpleStats/Commands/TopStats.cs @@ -0,0 +1,43 @@ +using SharedLibrary; +using SharedLibrary.Objects; +using SharedLibrary.Services; +using StatsPlugin.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Commands +{ + class TopStats : Command + { + public TopStats() : base("topstats", "view the top 5 players on this server", "ts", Player.Permission.User, false) { } + + public override async Task ExecuteAsync(Event E) + { + var statsSvc = new GenericRepository(); + var iqStats = statsSvc.GetQuery(cs => cs.Active); + + var topStats = iqStats.Where(cs => cs.Skill > 100) + .OrderByDescending(cs => cs.Skill) + .Take(5) + .ToList(); + + if (!E.Message.IsBroadcastCommand()) + { + await E.Origin.Tell("^5--Top Players--"); + + foreach (var stat in topStats) + await E.Origin.Tell($"^3{stat.Client.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7SKILL"); + } + else + { + await E.Owner.Broadcast("^5--Top Players--"); + + foreach (var stat in topStats) + await E.Owner.Broadcast($"^3{stat.Client.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7SKILL"); + } + } + } +} diff --git a/Plugins/SimpleStats/Commands/ViewStats.cs b/Plugins/SimpleStats/Commands/ViewStats.cs new file mode 100644 index 000000000..fe52f3be5 --- /dev/null +++ b/Plugins/SimpleStats/Commands/ViewStats.cs @@ -0,0 +1,72 @@ +using SharedLibrary; +using SharedLibrary.Objects; +using SharedLibrary.Services; +using StatsPlugin.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Commands +{ + public class CViewStats : Command + { + public CViewStats() : base("stats", "view your stats", "xlrstats", Player.Permission.User, false, new CommandArgument[] + { + new CommandArgument() + { + Name = "player", + Required = false + } + }) + { } + + public override async Task ExecuteAsync(Event E) + { + + if (E.Origin.ClientNumber < 0) + { + await E.Origin.Tell("You must be ingame to view your stats"); + return; + } + + String statLine; + EFClientStatistics pStats; + + if (E.Data.Length > 0 && E.Target == null) + { + await E.Origin.Tell("Cannot find the player you specified"); + return; + } + + var clientStats = new GenericRepository(); + + if (E.Target != null) + { + pStats = clientStats.Find(c => c.ClientId == E.Target.ClientId).First(); + statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); + } + + else + { + pStats = pStats = clientStats.Find(c => c.ClientId == E.Origin.ClientId).First(); + statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); + } + + if (E.Message.IsBroadcastCommand()) + { + string name = E.Target == null ? E.Origin.Name : E.Target.Name; + await E.Owner.Broadcast($"Stats for ^5{name}^7"); + await E.Owner.Broadcast(statLine); + } + + else + { + if (E.Target != null) + await E.Origin.Tell($"Stats for ^5{E.Target.Name}^7"); + await E.Origin.Tell(statLine); + } + } + } +} diff --git a/Plugins/SimpleStats/Helpers/StatManager.cs b/Plugins/SimpleStats/Helpers/StatManager.cs index 1e6e63b03..fcc305bb3 100644 --- a/Plugins/SimpleStats/Helpers/StatManager.cs +++ b/Plugins/SimpleStats/Helpers/StatManager.cs @@ -14,22 +14,16 @@ namespace StatsPlugin.Helpers public class StatManager { private Dictionary Servers; + private Dictionary ContextThreads; private ILogger Log; private IManager Manager; - private GenericRepository ClientStatSvc; - private GenericRepository ServerSvc; - private GenericRepository KillStatsSvc; - private GenericRepository ServerStatsSvc; public StatManager(IManager mgr) { Servers = new Dictionary(); + ContextThreads = new Dictionary(); Log = mgr.GetLogger(); Manager = mgr; - ClientStatSvc = new GenericRepository(); - ServerSvc = new GenericRepository(); - KillStatsSvc = new GenericRepository(); - ServerStatsSvc = new GenericRepository(); } ~StatManager() @@ -48,9 +42,11 @@ namespace StatsPlugin.Helpers try { int serverId = sv.GetHashCode(); + var statsSvc = new ThreadSafeStatsService(); + ContextThreads.Add(serverId, statsSvc); // get the server from the database if it exists, otherwise create and insert a new one - var server = ServerSvc.Find(c => c.ServerId == serverId).FirstOrDefault(); + var server = statsSvc.ServerSvc.Find(c => c.ServerId == serverId).FirstOrDefault(); if (server == null) { server = new EFServer() @@ -60,17 +56,16 @@ namespace StatsPlugin.Helpers ServerId = serverId }; - ServerSvc.Insert(server); + statsSvc.ServerSvc.Insert(server); } // this doesn't need to be async as it's during initialization - ServerSvc.SaveChanges(); - InitializeServerStats(sv); - ServerStatsSvc.SaveChanges(); - - var serverStats = ServerStatsSvc.Find(c => c.ServerId == serverId).FirstOrDefault(); + statsSvc.ServerSvc.SaveChanges(); // check to see if the stats have ever been initialized + InitializeServerStats(sv); + statsSvc.ServerStatsSvc.SaveChanges(); + var serverStats = statsSvc.ServerStatsSvc.Find(c => c.ServerId == serverId).FirstOrDefault(); Servers.Add(serverId, new ServerStats(server, serverStats)); } @@ -89,10 +84,11 @@ namespace StatsPlugin.Helpers { int serverId = pl.CurrentServer.GetHashCode(); var playerStats = Servers[serverId].PlayerStats; + var statsSvc = ContextThreads[serverId]; // get the client's stats from the database if it exists, otherwise create and attach a new one // if this fails we want to throw an exception - var clientStats = ClientStatSvc.Find(c => c.ClientId == pl.ClientId && c.ServerId == serverId).FirstOrDefault(); + var clientStats = statsSvc.ClientStatSvc.Find(c => c.ClientId == pl.ClientId && c.ServerId == serverId).FirstOrDefault(); if (clientStats == null) { clientStats = new EFClientStatistics() @@ -106,7 +102,7 @@ namespace StatsPlugin.Helpers SPM = 0.0, }; - clientStats = ClientStatSvc.Insert(clientStats); + clientStats = statsSvc.ClientStatSvc.Insert(clientStats); } // set these on connecting @@ -125,17 +121,32 @@ namespace StatsPlugin.Helpers return clientStats; } + /// + /// Perform stat updates for disconnecting client + /// + /// Disconnecting client + /// public async Task RemovePlayer(Player pl) { int serverId = pl.CurrentServer.GetHashCode(); var playerStats = Servers[serverId].PlayerStats; + var serverStats = Servers[serverId].ServerStatistics; + var statsSvc = ContextThreads[serverId]; + // get individual client's stats var clientStats = playerStats[pl.ClientNumber]; // remove the client from the stats dictionary as they're leaving lock (playerStats) playerStats.Remove(pl.ClientNumber); - var serverStats = ServerStatsSvc.Find(sv => sv.ServerId == serverId).FirstOrDefault(); + // sync their stats before they leave + clientStats.Client = pl; + UpdateStats(clientStats); + clientStats.Client = null; + + // todo: should this be saved every disconnect? + await statsSvc.ClientStatSvc.SaveChangesAsync(); + // increment the total play time serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds; } @@ -148,6 +159,8 @@ namespace StatsPlugin.Helpers { AddStandardKill(attacker, victim); + var statsSvc = ContextThreads[serverId]; + var kill = new EFClientKill() { Active = true, @@ -163,8 +176,8 @@ namespace StatsPlugin.Helpers Weapon = ParseEnum.Get(weapon, typeof(IW4Info.WeaponName)) }; - KillStatsSvc.Insert(kill); - await KillStatsSvc.SaveChangesAsync(); + statsSvc.KillStatsSvc.Insert(kill); + await statsSvc.KillStatsSvc.SaveChangesAsync(); } public void AddStandardKill(Player attacker, Player victim) @@ -183,8 +196,9 @@ namespace StatsPlugin.Helpers // immediately write changes in debug #if DEBUG - ClientStatSvc.SaveChanges(); - ServerStatsSvc.SaveChanges(); + var statsSvc = ContextThreads[serverId]; + statsSvc.ClientStatSvc.SaveChanges(); + statsSvc.ServerStatsSvc.SaveChanges(); #endif } @@ -262,7 +276,9 @@ namespace StatsPlugin.Helpers public void InitializeServerStats(Server sv) { int serverId = sv.GetHashCode(); - var serverStats = ServerStatsSvc.Find(s => s.ServerId == serverId).FirstOrDefault(); + var statsSvc = ContextThreads[serverId]; + + var serverStats = statsSvc.ServerStatsSvc.Find(s => s.ServerId == serverId).FirstOrDefault(); if (serverStats == null) { Log.WriteDebug($"Initializing server stats for {sv}"); @@ -275,29 +291,46 @@ namespace StatsPlugin.Helpers TotalPlayTime = 0, }; - var ieClientStats = ClientStatSvc.Find(cs => cs.ServerId == serverId); + var ieClientStats = statsSvc.ClientStatSvc.Find(cs => cs.ServerId == serverId); // set these incase they've we've imported settings serverStats.TotalKills = ieClientStats.Sum(cs => cs.Kills); serverStats.TotalPlayTime = Manager.GetClientService().GetTotalPlayTime().Result; - ServerStatsSvc.Insert(serverStats); + statsSvc.ServerStatsSvc.Insert(serverStats); } } - public async Task Sync() + public async Task AddMessageAsync(int clientId, int serverId, string message) { + var messageSvc = ContextThreads[serverId].MessageSvc; + messageSvc.Insert(new EFClientMessage() + { + Active = true, + ClientId = clientId, + Message = message, + ServerId = serverId, + TimeSent = DateTime.UtcNow + }); + await messageSvc.SaveChangesAsync(); + } + + public async Task Sync(Server sv) + { + int serverId = sv.GetHashCode(); + var statsSvc = ContextThreads[serverId]; + Log.WriteDebug("Syncing server stats"); - await ServerStatsSvc.SaveChangesAsync(); + await statsSvc.ServerStatsSvc.SaveChangesAsync(); Log.WriteDebug("Syncing client stats"); - await ClientStatSvc.SaveChangesAsync(); + await statsSvc.ClientStatSvc.SaveChangesAsync(); Log.WriteDebug("Syncing kill stats"); - await KillStatsSvc.SaveChangesAsync(); + await statsSvc.KillStatsSvc.SaveChangesAsync(); Log.WriteDebug("Syncing servers"); - await ServerSvc.SaveChangesAsync(); + await statsSvc.ServerSvc.SaveChangesAsync(); } } } diff --git a/Plugins/SimpleStats/Helpers/ThreadSafeStatsService.cs b/Plugins/SimpleStats/Helpers/ThreadSafeStatsService.cs new file mode 100644 index 000000000..d8063b2e2 --- /dev/null +++ b/Plugins/SimpleStats/Helpers/ThreadSafeStatsService.cs @@ -0,0 +1,29 @@ +using SharedLibrary.Services; +using StatsPlugin.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Helpers +{ + public class ThreadSafeStatsService + { + + public GenericRepository ClientStatSvc { get; private set; } + public GenericRepository ServerSvc { get; private set; } + public GenericRepository KillStatsSvc { get; private set; } + public GenericRepository ServerStatsSvc { get; private set; } + public GenericRepository MessageSvc { get; private set; } + + public ThreadSafeStatsService() + { + ClientStatSvc = new GenericRepository(); + ServerSvc = new GenericRepository(); + KillStatsSvc = new GenericRepository(); + ServerStatsSvc = new GenericRepository(); + MessageSvc = new GenericRepository(); + } + } +} diff --git a/Plugins/SimpleStats/Models/EFClientMessage.cs b/Plugins/SimpleStats/Models/EFClientMessage.cs new file mode 100644 index 000000000..b6e466f4b --- /dev/null +++ b/Plugins/SimpleStats/Models/EFClientMessage.cs @@ -0,0 +1,25 @@ +using SharedLibrary.Database.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Models +{ + public class EFClientMessage : SharedEntity + { + [Key] + public long MessageId { get; set; } + public int ServerId { get; set; } + [ForeignKey("ServerId")] + public virtual EFServer Server { get; set; } + public int ClientId { get; set; } + [ForeignKey("ClientId")] + public virtual EFClient Client { get; set; } + public string Message { get; set; } + public DateTime TimeSent { get; set; } + } +} diff --git a/Plugins/SimpleStats/Pages/ClientMessageJson.cs b/Plugins/SimpleStats/Pages/ClientMessageJson.cs new file mode 100644 index 000000000..ff6dcc0f4 --- /dev/null +++ b/Plugins/SimpleStats/Pages/ClientMessageJson.cs @@ -0,0 +1,44 @@ +using SharedLibrary; +using SharedLibrary.Database.Models; +using SharedLibrary.Services; +using StatsPlugin.Models; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Pages +{ + public class ClientMessageJson : IPage + { + public string GetName() => "Client Chat JSON"; + public string GetPath() => "/_clientchat"; + public string GetContentType() => "application/json"; + public bool Visible() => false; + + public async Task GetPage(NameValueCollection querySet, IDictionary headers) + { + int clientId = Convert.ToInt32(querySet["clientid"]); + var messageSvc = new GenericRepository(); + var clientMessages = (await messageSvc.FindAsync(m => m.ClientId == clientId)); + + HttpResponse resp = new HttpResponse() + { + contentType = GetContentType(), + content = clientMessages.Select(c => new + { + ClientID = c.ClientId, + ServerID = c.ServerId, + c.Message, + c.TimeSent, + ClientName = c.Client.Name, + }), + additionalHeaders = new Dictionary() + }; + + return resp; + } + } +} diff --git a/Plugins/SimpleStats/Pages/ClientMessages.cs b/Plugins/SimpleStats/Pages/ClientMessages.cs new file mode 100644 index 000000000..cd23b3791 --- /dev/null +++ b/Plugins/SimpleStats/Pages/ClientMessages.cs @@ -0,0 +1,30 @@ +using SharedLibrary; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Pages +{ + public class ClientMessages : HTMLPage + { + public override string GetContent(NameValueCollection querySet, IDictionary headers) + { + StringBuilder S = new StringBuilder(); + S.Append(LoadHeader()); + + IFile chat = new IFile("webfront\\chat.html"); + S.Append(chat.GetText()); + chat.Close(); + + S.Append(LoadFooter()); + + return S.ToString(); + } + + public override string GetName() => "Word Cloud"; + public override string GetPath() => "/chat"; + } +} diff --git a/Plugins/SimpleStats/Pages/LiveStats.cs b/Plugins/SimpleStats/Pages/LiveStats.cs new file mode 100644 index 000000000..aee30f0d1 --- /dev/null +++ b/Plugins/SimpleStats/Pages/LiveStats.cs @@ -0,0 +1,30 @@ +using SharedLibrary; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Pages +{ + public class LiveStats : HTMLPage + { + public override string GetContent(NameValueCollection querySet, IDictionary headers) + { + StringBuilder S = new StringBuilder(); + S.Append(LoadHeader()); + + IFile stats = new IFile("webfront\\stats.html"); + S.Append(stats.GetText()); + stats.Close(); + + S.Append(LoadFooter()); + + return S.ToString(); + } + + public override string GetName() => "Server Stats"; + public override string GetPath() => "/stats"; + } +} diff --git a/Plugins/SimpleStats/StatsPage.cs b/Plugins/SimpleStats/Pages/LiveStatsJson.cs similarity index 66% rename from Plugins/SimpleStats/StatsPage.cs rename to Plugins/SimpleStats/Pages/LiveStatsJson.cs index 6786a3c82..e791df0e3 100644 --- a/Plugins/SimpleStats/StatsPage.cs +++ b/Plugins/SimpleStats/Pages/LiveStatsJson.cs @@ -1,45 +1,25 @@ -using System; +using SharedLibrary; +using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Text; using System.Threading.Tasks; -using SharedLibrary; - -namespace StatsPlugin +namespace StatsPlugin.Pages { - public class StatsPage : HTMLPage - { - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - StringBuilder S = new StringBuilder(); - S.Append(LoadHeader()); - - IFile stats = new IFile("webfront\\stats.html"); - S.Append(stats.GetText()); - stats.Close(); - - S.Append(LoadFooter()); - - return S.ToString(); - } - - public override string GetName() => "Stats"; - public override string GetPath() => "/stats"; - } - - class KillStatsJSON : IPage + class LiveStatsJson : IPage { public string GetName() => "Kill Stats JSON"; public string GetPath() => "/_killstats"; public string GetContentType() => "application/json"; public bool Visible() => false; - public HttpResponse GetPage(NameValueCollection querySet, IDictionary headers) + public async Task GetPage(NameValueCollection querySet, IDictionary headers) { - - int selectCount = Stats.MAX_KILLEVENTS; + // todo: redo this + return await Task.FromResult(new HttpResponse()); + /*int selectCount = Stats.MAX_KILLEVENTS; if (querySet.Get("count") != null) selectCount = Int32.Parse(querySet.Get("count")); @@ -62,7 +42,7 @@ namespace StatsPlugin }, additionalHeaders = new Dictionary() }; - return resp; + return resp;*/ } } } diff --git a/Plugins/SimpleStats/Pages/WordCloudJson.cs b/Plugins/SimpleStats/Pages/WordCloudJson.cs new file mode 100644 index 000000000..614d4f7cb --- /dev/null +++ b/Plugins/SimpleStats/Pages/WordCloudJson.cs @@ -0,0 +1,32 @@ +using SharedLibrary; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Pages +{ + + public class WordCloudJson : IPage + { + public string GetName() => "Word Cloud JSON"; + public string GetPath() => "/_words"; + public string GetContentType() => "application/json"; + public bool Visible() => false; + + public async Task GetPage(NameValueCollection querySet, IDictionary headers) + { + // todo: this + HttpResponse resp = new HttpResponse() + { + contentType = GetContentType(), + content = null, + additionalHeaders = new Dictionary() + }; + + return resp; + } + } +} diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index 412571cce..bc6ff0999 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -10,6 +10,7 @@ using SharedLibrary.Interfaces; using SharedLibrary.Services; using StatsPlugin.Helpers; using StatsPlugin.Models; +using StatsPlugin.Pages; namespace StatsPlugin { @@ -22,6 +23,7 @@ namespace StatsPlugin public string Author => "RaidMax"; private StatManager Manager; + private IManager ServerManager; public async Task OnEventAsync(Event E, Server S) { @@ -39,11 +41,13 @@ namespace StatsPlugin await Manager.RemovePlayer(E.Origin); break; case Event.GType.Say: + if (E.Data != string.Empty) + await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data); break; case Event.GType.MapChange: break; case Event.GType.MapEnd: - await Manager.Sync(); + await Manager.Sync(S); break; case Event.GType.Broadcast: break; @@ -66,7 +70,7 @@ namespace StatsPlugin case Event.GType.Kill: string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill")) - await Manager.AddScriptKill(E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4]); + await Manager.AddScriptKill(E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4]); break; case Event.GType.Death: break; @@ -75,15 +79,11 @@ namespace StatsPlugin public Task OnLoadAsync(IManager manager) { - /* - * - ManagerInstance.GetMessageTokens().Add(new MessageToken("TOTALKILLS", GetTotalKills)); - ManagerInstance.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", GetTotalPlaytime)); -*/ + // todo: is this fast? string totalKills() { var serverStats = new GenericRepository(); - return serverStats.GetQuery(s => s.Active) + return serverStats.Find(s => s.Active) .Sum(c => c.TotalKills).ToString(); } @@ -96,6 +96,13 @@ namespace StatsPlugin manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills)); manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime)); + + WebService.PageList.Add(new ClientMessageJson()); + WebService.PageList.Add(new ClientMessages()); + WebService.PageList.Add(new LiveStats()); + + ServerManager = manager; + return Task.FromResult( Manager = new StatManager(manager) ); @@ -103,14 +110,13 @@ namespace StatsPlugin public async Task OnTickAsync(Server S) { - + } - public Task OnUnloadAsync() + public async Task OnUnloadAsync() { - return Task.FromResult( - Manager = null - ); + foreach (var sv in ServerManager.GetServers()) + await Manager.Sync(sv); } } } diff --git a/Plugins/SimpleStats/StatsPlugin.csproj b/Plugins/SimpleStats/StatsPlugin.csproj index f86f7e4cb..81cfb2d56 100644 --- a/Plugins/SimpleStats/StatsPlugin.csproj +++ b/Plugins/SimpleStats/StatsPlugin.csproj @@ -67,23 +67,28 @@ - - - + + + + + + + + + + - - diff --git a/Plugins/SimpleStats/TrustedGroupCommands.cs b/Plugins/SimpleStats/TrustedGroupCommands.cs deleted file mode 100644 index 98e7b5404..000000000 --- a/Plugins/SimpleStats/TrustedGroupCommands.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using SharedLibrary; -using SharedLibrary.Interfaces; -using SharedLibrary.Helpers; - -namespace StatsPlugin -{ - public class CEnableTrusted : Command - { - public CEnableTrusted() : base("enabletrusted", "enable trusted player group for the server", "et", Player.Permission.Owner, false) { } - - public override async Task ExecuteAsync(Event E) - { - var config = new ConfigurationManager(E.Owner); - if (config.GetProperty("EnableTrusted") == null) - config.AddProperty(new KeyValuePair("EnableTrusted", true)); - else - config.UpdateProperty(new KeyValuePair("EnableTrusted", true)); - - await E.Origin.Tell("Trusted group has been disabled for this server"); - } - } - - public class CDisableTrusted : Command - { - public CDisableTrusted() : base("disabletrusted", "disable trusted player group for the server", "dt", Player.Permission.Owner, false) { } - - public override async Task ExecuteAsync(Event E) - { - var config = new ConfigurationManager(E.Owner); - if (config.GetProperty("EnableTrusted") == null) - config.AddProperty(new KeyValuePair("EnableTrusted", false)); - else - config.UpdateProperty(new KeyValuePair("EnableTrusted", false)); - - await E.Origin.Tell("Trusted group has been disabled for this server"); - } - } -} diff --git a/Plugins/SimpleStats/_Plugin.cs b/Plugins/SimpleStats/_Plugin.cs index d426bfc1e..59cce204b 100644 --- a/Plugins/SimpleStats/_Plugin.cs +++ b/Plugins/SimpleStats/_Plugin.cs @@ -13,145 +13,6 @@ using StatsPlugin.Models; namespace StatsPlugin { - public class CViewStats : Command - { - public CViewStats() : base("stats", "view your stats", "xlrstats", Player.Permission.User, false, new CommandArgument[] - { - new CommandArgument() - { - Name = "player", - Required = false - } - }) - { } - - public override async Task ExecuteAsync(Event E) - { - - if (E.Origin.ClientNumber < 0) - { - await E.Origin.Tell("You must be ingame to view your stats"); - return; - } - - String statLine; - EFClientStatistics pStats; - - if (E.Data.Length > 0 && E.Target == null) - { - await E.Origin.Tell("Cannot find the player you specified"); - return; - } - - if (E.Target != null) - { - pStats = Stats.statLists.Find(x => x.Port == E.Owner.GetPort()).clientStats[E.Origin.ClientNumber]; - statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); - } - - else - { - pStats = Stats.statLists.Find(x => x.Port == E.Owner.GetPort()).clientStats[E.Origin.ClientNumber]; - statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); - } - - if (E.Message.IsBroadcastCommand()) - { - string name = E.Target == null ? E.Origin.Name : E.Target.Name; - await E.Owner.Broadcast($"Stats for ^5{name}^7"); - await E.Owner.Broadcast(statLine); - } - - else - { - if (E.Target != null) - await E.Origin.Tell($"Stats for ^5{E.Target.Name}^7"); - await E.Origin.Tell(statLine); - } - } - } - - public class CViewTopStats : Command - { - public CViewTopStats() : - base("topstats", "view the top 5 players on this server", "ts", Player.Permission.User, false) - { } - - public override async Task ExecuteAsync(Event E) - { - List> pStats = Stats.statLists.Find(x => x.Port == E.Owner.GetPort()).playerStats.GetTopStats(); - StringBuilder msgBlder = new StringBuilder(); - - await E.Origin.Tell("^5--Top Players--"); - foreach (KeyValuePair pStat in pStats) - { - /* Player P = E.Owner.Manager.GetDatabase().GetClient(pStat.Key) as Player; - if (P == null) - continue; - await E.Origin.Tell(String.Format("^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL", P.Name, pStat.Value.KDR, pStat.Value.Skill));*/ - } - } - } - - - public class CResetStats : Command - { - public CResetStats() : base("resetstats", "reset your stats to factory-new", "rs", Player.Permission.User, false) { } - - public override async Task ExecuteAsync(Event E) - { - if (E.Origin.ClientNumber >= 0) - { - var svc = new SharedLibrary.Services.GenericService(); - var stats = Stats.statLists[E.Owner.GetPort()].clientStats[E.Origin.ClientNumber]; - await svc.Delete(stats); - await E.Origin.Tell("Your stats have been reset"); - } - - else - { - await E.Origin.Tell("You must be connected to a server to reset your stats"); - } - } - } - - public class CPruneAdmins : Command - { - public CPruneAdmins() : base("prune", "demote any admins that have not connected recently (defaults to 30 days)", "p", Player.Permission.Owner, false, new CommandArgument[] - { - new CommandArgument() - { - Name = "inactive days", - Required = false - } - }) - { } - - public override async Task ExecuteAsync(Event E) - { - int inactiveDays = 30; - - try - { - if (E.Data.Length > 0) - { - inactiveDays = Int32.Parse(E.Data); - if (inactiveDays < 1) - throw new FormatException(); - } - } - - catch (FormatException) - { - await E.Origin.Tell("Invalid number of inactive days"); - return; - } - - var inactiveAdmins = await E.Owner.Manager.GetDatabase().PruneInactivePrivilegedClients(inactiveDays); - await E.Origin.Tell($"Pruned inactive {inactiveAdmins.Count} privileged users"); - - } - } /// /// Each server runs from the same plugin ( for easier reloading and reduced memory usage ). @@ -181,63 +42,7 @@ namespace StatsPlugin public Queue GetKillQueue() { return KillQueue; } } - public class KillInfo - { - public IW4Info.HitLocation HitLoc { get; set; } - public string HitLocString => HitLoc.ToString(); - public IW4Info.MeansOfDeath DeathType { get; set; } - public string DeathTypeString => DeathType.ToString(); - public int Damage { get; set; } - public IW4Info.WeaponName Weapon { get; set; } - public string WeaponString => Weapon.ToString(); - public Vector3 KillOrigin { get; set; } - public Vector3 DeathOrigin { get; set; } - // http://wiki.modsrepository.com/index.php?title=Call_of_Duty_5:_Gameplay_standards for conversion to meters - public double Distance => Vector3.Distance(KillOrigin, DeathOrigin) * 0.0254; - public string KillerPlayer { get; set; } - public int KillerPlayerID { get; set; } - public string VictimPlayer { get; set; } - public int VictimPlayerID { get; set; } - public IW4Info.MapName Map { get; set; } - public int ID => GetHashCode(); - - public KillInfo() { } - - public KillInfo(int killer, int victim, string map, string hit, string type, string damage, string weapon, string kOrigin, string dOrigin) - { - KillerPlayerID = killer; - VictimPlayerID = victim; - Map = ParseEnum.Get(map, typeof(IW4Info.MapName)); - HitLoc = ParseEnum.Get(hit, typeof(IW4Info.HitLocation)); - DeathType = ParseEnum.Get(type, typeof(IW4Info.MeansOfDeath)); - Damage = Int32.Parse(damage); - Weapon = ParseEnum.Get(weapon, typeof(IW4Info.WeaponName)); - KillOrigin = Vector3.Parse(kOrigin); - DeathOrigin = Vector3.Parse(dOrigin); - } - } - - public static List statLists; - - public class StatTracking - { - public DateTime[] lastKill, connectionTime; - public int[] inactiveMinutes, Kills, deathStreaks, killStreaks; - public int Port; - public Models.EFClientStatistics[] clientStats; - - public StatTracking(int port) - { - clientStats = new Models.EFClientStatistics[18]; - inactiveMinutes = new int[18]; - Kills = new int[18]; - deathStreaks = new int[18]; - killStreaks = new int[18]; - lastKill = new DateTime[18]; - connectionTime = new DateTime[18]; - Port = port; - } - } + public string Name => "Basic Stats"; @@ -365,214 +170,9 @@ namespace StatsPlugin ServerStats[S.GetPort()].GetKillQueue().Clear(); ServerStats[S.GetPort()].RoundStartTime = DateTime.Now; } - - if (E.Type == Event.GType.Disconnect) - { - CalculateAndSaveSkill(E.Origin, statLists.Find(x => x.Port == S.GetPort())); - ResetCounters(E.Origin.ClientNumber, S.GetPort()); - E.Owner.Logger.WriteInfo($"Updated skill for disconnecting client {E.Origin}"); - } - - if (E.Type == Event.GType.Kill) - { - if (E.Origin == E.Target || E.Origin == null) - return; - - string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; - - if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill")) - { - var killEvent = new KillInfo(E.Origin.ClientNumber, E.Target.ClientNumber, S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4]) - { - KillerPlayer = E.Origin.Name, - VictimPlayer = E.Target.Name, - }; - - if (ServerStats[S.GetPort()].GetKillQueue().Count > MAX_KILLEVENTS - 1) - ServerStats[S.GetPort()].GetKillQueue().Dequeue(); - ServerStats[S.GetPort()].GetKillQueue().Enqueue(killEvent); - //S.Logger.WriteInfo($"{E.Origin.Name} killed {E.Target.Name} with a {killEvent.Weapon} from a distance of {Vector3.Distance(killEvent.KillOrigin, killEvent.DeathOrigin)} with {killEvent.Damage} damage, at {killEvent.HitLoc}"); - var cs = statLists.Find(x => x.Port == S.GetPort()); - cs.playerStats.AddKill(killEvent); - } - - Player Killer = E.Origin; - StatTracking curServer = statLists.Find(x => x.Port == S.GetPort()); - var killerStats = curServer.clientStats[] - - if (killerStats == null) - killerStats = new PlayerStats(0, 0, 0, 0, 0, 0); - - curServer.lastKill[E.Origin.ClientNumber] = DateTime.Now; - curServer.Kills[E.Origin.ClientNumber]++; - - if ((DateTime.Now - curServer.lastKill[E.Origin.ClientNumber]).TotalSeconds > 120) - curServer.inactiveMinutes[E.Origin.ClientNumber] += 2; - - killerStats.Kills++; - - killerStats.KDR = (killerStats.Deaths == 0) ? killerStats.Kills : killerStats.KDR = Math.Round((double)killerStats.Kills / (double)killerStats.Deaths, 2); - - - - curServer.playerStats.UpdateStats(Killer, killerStats); - - curServer.killStreaks[Killer.ClientNumber] += 1; - curServer.deathStreaks[Killer.ClientNumber] = 0; - - await Killer.Tell(MessageOnStreak(curServer.killStreaks[Killer.ClientNumber], curServer.deathStreaks[Killer.ClientNumber])); - } - - if (E.Type == Event.GType.Death) - { - if (E.Origin == E.Target || E.Origin == null) - return; - - Player Victim = E.Origin; - StatTracking curServer = statLists.Find(x => x.Port == S.GetPort()); - PlayerStats victimStats = curServer.playerStats.GetStats(Victim); - - if (victimStats == null) - victimStats = new PlayerStats(0, 0, 0, 0, 0, 0); - - victimStats.Deaths++; - victimStats.KDR = Math.Round(victimStats.Kills / (double)victimStats.Deaths, 2); - - curServer.playerStats.UpdateStats(Victim, victimStats); - - curServer.deathStreaks[Victim.ClientNumber] += 1; - curServer.killStreaks[Victim.ClientNumber] = 0; - - await Victim.Tell(MessageOnStreak(curServer.killStreaks[Victim.ClientNumber], curServer.deathStreaks[Victim.ClientNumber])); - } - - if (E.Type == Event.GType.Say) - { - ChatDB.AddChatHistory(E.Origin.ClientNumber, E.Owner.GetPort(), E.Data); - } } - - catch (Exception e) - { - S.Logger.WriteWarning("StatsPlugin::OnEventAsync failed to complete"); - S.Logger.WriteDebug($"Server:{S}\r\nOrigin:{E.Origin}\r\nTarget:{E.Target}"); - S.Logger.WriteDebug($"Exception: {e.Message}"); - } - } - - public static string GetTotalKills() - { - long Kills = 0; - foreach (var S in statLists) - Kills += S.playerStats.GetTotalServerKills(); - return Kills.ToString("#,##0"); - } - - public static string GetTotalPlaytime() - { - long Playtime = 0; - foreach (var S in statLists) - Playtime += S.playerStats.GetTotalServerPlaytime(); - return Playtime.ToString("#,##0"); - } - - private void CalculateAndSaveSkill(Player P, StatTracking curServer) - { - if (P == null) - return; - - var DisconnectingPlayerStats = curServer.clientStats[P.ClientNumber]; - - if (curServer.Kills[P.ClientNumber] == 0) - return; - - //else if (curServer.lastKill[P.ClientNumber] > curServer.connectionTime[P.ClientNumber]) - // curServer.inactiveMinutes[P.ClientNumber] += (int)(DateTime.Now - curServer.lastKill[P.ClientNumber]).TotalMinutes; - - int newPlayTime = (int)(DateTime.Now - P.LastConnection).TotalMinutes; - // (int)(DateTime.Now - curServer.connectionTime[P.ClientNumber]).TotalMinutes - curServer.inactiveMinutes[P.ClientNumber]; - // calculate the players Score Per Minute for the current session - double SessionSPM = curServer.Kills[P.ClientNumber] * 100 / Math.Max(1, newPlayTime); - // calculate how much the KDR should way - // 1.637 is a Eddie-Generated number that weights the KDR nicely - double KDRWeight = Math.Round(Math.Pow(DisconnectingPlayerStats.KDR, 1.637 / Math.E), 3); - double SPMWeightAgainstAverage; - - // if no SPM, weight is 1 else the weight is the current sessions spm / lifetime average score per minute - SPMWeightAgainstAverage = (DisconnectingPlayerStats.SPM == 1) ? 1 : SessionSPM / DisconnectingPlayerStats.SPM; - - // calculate the weight of the new play time againmst lifetime playtime - double SPMAgainstPlayWeight = newPlayTime / Math.Min(600, P.TotalConnectionTime + newPlayTime); - // calculate the new weight against average times the weight against play time - double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight * SessionSPM; - - // if the weight is greater than 1, add, else subtract - DisconnectingPlayerStats.SPM += (SPMWeightAgainstAverage >= 1) ? newSkillFactor : -newSkillFactor; - - DisconnectingPlayerStats.Skill = DisconnectingPlayerStats.SPM * KDRWeight * 10; - - ClientStatsSvc.Update(DisconnectingPlayerStats); - } - - private void ResetCounters(int cID, int serverPort) - { - StatTracking selectedPlayers = statLists.Find(x => x.Port == serverPort); - - if (selectedPlayers == null) - return; - - selectedPlayers.Kills[cID] = 0; - selectedPlayers.connectionTime[cID] = DateTime.Now; - selectedPlayers.inactiveMinutes[cID] = 0; - selectedPlayers.deathStreaks[cID] = 0; - selectedPlayers.killStreaks[cID] = 0; - } - - private String MessageOnStreak(int killStreak, int deathStreak) - { - String Message = ""; - switch (killStreak) - { - case 5: - Message = "Great job! You're on a ^55 killstreak!"; - break; - case 10: - Message = "Amazing! ^510 kills ^7without dying!"; - break; - } - - switch (deathStreak) - { - case 5: - Message = "Pick it up soldier, you've died ^55 times ^7in a row..."; - break; - case 10: - Message = "Seriously? ^510 deaths ^7without getting a kill?"; - break; - } - - return Message; - } } + - public class PlayerStats - { - public PlayerStats(int K, int D, double DR, double S, double sc, int P) - { - Kills = K; - Deaths = D; - KDR = DR; - Skill = S; - scorePerMinute = sc; - TotalPlayTime = P; - } - - public int Kills; - public int Deaths; - public double KDR; - public double Skill; - public double scorePerMinute; - public int TotalPlayTime; - } -} \ No newline at end of file + \ No newline at end of file diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index c306e0653..4eae89f6c 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -7,7 +7,9 @@ using System.Threading.Tasks; using SharedLibrary.Network; using SharedLibrary.Helpers; using SharedLibrary.Objects; - +using SharedLibrary.Database; +using System.Data.Entity; +using SharedLibrary.Database.Models; namespace SharedLibrary.Commands { @@ -917,4 +919,56 @@ namespace SharedLibrary.Commands await E.Origin.Tell($"Your external IP is ^5{E.Origin.IPAddress}"); } } + + public class CPruneAdmins : Command + { + public CPruneAdmins() : base("prune", "demote any admins that have not connected recently (defaults to 30 days)", "p", Player.Permission.Owner, false, new CommandArgument[] + { + new CommandArgument() + { + Name = "inactive days", + Required = false + } + }) + { } + + public override async Task ExecuteAsync(Event E) + { + int inactiveDays = 30; + + try + { + if (E.Data.Length > 0) + { + inactiveDays = Int32.Parse(E.Data); + if (inactiveDays < 1) + throw new FormatException(); + } + } + + catch (FormatException) + { + await E.Origin.Tell("Invalid number of inactive days"); + return; + } + + List inactiveUsers = null; + + // update user roles + using (var context = new DatabaseContext()) + { + var lastActive = DateTime.UtcNow.AddDays(-inactiveDays); + inactiveUsers = await context.Clients + .Where(c => c.Level > Player.Permission.Flagged && c.Level <= Player.Permission.Moderator) + .Where(c => c.LastConnection < lastActive) + .ToListAsync(); + inactiveUsers.ForEach(c => c.Level = Player.Permission.User); + await context.SaveChangesAsync(); + } + await E.Origin.Tell($"Pruned inactive {inactiveUsers.Count} privileged users"); + + } + } } + + diff --git a/SharedLibrary/Database/DatabaseContext.cs b/SharedLibrary/Database/DatabaseContext.cs index 5743b2589..f6f8763b2 100644 --- a/SharedLibrary/Database/DatabaseContext.cs +++ b/SharedLibrary/Database/DatabaseContext.cs @@ -21,7 +21,7 @@ namespace SharedLibrary.Database public DatabaseContext() : base("DefaultConnection") { System.Data.Entity.Database.SetInitializer(new Initializer()); - Configuration.LazyLoadingEnabled = false; + Configuration.LazyLoadingEnabled = true; } protected override void OnModelCreating(DbModelBuilder modelBuilder) diff --git a/SharedLibrary/Helpers/AsyncStatus.cs b/SharedLibrary/Helpers/AsyncStatus.cs index 73da78a63..6162f85d8 100644 --- a/SharedLibrary/Helpers/AsyncStatus.cs +++ b/SharedLibrary/Helpers/AsyncStatus.cs @@ -9,17 +9,17 @@ namespace SharedLibrary.Helpers { public sealed class AsyncStatus { - CancellationToken Token; DateTime StartTime; int TimesRun; int UpdateFrequency; public double RunAverage { get; private set; } public object Dependant { get; private set; } public Task RequestedTask { get; private set; } + public CancellationTokenSource TokenSrc { get; private set; } public AsyncStatus(object dependant, int frequency) { - Token = new CancellationToken(); + TokenSrc = new CancellationTokenSource(); StartTime = DateTime.Now; Dependant = dependant; UpdateFrequency = frequency; @@ -29,7 +29,7 @@ namespace SharedLibrary.Helpers public CancellationToken GetToken() { - return Token; + return TokenSrc.Token; } public double ElapsedMillisecondsTime() @@ -39,6 +39,10 @@ namespace SharedLibrary.Helpers public void Update(Task T) { + // reset the token source + TokenSrc.Dispose(); + TokenSrc = new CancellationTokenSource(); + RequestedTask = T; // Console.WriteLine($"Starting Task {T.Id} "); RequestedTask.Start(); diff --git a/SharedLibrary/RCON.cs b/SharedLibrary/RCON.cs index c1b7f8b52..e4562cdeb 100644 --- a/SharedLibrary/RCON.cs +++ b/SharedLibrary/RCON.cs @@ -26,77 +26,78 @@ namespace SharedLibrary.Network static string[] SendQuery(QueryType Type, Server QueryServer, string Parameters = "") { - if ((DateTime.Now - LastQuery).TotalMilliseconds < 300) - Task.Delay(300).Wait(); - LastQuery = DateTime.Now; - var ServerOOBConnection = new UdpClient(); - ServerOOBConnection.Client.SendTimeout = 1000; - ServerOOBConnection.Client.ReceiveTimeout = 1000; - var Endpoint = new IPEndPoint(IPAddress.Parse(QueryServer.GetIP()), QueryServer.GetPort()); - - string QueryString = String.Empty; - - switch (Type) + using (var ServerOOBConnection = new UdpClient()) { - case QueryType.DVAR: - case QueryType.COMMAND: - QueryString = $"ÿÿÿÿrcon {QueryServer.Password} {Parameters}"; - break; - case QueryType.GET_STATUS: - QueryString = "ÿÿÿÿ getstatus"; - break; - } + // prevent flooding + if ((DateTime.Now - LastQuery).TotalMilliseconds < 300) + Task.Delay(300).Wait(); + LastQuery = DateTime.Now; - byte[] Payload = GetRequestBytes(QueryString); + ServerOOBConnection.Client.SendTimeout = 1000; + ServerOOBConnection.Client.ReceiveTimeout = 1000; + var Endpoint = new IPEndPoint(IPAddress.Parse(QueryServer.GetIP()), QueryServer.GetPort()); - int attempts = 0; - retry: + string QueryString = String.Empty; - try - { - ServerOOBConnection.Connect(Endpoint); - ServerOOBConnection.Send(Payload, Payload.Length); - - byte[] ReceiveBuffer = new byte[8192]; - StringBuilder QueryResponseString = new StringBuilder(); - - do + switch (Type) { - ReceiveBuffer = ServerOOBConnection.Receive(ref Endpoint); - QueryResponseString.Append(Encoding.ASCII.GetString(ReceiveBuffer).TrimEnd('\0')); - } while (ServerOOBConnection.Available > 0 && ServerOOBConnection.Client.Connected); - - ServerOOBConnection.Close(); - - if (QueryResponseString.ToString().Contains("Invalid password")) - throw new Exceptions.NetworkException("RCON password is invalid"); - if (QueryResponseString.ToString().Contains("rcon_password")) - throw new Exceptions.NetworkException("RCON password has not been set"); - - int num = int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier); - string[] SplitResponse = QueryResponseString.ToString().Split(new char[] { (char)num }, StringSplitOptions.RemoveEmptyEntries); - return SplitResponse; - } - - catch (Exceptions.NetworkException e) - { - throw e; - } - - catch (Exception e) - { - attempts++; - if (attempts > 2) - { - var ne = new Exceptions.NetworkException("Could not communicate with the server"); - ne.Data["internal_exception"] = e.Message; - ne.Data["server_address"] = ServerOOBConnection.Client.RemoteEndPoint.ToString(); - ServerOOBConnection.Close(); - throw ne; + case QueryType.DVAR: + case QueryType.COMMAND: + QueryString = $"ÿÿÿÿrcon {QueryServer.Password} {Parameters}"; + break; + case QueryType.GET_STATUS: + QueryString = "ÿÿÿÿ getstatus"; + break; } - Thread.Sleep(1000); - goto retry; + byte[] Payload = GetRequestBytes(QueryString); + + int attempts = 0; + retry: + + try + { + ServerOOBConnection.Connect(Endpoint); + ServerOOBConnection.Send(Payload, Payload.Length); + + byte[] ReceiveBuffer = new byte[8192]; + StringBuilder QueryResponseString = new StringBuilder(); + + do + { + ReceiveBuffer = ServerOOBConnection.Receive(ref Endpoint); + QueryResponseString.Append(Encoding.ASCII.GetString(ReceiveBuffer).TrimEnd('\0')); + } while (ServerOOBConnection.Available > 0 && ServerOOBConnection.Client.Connected); + + if (QueryResponseString.ToString().Contains("Invalid password")) + throw new Exceptions.NetworkException("RCON password is invalid"); + if (QueryResponseString.ToString().Contains("rcon_password")) + throw new Exceptions.NetworkException("RCON password has not been set"); + + int num = int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier); + string[] SplitResponse = QueryResponseString.ToString().Split(new char[] { (char)num }, StringSplitOptions.RemoveEmptyEntries); + return SplitResponse; + } + + catch (Exceptions.NetworkException e) + { + throw e; + } + + catch (Exception e) + { + attempts++; + if (attempts > 2) + { + var ne = new Exceptions.NetworkException("Could not communicate with the server"); + ne.Data["internal_exception"] = e.Message; + ne.Data["server_address"] = ServerOOBConnection.Client.RemoteEndPoint.ToString(); + throw ne; + } + + Thread.Sleep(1000); + goto retry; + } } } diff --git a/SharedLibrary/ServerConfiguration.cs b/SharedLibrary/ServerConfiguration.cs index 5e8b6f7d9..2b6aa0c3c 100644 --- a/SharedLibrary/ServerConfiguration.cs +++ b/SharedLibrary/ServerConfiguration.cs @@ -9,6 +9,7 @@ namespace SharedLibrary public string Password; public string FtpPrefix; public bool AllowMultipleOwners; + public bool AllowTrustedRank; public override string Filename() { diff --git a/SharedLibrary/Services/GenericRepository.cs b/SharedLibrary/Services/GenericRepository.cs index e58f9e26d..6ef449355 100644 --- a/SharedLibrary/Services/GenericRepository.cs +++ b/SharedLibrary/Services/GenericRepository.cs @@ -41,11 +41,17 @@ namespace SharedLibrary.Services } } + public virtual async Task> FindAsync(Expression> predicate, Func, IOrderedQueryable> orderExpression = null) + { + return await this.GetQuery(predicate, orderExpression).ToListAsync(); + } + public virtual IEnumerable Find(Expression> predicate, Func, IOrderedQueryable> orderExpression = null) { return this.GetQuery(predicate, orderExpression).AsEnumerable(); } + public virtual IQueryable GetQuery(Expression> predicate = null, Func, IOrderedQueryable> orderExpression = null) { IQueryable qry = this.DBSet; @@ -131,16 +137,10 @@ namespace SharedLibrary.Services this.Context.SaveChanges(); } - public virtual async Task SaveChangesAsync() + public virtual Task SaveChangesAsync() { - try - { - await this.Context.SaveChangesAsync(); - } - catch (Exception e) - { - throw e; - } + return this.Context.SaveChangesAsync(); } + } } diff --git a/SharedLibrary/WebService.cs b/SharedLibrary/WebService.cs index 7b1bcc126..921e2c606 100644 --- a/SharedLibrary/WebService.cs +++ b/SharedLibrary/WebService.cs @@ -87,8 +87,8 @@ namespace SharedLibrary { return new Dictionary(); } + abstract public string GetContent(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers); - public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) {