diff options
Diffstat (limited to 'utils/tfstats/logevent.cpp')
| -rw-r--r-- | utils/tfstats/logevent.cpp | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/utils/tfstats/logevent.cpp b/utils/tfstats/logevent.cpp new file mode 100644 index 0000000..1e7a7b9 --- /dev/null +++ b/utils/tfstats/logevent.cpp @@ -0,0 +1,391 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implementation of CLogEvent +// +// $Workfile: $ +// $Date: $ +// +//------------------------------------------------------------------------------------------------------ +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// +#include <stdio.h> +#include <time.h> +#include <string.h> +#include "LogEvent.h" +#include "util.h" +#include "memdbg.h" + + + +//For debugging more than anything +const char* CLogEvent::TypeNames[]= +{ + {"No Type/Invalid!"}, + {"Log File Initialize"}, + {"Server Spawn"}, + {"Server Shutdown"}, + {"Log Closed"}, + {"Server Misc"}, + {"Server Name"}, + {"Team Rename"}, + {"Level Change"}, + {"Cvar Assignment"}, + {"Map CRC"}, + {"Team Join"}, + {"Connect"}, + {"Enter game"}, + {"Disconnect"}, + {"Name Change"}, + {"Frag!"}, + {"Team frag!"}, + {"Suicide!"}, + {"Killed by world!"}, + {"Build"}, + {"Match Results Marker"}, + {"Match Draw"}, + {"Match Victor"}, + {"Match Team Results"}, + {"Talk"}, + {"Team Talk"}, + {"Cure"}, + {"Named Goal Activated"}, + {"Anon Goal Activated"}, + {"Named Broadcast"}, + {"Anon Broadcast"}, + {"Change Class"}, +}; + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::getArgument +// Purpose: returns the iWhichArg'th argument +// Input: iWhichArg - the desired argument +// Output: const CLogEventArgument* +//------------------------------------------------------------------------------------------------------ +const CLogEventArgument* CLogEvent::getArgument(int iWhichArg) const +{ + if (iWhichArg < m_args.size()) + return m_args[iWhichArg]; + else + return NULL; +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::parseArgs +// Purpose: extracts the arguments out of the event text. +//------------------------------------------------------------------------------------------------------ +void CLogEvent::parseArgs() +{ + + char temp[512]; + char* write=temp; + const char* read=m_EventMessage; + + int i=0; + while (*read) + { + + if (*read == '\"') + { + //parseArgument moves the read pointer to the char after the closing " + parseArgument(++read); + *(write++)='['; + *(write++)=(char)(i++)+48; //convert int to char by adding 48 + *(write++)=']'; + } + else + *write++=*read; + + *read++; + } + *write=0; + + Util::str2lowercase(temp,temp); + + m_StrippedText=new TRACKED char[strlen(temp)+1]; + strcpy(m_StrippedText,temp); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::parseArgument +// Purpose: helper function for parseArgs, this actually removes the argument +// Input: raw - the string from which we want to remove the argument +//------------------------------------------------------------------------------------------------------ +void CLogEvent::parseArgument(const char*& raw) +{ + + char* atemp; + if (!(atemp=strchr(raw,'\"'))) + return; + + *atemp=0; //null out the closing " + + CLogEventArgument* newarg=new CLogEventArgument(raw); + newarg->init(raw); + m_args.push_back(newarg); + + + *atemp='\"'; //restore it. + raw=atemp; //advance the pointer +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::keywordsOccur +// Purpose: tests to see if all of the given keywords occur in the text for this event +// Input: s1 - first keyword (required) +// s2 - second keyword (optional) +// s3 - third keyword (optional) +// Output: Returns true if the event text contains all of the keywords passed in +//------------------------------------------------------------------------------------------------------ +bool CLogEvent::keywordsOccur(char* s1,char* s2,char* s3) +{ + bool result=(strstr(m_StrippedText,s1)!=NULL); + if (s2) + { + result = result && (strstr(m_StrippedText,s2)!=NULL); + if (s3) + { + result = result && (strstr(m_StrippedText,s3)!=NULL); + } + } + return result; +} + + + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::determineType +// Purpose: this is a big dumb if statement to determine the type of this event +//------------------------------------------------------------------------------------------------------ +//this is pretty cheesy +void CLogEvent::determineType() +{ + + //for now just do this in a big dumb if statement + + if (keywordsOccur("killed","self","with")) + m_EventType=SUICIDE; + else if (keywordsOccur("log closed")) + m_EventType=LOG_CLOSED; + else if (keywordsOccur("server name is")) + m_EventType=SERVER_NAME; + else if (keywordsOccur("team name of")) + m_EventType=TEAM_RENAME; + else if (keywordsOccur("killed","by","world")) + m_EventType=KILLED_BY_WORLD; + else if (keywordsOccur("killed","(teammate)")) + m_EventType=TEAM_FRAG; + else if (keywordsOccur("killed","with")) + m_EventType=FRAG; + else if (keywordsOccur("say_team")) + m_EventType=SAY_TEAM; + else if (keywordsOccur("say")) + m_EventType=SAY; + else if (keywordsOccur("joined team")) + m_EventType=TEAM_JOIN; + else if (keywordsOccur("changed to team")) + m_EventType=TEAM_JOIN; + else if (keywordsOccur("log file started")) + m_EventType=LOG_FILE_INIT; + else if (keywordsOccur("spawning server")) + m_EventType=SERVER_SPAWN; + else if (keywordsOccur("connected","address")) + m_EventType=CONNECT; + else if (keywordsOccur("has entered the game")) + m_EventType=ENTER_GAME; + else if (keywordsOccur("disconnected")) + m_EventType=DISCONNECT; + else if (keywordsOccur("changed name to")) + m_EventType=NAME_CHANGE; + else if (keywordsOccur("built")) + m_EventType=BUILD; + else if (keywordsOccur("map crc")) + m_EventType=MAP_CRC; + else if (keywordsOccur("match","results","=------=")) + m_EventType=MATCH_RESULTS_MARKER; + else if (keywordsOccur("activated the goal")) + m_EventType=NAMED_GOAL_ACTIVATE; + else if (keywordsOccur("goal", "was activated")) + m_EventType=ANON_GOAL_ACTIVATE; + else if (keywordsOccur("named broadcast")) + m_EventType=NAMED_BROADCAST; + else if (keywordsOccur("broadcast")) + m_EventType=ANON_BROADCAST; + else if (keywordsOccur("changed class")) + m_EventType=CLASS_CHANGE; + else if (keywordsOccur("-> draw <-")) + m_EventType=MATCH_DRAW; + else if (keywordsOccur("defeated")) + m_EventType=MATCH_VICTOR; + else if (keywordsOccur("results")) + m_EventType=MATCH_TEAM_RESULTS; + else if (keywordsOccur("=")) + m_EventType=CVAR_ASSIGN; + else m_EventType=SERVER_MISC; +} + + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::CLogEvent +// Purpose: CLogEvent constructor +//------------------------------------------------------------------------------------------------------ +CLogEvent::CLogEvent() +:m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL) +{} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::~CLogEvent +// Purpose: CLogEvent destructor +//------------------------------------------------------------------------------------------------------ +CLogEvent::~CLogEvent() +{ + //this errors?! + if (m_EventMessage) + delete[] m_EventMessage; + if (m_StrippedText) + delete[] m_StrippedText; +} + + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::print +// Purpose: debugging function, prints this event to a file +// Input: f - the file to print to +//------------------------------------------------------------------------------------------------------ +void CLogEvent::print(FILE* f) +{ + fprintf(f,"(%li) Event: %s\n",m_EventTime,m_EventMessage); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::CLogEvent +// Purpose: CLogEvent constructor that reads an event from the specified file +// Input: f - the file to read from +//------------------------------------------------------------------------------------------------------ +CLogEvent::CLogEvent(FILE* f) +:m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL) +{ + readEvent(f); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::readEvent +// Purpose: reads an event by reading each part, then checking if it was successful +// Input: f - the file to read from +//------------------------------------------------------------------------------------------------------ +void CLogEvent::readEvent(FILE* f) +{ + m_Valid=true; + if (m_Valid) readEventCode(f); + if (m_Valid) readEventTime(f); + if (m_Valid) readEventMessage(f); + if (m_Valid) parseArgs(); + if (m_Valid) determineType(); + if (m_Valid) m_Valid=!feof(f); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::readEventCode +// Purpose: reads the event code, the first character on the line (should be 'L') +// Input: f - the file to read from +//------------------------------------------------------------------------------------------------------ +void CLogEvent::readEventCode(FILE* f) +{ + fscanf(f," %c ",&m_EventCode); + if (m_EventCode!='L') + m_Valid=false; + + if (feof(f)) + m_Valid=false; +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::readEventMessage +// Purpose: reads the text of the event message. +// Input: f - the file to read from +//------------------------------------------------------------------------------------------------------ +void CLogEvent::readEventMessage(FILE* f) +{ + char temp[512]; + fgets(temp,512,f); + + //special case hack for broadcasts + if (strncmp(temp,"Named Broadcast:",16)==0 || strncmp(temp,"Broadcast:",16)==0) + { + while(1) + { + fpos_t temp_pos; + fgetpos(f,&temp_pos); + CLogEvent cle(f); + fseek(f,temp_pos,SEEK_SET); + if (cle.isValid()) + { + //if the next log event is valid, then this broadcast did not span lines + break; + } + else + { + temp[strlen(temp)-1]=' '; //rid ourselves of newline + temp[strlen(temp)]=0; //rid ourselves of newline + char buf[512]; + fgets(buf,512,f); + strcat(temp,buf); + } + } + } + + if (feof(f)) + { + m_Valid=false; + } + else + { + temp[strlen(temp)-1]=0; //rid ourselves of newline + m_EventMessage=new TRACKED char[strlen(temp)+1]; + strcpy(m_EventMessage,temp); + } + +} + +//------------------------------------------------------------------------------------------------------ +// Function: CLogEvent::readEventTime +// Purpose: reads and converts the time the event happened into a time_t +// Input: f - the file to read from +//------------------------------------------------------------------------------------------------------ +void CLogEvent::readEventTime(FILE* f) +{ + + int month=-1,day=-1,year=-1; + int hour=-1,minute=-1,second=-1; + fscanf(f," %d/%d/%d - %d:%d:%d: ",&month,&day,&year,&hour,&minute,&second); + if (month==-1 ||day==-1 ||year==-1 || hour==-1 || minute==-1 || second==-1) + m_Valid=false; + else if (feof(f)) + m_Valid=false; + else + { + tm t; + t.tm_isdst=0; + t.tm_hour=hour; + t.tm_mday=day; + t.tm_min=minute; + t.tm_sec=second; + t.tm_year=year-1900; //note no y2k prob here, so says the CRT manual + //this allows values greater than 99, but it + //just wants the input with 1900 subtracted. + t.tm_mon=month-1; //jan = 0 + m_EventTime=mktime(&t); + + + + } + +} + |