News
FAQ
HTML Tags
App Settings
Downloads
Samples
Links

E-Mail

Proudly Hosted By
Telefragged Home

[an error occurred while processing this directive]

Overview

cs_stats is an application that generates and maintains persistent Counter-Strike statistics. It parses log files spit out by a server, and updates it's custom binary data files for every player that meets a user-defined basic requirement (eg: a player must have 10 kills + deaths in a round before they start being tracked.) It outputs custom-generated HTML for every player that meets the minimum requirements, along with sorted lists ranking players by specific statistics.

This app was the result of my own desire to check out persistent stats, and the lack of any tools out there to do so. All the other log parsers that I could find only generated round-by-round results, and didn't keep a running total for players. I hooked up with a friend who runs a server, and have been writing/testing this over the past couple weeks.

What stats are kept?

Individual stats:

  • Overall number of kills
  • Overall number of deaths
  • Overall K:D ratio
  • Best round (K:D)
  • Best round (number of kills)
  • Kill streak
  • Death streak
  • Total number of minutes on server
  • Average kills per minute
  • Average deaths per minute
  • Total number of rounds played
  • Average kills per round
  • Average deaths per round
  • Top 5 opponents (opponents that the player has the best K:D against)
  • Bottom 5 opponents (opponents that have owned the player)
  • Weapon distribution (how many kills/deaths for various weapon names)
  • Comparison vs average player
For the best round stats and kill/death streaks, the date/time and map name are also recorded and displayed.

Check out the sample listings

How do I turn on logging on my server?

It's a command located in your autoexec.cfg file. Place this line:

log on

Somewhere near the top, preferably before the map command. This will start logging whenever the server starts. A logs directory will be created under the mod's game folder, like c:\half-life\cstrike\logs. This is where cs_stats will grab the files from.

Getting Started

The app itself is self-sufficient; there are no external files needed to run it. You do, however, need to do a bit of configuration first in order to get it up and running. Let me first explain how the application works.

There are two different "modes of operation" as I like to call them. There really is no difference in the code, it's more a way of how you use the app. The first mode is "Automated Background Processing." In this mode, the app acts as a background process that runs in tandem with the game server. It sits, waiting for log files to appear. As the log files get generated by the game server, the app picks them up, processes them, and does its thing, so to speak. After the log file has been processed, it goes back to sleep, waiting for the next one to show up.

The second mode of operation is "Batch Processing Mode." Here, the app runs through a whole collection of log files at one time, like after a clan match or at the end of a day, etc. This mode is meant more for people that either don't want to run the app in the background, have log files from a Linux server, or just simply prefer to do it manually. Processing is identical to the automated mode, except really there won't be any new log files coming along, and the process can just be stopped.

Now for the initial setup. Once you've downloaded the application and let it extract to some directory, just run the app for the first time to do the configuration. By default, the app creates sub-directories for the templates, stats, and html output folders. These are all located underneath the main directory you chose to extract to, and contain initial placeholders (except for templates, which contains valid data.) The app builds the registry keys at first based on these directories.

Click on the Config button on the main cs_stats dialog form to bring up the cs_stats property sheet. You'll see two tabs, one for Directories and Files and one for Statistics. The name statistics is misleading because there are general application parameters in there, as well, but I forgot to change the tab (doh!) These are the screenshots for these tabs:


The Directories tab is where you configure, well, directories and files. It is here that you specify the various templates, the output directories, the stats directories, etc. The most important thing for your initial setup is the Log Directory. This you must specify manually, as it is not created by the application during extraction. Click on the item in the listbox to bring it up for changes. Click the little [..] box to the right of the edit field to bring up the folder browser. Browse to where the cstrike\logs directory is located, and click OK. For now, browse through the other fields available, and click on the Statistics tab to check out some of the options available there. Every possible configuration parameter is settable through this config dialog. Click on OK when you've finished.

How do you keep all these players separate?

cs_stats was originally written to use the Won ID of a player to keep everyone separate. While it sounded good, and sure looked nice on paper, in practice it turned out to be not quite the Utopia one would hope for. Duplicate WonIDs, completely missing WonIDs, and multiple WonIDs for the same player rounded out the list of major reasons for why this didn't work.

So for now, and the forseeable future, cs_stats tracks players purely by their name. This means that if someone comes along on the server after a player and happens to have the same name (knowingly or not), those two players will share the same stats. While this can be a pain, there really is no other way around it. Won just didn't cut it, unfortunately.

What's with the $ in the file names?

A player can choose all sorts of ASCII characters to denote their name. Many characters are legal in the game, but result in bad file names in Windows. Things like colons (:), plus signs (+), and greater-than/less-than symbols (< >) are invalid symbols for file names. For this reason, I implemented a system similar to what HTML and URLs use for special characters that have useful meanings otherwise. I chose the dollar sign ($) to denote one of these special characters, followed by a two-character hexadecimal representation of the ASCII equivalent for the symbol in the player's name. There are some 18 characters in all that fit the description of either A) an illegal character for a Windows filename, or B) a useful tag for a URL. The following characters are all converted to $xx:

$ % # < > / \ + * = | : ; " , . ?

One you can't see is the space character (hex 0x20) which is invalid in a URL tag, along with being invalid on a Unix file system. So as an example, say someone's name is <+= Hacker =+>. After conversion, that player's name turns into $3c$2b$3d$20Hacker$20$3d$2b$3e. Fun, isn't it? You shouldn't ever have to be concerned with a player's file name vs what their real name is except if you choose to manually remove someone outside of the application. The new editor lets you remove players, and of course lists their real name. If you should find a need to convert a file name that has a dollar sign ($) in it, just take the two characters after the $, convert that to decimal using your favorite hex-to-decimal calculator (calc.exe works for me), and look up the value in any ASCII table.

Can I customize the output?

This was the one thing I wanted to make sure was done right: the HTML that is spit out is completely customizable by the server admin who's keeping the log files. There is a set of standard templates that ships with the app. The sample listings show these templates. The application doesn't build a single file from scratch; everything is based on the templates. Each template file name is easily changed through the cs_stats property sheet, so you don't even have to use the names provided. The app uses <!--VARIABLE--> tags in the HTML to replace things such as number of kills, deaths, K:D ratio, etc. More info on that in a few sections. If you don't care for a particular stat, just remove the tag from the template and it won't be inserted. Click here for a sample template showing what each player page uses. This results in quite a few <!-- tags, but it's well worth it, and they're very descriptive.

By default, the application looks for templates in the cs_stats\templates\current folder. This folder is created when the app first starts up. If any of the base templates are missing from that folder, they are copied from the Classic folder and referenced from there. This current folder is your location for placing custom templates and the like. This is so that if you drastically change one of the templates and accidentally delete some tags that you actually wanted, you can go back to the Classic or Contemporary folders and copy them back in. If you're looking to make some new templates, use the Current folder and play to your heart's content... don't change any of the files in Classic or Contemporary.

When new templates come out, for things like new stat tracking and whatnot, the app is going to default to copying a template from the Classic folder. If you've been using the Contemporary templates, just copy over the proper HTML from the Contemporary folder to the Current directory and you're good to go.

What is PlayerSortStyleSheet.css?

As of version 0.84 of cs_stats, I moved most of the hard-coded color schemes and font sizes/types to a single cascading style sheet, called PlayerSortStyleSheet.css. Despite the name, this file is actually used by every template in the Contemporary folder. Please note that the Classic folder is not affected by this style sheet.

For anyone not familiar with style sheets, let me give a brief explanation. Style sheets are a method for altering the way your HTML looks. They are a set of "rules" that apply to the various tags that you might use in your HTML. For instance, you can change the background of your <TD> tag by doing this: <TD style="background-color: #FFFF00"> This is known as inline style, and is a quick and dirty way of changing the element. That's fine, but it doesn't really help here since we want to affect the entire page. This is where style classes comes in.

Style classes are a group of rules that apply to any element belonging to that class. You define these classes in a <STYLE> block someplace near the top before you actually need to use the style. In cs_stats, all of the style classes are located in the PlayerSortStyleSheet.css file. You'll see entries in there beginning with a period (.) These are the classes. When it comes time to reference a class, you add class="classname" to the properties of your tag, and the rules that you set up earlier will apply to that element.

There's a lot more to do with style sheets and the like, much more so than I have described here. I'd suggest grabbing an updated HTML book that covers the latest specfications if you're interested in learning more about what all you can do with style sheets.

What about those player listings, can I tweak those?

Just like per-player stats, the player listings, such as ranked by number of kills, ranked by K:D ratio, etc. can all be modified to your heart's content. The app uses tags like <!--PLAYER_LIST_TABLE_BEGIN--> and <!--PLAYER_LIST_TABLE_END--> to strip out the section that should be duplicated for every player that is listed. Click here for a sample template. Basically you put the < tr > and < td > stuff you'd normally use in a table listing between those two tags, and include the custom stat tags that the app is looking for. The app takes it from there, filling in each player's stats in the specified fields, and inserting that entire row into whatever table or structure you've got configured.

The sample listings show every player that met the minimum requirements, but that's just how I created them. There is a setting to display only the top X amount of players for any given category, like the Top 10 players with the most kills. The default for this setting is 0, which means all players that met the criteria will be displayed. For really popular servers with thousands and thousands of players, it's probably a good thing to strip the output down to only a couple hundred.

What are these average stats?

The application has the ability to generate average stats for all the players it finds that meet the minimum requirements. Based on what this "average" player would score, you can compare a player against it to see whether they're an "above average" or "below average" player in a given category. The average stats give some validity to the various stats so you can get a feel for how good (or bad) a player is. These average stats, like everything else, are an optional thing.

How do you calculate the overall rating?

The overall rating is based on a set of five stats: K:D ratio, kills per minute, deaths per minute, kills per round, and deaths per round. I've taken the averages gathered from many months of stat collection, and determined what an average player would score in any given stat. Using 100 as being completely average, anything less being under average, and anything greater being above average. The five stats are weighted differently, based on a more personal decision as to what is more meaningful. For instance, I consider K:D ratio to be the most telling stat out of any for what makes a player good. Thus, it makes up 30% of the overall rating. Essentially, you divide the weight of a stat by the average, then multiply that result by the player's score. For the death stats, lower is better, so it inverts the score to result in a more positive value. Here's the formula:

Player scoring values: Stat weights: Average stat values:
  • KD = Kill:Death ratio
  • KPM = Kills per minute
  • DPM = Deaths per minute
  • KPR = Kills per round
  • DPR = Deaths per round
  • KD_W = KD weight = 30.0
  • KPM_W = KPM weight = 20.0
  • DPM_W = DPM weight = 15.0
  • KPR_W = KPR weight = 20.0
  • DPR_W = DRP weight = 15.0
  • KD_A = KD average = 1.0
  • KPM_A = KPM average = .382
  • DPM_A = DPM average = .382
  • KPR_A = KPR average = 7.431
  • DPR_A = DPR average = 7.431

Rating = (KD * (KD_W / KD_A)) + (KPM * (KPM_W / KPM_A)) + ( ((DPM_A - DPM) + DPM_A) * (DPM_W / DPM_A) ) + (KPR * (KPR_W / KPR_A)) + ( ((DPR_A - DPR) + DPR_A) * (DPR_W / DPR_A) )

There's one last twist to this. The formula then takes into account the number of minutes played. Obviously, someone who scores well for 30 minutes of play has not shown the same level of consistency as someone who has an identical score with 1000 minutes of play. This only applies to players who score above 100 with the above calculation... I didn't feel it necessary to deduct from below average players since there wouldn't be much discussion as to how valid their scores are compared to others with more minutes. So here's the last step:

Rating = ((Rating - 100) * (NumMinutes * .002)) + Rating

This means that someone with 500 minutes will get the full above average score. Someone with only 50 minutes will only get 1/10th of their above-average score. They're still above average, just not as much. Anyone with 500 minutes or more will always have the pure formula calculation.

Okay, what are all these tags? There's tons of them!

The various tags can be separated into types:

  • Application settings
  • Output URL links
  • HTML code blocks
  • Statistics
One important thing to remember about these tags: not one of them is required. They are all optional. What does that mean, exactly? It means the app will simply skip outputting HTML into your templates if the tags are not there. If you don't care about showing kills per minute, for example, you can leave that section out entirely, and it will never get inserted. The same holds true for all of the tags the application knows about. You could specify complete junk as a template, and the app won't be bothered at all. Following the HTML standard for comments, all tags begin with <!-- and end with -->

View the current HTML tags

Help! I'm lost in all these tags!

There are quite a few of them, aren't there? That's the one down-side to being completely customizable; there's lots and lots of little pieces that go into it. The templates should act as your starting point, like I mentioned earlier. Create your own directory, and copy them over. Don't be afraid to tweak the heck out of them, but do it with a backup so you're not re-installing the application just to get the original templates back.

All of the classic templates show every single stat that the application keeps track of. Some people probably won't want a given stat, and they can safely remove them. That's the whole idea of customization! If you run into trouble with a new template you're creating, and the app doesn't want to put the right data in there, don't hesitate to send me a note and I'd be happy to take a look at it.

The tags should not be case-sensitive at all. I used UPPER_CASE everywhere to make them stand out, but you can use lower-case if you prefer.

What are the various application settings?

I'm working on doing the HTML for this; in the meantime, the application itself gives a pretty good description for all of the various settings, what they mean, what their default is, etc.

Can I edit a player's stats?

In a word: yes! With version 0.82, I've added a built-in player editor. This is found on the main dialog, a button labelled "Editor". Strange, I know. When you click on this, you are presented with the dialog box on the right.

Before I begin, let me make this point: nothing will happen to any of the changes you make during editing until you click on the OK button. You can remove players, edit their stats, combine players, all kinds of things... not one of those changes will take effect until you OK it. This is just a safety in case you make a mistake and remove the wrong player, etc.

Most of the buttons should be obvious. Highlight a player (or multiple players), then click on Remove to remove that player. Highlight two or more players, then click on Combine to take and combine the stats of those selected players. You would use this if you knew someone who had changed names, and you want the stats to be combined. You will be prompted to choose the name that you want to have remaining as the newly combined player.

Below the player list is a text field with a button labelled Find. This is where you can type in a name, click the button, and the app will find and highlight the closest match to that name. With thousands of potential players, this makes it much easier to find someone. The list is sorted, but this is just a quick-access method.

Probably the most useful function here is the Edit button. This allows you to manually edit the stats for a player. See image on left. Every stat that is tracked can be changed here. Please note, however, that some of the ratios are derived from other stats. Things like overall K:D is calculated from, oddly enough, the number of Kills divided by number of Deaths. So you could change the K:D stat, but as soon as that player shows up again and has new data input, the ratio is going to change.

To change a stat, just highlight it in the list, and change the value in the Value: edit box. Like the application settings, you don't need to do anything to save the value. Just by changing it in the edit box is enough to have the new value set.

The Opponents list is where you can view all of the players that this particular player has come up against. You can change the number of kills and deaths, or just completely remove that opponent from the player's list. Clicking on the header items of the list will sort the opponents by that header.