source-engine/utils/videocardstats/cardstats.cpp

1047 lines
24 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include <stdio.h>
#include <stdlib.h>
#include "CardStats.h"
//-----------------------------------------------------------------------------
// Main stats loop
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
if ( argc != 3 ) // a unix style usage string
{
printf ( "Usage: <SearchString> <Filename>\n" );
printf ( "Output file will be <filename>.<searchstring>.txt" );
return 0;
}
char* pszCardtype = argv[1]; // video card type we are looking for
char* pszFilename = argv[2]; // file containing the data
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
int nFileSize = LoadFileIntoBuffer(buf, pszFilename);
ParseHeader ( buf );
CUtlBuffer output ( 0, 255, CUtlBuffer::TEXT_BUFFER );
int binwidth=100;
// video card stats over time
//TimeSeriesVCard ( buf, output, pszCardtype, nFileSize, binwidth );
// cpu type stats over time
//TimeSeriesCPU ( buf, output, pszCardtype, nFileSize, binwidth );
// CPU vs Videocard
//ParseFile ( buf, output, pszCardtype, nFileSize, binwidth, 0);
// CPU vs Memory
//ParseFile2 ( buf, output, pszCardtype, nFileSize, binwidth );
//CPU vs network speed
//ParseFile3 ( buf, output, pszCardtype, nFileSize, binwidth );
// histogram of video card distribution
HistogramVidCards ( buf, output, pszCardtype, nFileSize, binwidth );
//HistogramNetSpeed ( buf, output, pszCardtype, nFileSize, binwidth );
//HistogramRam ( buf, output, pszCardtype, nFileSize, binwidth );
//HistogramCPU ( buf, output, pszCardtype, nFileSize, binwidth );
WriteOutputToFile ( output, pszFilename, pszCardtype );
return 0;
}
void HistogramCPU( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
ParseFile ( inbuf, outbuf, "", size, binwidth, 1 );
}
//-----------------------------------------------------------------------------
// Reads entire file contents in to utlbuffer
// input-buffer to load fileinto, filename
// output-filesize
//-----------------------------------------------------------------------------
int LoadFileIntoBuffer(CUtlBuffer &buf, char *pszFilename)
{
// Open the file
FILE *fh = fopen ( pszFilename, "rb" );
if (fh == NULL)
{
printf ("Unable to open datafile. Check path/name.");
exit( 0 );
}
fseek( fh, 0, SEEK_END );
int nFileSize = ftell( fh );
fseek ( fh, 0, SEEK_SET );
// Read the file in one gulp
buf.EnsureCapacity( nFileSize );
int result=fread( buf.Base(), sizeof( char ), nFileSize, fh );
fclose( fh );
buf.SeekPut( CUtlBuffer::SEEK_HEAD, result );
return nFileSize;
}
//-----------------------------------------------------------------------------
// Writes the contents of the utlbuffer to file
// datafile name becomes name.card.txt for results
//-----------------------------------------------------------------------------
void WriteOutputToFile( CUtlBuffer &buf, char *pszFilename, char *pszCardtype )
{
char pszOutFilename[500];
strncpy( pszOutFilename, pszFilename, strlen( pszFilename )-3 );
pszOutFilename[strlen(pszFilename)-3]='\0';
strcat ( pszOutFilename, pszCardtype );
strcat ( pszOutFilename, ".txt\0" );
FILE *fh = fopen ( pszOutFilename, "w" );
if ( fh == NULL )
{
printf ( "Unable to open outputfile." );
exit(0);
}
fwrite ( buf.Base(), sizeof( char ), buf.TellPut(), fh );
fclose( fh );
}
//-----------------------------------------------------------------------------
// Strips off header fields from datafile
//-----------------------------------------------------------------------------
void ParseHeader( CUtlBuffer &buf )
{
// remove first line of data (field labels)
char pszTrash[256];
buf.Scanf( "%s ", pszTrash);
buf.Scanf( "%s ", pszTrash);
buf.Scanf( "%s ", pszTrash);
buf.Scanf( "%s ", pszTrash);
buf.Scanf( "%s ", pszTrash);
buf.Scanf( "%s \n", pszTrash);
}
//-----------------------------------------------------------------------------
// Counts number of users that have a given cpu bin speed for videocard string
//
// Parses buffer into fields and puts results into outbuf
// size is size of the file read in
//-----------------------------------------------------------------------------
void ParseFile( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth, int nofilter)
{
// Each bin is how many computers with the given card had cpus > cpubin
// and less than the next bin so cpu 200 covers cpu's from 200 to 299
CUtlVector<int> nCpuList;
CUtlVector<int> nQuantity;
for ( int i=0; i <= 2400 ; i+=binwidth) // a reasonable cpu range
{
nCpuList.AddToTail(i);
nQuantity.AddToTail(0);
}
int totalUsers=0;
while ( inbuf.TellGet() < size )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[300];
int nNetSpeed, nRam, nCpu;
int nRead=inbuf.Scanf( "%s %d %d %d ", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
}
pszCard[i] = '\0';
if (nRead != 4)
continue;
// if card is our type
if ( nofilter || Q_stristr ( pszCard, pszSearchString ) != NULL )
{
InsertResult(nCpu, nCpuList, nQuantity);
}
totalUsers++;
}
if (nCpuList.Size()>65000)
{
printf ("Too many points, increase bin width\n");
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
int total=0;
outbuf.Printf ( "Cpu\tQuantity\n" ); // headers
for ( int i=0; i < nCpuList.Size(); ++i )
{
outbuf.Printf ( "%d\t%d\n", nCpuList[i], nQuantity[i] );
total+=nQuantity[i];
}
printf ("Users in this subset %d\n", total);
printf ("Percent of dataset %.2f", ((float)total/(float)totalUsers)*100);
}
//-----------------------------------------------------------------------------
// given cpu bin, plots number of users in a given memory bin
//
// Parses buffer into fields and puts results into outbuf
// size is size of the file read in
//-----------------------------------------------------------------------------
#define NMEMBINS 6
//#define NCPUBINS 48 // binwidth 50
#define NCPUBINS 24 // binwidth 100
void ParseFile2( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
binwidth=100;
// Each bin is how many computers with the given card had cpus > cpubin
// and less than the next bin so cpu 200 covers cpu's from 200 to 299
CUtlVector<int> nCpuList;
CUtlVector<int> nMemList;
int nQuantity[NMEMBINS][NCPUBINS];
for (int i=0; i < NMEMBINS; ++i)
{
for (int j=0; j< NCPUBINS; ++j)
nQuantity[i][j]=0;
}
for ( int i=0; i <= 2400 ; i+=binwidth) // a reasonable cpu range
{
nCpuList.AddToTail(i);
}
nMemList.AddToTail(0);
int basemem=64;
while ( basemem < 2050 )
{
nMemList.AddToTail(basemem);
basemem<<=1;
}
int totalUsers=0;
int maxram=0;
while ( inbuf.TellGet() < size )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
// scan through the rest of the junk
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
++i;
}
// determine cpu bin
if (nCpu < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nCpu > nCpuList[nCpuList.Size()-1] )
continue;
i=0;
while ( nCpu > nCpuList[i] )
{
++i;
}
int cpuIndex = i-1;
assert(i<nCpuList.Size());
// determine memory bin
if (nRam < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nRam > nMemList[nMemList.Size()-1] )
continue;
i=0;
while ( nRam > nMemList[i] )
{
++i;
}
int memIndex = i-1;
assert(i<nMemList.Size());
// insert data
assert(memIndex<NMEMBINS);
assert(cpuIndex<NCPUBINS);
(nQuantity[memIndex][cpuIndex])++;
totalUsers++;
//printf ("%d\n", totalUsers);
if (nRam> maxram)
maxram=nRam;
}
if (nCpuList.Size()>65000)
{
printf ("Too many points, increase bin width\n");
}
printf("TotalUsers %d\n", totalUsers);
printf("Max ram %d\n", maxram);
// write results to an output buffer
outbuf.Printf ( "Cpu" ); // headers
for (int j=1; j < nMemList.Size(); ++j)
outbuf.Printf ("\tMemoryBin%d", nMemList[j]);
outbuf.Printf ("\n");
for ( int i=0; i < NCPUBINS; ++i )
{
outbuf.Printf ( "%d", nCpuList[i]);
for (int j=0; j < NMEMBINS; ++j)
outbuf.Printf ("\t%d", nQuantity[j][i]);
outbuf.Printf ("\n");
}
}
//-----------------------------------------------------------------------------
// given cpu bin, plots number of users in a given network speed bin
//
// Parses buffer into fields and puts results into outbuf
// size is size of the file read in
//-----------------------------------------------------------------------------
#define NNETBINS 9
void ParseFile3( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
binwidth=100;
// Each bin is how many computers with the given card had cpus > cpubin
// and less than the next bin so cpu 200 covers cpu's from 200 to 299
CUtlVector<int> nCpuList;
CUtlVector<int> nNetList;
int nQuantity[NNETBINS][NCPUBINS];
for (int i=0; i < NNETBINS; ++i)
{
for (int j=0; j< NCPUBINS; ++j)
nQuantity[i][j]=0;
}
for (int i=0; i <= 2400 ; i+=binwidth) // a reasonable cpu range
{
nCpuList.AddToTail(i);
}
nNetList.AddToTail(0);
nNetList.AddToTail(28);
nNetList.AddToTail(33);
nNetList.AddToTail(56);
nNetList.AddToTail(112);
nNetList.AddToTail(256);
nNetList.AddToTail(512);
nNetList.AddToTail(1000);
nNetList.AddToTail(2000);
int totalUsers=0;
int maxspeed=0;
while ( inbuf.TellGet() < size )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
// scan through the rest of the junk
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
++i;
}
// determine cpu bin
if (nCpu < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nCpu > nCpuList[nCpuList.Size()-1] )
continue;
i=0;
while ( nCpu > nCpuList[i] )
{
++i;
}
int cpuIndex = i-1;
assert(i<nCpuList.Size());
// determine netspeed bin
if (nNetSpeed < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nNetSpeed > nNetList[nNetList.Size()-1] )
continue;
i=0;
while ( nNetSpeed > nNetList[i] )
{
++i;
}
int netIndex = i;
assert(i<nNetList.Size());
// insert data
assert(netIndex<NNETBINS);
assert(cpuIndex<NCPUBINS);
(nQuantity[netIndex][cpuIndex])++;
totalUsers++;
//printf ("%d\n", totalUsers);
if (nNetSpeed> maxspeed)
maxspeed=nNetSpeed;
}
if (nCpuList.Size()>65000)
{
printf ("Too many points, increase bin width\n");
}
printf("TotalUsers %d\n", totalUsers);
printf("Max ram %d\n", maxspeed);
// write results to an output buffer
outbuf.Printf ( "Cpu" ); // headers
for (int j=0; j < nNetList.Size()-1; ++j)
outbuf.Printf ("\t%d-%d", nNetList[j], nNetList[j+1]);
outbuf.Printf ("\n");
for (int i=0; i < NCPUBINS; ++i )
{
outbuf.Printf ( "%d", nCpuList[i]);
for (int j=0; j < NNETBINS; ++j)
outbuf.Printf ("\t%d", nQuantity[j][i]);
outbuf.Printf ("\n");
}
}
//-----------------------------------------------------------------------------
// given time bin, plots number of users in a given cpu TYPE over time,
// as the numbers came into the server
//
// Parses buffer into fields and puts results into outbuf
// size is size of the file read in
//-----------------------------------------------------------------------------
#define CPUBINS 3 // 0=AMD, 1=Intel, 2=Unknown
#define MAXUSERS 750000
void TimeSeriesCPU( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
binwidth=600;
// unequally sized bins
// Each bin is how many computers with the given card had cpus > cpubin
// and less than the next bin so cpu 200 covers cpu's from 200 to 299
CUtlVector<int> nTimeList;
int nQuantity[30][CPUBINS];
for (int i=0; i < 30; ++i)
{
for (int j=0; j< CPUBINS; ++j)
nQuantity[i][j]=0;
}
nTimeList.AddToTail(0);
int bin=10000;
int i=bin;
for (i; i<=MAXUSERS; i=bin)
{
nTimeList.AddToTail(i);
bin<<=1;
}
nTimeList.AddToTail(i);
// for unequal bins
int currentTimeBin=1;
int totalUsers=0;
while ( (inbuf.TellGet() < size) )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
if (i >= 300)
break;
}
// check for those blasted hackers
if (i>= 300)
{
// read rest
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
}
continue;
}
pszCard[i] = '\0';
int cpuIndex=2; // default is unknown
if ( Q_stristr ( pszCard, "SSE" ) != NULL )
{
cpuIndex=1; // intel
}
else if ( Q_stristr ( pszCard, "KNI" ) != NULL )
{
cpuIndex=1; // intel
}
else if ( Q_stristr ( pszCard, "3DNOW" ) != NULL )
{
cpuIndex=0;
}
// update nTimeList bin if necessary
if (nTimeList[currentTimeBin] <= totalUsers)
{
currentTimeBin++;
}
nQuantity[currentTimeBin][cpuIndex]++;
assert(nQuantity[currentTimeBin][cpuIndex]>0);
totalUsers++;
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
outbuf.Printf ( "CPU" ); // headers
for (int j=1; j < nTimeList.Size(); ++j)
outbuf.Printf ("\tUsersSoFar%d", nTimeList[j]);
outbuf.Printf ("\n");
for (int i=0; i < CPUBINS; ++i )
{
outbuf.Printf ( "-");
for (int j=1; j < nTimeList.Size(); ++j) // use NTIMEBINS for equal sized bins
outbuf.Printf ("\t%d", nQuantity[j][i]);
outbuf.Printf ("\n");
}
}
//-----------------------------------------------------------------------------
// given time bin, plots number of users in a given video card TYPE over time,
// as the numbers came into the server
//
// Parses buffer into fields and puts results into outbuf
// size is size of the file read in
//-----------------------------------------------------------------------------
// 0=RIVA TNT
// 1=GeForce2 MX
// 2=Microsoft Corporation GDI Generic
// 3=GeForce2 GTS
// 4=Voodoo 3
// 5=Intel 810
// 6=GeForce3
#define CARDBINS 8
void TimeSeriesVCard( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
// unequally sized bins
CUtlVector<int> nTimeList;
int nQuantity[30][CARDBINS];
for (int i=0; i < 30; ++i)
{
for (int j=0; j< CARDBINS; ++j)
nQuantity[i][j]=0;
}
nTimeList.AddToTail(0);
int bin=10000;
int i=bin;
for (i; i<=MAXUSERS; i=bin)
{
nTimeList.AddToTail(i);
bin<<=1;
}
nTimeList.AddToTail(i);
//int currentTimeBin=1;
// for unequal bins
int currentTimeBin=1;
int numTimeBins=nTimeList.Size();
int totalUsers=0;
while ( (inbuf.TellGet() < size) )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
if (i >= 300)
break;
}
// check for those blasted hackers
if (i>= 300)
{
// read rest
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
}
continue;
}
pszCard[i] = '\0';
// 0=RIVA TNT
// 1=GeForce2 MX
// 2=Microsoft Corporation GDI Generic
// 3=GeForce2 GTS
// 4=Voodoo 3
// 5=Intel 810
// 6=GeForce3
// 7=All others
int cardIndex=7; // default is other
if ( Q_stristr ( pszCard, "RIVA TNT2" ) != NULL )
{
//printf ("%s", pszCard);
cardIndex=0;
}
else if ( Q_stristr ( pszCard, "GeForce2 MX" ) != NULL )
{
cardIndex=1;
}
else if ( Q_stristr ( pszCard, "Microsoft Corporation GDI Generic" ) != NULL )
{
cardIndex=2;
}
else if ( Q_stristr ( pszCard, "GeForce2 GTS" ) != NULL )
{
cardIndex=3;
}
else if ( Q_stristr ( pszCard, "Voodoo3" ) != NULL )
{
cardIndex=4;
}
else if ( Q_stristr ( pszCard, "Intel 810" ) != NULL )
{
cardIndex=5;
}
else if ( Q_stristr ( pszCard, "GeForce3" ) != NULL )
{
cardIndex=6;
}
// update nTimeList bin if necessary
if (nTimeList[currentTimeBin] <= totalUsers)
{
currentTimeBin++;
}
nQuantity[currentTimeBin][cardIndex]++;
totalUsers++;
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
outbuf.Printf ( "Video Card" ); // headers
for (int j=1; j < nTimeList.Size(); ++j)
outbuf.Printf ("\tUsersSoFar%d", nTimeList[j]);
outbuf.Printf ("\n");
for (int i=0; i < CARDBINS; ++i )
{
outbuf.Printf ( "-");
for (int j=1; j < numTimeBins; ++j) // use NTIMEBINS for equal sized bins
outbuf.Printf ("\t%d", nQuantity[j][i]);
outbuf.Printf ("\n");
}
}
//-----------------------------------------------------------------------------
// Increment the proper bin's counter
//-----------------------------------------------------------------------------
void InsertResult( int nCpu, CUtlVector<int> &nCpuList, CUtlVector<int> &nQuantity )
{
if (nCpu < 0) // handle corrupt data
return;
// handle outliers--bin is off the scale
if ( nCpu > nCpuList[nCpuList.Size()-1] )
{
//nCpuList.AddToTail( nCpu );
//nQuantity.AddToTail( 1 );
return;
}
int i=0;
while ( nCpu > nCpuList[i] )
{
++i;
}
nQuantity[i-1]++;
}
void HistogramVidCards( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
#define CARDHISTBINS 15
// unequally sized bins
int nQuantity[CARDHISTBINS];
for (int j=0; j< CARDHISTBINS; ++j)
nQuantity[j]=0;
int totalUsers=0;
while ( (inbuf.TellGet() < size) )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
if (i >= 300)
break;
}
// check for those blasted hackers
if (i>= 300)
{
// read rest
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
}
continue;
}
pszCard[i] = '\0';
// 0=RIVA TNT2
// 1=GeForce2 MX
// 2=Microsoft Corporation GDI Generic
// 3=GeForce2 GTS
// 4=Voodoo 3
// 5=Intel 810
// 6=GeForce3
// 7=Riva TNT
// 8=GeForce 256
// 9=Rage 128
// 10=S3 Savage4
// 11=SiS 630
// 12=Radeon DDR
// 13=Rage 128 Pro
// 14=All others
int cardIndex=14; // default is other
if ( Q_stristr ( pszCard, "RIVA TNT2" ) != NULL )
{
//printf ("%s", pszCard);
cardIndex=0;
}
else if ( Q_stristr ( pszCard, "GeForce2 MX" ) != NULL )
{
cardIndex=1;
}
else if ( Q_stristr ( pszCard, "Microsoft Corporation GDI Generic" ) != NULL )
{
cardIndex=2;
}
else if ( Q_stristr ( pszCard, "GeForce2 GTS" ) != NULL )
{
cardIndex=3;
}
else if ( Q_stristr ( pszCard, "Voodoo3" ) != NULL )
{
cardIndex=4;
}
else if ( Q_stristr ( pszCard, "Intel 810" ) != NULL )
{
cardIndex=5;
}
else if ( Q_stristr ( pszCard, "GeForce3" ) != NULL )
{
cardIndex=6;
}
else if ( Q_stristr ( pszCard, "Riva TNT" ) != NULL )
{
cardIndex=7;
}
else if ( Q_stristr ( pszCard, "GeForce 256" ) != NULL )
{
cardIndex=8;
}
else if ( Q_stristr ( pszCard, "Rage 128 Pro" ) != NULL )
{
cardIndex=13;
}
else if ( Q_stristr ( pszCard, "Rage 128" ) != NULL )
{
cardIndex=9;
}
else if ( Q_stristr ( pszCard, "S3 Savage4" ) != NULL )
{
cardIndex=10;
}
else if ( Q_stristr ( pszCard, "SiS 630" ) != NULL )
{
cardIndex=11;
}
else if ( Q_stristr ( pszCard, "Radeon DDR" ) != NULL )
{
cardIndex=12;
}
nQuantity[cardIndex]++;
totalUsers++;
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
outbuf.Printf ( "Video Card" ); // headers
outbuf.Printf ("\tNumber of Users\n");
outbuf.Printf ("\n");
for ( int i=0; i < CARDHISTBINS; ++i )
{
outbuf.Printf ( "-");
outbuf.Printf ("\t%d", nQuantity[i]);
outbuf.Printf ("\n");
}
}
void HistogramNetSpeed( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
#define NETHISTBINS 9
// unequally sized bins
int nQuantity[NETHISTBINS];
for (int j=0; j< NETHISTBINS; ++j)
nQuantity[j]=0;
CUtlVector<int> nNetList;
nNetList.AddToTail(0);
nNetList.AddToTail(28);
nNetList.AddToTail(33);
nNetList.AddToTail(56);
nNetList.AddToTail(112);
nNetList.AddToTail(256);
nNetList.AddToTail(512);
nNetList.AddToTail(1100);
nNetList.AddToTail(2000);
int totalUsers=0;
while ( (inbuf.TellGet() < size) )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
if (i >= 300)
break;
}
// check for those blasted hackers
if (i>= 300)
{
// read rest
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
}
continue;
}
pszCard[i] = '\0';
if (nNetSpeed < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nNetSpeed > nNetList[nNetList.Size()-1] )
continue;
i=0;
while ( nNetSpeed > nNetList[i] )
{
++i;
}
int netIndex = i;
nQuantity[netIndex]++;
totalUsers++;
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
outbuf.Printf ( "Network Speed" ); // headers
for (int j=0; j < nNetList.Size()-1; ++j)
outbuf.Printf ("\t%d-%d", nNetList[j], nNetList[j+1]);
outbuf.Printf ("\n");
for ( int i=0; i < NETHISTBINS; ++i )
{
outbuf.Printf ( "-");
outbuf.Printf ("\t%d", nQuantity[i]);
outbuf.Printf ("\n");
}
}
void HistogramRam( CUtlBuffer &inbuf, CUtlBuffer &outbuf, char *pszSearchString, int size, int binwidth)
{
#define RAMHISTBINS 20
// unequally sized bins
int nQuantity[RAMHISTBINS];
for (int j=0; j< RAMHISTBINS; ++j)
nQuantity[j]=0;
CUtlVector<int> nRamList;
nRamList.AddToTail(0);
int basemem=16;
while ( basemem < 2050 )
{
nRamList.AddToTail(basemem);
basemem<<=1;
}
int totalUsers=0;
while ( (inbuf.TellGet() < size) )
{
// Now parse the utlbuffer
// file has fields of version, netspeed, ram, cpu and card type
char pszVersion[256];
int nNetSpeed, nRam, nCpu;
inbuf.Scanf( "%s %d %d %d", pszVersion, &nNetSpeed, &nRam, &nCpu );
char pszCard[300];
char chSentinel = ' ';
int i=0;
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
pszCard[i] = chSentinel;
++i;
if (i >= 300)
break;
}
// check for those blasted hackers
if (i>= 300)
{
// read rest
while (( chSentinel != '\n' ))
{
chSentinel = inbuf.GetChar();
}
continue;
}
pszCard[i] = '\0';
if (nRam < 0) // handle corrupt data
continue;
// handle outliers--bin is off the scale
if ( nRam > nRamList[nRamList.Size()-1] )
continue;
i=0;
while ( nRam > nRamList[i] )
{
++i;
}
int ramIndex = i;
nQuantity[ramIndex]++;
totalUsers++;
}
printf("TotalUsers %d\n", totalUsers);
// write results to an output buffer
outbuf.Printf ( "RAM" ); // headers
for (int j=0; j < nRamList.Size()-1; ++j)
outbuf.Printf ("\t%d-%d", nRamList[j], nRamList[j+1]);
outbuf.Printf ("\n");
for ( int i=0; i < nRamList.Size(); ++i )
{
outbuf.Printf ( "-");
outbuf.Printf ("\t%d", nQuantity[i]);
outbuf.Printf ("\n");
}
}