Stats plugin modifications

This commit is contained in:
RaidMax 2015-08-26 00:49:47 -05:00
parent 7ae6c7e07f
commit c23e578319
10 changed files with 180 additions and 62 deletions

View File

@ -149,14 +149,25 @@ namespace IW4MAdmin
public override void Execute(Event E) public override void Execute(Event E)
{ {
StringBuilder playerList = new StringBuilder();
lock (E.Owner.getPlayers()) lock (E.Owner.getPlayers())
{ {
int count = 0;
foreach (Player P in E.Owner.getPlayers()) foreach (Player P in E.Owner.getPlayers())
{ {
if (P == null) if (P == null)
continue; continue;
E.Origin.Tell(String.Format("[^3{0}^7]{3}[^3{1}^7] {2}", SharedLibrary.Utilities.levelToColor(P.Level), P.clientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length))); playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", SharedLibrary.Utilities.levelToColor(P.Level), P.clientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length));
if (count == 2)
{
E.Origin.Tell(playerList.ToString());
count = 0;
playerList = new StringBuilder();
continue;
}
count++;
} }
} }
} }
@ -519,6 +530,13 @@ namespace IW4MAdmin
public override void Execute(Event E) public override void Execute(Event E)
{ {
if (E.Data != null && E.Data.ToLower().Contains("clear"))
{
E.Owner.Reports = new List<Report>();
E.Origin.Tell("Reports successfully cleared!");
return;
}
if (E.Owner.Reports.Count < 1) if (E.Owner.Reports.Count < 1)
{ {
E.Origin.Tell("No players reported yet."); E.Origin.Tell("No players reported yet.");
@ -659,5 +677,19 @@ namespace IW4MAdmin
E.Origin.Tell("Successfuly sent RCON command!"); E.Origin.Tell("Successfuly sent RCON command!");
} }
} }
class Plugins : Command
{
public Plugins(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
public override void Execute(Event E)
{
E.Origin.Tell("^5Loaded Plugins:");
foreach (Plugin P in PluginImporter.potentialPlugins)
{
E.Origin.Tell(String.Format("^3{0} ^7[^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author));
}
}
}
} }

View File

@ -30,7 +30,7 @@ namespace IW4MAdmin
Console.WriteLine(" Version " + Version + " (unable to retrieve latest)"); Console.WriteLine(" Version " + Version + " (unable to retrieve latest)");
Console.WriteLine("====================================================="); Console.WriteLine("=====================================================");
serverManager = new IW4MAdmin.Manager(); serverManager = new Manager();
Thread serverMGRThread = new Thread(serverManager.Init); Thread serverMGRThread = new Thread(serverManager.Init);
serverMGRThread.Name = "Server Manager thread"; serverMGRThread.Name = "Server Manager thread";
@ -42,11 +42,11 @@ namespace IW4MAdmin
} }
if (serverManager.getServers() != null) if (serverManager.getServers() != null)
Program.getManager().mainLog.Write("IW4M Now Initialized!", Log.Level.Production); getManager().mainLog.Write("IW4M Now Initialized!", Log.Level.Production);
String userInput; String userInput;
Server serverToExecuteOn = serverManager.getServers()[0]; Server serverToExecuteOn = serverManager.getServers()[0];
Player Origin = new Player("IW4MAdmin Console", "", -1, Player.Permission.Console, -1, "", 0, ""); Player Origin = new Player("IW4MAdmin", "", -1, Player.Permission.Console, -1, "", 0, "");
do do
{ {
@ -68,7 +68,7 @@ namespace IW4MAdmin
{ {
try try
{ {
foreach (Server S in IW4MAdmin.Program.getServers()) foreach (Server S in getServers())
{ {
if (S == null) if (S == null)
continue; continue;
@ -77,12 +77,12 @@ namespace IW4MAdmin
S.isRunning = false; S.isRunning = false;
if (Utilities.shutdownInterface(S.pID())) if (Utilities.shutdownInterface(S.pID()))
Program.getManager().mainLog.Write("Successfully removed IW4MAdmin from server with PID " + S.pID(), Log.Level.Debug); getManager().mainLog.Write("Successfully removed IW4MAdmin from server with PID " + S.pID(), Log.Level.Debug);
else else
Program.getManager().mainLog.Write("Could not remove IW4MAdmin from server with PID " + S.pID(), Log.Level.Debug); getManager().mainLog.Write("Could not remove IW4MAdmin from server with PID " + S.pID(), Log.Level.Debug);
} }
Program.getManager().shutDown(); getManager().shutDown();
return false; return false;
} }

View File

@ -589,6 +589,12 @@ namespace IW4MAdmin
// basic info dvars // basic info dvars
hostname = SharedLibrary.Utilities.stripColors(getDvar("sv_hostname").current); hostname = SharedLibrary.Utilities.stripColors(getDvar("sv_hostname").current);
mapname = getDvar("mapname").current; mapname = getDvar("mapname").current;
Map localizedMapName = maps.Find(x => x.Name.Equals(mapname));
if (localizedMapName != null)
mapname = localizedMapName.Alias;
IW_Ver = getDvar("shortversion").current; IW_Ver = getDvar("shortversion").current;
maxClients = -1; maxClients = -1;
Int32.TryParse(getDvar("party_maxplayers").current, out maxClients); Int32.TryParse(getDvar("party_maxplayers").current, out maxClients);
@ -910,6 +916,9 @@ namespace IW4MAdmin
if(owner == null) if(owner == null)
commands.Add(new Owner("owner", "claim ownership of the server", "owner", Player.Permission.User, 0, false)); commands.Add(new Owner("owner", "claim ownership of the server", "owner", Player.Permission.User, 0, false));
foreach (Command C in PluginImporter.potentialCommands)
commands.Add(C);
commands.Add(new Kick("kick", "kick a player by name. syntax: !kick <player> <reason>.", "k", Player.Permission.Moderator, 2, true)); commands.Add(new Kick("kick", "kick a player by name. syntax: !kick <player> <reason>.", "k", Player.Permission.Moderator, 2, true));
commands.Add(new Say("say", "broadcast message to all players. syntax: !say <message>.", "s", Player.Permission.Moderator, 1, false)); commands.Add(new Say("say", "broadcast message to all players. syntax: !say <message>.", "s", Player.Permission.Moderator, 1, false));
commands.Add(new TempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban <player> <reason>.", "tb", Player.Permission.Moderator, 2, true)); commands.Add(new TempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban <player> <reason>.", "tb", Player.Permission.Moderator, 2, true));
@ -942,10 +951,7 @@ namespace IW4MAdmin
commands.Add(new Alias("alias", "get past aliases and ips of a player. syntax: !alias <player>", "known", Player.Permission.Moderator, 1, true)); commands.Add(new Alias("alias", "get past aliases and ips of a player. syntax: !alias <player>", "known", Player.Permission.Moderator, 1, true));
commands.Add(new _RCON("rcon", "send rcon command to server. syntax: !rcon <command>", "rcon", Player.Permission.Owner, 1, false)); commands.Add(new _RCON("rcon", "send rcon command to server. syntax: !rcon <command>", "rcon", Player.Permission.Owner, 1, false));
commands.Add(new FindAll("findall", "find a player by their aliase(s). syntax: !findall <player>", "fa", Player.Permission.Moderator, 1, false)); commands.Add(new FindAll("findall", "find a player by their aliase(s). syntax: !findall <player>", "fa", Player.Permission.Moderator, 1, false));
commands.Add(new Plugins("plugins", "view all loaded plugins. syntax: !plugins", "p", Player.Permission.Administrator, 0, false));
foreach (Command C in PluginImporter.potentialCommands)
commands.Add(C);
} }
//Objects //Objects

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,4 @@
<div id="footer">IW4M Admin v{{VERSION}} &mdash; <a href="http://raidmax.org/IW4MAdmin">RaidMax.org</a></div> <div id="footer">IW4M Admin v{{VERSION}} &mdash; <a href="http://raidmax.org/IW4MAdmin">RaidMax.org</a></div>
<script>
$('a').each(function () {
this.href = this.href.replace('userip', userip);
});
</script>
<script> <script>
$(function () { $(function () {
$("#history_dialog").dialog({ $("#history_dialog").dialog({

View File

@ -317,8 +317,8 @@
margin-top: 10px; margin-top: 10px;
width: auto; width: auto;
height: auto; height: auto;
border: 1px solid #171717; border: 1px solid rgba(23, 23, 23, 0.49);
border-radius: 3px; border-radius: 0;
} }
#player_search input[type="text"] { #player_search input[type="text"] {

View File

@ -80,14 +80,53 @@ namespace SamplePlugin
public class Stats : Plugin public class Stats : Plugin
{ {
public static StatsDB playerStats { get; private set; } public static StatsDB playerStats { get; private set; }
private DateTime[] lastKill = new DateTime[18];
private DateTime[] connectionTime = new DateTime[18];
private int[] inactiveMinutes = new int[18];
private int[] Kills = new int[18];
private int[] deathStreaks = new int[18];
private int[] killStreaks = new int[18];
public override void onEvent(Event E) public override void onEvent(Event E)
{ {
playerStats = new StatsDB("stats_" + E.Owner.getPort() + ".rm");
if (E.Type == Event.GType.Connect)
{
resetCounters(E.Origin.clientID);
}
if (E.Type == Event.GType.MapEnd)
{
foreach (Player P in E.Owner.getPlayers())
{
calculateAndSaveSkill(P);
resetCounters(P.clientID);
E.Owner.Log.Write("Updated skill for client #" + P.databaseID, Log.Level.Debug);
//E.Owner.Log.Write(String.Format("\r\nJoin: {0}\r\nInactive Minutes: {1}\r\nnewPlayTime: {2}\r\nnewSPM: {3}\r\nkdrWeight: {4}\r\nMultiplier: {5}\r\nscoreWeight: {6}\r\nnewSkillFactor: {7}\r\nprojectedNewSkill: {8}\r\nKills: {9}\r\nDeaths: {10}", connectionTime[P.clientID].ToShortTimeString(), inactiveMinutes[P.clientID], newPlayTime, newSPM, kdrWeight, Multiplier, scoreWeight, newSkillFactor, disconnectStats.Skill, disconnectStats.Kills, disconnectStats.Deaths));
}
}
if (E.Type == Event.GType.Disconnect)
{
calculateAndSaveSkill(E.Origin);
E.Owner.Log.Write("Updated skill for disconnecting client #" + E.Origin.databaseID, Log.Level.Debug);
}
if (E.Type == Event.GType.Kill) if (E.Type == Event.GType.Kill)
{ {
Player Killer = E.Origin; Player Killer = E.Origin;
PlayerStats killerStats = playerStats.getStats(Killer); PlayerStats killerStats = playerStats.getStats(Killer);
lastKill[E.Origin.clientID] = DateTime.Now;
Kills[E.Origin.clientID]++;
if ((lastKill[E.Origin.clientID] - DateTime.Now).TotalSeconds > 60)
{
inactiveMinutes[E.Origin.clientID]++;
}
if (Killer != E.Target) if (Killer != E.Target)
{ {
killerStats.Kills++; killerStats.Kills++;
@ -95,15 +134,15 @@ namespace SamplePlugin
if (killerStats.Deaths == 0) if (killerStats.Deaths == 0)
killerStats.KDR = killerStats.Kills; killerStats.KDR = killerStats.Kills;
else else
killerStats.KDR = killerStats.Kills / killerStats.Deaths; killerStats.KDR = (double)killerStats.Kills / (double)killerStats.Deaths;
playerStats.updateStats(Killer, killerStats); playerStats.updateStats(Killer, killerStats);
killerStats.killStreak++; killStreaks[E.Origin.clientID]++;
killerStats.deathStreak = 0; deathStreaks[E.Origin.clientID] = 0;
} }
Killer.Tell(messageOnStreak(killerStats.killStreak, killerStats.deathStreak)); Killer.Tell(messageOnStreak(killStreaks[E.Origin.clientID], deathStreaks[E.Origin.clientID]));
} }
if (E.Type == Event.GType.Death) if (E.Type == Event.GType.Death)
@ -112,20 +151,71 @@ namespace SamplePlugin
PlayerStats victimStats = playerStats.getStats(Victim); PlayerStats victimStats = playerStats.getStats(Victim);
victimStats.Deaths++; victimStats.Deaths++;
victimStats.KDR = victimStats.Kills / victimStats.Deaths; victimStats.KDR = (double)victimStats.Kills / (double)victimStats.Deaths;
playerStats.updateStats(Victim, victimStats); playerStats.updateStats(Victim, victimStats);
victimStats.deathStreak++; deathStreaks[E.Origin.clientID]++;
victimStats.killStreak = 0; killStreaks[E.Origin.clientID] = 0;
Victim.Tell(messageOnStreak(victimStats.killStreak, victimStats.deathStreak)); Victim.Tell(messageOnStreak(killStreaks[E.Origin.clientID], deathStreaks[E.Origin.clientID]));
} }
} }
private void calculateAndSaveSkill(Player P)
{
PlayerStats disconnectStats = playerStats.getStats(P);
if (Kills[P.clientID] == 0)
return;
else if (lastKill[P.clientID] > connectionTime[P.clientID])
inactiveMinutes[P.clientID] += (int)(DateTime.Now - lastKill[P.clientID]).TotalMinutes;
int newPlayTime = (int)(DateTime.Now - connectionTime[P.clientID]).TotalMinutes - inactiveMinutes[P.clientID];
double newSPM = Kills[P.clientID] * 50 / Math.Max(newPlayTime, 1);
double kdrWeight = Math.Round(Math.Pow(disconnectStats.KDR, 2 / Math.E), 3);
double Multiplier;
if (disconnectStats.scorePerMinute == 1)
Multiplier = 1;
else
Multiplier = newSPM / disconnectStats.scorePerMinute;
double scoreWeight = (newSPM * (newPlayTime / disconnectStats.playTime));
double newSkillFactor = Multiplier * scoreWeight;
if (Multiplier >= 1)
disconnectStats.scorePerMinute += newSkillFactor;
else
disconnectStats.scorePerMinute -= (scoreWeight - newSkillFactor);
disconnectStats.Skill = disconnectStats.scorePerMinute * kdrWeight / 10;
disconnectStats.playTime += newPlayTime;
playerStats.updateStats(P, disconnectStats);
}
private void resetCounters(int cID)
{
Kills[cID] = 0;
connectionTime[cID] = DateTime.Now;
inactiveMinutes[cID] = 0;
deathStreaks[cID] = 0;
killStreaks[cID] = 0;
}
public override void onLoad() public override void onLoad()
{ {
playerStats = new StatsDB("stats.rm"); for (int i = 0; i < 18; i++)
{
Kills[i] = 0;
connectionTime[i] = DateTime.Now;
inactiveMinutes[i] = 0;
deathStreaks[i] = 0;
killStreaks[i] = 0;
}
} }
public override void onUnload() public override void onUnload()
@ -142,17 +232,17 @@ namespace SamplePlugin
Message = "Great job! You're on a ^55 killstreak!"; Message = "Great job! You're on a ^55 killstreak!";
break; break;
case 10: case 10:
Message = "Amazing! ^510 ^7kills without dying!"; Message = "Amazing! ^510 kills ^7without dying!";
break; break;
} }
switch (deathStreak) switch (deathStreak)
{ {
case 5: case 5:
Message = "Pick it up soldier, you've died 5 times in a row..."; Message = "Pick it up soldier, you've died ^55 times ^7in a row...";
break; break;
case 10: case 10:
Message = "Seriously? ^510 ^7deaths without getting a kill?"; Message = "Seriously? ^510 deaths ^7without getting a kill?";
break; break;
} }
@ -171,7 +261,7 @@ namespace SamplePlugin
{ {
get get
{ {
return 0.1f; return 0.2f;
} }
} }
@ -192,7 +282,7 @@ namespace SamplePlugin
{ {
if (!File.Exists(FileName)) if (!File.Exists(FileName))
{ {
String Create = "CREATE TABLE [STATS] ( [npID] TEXT, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] REAL DEFAULT 0, [SKILL] REAL DEFAULT 0, [MEAN] REAL DEFAULT 0, [DEV] REAL DEFAULT 0 );"; String Create = "CREATE TABLE [STATS] ( [npID] TEXT, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] TEXT DEFAULT 0, [SKILL] TEXT DEFAULT 0, [MEAN] REAL DEFAULT 0, [DEV] REAL DEFAULT 0, [SPM] TEXT DEFAULT 0, [PLAYTIME] INTEGER DEFAULT 0);";
ExecuteNonQuery(Create); ExecuteNonQuery(Create);
} }
} }
@ -204,8 +294,10 @@ namespace SamplePlugin
newPlayer.Add("npID", P.npID); newPlayer.Add("npID", P.npID);
newPlayer.Add("KILLS", 0); newPlayer.Add("KILLS", 0);
newPlayer.Add("DEATHS", 0); newPlayer.Add("DEATHS", 0);
newPlayer.Add("KDR", 0); newPlayer.Add("KDR", 0.0);
newPlayer.Add("SKILL", 0); newPlayer.Add("SKILL", 1.0);
newPlayer.Add("SPM", 1.0);
newPlayer.Add("PLAYTIME", 1.0);
Insert("STATS", newPlayer); Insert("STATS", newPlayer);
} }
@ -222,7 +314,9 @@ namespace SamplePlugin
Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["KILLS"]),
Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToInt32(ResponseRow["DEATHS"]),
Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["KDR"]),
Convert.ToDouble(ResponseRow["SKILL"]) Convert.ToDouble(ResponseRow["SKILL"]),
Convert.ToDouble(ResponseRow["SPM"]),
Convert.ToInt32(ResponseRow["PLAYTIME"])
); );
} }
@ -240,7 +334,9 @@ namespace SamplePlugin
updatedPlayer.Add("KILLS", S.Kills); updatedPlayer.Add("KILLS", S.Kills);
updatedPlayer.Add("DEATHS", S.Deaths); updatedPlayer.Add("DEATHS", S.Deaths);
updatedPlayer.Add("KDR", Math.Round(S.KDR, 2)); updatedPlayer.Add("KDR", Math.Round(S.KDR, 2));
updatedPlayer.Add("SKILL", S.Skill); updatedPlayer.Add("SKILL", Math.Round(S.Skill, 1));
updatedPlayer.Add("SPM", Math.Round(S.scorePerMinute, 0));
updatedPlayer.Add("PLAYTIME", S.playTime);
Update("STATS", updatedPlayer, String.Format("npID = '{0}'", P.npID)); Update("STATS", updatedPlayer, String.Format("npID = '{0}'", P.npID));
} }
@ -248,21 +344,21 @@ namespace SamplePlugin
public struct PlayerStats public struct PlayerStats
{ {
public PlayerStats(int K, int D, double DR, double S) public PlayerStats(int K, int D, double DR, double S, double sc, int P)
{ {
Kills = K; Kills = K;
Deaths = D; Deaths = D;
KDR = DR; KDR = DR;
Skill = S; Skill = S;
deathStreak = 0; scorePerMinute = sc;
killStreak = 0; playTime = P;
} }
public int Kills; public int Kills;
public int Deaths; public int Deaths;
public double KDR; public double KDR;
public double Skill; public double Skill;
public int deathStreak; public double scorePerMinute;
public int killStreak; public int playTime;
} }
} }

View File

@ -100,12 +100,15 @@ namespace Webfront_Plugin
private String processReplacements(String Input, String Macro, int curPage, int ID, String Query, params Server[] Servers) private String processReplacements(String Input, String Macro, int curPage, int ID, String Query, params Server[] Servers)
{ {
bool Authenticated = false; bool Authenticated = false;
bool UserPrivelege = false;
if (Servers[0] != null && Manager.lastIP != null) if (Servers[0] != null && Manager.lastIP != null)
{ {
Player User = Servers[0].clientDB.getPlayer(Manager.lastIP.ToString()); Player User = Servers[0].clientDB.getPlayer(Manager.lastIP.ToString());
if (User != null && User.Level > Player.Permission.Flagged) if (User != null && User.Level > Player.Permission.Flagged)
Authenticated = true; Authenticated = true;
if (User != null && User.Level == Player.Permission.User)
UserPrivelege = true;
} }
if (Macro.Length < 5) if (Macro.Length < 5)
@ -176,9 +179,11 @@ namespace Webfront_Plugin
S.getName(), S.getMap(), S.getClientNum() + "/" + S.getMaxClients(), SharedLibrary.Utilities.gametypeLocalized(S.getGametype()), S.pID(), players.ToString()); S.getName(), S.getMap(), S.getClientNum() + "/" + S.getMaxClients(), SharedLibrary.Utilities.gametypeLocalized(S.getGametype()), S.pID(), players.ToString());
if (S.getClientNum() > 0) if (S.getClientNum() > 0)
{
buffer.AppendFormat("<div class='chatHistory' id='chatHistory_{0}'></div><script type='text/javascript'>$( document ).ready(function() {{ setInterval({1}loadChatMessages({0}, '#chatHistory_{0}'){1}, 2500); }});</script><div class='null' style='clear:both;'></div>", S.pID(), '\"'); buffer.AppendFormat("<div class='chatHistory' id='chatHistory_{0}'></div><script type='text/javascript'>$( document ).ready(function() {{ setInterval({1}loadChatMessages({0}, '#chatHistory_{0}'){1}, 2500); }});</script><div class='null' style='clear:both;'></div>", S.pID(), '\"');
//if (S.getClientNum() > 0) if (UserPrivelege || Authenticated)
// buffer.AppendFormat("<form class='chatOutFormat' action={1}javascript:chatRequest({0}, 'chatEntry_{0}'){1}><input class='chatFormat_text' type='text' placeholder='Enter a message...' id='chatEntry_{0}'/><input class='chatFormat_submit' type='submit'/></form>", S.pID(), '\"'); buffer.AppendFormat("<form class='chatOutFormat' action={1}javascript:chatRequest({0}, 'chatEntry_{0}'){1}><input class='chatFormat_text' type='text' placeholder='Enter a message...' id='chatEntry_{0}'/><input class='chatFormat_submit' type='submit'/></form>", S.pID(), '\"');
}
buffer.Append("<hr/>"); buffer.Append("<hr/>");
} }
return Input.Replace(Macro, buffer.ToString()); return Input.Replace(Macro, buffer.ToString());
@ -352,7 +357,7 @@ namespace Webfront_Plugin
Player P = bannedPlayers[i]; Player P = bannedPlayers[i];
Player B; Player B;
if (Bans[i].bannedByID == Bans[i].npID) if (P.npID == Bans[i].bannedByID)
B = new Player("IW4MAdmin", "", 0, SharedLibrary.Player.Permission.Banned, 0, "", 0, ""); B = new Player("IW4MAdmin", "", 0, SharedLibrary.Player.Permission.Banned, 0, "", 0, "");
else else
@ -441,9 +446,6 @@ namespace Webfront_Plugin
case "graph": case "graph":
requestedPage = new graph(); requestedPage = new graph();
return processTemplate(requestedPage.Load(), request.QueryString); return processTemplate(requestedPage.Load(), request.QueryString);
case "stats":
requestedPage = new stats();
break;
case "chat": case "chat":
requestedPage = new chat(); requestedPage = new chat();
return processTemplate(requestedPage.Load(), request.QueryString); return processTemplate(requestedPage.Load(), request.QueryString);
@ -552,19 +554,6 @@ namespace Webfront_Plugin
} }
} }
class stats : Page
{
public override String Name
{
get { return "stats"; }
}
public override String Load()
{
return loadHTML();
}
}
class graph : Page class graph : Page
{ {
public override String Name public override String Name