2015-08-20 01:06:44 -04:00
using System ;
using System.Text ;
2015-08-20 17:54:38 -04:00
using System.IO ;
using System.Collections.Generic ;
using System.Data ;
2017-05-26 18:49:27 -04:00
using System.Threading.Tasks ;
2017-05-27 00:22:50 -04:00
using SharedLibrary ;
2015-08-28 00:39:36 -04:00
namespace StatsPlugin
2015-08-20 01:06:44 -04:00
{
2017-05-27 00:22:50 -04:00
public class CViewStats : Command
2015-08-20 01:06:44 -04:00
{
2017-05-27 00:22:50 -04:00
public CViewStats ( ) : base ( "stats" , "view your stats. syntax !stats" , "xlrstats" , Player . Permission . User , 0 , false ) { }
2015-08-20 01:06:44 -04:00
2017-05-26 18:49:27 -04:00
public override async Task ExecuteAsync ( Event E )
2015-08-20 01:06:44 -04:00
{
2015-09-01 12:00:12 -04:00
String statLine ;
PlayerStats pStats ;
2017-06-01 13:42:28 -04:00
if ( E . Data . Length > 0 & & E . Target = = null )
{
await E . Origin . Tell ( "Cannot find the player you specified" ) ;
return ;
}
2015-09-01 12:00:12 -04:00
if ( E . Target ! = null )
{
2017-06-12 13:50:00 -04:00
pStats = Stats . statLists . Find ( x = > x . Port = = E . Owner . GetPort ( ) ) . playerStats . GetStats ( E . Target ) ;
2015-09-01 12:00:12 -04:00
statLine = String . Format ( "^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL" , pStats . Kills , pStats . Deaths , pStats . KDR , pStats . Skill ) ;
}
else
{
2017-06-12 13:50:00 -04:00
pStats = Stats . statLists . Find ( x = > x . Port = = E . Owner . GetPort ( ) ) . playerStats . GetStats ( E . Origin ) ;
2015-09-01 12:00:12 -04:00
statLine = String . Format ( "^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL" , pStats . Kills , pStats . Deaths , pStats . KDR , pStats . Skill ) ;
}
2017-05-31 01:31:56 -04:00
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 ) ;
}
2017-06-01 13:42:28 -04:00
2017-05-31 01:31:56 -04:00
else
2017-06-01 13:42:28 -04:00
{
if ( E . Target ! = null )
await E . Origin . Tell ( $"Stats for ^5{E.Target.Name}^7" ) ;
2017-05-31 01:31:56 -04:00
await E . Origin . Tell ( statLine ) ;
2017-06-01 13:42:28 -04:00
}
2015-08-20 01:06:44 -04:00
}
}
2017-05-27 00:22:50 -04:00
public class CViewTopStats : Command
2015-08-20 01:06:44 -04:00
{
2017-05-31 01:31:56 -04:00
public CViewTopStats ( ) : base ( "topstats" , "view the top 5 players on this server. syntax !topstats" , "ts" , Player . Permission . User , 0 , false ) { }
2015-08-20 01:06:44 -04:00
2017-05-26 18:49:27 -04:00
public override async Task ExecuteAsync ( Event E )
2015-08-20 01:06:44 -04:00
{
2017-06-12 13:50:00 -04:00
List < KeyValuePair < String , PlayerStats > > pStats = Stats . statLists . Find ( x = > x . Port = = E . Owner . GetPort ( ) ) . playerStats . GetTopStats ( ) ;
2015-08-28 00:39:36 -04:00
StringBuilder msgBlder = new StringBuilder ( ) ;
2015-08-20 17:54:38 -04:00
2017-05-26 18:49:27 -04:00
await E . Origin . Tell ( "^5--Top Players--" ) ;
2015-08-28 00:39:36 -04:00
foreach ( KeyValuePair < String , PlayerStats > pStat in pStats )
{
2017-05-29 22:25:49 -04:00
Player P = E . Owner . Manager . GetClientDatabase ( ) . GetPlayer ( pStat . Key , - 1 ) ;
2015-08-28 00:39:36 -04:00
if ( P = = null )
continue ;
2017-05-26 18:49:27 -04:00
await E . Origin . Tell ( String . Format ( "^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL" , P . Name , pStat . Value . KDR , pStat . Value . Skill ) ) ;
2015-08-28 00:39:36 -04:00
}
2015-08-20 17:54:38 -04:00
}
}
2017-06-01 13:42:28 -04:00
2017-05-31 01:31:56 -04:00
public class CResetStats : Command
{
public CResetStats ( ) : base ( "resetstats" , "reset your stats to factory-new, !syntax !resetstats" , "rs" , Player . Permission . User , 0 , false ) { }
public override async Task ExecuteAsync ( Event E )
{
2017-06-12 13:50:00 -04:00
var stats = Stats . statLists . Find ( x = > x . Port = = E . Owner . GetPort ( ) ) . playerStats . GetStats ( E . Origin ) ;
2017-05-31 01:31:56 -04:00
stats . Deaths = 0 ;
stats . Kills = 0 ;
2017-06-01 13:42:28 -04:00
stats . scorePerMinute = 1.0 ;
stats . Skill = 1 ;
2017-05-31 01:31:56 -04:00
stats . KDR = 0.0 ;
2017-06-12 13:50:00 -04:00
await Task . Run ( ( ) = > { Stats . statLists . Find ( x = > x . Port = = E . Owner . GetPort ( ) ) . playerStats . UpdateStats ( E . Origin , stats ) ; } ) ;
2017-05-31 01:31:56 -04:00
await E . Origin . Tell ( "Your stats have been reset" ) ;
}
}
2017-05-26 18:49:27 -04:00
/// <summary>
/// Each server runs from the same plugin ( for easier reloading and reduced memory usage ).
/// So, to have multiple stat tracking, we must store a stat struct for each server
/// </summary>
2017-05-27 00:22:50 -04:00
public class Stats : SharedLibrary . Interfaces . IPlugin
2015-08-20 17:54:38 -04:00
{
2017-05-26 18:49:27 -04:00
public static List < StatTracking > statLists ;
public struct StatTracking
{
public StatsDB playerStats ;
public DateTime [ ] lastKill , connectionTime ;
public int [ ] inactiveMinutes , Kills , deathStreaks , killStreaks ;
public int Port ;
public StatTracking ( int port )
{
2017-05-27 18:08:04 -04:00
playerStats = new StatsDB ( "Database/stats_" + port + ".rm" ) ;
2017-05-26 18:49:27 -04:00
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
{
get { return "Basic Stats" ; }
}
public float Version
{
2017-05-31 01:31:56 -04:00
get { return 1.1f ; }
2017-05-26 18:49:27 -04:00
}
public string Author
2015-08-20 17:54:38 -04:00
{
2017-05-26 18:49:27 -04:00
get { return "RaidMax" ; }
}
2017-06-12 17:47:31 -04:00
public async Task OnLoadAsync ( Server S )
2017-05-26 18:49:27 -04:00
{
statLists = new List < StatTracking > ( ) ;
}
2017-06-12 17:47:31 -04:00
public async Task OnUnloadAsync ( Server S )
2017-05-26 18:49:27 -04:00
{
statLists . Clear ( ) ;
}
2017-05-27 18:08:04 -04:00
public async Task OnTickAsync ( Server S )
2017-05-26 18:49:27 -04:00
{
2017-05-27 00:22:50 -04:00
return ;
2017-05-26 18:49:27 -04:00
}
2017-05-27 18:08:04 -04:00
public async Task OnEventAsync ( Event E , Server S )
2017-05-26 18:49:27 -04:00
{
if ( E . Type = = Event . GType . Start )
{
2017-06-12 13:50:00 -04:00
statLists . Add ( new StatTracking ( S . GetPort ( ) ) ) ;
2017-06-01 13:42:28 -04:00
if ( statLists . Count = = 1 )
{
2017-06-12 17:47:31 -04:00
S . Manager . GetMessageTokens ( ) . Add ( new SharedLibrary . Helpers . MessageToken ( "TOTALKILLS" , GetTotalKills ) ) ;
S . Manager . GetMessageTokens ( ) . Add ( new SharedLibrary . Helpers . MessageToken ( "TOTALPLAYTIME" , GetTotalPlaytime ) ) ;
2017-06-01 13:42:28 -04:00
}
2017-05-26 18:49:27 -04:00
}
if ( E . Type = = Event . GType . Stop )
{
2017-06-12 13:50:00 -04:00
statLists . RemoveAll ( x = > x . Port = = S . GetPort ( ) ) ;
2017-05-26 18:49:27 -04:00
}
2015-08-26 01:49:47 -04:00
if ( E . Type = = Event . GType . Connect )
{
2017-06-12 13:50:00 -04:00
ResetCounters ( E . Origin . ClientID , S . GetPort ( ) ) ;
2016-01-16 17:58:24 -05:00
2017-06-12 13:50:00 -04:00
PlayerStats checkForTrusted = statLists . Find ( x = > x . Port = = S . GetPort ( ) ) . playerStats . GetStats ( E . Origin ) ;
2017-05-31 01:31:56 -04:00
if ( checkForTrusted . TotalPlayTime > = 4320 & & E . Origin . Level < Player . Permission . Trusted )
2016-01-16 17:58:24 -05:00
{
2017-06-12 13:50:00 -04:00
E . Origin . SetLevel ( Player . Permission . Trusted ) ;
2017-05-29 22:25:49 -04:00
E . Owner . Manager . GetClientDatabase ( ) . UpdatePlayer ( E . Origin ) ;
2017-05-26 18:49:27 -04:00
await E . Origin . Tell ( "Congratulations, you are now a ^5trusted ^7player! Type ^5!help ^7to view new commands." ) ;
await E . Origin . Tell ( "You earned this by playing for ^53 ^7full days!" ) ;
2016-01-16 17:58:24 -05:00
}
2015-08-26 01:49:47 -04:00
}
2017-05-26 18:49:27 -04:00
if ( E . Type = = Event . GType . MapEnd | | E . Type = = Event . GType . Stop )
2015-08-26 01:49:47 -04:00
{
2017-06-07 20:59:59 -04:00
foreach ( Player P in S . GetPlayersAsList ( ) )
2015-08-26 01:49:47 -04:00
{
2015-08-28 00:39:36 -04:00
if ( P = = null )
continue ;
2017-06-12 13:50:00 -04:00
CalculateAndSaveSkill ( P , statLists . Find ( x = > x . Port = = S . GetPort ( ) ) ) ;
ResetCounters ( P . ClientID , S . GetPort ( ) ) ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
E . Owner . Logger . WriteInfo ( "Updated skill for client #" + P . DatabaseID ) ;
2015-08-26 01:49:47 -04:00
//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 )
{
2017-06-12 13:50:00 -04:00
CalculateAndSaveSkill ( E . Origin , statLists . Find ( x = > x . Port = = S . GetPort ( ) ) ) ;
ResetCounters ( E . Origin . ClientID , S . GetPort ( ) ) ;
2017-05-31 01:31:56 -04:00
E . Owner . Logger . WriteInfo ( "Updated skill for disconnecting client #" + E . Origin . DatabaseID ) ;
2015-08-26 01:49:47 -04:00
}
2015-08-20 17:54:38 -04:00
if ( E . Type = = Event . GType . Kill )
{
2015-10-14 23:10:14 -04:00
if ( E . Origin = = E . Target | | E . Origin = = null )
2015-08-28 00:39:36 -04:00
return ;
2015-08-20 17:54:38 -04:00
Player Killer = E . Origin ;
2017-06-12 13:50:00 -04:00
StatTracking curServer = statLists . Find ( x = > x . Port = = S . GetPort ( ) ) ;
2017-05-31 01:31:56 -04:00
PlayerStats killerStats = curServer . playerStats . GetStats ( Killer ) ;
2017-05-26 18:49:27 -04:00
2015-08-20 17:54:38 -04:00
2017-05-31 01:31:56 -04:00
curServer . lastKill [ E . Origin . ClientID ] = DateTime . Now ;
curServer . Kills [ E . Origin . ClientID ] + + ;
2015-08-26 01:49:47 -04:00
2017-06-01 13:42:28 -04:00
if ( ( DateTime . Now - curServer . lastKill [ E . Origin . ClientID ] ) . TotalSeconds > 120 )
curServer . inactiveMinutes [ E . Origin . ClientID ] + = 2 ;
2015-10-14 23:10:14 -04:00
2015-08-28 00:39:36 -04:00
killerStats . Kills + + ;
2015-08-20 17:54:38 -04:00
2017-06-01 13:42:28 -04:00
killerStats . KDR = ( killerStats . Deaths = = 0 ) ? killerStats . Kills : killerStats . KDR = Math . Round ( ( double ) killerStats . Kills / ( double ) killerStats . Deaths , 2 ) ;
2015-08-20 17:54:38 -04:00
2017-05-31 01:31:56 -04:00
curServer . playerStats . UpdateStats ( Killer , killerStats ) ;
2015-08-23 17:58:48 -04:00
2017-05-31 01:31:56 -04:00
curServer . killStreaks [ Killer . ClientID ] + = 1 ;
curServer . deathStreaks [ Killer . ClientID ] = 0 ;
2015-08-23 17:58:48 -04:00
2017-05-31 01:31:56 -04:00
await Killer . Tell ( MessageOnStreak ( curServer . killStreaks [ Killer . ClientID ] , curServer . deathStreaks [ Killer . ClientID ] ) ) ;
2015-08-20 17:54:38 -04:00
}
if ( E . Type = = Event . GType . Death )
{
2015-10-14 23:10:14 -04:00
if ( E . Origin = = E . Target | | E . Origin = = null )
return ;
2015-08-20 17:54:38 -04:00
Player Victim = E . Origin ;
2017-06-12 13:50:00 -04:00
StatTracking curServer = statLists . Find ( x = > x . Port = = S . GetPort ( ) ) ;
2017-05-31 01:31:56 -04:00
PlayerStats victimStats = curServer . playerStats . GetStats ( Victim ) ;
2017-05-26 18:49:27 -04:00
2015-08-20 17:54:38 -04:00
victimStats . Deaths + + ;
2017-06-01 13:42:28 -04:00
victimStats . KDR = Math . Round ( victimStats . Kills / ( double ) victimStats . Deaths , 2 ) ;
2015-08-22 02:04:30 -04:00
2017-05-31 01:31:56 -04:00
curServer . playerStats . UpdateStats ( Victim , victimStats ) ;
2015-08-23 17:58:48 -04:00
2017-05-31 01:31:56 -04:00
curServer . deathStreaks [ Victim . ClientID ] + = 1 ;
curServer . killStreaks [ Victim . ClientID ] = 0 ;
2015-08-23 17:58:48 -04:00
2017-05-31 01:31:56 -04:00
await Victim . Tell ( MessageOnStreak ( curServer . killStreaks [ Victim . ClientID ] , curServer . deathStreaks [ Victim . ClientID ] ) ) ;
2015-08-20 17:54:38 -04:00
}
}
2017-06-01 13:42:28 -04:00
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" ) ;
}
2017-05-31 01:31:56 -04:00
private void CalculateAndSaveSkill ( Player P , StatTracking curServer )
2015-08-26 01:49:47 -04:00
{
2015-08-28 00:39:36 -04:00
if ( P = = null )
return ;
2017-05-31 01:31:56 -04:00
PlayerStats DisconnectingPlayerStats = curServer . playerStats . GetStats ( P ) ;
if ( curServer . Kills [ P . ClientID ] = = 0 )
2015-08-26 01:49:47 -04:00
return ;
2017-05-31 01:31:56 -04:00
else if ( curServer . lastKill [ P . ClientID ] > curServer . connectionTime [ P . ClientID ] )
curServer . inactiveMinutes [ P . ClientID ] + = ( int ) ( DateTime . Now - curServer . lastKill [ P . ClientID ] ) . TotalMinutes ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
int newPlayTime = ( int ) ( DateTime . Now - curServer . connectionTime [ P . ClientID ] ) . TotalMinutes - curServer . inactiveMinutes [ P . ClientID ] ;
2015-08-26 01:49:47 -04:00
2015-08-28 00:39:36 -04:00
if ( newPlayTime < 2 )
return ;
2017-05-31 01:31:56 -04:00
// calculate the players Score Per Minute for the current session
double SessionSPM = curServer . Kills [ P . ClientID ] * 100 / Math . Max ( 1 , newPlayTime ) ;
// calculate how much the KDR should way
// 0.81829 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 ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
// if no SPM, weight is 1 else the weight is the current sessions spm / lifetime average score per minute
SPMWeightAgainstAverage = ( DisconnectingPlayerStats . scorePerMinute = = 1 ) ? 1 : SessionSPM / DisconnectingPlayerStats . scorePerMinute ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
// calculate the weight of the new play time againmst lifetime playtime
//
2017-06-01 13:42:28 -04:00
double SPMAgainstPlayWeight = newPlayTime / Math . Min ( 600 , DisconnectingPlayerStats . TotalPlayTime + newPlayTime ) ;
2017-05-31 01:31:56 -04:00
// calculate the new weight against average times the weight against play time
2017-06-01 13:42:28 -04:00
double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight * SessionSPM ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
// if the weight is greater than 1, add, else subtract
DisconnectingPlayerStats . scorePerMinute + = ( SPMWeightAgainstAverage > = 1 ) ? newSkillFactor : - newSkillFactor ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
DisconnectingPlayerStats . Skill = DisconnectingPlayerStats . scorePerMinute * KDRWeight / 10 ;
DisconnectingPlayerStats . TotalPlayTime + = newPlayTime ;
2015-08-26 01:49:47 -04:00
2017-05-31 01:31:56 -04:00
curServer . playerStats . UpdateStats ( P , DisconnectingPlayerStats ) ;
2015-08-26 01:49:47 -04:00
}
2017-05-31 01:31:56 -04:00
private void ResetCounters ( int cID , int serverPort )
2015-08-22 12:41:14 -04:00
{
2017-05-26 18:49:27 -04:00
StatTracking selectedPlayers = statLists . Find ( x = > x . Port = = serverPort ) ;
2015-08-22 12:41:14 -04:00
2017-05-26 18:49:27 -04:00
selectedPlayers . Kills [ cID ] = 0 ;
selectedPlayers . connectionTime [ cID ] = DateTime . Now ;
selectedPlayers . inactiveMinutes [ cID ] = 0 ;
selectedPlayers . deathStreaks [ cID ] = 0 ;
selectedPlayers . killStreaks [ cID ] = 0 ;
2015-08-22 12:41:14 -04:00
}
2017-05-31 01:31:56 -04:00
private String MessageOnStreak ( int killStreak , int deathStreak )
2015-08-23 17:58:48 -04:00
{
String Message = "" ;
switch ( killStreak )
{
case 5 :
Message = "Great job! You're on a ^55 killstreak!" ;
break ;
case 10 :
2015-08-26 01:49:47 -04:00
Message = "Amazing! ^510 kills ^7without dying!" ;
2015-08-23 17:58:48 -04:00
break ;
}
switch ( deathStreak )
{
case 5 :
2015-08-26 01:49:47 -04:00
Message = "Pick it up soldier, you've died ^55 times ^7in a row..." ;
2015-08-23 17:58:48 -04:00
break ;
case 10 :
2015-08-26 01:49:47 -04:00
Message = "Seriously? ^510 deaths ^7without getting a kill?" ;
2015-08-23 17:58:48 -04:00
break ;
}
return Message ;
}
2015-08-20 17:54:38 -04:00
}
public class StatsDB : Database
{
public StatsDB ( String FN ) : base ( FN ) { }
public override void Init ( )
{
if ( ! File . Exists ( FileName ) )
{
2015-08-28 00:39:36 -04:00
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, [SPM] REAL DEFAULT 0, [PLAYTIME] INTEGER DEFAULT 0);" ;
2015-08-20 17:54:38 -04:00
ExecuteNonQuery ( Create ) ;
}
}
2017-05-31 01:31:56 -04:00
public void AddPlayer ( Player P )
2015-08-20 17:54:38 -04:00
{
2017-05-31 01:31:56 -04:00
Dictionary < String , object > newPlayer = new Dictionary < String , object >
{
{ "npID" , P . NetworkID } ,
{ "KILLS" , 0 } ,
{ "DEATHS" , 0 } ,
{ "KDR" , 0.0 } ,
{ "SKILL" , 1.0 } ,
{ "SPM" , 1.0 } ,
{ "PLAYTIME" , 1.0 }
} ;
2015-08-20 17:54:38 -04:00
Insert ( "STATS" , newPlayer ) ;
}
2017-05-31 01:31:56 -04:00
public PlayerStats GetStats ( Player P )
2015-08-20 17:54:38 -04:00
{
2017-05-31 01:31:56 -04:00
DataTable Result = GetDataTable ( "STATS" , new KeyValuePair < string , object > ( "npID" , P . NetworkID ) ) ;
2015-08-20 17:54:38 -04:00
if ( Result ! = null & & Result . Rows . Count > 0 )
{
DataRow ResponseRow = Result . Rows [ 0 ] ;
return new PlayerStats (
Convert . ToInt32 ( ResponseRow [ "KILLS" ] ) ,
Convert . ToInt32 ( ResponseRow [ "DEATHS" ] ) ,
Convert . ToDouble ( ResponseRow [ "KDR" ] ) ,
2015-08-26 01:49:47 -04:00
Convert . ToDouble ( ResponseRow [ "SKILL" ] ) ,
Convert . ToDouble ( ResponseRow [ "SPM" ] ) ,
Convert . ToInt32 ( ResponseRow [ "PLAYTIME" ] )
2015-08-20 17:54:38 -04:00
) ;
}
else
{
2017-05-31 01:31:56 -04:00
AddPlayer ( P ) ;
return GetStats ( P ) ;
2015-08-20 17:54:38 -04:00
}
}
2017-06-01 13:42:28 -04:00
public long GetTotalServerKills ( )
2015-08-20 17:54:38 -04:00
{
2017-05-31 01:31:56 -04:00
var Result = GetDataTable ( "SELECT SUM(KILLS) FROM STATS" ) ;
2017-06-01 13:42:28 -04:00
return Result . Rows [ 0 ] [ 0 ] . GetType ( ) = = typeof ( DBNull ) ? 0 : Convert . ToInt64 ( Result . Rows [ 0 ] [ 0 ] ) ;
2017-05-31 01:31:56 -04:00
}
2015-08-20 17:54:38 -04:00
2017-06-01 13:42:28 -04:00
public long GetTotalServerPlaytime ( )
2017-05-31 01:31:56 -04:00
{
var Result = GetDataTable ( "SELECT SUM(PLAYTIME) FROM STATS" ) ;
2017-06-01 13:42:28 -04:00
return Result . Rows [ 0 ] [ 0 ] . GetType ( ) = = typeof ( DBNull ) ? 0 : Convert . ToInt64 ( Result . Rows [ 0 ] [ 0 ] ) / 60 ;
2017-05-31 01:31:56 -04:00
}
2015-08-20 17:54:38 -04:00
2017-05-31 01:31:56 -04:00
public void UpdateStats ( Player P , PlayerStats S )
{
Dictionary < String , object > updatedPlayer = new Dictionary < String , object >
{
{ "KILLS" , S . Kills } ,
{ "DEATHS" , S . Deaths } ,
{ "KDR" , Math . Round ( S . KDR , 2 ) } ,
2017-06-01 13:42:28 -04:00
{ "SKILL" , Math . Round ( S . Skill , 2 ) } ,
{ "SPM" , Math . Round ( S . scorePerMinute , 2 ) } ,
2017-05-31 01:31:56 -04:00
{ "PLAYTIME" , S . TotalPlayTime }
} ;
Update ( "STATS" , updatedPlayer , new KeyValuePair < string , object > ( "npID" , P . NetworkID ) ) ;
2015-08-20 17:54:38 -04:00
}
2015-08-28 00:39:36 -04:00
2017-05-31 01:31:56 -04:00
public List < KeyValuePair < String , PlayerStats > > GetTopStats ( )
2015-08-28 00:39:36 -04:00
{
2017-05-26 18:49:27 -04:00
String Query = String . Format ( "SELECT * FROM STATS WHERE SKILL > 0 AND KDR < '{0}' AND KILLS > '{1}' AND PLAYTIME > '{2}' ORDER BY SKILL DESC LIMIT '{3}'" , 10 , 150 , 60 , 5 ) ;
2015-08-28 00:39:36 -04:00
DataTable Result = GetDataTable ( Query ) ;
List < KeyValuePair < String , PlayerStats > > pStats = new List < KeyValuePair < String , PlayerStats > > ( ) ;
if ( Result ! = null & & Result . Rows . Count > 0 )
{
foreach ( DataRow ResponseRow in Result . Rows )
{
pStats . Add ( new KeyValuePair < String , PlayerStats > ( ResponseRow [ "npID" ] . ToString ( ) ,
new PlayerStats (
Convert . ToInt32 ( ResponseRow [ "KILLS" ] ) ,
Convert . ToInt32 ( ResponseRow [ "DEATHS" ] ) ,
Convert . ToDouble ( ResponseRow [ "KDR" ] ) ,
Convert . ToDouble ( ResponseRow [ "SKILL" ] ) ,
Convert . ToDouble ( ResponseRow [ "SPM" ] ) ,
Convert . ToInt32 ( ResponseRow [ "PLAYTIME" ] )
)
) ) ;
}
}
return pStats ;
}
2015-08-20 17:54:38 -04:00
}
public struct PlayerStats
{
2015-08-26 01:49:47 -04:00
public PlayerStats ( int K , int D , double DR , double S , double sc , int P )
2015-08-20 17:54:38 -04:00
{
Kills = K ;
Deaths = D ;
KDR = DR ;
Skill = S ;
2015-08-26 01:49:47 -04:00
scorePerMinute = sc ;
2017-05-31 01:31:56 -04:00
TotalPlayTime = P ;
2015-08-20 17:54:38 -04:00
}
public int Kills ;
public int Deaths ;
public double KDR ;
public double Skill ;
2015-08-26 01:49:47 -04:00
public double scorePerMinute ;
2017-05-31 01:31:56 -04:00
public int TotalPlayTime ;
2015-08-20 17:54:38 -04:00
}
2015-08-20 01:06:44 -04:00
}