More stats polishing
fixed player specification for commands with multiple words
This commit is contained in:
parent
f929e606f4
commit
b9900707b5
@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
#define USINGMEMORY
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using SharedLibrary;
|
using SharedLibrary;
|
||||||
|
@ -199,6 +199,12 @@ namespace IW4MAdmin
|
|||||||
var Status = TaskStatuses[i];
|
var Status = TaskStatuses[i];
|
||||||
if (Status.RequestedTask == null || Status.RequestedTask.Status == TaskStatus.RanToCompletion)
|
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<bool>(() => { return (Status.Dependant as Server).ProcessUpdatesAsync(Status.GetToken()).Result; }));
|
Status.Update(new Task<bool>(() => { return (Status.Dependant as Server).ProcessUpdatesAsync(Status.GetToken()).Result; }));
|
||||||
if (Status.RunAverage > 1000 + UPDATE_FREQUENCY)
|
if (Status.RunAverage > 1000 + UPDATE_FREQUENCY)
|
||||||
Logger.WriteWarning($"Update task average execution is longer than desired for {(Status.Dependant as Server)} [{Status.RunAverage}ms]");
|
Logger.WriteWarning($"Update task average execution is longer than desired for {(Status.Dependant as Server)} [{Status.RunAverage}ms]");
|
||||||
|
@ -34,6 +34,7 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
// update their ping
|
// update their ping
|
||||||
Players[polledPlayer.ClientNumber].Ping = polledPlayer.Ping;
|
Players[polledPlayer.ClientNumber].Ping = polledPlayer.Ping;
|
||||||
|
Players[polledPlayer.ClientNumber].Score = polledPlayer.Score;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +113,7 @@ namespace IW4MAdmin
|
|||||||
// NewPlayer.Level = Player.Permission.Flagged;
|
// NewPlayer.Level = Player.Permission.Flagged;
|
||||||
// Do the player specific stuff
|
// Do the player specific stuff
|
||||||
player.ClientNumber = polledPlayer.ClientNumber;
|
player.ClientNumber = polledPlayer.ClientNumber;
|
||||||
|
player.Score = polledPlayer.Score;
|
||||||
Players[player.ClientNumber] = player;
|
Players[player.ClientNumber] = player;
|
||||||
Logger.WriteInfo($"Client {player} connecting...");
|
Logger.WriteInfo($"Client {player} connecting...");
|
||||||
|
|
||||||
@ -210,7 +212,15 @@ namespace IW4MAdmin
|
|||||||
if (C.RequiresTarget || Args.Length > 0)
|
if (C.RequiresTarget || Args.Length > 0)
|
||||||
{
|
{
|
||||||
int cNum = -1;
|
int cNum = -1;
|
||||||
int.TryParse(Args[0], out cNum);
|
try
|
||||||
|
{
|
||||||
|
cNum = Convert.ToInt32(Args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(FormatException)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (Args[0][0] == '@') // user specifying target by database ID
|
if (Args[0][0] == '@') // user specifying target by database ID
|
||||||
{
|
{
|
||||||
@ -227,7 +237,7 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Args[0].Length < 3 && cNum > -1 && cNum < 18) // user specifying target by client num
|
else if (Args[0].Length < 3 && cNum > -1 && cNum < MaxClients) // user specifying target by client num
|
||||||
{
|
{
|
||||||
if (Players[cNum] != null)
|
if (Players[cNum] != null)
|
||||||
{
|
{
|
||||||
@ -250,6 +260,13 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
E.Target = matchingPlayers.First();
|
E.Target = matchingPlayers.First();
|
||||||
E.Data = Regex.Replace(E.Data, $"\"{E.Target.Name}\"", "", RegexOptions.IgnoreCase).Trim();
|
E.Data = Regex.Replace(E.Data, $"\"{E.Target.Name}\"", "", RegexOptions.IgnoreCase).Trim();
|
||||||
|
|
||||||
|
if (E.Data.ToLower().Trim() == E.Target.Name.ToLower().Trim())
|
||||||
|
{
|
||||||
|
await E.Origin.Tell($"Not enough arguments supplied!");
|
||||||
|
await E.Origin.Tell(C.Syntax);
|
||||||
|
throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +284,13 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
E.Target = matchingPlayers.First();
|
E.Target = matchingPlayers.First();
|
||||||
E.Data = Regex.Replace(E.Data, $"{E.Target.Name}", "", RegexOptions.IgnoreCase).Trim();
|
E.Data = Regex.Replace(E.Data, $"{E.Target.Name}", "", RegexOptions.IgnoreCase).Trim();
|
||||||
|
|
||||||
|
if (E.Data.Trim() == E.Target.Name.ToLower().Trim())
|
||||||
|
{
|
||||||
|
await E.Origin.Tell($"Not enough arguments supplied!");
|
||||||
|
await E.Origin.Tell(C.Syntax);
|
||||||
|
throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -11,11 +11,13 @@ namespace StatsPlugin.Helpers
|
|||||||
public class ServerStats
|
public class ServerStats
|
||||||
{
|
{
|
||||||
public Dictionary<int, EFClientStatistics> PlayerStats { get; set; }
|
public Dictionary<int, EFClientStatistics> PlayerStats { get; set; }
|
||||||
|
public EFServerStatistics ServerStatistics { get; private set; }
|
||||||
public EFServer Server { get; private set; }
|
public EFServer Server { get; private set; }
|
||||||
|
|
||||||
public ServerStats(EFServer sv)
|
public ServerStats(EFServer sv, EFServerStatistics st)
|
||||||
{
|
{
|
||||||
PlayerStats = new Dictionary<int, EFClientStatistics>();
|
PlayerStats = new Dictionary<int, EFClientStatistics>();
|
||||||
|
ServerStatistics = st;
|
||||||
Server = sv;
|
Server = sv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SharedLibrary;
|
using SharedLibrary;
|
||||||
using SharedLibrary.Helpers;
|
using SharedLibrary.Helpers;
|
||||||
@ -19,7 +18,8 @@ namespace StatsPlugin.Helpers
|
|||||||
private IManager Manager;
|
private IManager Manager;
|
||||||
private GenericRepository<EFClientStatistics> ClientStatSvc;
|
private GenericRepository<EFClientStatistics> ClientStatSvc;
|
||||||
private GenericRepository<EFServer> ServerSvc;
|
private GenericRepository<EFServer> ServerSvc;
|
||||||
private GenericRepository<EFClientKill> KillSvc;
|
private GenericRepository<EFClientKill> KillStatsSvc;
|
||||||
|
private GenericRepository<EFServerStatistics> ServerStatsSvc;
|
||||||
|
|
||||||
public StatManager(IManager mgr)
|
public StatManager(IManager mgr)
|
||||||
{
|
{
|
||||||
@ -28,13 +28,13 @@ namespace StatsPlugin.Helpers
|
|||||||
Manager = mgr;
|
Manager = mgr;
|
||||||
ClientStatSvc = new GenericRepository<EFClientStatistics>();
|
ClientStatSvc = new GenericRepository<EFClientStatistics>();
|
||||||
ServerSvc = new GenericRepository<EFServer>();
|
ServerSvc = new GenericRepository<EFServer>();
|
||||||
KillSvc = new GenericRepository<EFClientKill>();
|
KillStatsSvc = new GenericRepository<EFClientKill>();
|
||||||
|
ServerStatsSvc = new GenericRepository<EFServerStatistics>();
|
||||||
}
|
}
|
||||||
|
|
||||||
~StatManager()
|
~StatManager()
|
||||||
{
|
{
|
||||||
Servers.Clear();
|
Servers.Clear();
|
||||||
Log.WriteInfo("Cleared StatManager servers");
|
|
||||||
Log = null;
|
Log = null;
|
||||||
Servers = null;
|
Servers = null;
|
||||||
}
|
}
|
||||||
@ -48,6 +48,7 @@ namespace StatsPlugin.Helpers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
int serverId = sv.GetHashCode();
|
int serverId = sv.GetHashCode();
|
||||||
|
|
||||||
// get the server from the database if it exists, otherwise create and insert a new one
|
// 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 = ServerSvc.Find(c => c.ServerId == serverId).FirstOrDefault();
|
||||||
if (server == null)
|
if (server == null)
|
||||||
@ -64,7 +65,13 @@ namespace StatsPlugin.Helpers
|
|||||||
|
|
||||||
// this doesn't need to be async as it's during initialization
|
// this doesn't need to be async as it's during initialization
|
||||||
ServerSvc.SaveChanges();
|
ServerSvc.SaveChanges();
|
||||||
Servers.Add(sv.GetHashCode(), new ServerStats(server));
|
InitializeServerStats(sv);
|
||||||
|
ServerStatsSvc.SaveChanges();
|
||||||
|
|
||||||
|
var serverStats = ServerStatsSvc.Find(c => c.ServerId == serverId).FirstOrDefault();
|
||||||
|
// check to see if the stats have ever been initialized
|
||||||
|
|
||||||
|
Servers.Add(serverId, new ServerStats(server, serverStats));
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -102,6 +109,10 @@ namespace StatsPlugin.Helpers
|
|||||||
clientStats = ClientStatSvc.Insert(clientStats);
|
clientStats = ClientStatSvc.Insert(clientStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set these on connecting
|
||||||
|
clientStats.LastActive = DateTime.UtcNow;
|
||||||
|
clientStats.LastStatCalculation = DateTime.UtcNow;
|
||||||
|
|
||||||
lock (playerStats)
|
lock (playerStats)
|
||||||
{
|
{
|
||||||
if (playerStats.ContainsKey(pl.ClientNumber))
|
if (playerStats.ContainsKey(pl.ClientNumber))
|
||||||
@ -123,17 +134,9 @@ namespace StatsPlugin.Helpers
|
|||||||
// remove the client from the stats dictionary as they're leaving
|
// remove the client from the stats dictionary as they're leaving
|
||||||
lock (playerStats)
|
lock (playerStats)
|
||||||
playerStats.Remove(pl.ClientNumber);
|
playerStats.Remove(pl.ClientNumber);
|
||||||
// allow accessing certain properties
|
|
||||||
//clientStats.Client = pl;
|
var serverStats = ServerStatsSvc.Find(sv => sv.ServerId == serverId).FirstOrDefault();
|
||||||
// update skill
|
serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds;
|
||||||
// clientStats = UpdateStats(clientStats);
|
|
||||||
// reset for EF cache
|
|
||||||
//clientStats.SessionDeaths = 0;
|
|
||||||
// clientStats.SessionKills = 0;
|
|
||||||
// prevent mismatched primary key
|
|
||||||
//clientStats.Client = null;
|
|
||||||
// update in database
|
|
||||||
//await ClientStatSvc.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -160,18 +163,29 @@ namespace StatsPlugin.Helpers
|
|||||||
Weapon = ParseEnum<IW4Info.WeaponName>.Get(weapon, typeof(IW4Info.WeaponName))
|
Weapon = ParseEnum<IW4Info.WeaponName>.Get(weapon, typeof(IW4Info.WeaponName))
|
||||||
};
|
};
|
||||||
|
|
||||||
KillSvc.Insert(kill);
|
KillStatsSvc.Insert(kill);
|
||||||
await KillSvc.SaveChangesAsync();
|
await KillStatsSvc.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddStandardKill(Player attacker, Player victim)
|
public void AddStandardKill(Player attacker, Player victim)
|
||||||
{
|
{
|
||||||
var attackerStats = Servers[attacker.CurrentServer.GetHashCode()].PlayerStats[attacker.ClientNumber];
|
int serverId = attacker.CurrentServer.GetHashCode();
|
||||||
// set to access total time
|
var attackerStats = Servers[serverId].PlayerStats[attacker.ClientNumber];
|
||||||
|
// set to access total time played
|
||||||
attackerStats.Client = attacker;
|
attackerStats.Client = attacker;
|
||||||
var victimStats = Servers[victim.CurrentServer.GetHashCode()].PlayerStats[victim.ClientNumber];
|
var victimStats = Servers[serverId].PlayerStats[victim.ClientNumber];
|
||||||
|
|
||||||
|
// update the total stats
|
||||||
|
Servers[serverId].ServerStatistics.TotalKills += 1;
|
||||||
|
|
||||||
|
// calculate for the clients
|
||||||
CalculateKill(attackerStats, victimStats);
|
CalculateKill(attackerStats, victimStats);
|
||||||
|
|
||||||
|
// immediately write changes in debug
|
||||||
|
#if DEBUG
|
||||||
|
ClientStatSvc.SaveChanges();
|
||||||
|
ServerStatsSvc.SaveChanges();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -195,10 +209,9 @@ namespace StatsPlugin.Helpers
|
|||||||
UpdateStats(attackerStats);
|
UpdateStats(attackerStats);
|
||||||
attackerStats.Client = null;
|
attackerStats.Client = null;
|
||||||
|
|
||||||
// immediately write changes in debug
|
// update after calculation
|
||||||
#if DEBUG
|
attackerStats.LastActive = DateTime.UtcNow;
|
||||||
ClientStatSvc.SaveChanges();
|
victimStats.LastActive = DateTime.UtcNow;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -208,44 +221,83 @@ namespace StatsPlugin.Helpers
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private EFClientStatistics UpdateStats(EFClientStatistics clientStats)
|
private EFClientStatistics UpdateStats(EFClientStatistics clientStats)
|
||||||
{
|
{
|
||||||
// if it's their first kill we need to set the last kill as the time they joined
|
|
||||||
clientStats.LastStatCalculation = (clientStats.LastStatCalculation == DateTime.MinValue) ? DateTime.UtcNow : clientStats.LastStatCalculation;
|
|
||||||
double timeSinceLastCalc = (DateTime.UtcNow - clientStats.LastStatCalculation).TotalSeconds / 60.0;
|
double timeSinceLastCalc = (DateTime.UtcNow - clientStats.LastStatCalculation).TotalSeconds / 60.0;
|
||||||
|
double timeSinceLastActive = (DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0;
|
||||||
|
|
||||||
// each 'session' is one minute
|
// prevent NaN or inactive time lowering SPM
|
||||||
if (timeSinceLastCalc >= 1)
|
if (timeSinceLastCalc == 0 || timeSinceLastActive > 3)
|
||||||
{
|
return clientStats;
|
||||||
Log.WriteDebug($"Updated stats for {clientStats.ClientId} ({clientStats.SessionKills})");
|
|
||||||
// calculate the players Score Per Minute for the current session
|
|
||||||
// todo: score should be based on gamemode
|
|
||||||
double killSPM = clientStats.SessionKills * 100.0;
|
|
||||||
|
|
||||||
// calculate how much the KDR should weigh
|
// calculate the players Score Per Minute for the current session
|
||||||
// 1.637 is a Eddie-Generated number that weights the KDR nicely
|
int currentScore = Manager.GetActiveClients()
|
||||||
double KDRWeight = Math.Round(Math.Pow(clientStats.KDR, 1.637 / Math.E), 3);
|
.First(c => c.ClientId == clientStats.ClientId)
|
||||||
|
.Score;
|
||||||
|
double killSPM = currentScore / (timeSinceLastCalc * 60.0);
|
||||||
|
|
||||||
// if no SPM, weight is 1 else the weight ishe current session's spm / lifetime average score per minute
|
// calculate how much the KDR should weigh
|
||||||
double SPMWeightAgainstAverage = (clientStats.SPM < 1) ? 1 : killSPM / clientStats.SPM;
|
// 1.637 is a Eddie-Generated number that weights the KDR nicely
|
||||||
|
double KDRWeight = Math.Round(Math.Pow(clientStats.KDR, 1.637 / Math.E), 3);
|
||||||
|
|
||||||
// calculate the weight of the new play time against last 10 hours of gameplay
|
// if no SPM, weight is 1 else the weight ishe current session's spm / lifetime average score per minute
|
||||||
int totalConnectionTime = (clientStats.Client.TotalConnectionTime == 0) ?
|
double SPMWeightAgainstAverage = (clientStats.SPM < 1) ? 1 : killSPM / clientStats.SPM;
|
||||||
(int)(DateTime.UtcNow - clientStats.Client.FirstConnection).TotalSeconds :
|
|
||||||
clientStats.Client.TotalConnectionTime + (int)(DateTime.UtcNow - clientStats.Client.LastConnection).TotalSeconds;
|
|
||||||
|
|
||||||
double SPMAgainstPlayWeight = timeSinceLastCalc / Math.Min(600, (totalConnectionTime / 60.0));
|
// calculate the weight of the new play time against last 10 hours of gameplay
|
||||||
|
int totalConnectionTime = (clientStats.Client.TotalConnectionTime == 0) ?
|
||||||
|
(int)(DateTime.UtcNow - clientStats.Client.FirstConnection).TotalSeconds :
|
||||||
|
clientStats.Client.TotalConnectionTime + (int)(DateTime.UtcNow - clientStats.Client.LastConnection).TotalSeconds;
|
||||||
|
|
||||||
// calculate the new weight against average times the weight against play time
|
double SPMAgainstPlayWeight = timeSinceLastCalc / Math.Min(600, (totalConnectionTime / 60.0));
|
||||||
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
|
||||||
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
|
||||||
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight) / 10.0, 3);
|
|
||||||
|
|
||||||
clientStats.SessionKills = 0;
|
// calculate the new weight against average times the weight against play time
|
||||||
clientStats.SessionDeaths = 0;
|
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
||||||
|
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
||||||
|
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
||||||
|
|
||||||
clientStats.LastStatCalculation = DateTime.UtcNow;
|
clientStats.LastStatCalculation = DateTime.UtcNow;
|
||||||
}
|
clientStats.LastScore = currentScore;
|
||||||
|
|
||||||
return clientStats;
|
return clientStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InitializeServerStats(Server sv)
|
||||||
|
{
|
||||||
|
int serverId = sv.GetHashCode();
|
||||||
|
var serverStats = ServerStatsSvc.Find(s => s.ServerId == serverId).FirstOrDefault();
|
||||||
|
if (serverStats == null)
|
||||||
|
{
|
||||||
|
Log.WriteDebug($"Initializing server stats for {sv}");
|
||||||
|
// server stats have never been generated before
|
||||||
|
serverStats = new EFServerStatistics()
|
||||||
|
{
|
||||||
|
Active = true,
|
||||||
|
ServerId = serverId,
|
||||||
|
TotalKills = 0,
|
||||||
|
TotalPlayTime = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var ieClientStats = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Sync()
|
||||||
|
{
|
||||||
|
Log.WriteDebug("Syncing server stats");
|
||||||
|
await ServerStatsSvc.SaveChangesAsync();
|
||||||
|
|
||||||
|
Log.WriteDebug("Syncing client stats");
|
||||||
|
await ClientStatSvc.SaveChangesAsync();
|
||||||
|
|
||||||
|
Log.WriteDebug("Syncing kill stats");
|
||||||
|
await KillStatsSvc.SaveChangesAsync();
|
||||||
|
|
||||||
|
Log.WriteDebug("Syncing servers");
|
||||||
|
await ServerSvc.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
Plugins/SimpleStats/Helpers/StreakMessage.cs
Normal file
37
Plugins/SimpleStats/Helpers/StreakMessage.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StatsPlugin.Helpers
|
||||||
|
{
|
||||||
|
public class StreakMessage
|
||||||
|
{
|
||||||
|
public static 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1333,7 +1333,8 @@ namespace StatsPlugin
|
|||||||
ak74u_silencer_thermal_mp,
|
ak74u_silencer_thermal_mp,
|
||||||
ak74u_silencer_xmags_mp,
|
ak74u_silencer_xmags_mp,
|
||||||
ak74u_thermal_xmags_mp,
|
ak74u_thermal_xmags_mp,
|
||||||
m40a3_mp = 1194,
|
m16_reflex_silencer_mp,
|
||||||
|
m40a3_mp,
|
||||||
peacekeeper_mp,
|
peacekeeper_mp,
|
||||||
dragunov_mp,
|
dragunov_mp,
|
||||||
cobra_player_minigun_mp
|
cobra_player_minigun_mp
|
||||||
|
@ -45,5 +45,9 @@ namespace StatsPlugin.Models
|
|||||||
public int DeathStreak { get; set; }
|
public int DeathStreak { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public DateTime LastStatCalculation { get; set; }
|
public DateTime LastStatCalculation { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public int LastScore { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public DateTime LastActive { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
Plugins/SimpleStats/Models/EFServerStatistics.cs
Normal file
17
Plugins/SimpleStats/Models/EFServerStatistics.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using SharedLibrary.Database.Models;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace StatsPlugin.Models
|
||||||
|
{
|
||||||
|
public class EFServerStatistics : SharedEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int StatisticId { get; set; }
|
||||||
|
public int ServerId { get; set; }
|
||||||
|
[ForeignKey("ServerId")]
|
||||||
|
public virtual EFServer Server { get; set; }
|
||||||
|
public long TotalKills { get; set; }
|
||||||
|
public long TotalPlayTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,11 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using SharedLibrary;
|
using SharedLibrary;
|
||||||
|
using SharedLibrary.Helpers;
|
||||||
using SharedLibrary.Interfaces;
|
using SharedLibrary.Interfaces;
|
||||||
|
using SharedLibrary.Services;
|
||||||
using StatsPlugin.Helpers;
|
using StatsPlugin.Helpers;
|
||||||
|
using StatsPlugin.Models;
|
||||||
|
|
||||||
namespace StatsPlugin
|
namespace StatsPlugin
|
||||||
{
|
{
|
||||||
@ -40,6 +43,7 @@ namespace StatsPlugin
|
|||||||
case Event.GType.MapChange:
|
case Event.GType.MapChange:
|
||||||
break;
|
break;
|
||||||
case Event.GType.MapEnd:
|
case Event.GType.MapEnd:
|
||||||
|
await Manager.Sync();
|
||||||
break;
|
break;
|
||||||
case Event.GType.Broadcast:
|
case Event.GType.Broadcast:
|
||||||
break;
|
break;
|
||||||
@ -71,6 +75,27 @@ namespace StatsPlugin
|
|||||||
|
|
||||||
public Task OnLoadAsync(IManager manager)
|
public Task OnLoadAsync(IManager manager)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
ManagerInstance.GetMessageTokens().Add(new MessageToken("TOTALKILLS", GetTotalKills));
|
||||||
|
ManagerInstance.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", GetTotalPlaytime));
|
||||||
|
*/
|
||||||
|
string totalKills()
|
||||||
|
{
|
||||||
|
var serverStats = new GenericRepository<EFServerStatistics>();
|
||||||
|
return serverStats.GetQuery(s => s.Active)
|
||||||
|
.Sum(c => c.TotalKills).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string totalPlayTime()
|
||||||
|
{
|
||||||
|
var serverStats = new GenericRepository<EFServerStatistics>();
|
||||||
|
return serverStats.GetQuery(s => s.Active)
|
||||||
|
.Sum(c => c.TotalPlayTime).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills));
|
||||||
|
manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime));
|
||||||
return Task.FromResult(
|
return Task.FromResult(
|
||||||
Manager = new StatManager(manager)
|
Manager = new StatManager(manager)
|
||||||
);
|
);
|
||||||
|
@ -72,11 +72,13 @@
|
|||||||
<None Include="Chat\ChatHistoryPage.cs" />
|
<None Include="Chat\ChatHistoryPage.cs" />
|
||||||
<Compile Include="Helpers\ServerStats.cs" />
|
<Compile Include="Helpers\ServerStats.cs" />
|
||||||
<Compile Include="Helpers\StatManager.cs" />
|
<Compile Include="Helpers\StatManager.cs" />
|
||||||
|
<Compile Include="Helpers\StreakMessage.cs" />
|
||||||
<Compile Include="IW4Info.cs" />
|
<Compile Include="IW4Info.cs" />
|
||||||
<Compile Include="MinimapConfig.cs" />
|
<Compile Include="MinimapConfig.cs" />
|
||||||
<Compile Include="Models\EFClientKill.cs" />
|
<Compile Include="Models\EFClientKill.cs" />
|
||||||
<Compile Include="Models\EFServer.cs" />
|
<Compile Include="Models\EFServer.cs" />
|
||||||
<Compile Include="Models\EFClientStatistics.cs" />
|
<Compile Include="Models\EFClientStatistics.cs" />
|
||||||
|
<Compile Include="Models\EFServerStatistics.cs" />
|
||||||
<Compile Include="Plugin.cs" />
|
<Compile Include="Plugin.cs" />
|
||||||
<None Include="_Plugin.cs" />
|
<None Include="_Plugin.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -744,7 +744,7 @@ namespace SharedLibrary.Commands
|
|||||||
E.Data = E.Data.RemoveWords(1);
|
E.Data = E.Data.RemoveWords(1);
|
||||||
E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data));
|
E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data));
|
||||||
|
|
||||||
await E.Origin.Tell($"Thank you for your report, and administrator has been notified");
|
await E.Origin.Tell($"Thank you for your report, an administrator has been notified");
|
||||||
await E.Owner.ExecuteEvent(new Event(Event.GType.Report, E.Data, E.Origin, E.Target, E.Owner));
|
await E.Owner.ExecuteEvent(new Event(Event.GType.Report, E.Data, E.Origin, E.Target, E.Owner));
|
||||||
await E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data));
|
await E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data));
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,8 @@ namespace SharedLibrary.Objects
|
|||||||
public DateTime ConnectionTime { get; set; }
|
public DateTime ConnectionTime { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public Server CurrentServer { get; set; }
|
public Server CurrentServer { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public int Score { get; set; }
|
||||||
|
|
||||||
private string _ipaddress;
|
private string _ipaddress;
|
||||||
public override string IPAddress
|
public override string IPAddress
|
||||||
|
@ -26,8 +26,8 @@ namespace SharedLibrary.Network
|
|||||||
|
|
||||||
static string[] SendQuery(QueryType Type, Server QueryServer, string Parameters = "")
|
static string[] SendQuery(QueryType Type, Server QueryServer, string Parameters = "")
|
||||||
{
|
{
|
||||||
if ((DateTime.Now - LastQuery).TotalMilliseconds < 100)
|
if ((DateTime.Now - LastQuery).TotalMilliseconds < 300)
|
||||||
Task.Delay(100).Wait();
|
Task.Delay(300).Wait();
|
||||||
LastQuery = DateTime.Now;
|
LastQuery = DateTime.Now;
|
||||||
var ServerOOBConnection = new UdpClient();
|
var ServerOOBConnection = new UdpClient();
|
||||||
ServerOOBConnection.Client.SendTimeout = 1000;
|
ServerOOBConnection.Client.SendTimeout = 1000;
|
||||||
|
@ -233,6 +233,12 @@ namespace SharedLibrary.Services
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotalPlayTime()
|
||||||
|
{
|
||||||
|
using (var context = new DatabaseContext())
|
||||||
|
return await context.Clients.SumAsync(c => c.TotalConnectionTime);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,9 @@ namespace SharedLibrary
|
|||||||
int.TryParse(playerInfo[0], out cID);
|
int.TryParse(playerInfo[0], out cID);
|
||||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||||
string cIP = regex.Value.Split(':')[0];
|
string cIP = regex.Value.Split(':')[0];
|
||||||
Player P = new Player() { Name = cName, NetworkId = npID, ClientNumber = cID, IPAddress = cIP, Ping = Ping };
|
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
||||||
|
int score = Int32.Parse(regex.Value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1]);
|
||||||
|
Player P = new Player() { Name = cName, NetworkId = npID, ClientNumber = cID, IPAddress = cIP, Ping = Ping, Score = score};
|
||||||
StatusPlayers.Add(P);
|
StatusPlayers.Add(P);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user