diff options
Diffstat (limited to 'utils/tfstats/customawardtriggers.cpp')
| -rw-r--r-- | utils/tfstats/customawardtriggers.cpp | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/utils/tfstats/customawardtriggers.cpp b/utils/tfstats/customawardtriggers.cpp new file mode 100644 index 0000000..29bf8f0 --- /dev/null +++ b/utils/tfstats/customawardtriggers.cpp @@ -0,0 +1,399 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#pragma warning (disable:4786) +//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: Implementation of all the custom award trigger classes +// +// $Workfile: $ +// $Date: $ +// +//------------------------------------------------------------------------------------------------------ +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= +#include "TFStatsApplication.h" +#include "CustomAwardTriggers.h" +#include "memdbg.h" +#include "util.h" + +using namespace std; +//------------------------------------------------------------------------------------------------------ +// Function: CCustomAwardTrigger::readTrigger +// Purpose: reads a trigger definition from the given rule file and returns a new trigger +// Input: f - a pointer to the TextFile object that represents the rule file to read from +// Output: CCustomAwardTrigger* +//------------------------------------------------------------------------------------------------------ +CCustomAwardTrigger* CCustomAwardTrigger::readTrigger(CTextFile& f) +{ + CCustomAwardTrigger* retval=NULL; + + string type="fullsearch"; + vector<string> keys; + int value = 1 ; + int teamValue = 1; + + + f.discard("{"); + map<string,string> extraProps; + const char* token=f.getToken(); + + while (token) + { + if (stricmp(token,"value")==0) + { + f.discard("="); + value=atoi(f.readString()); + f.discard(";"); + } + else if (stricmp(token,"teamvalue")==0) + { + f.discard("="); + teamValue=atoi(f.readString()); + f.discard(";"); + } + else if (stricmp(token,"type")==0) + { + f.discard("="); + type=f.readString(); + f.discard(";"); + } + else if (stricmp(token,"key")==0) + { + f.discard("="); + char lowerbuf[500]; + Util::str2lowercase(lowerbuf,f.readString()); + keys.push_back(lowerbuf); + f.discard(";"); + } + else if (stricmp(token,"}")==0) + { + break; + } + else + { + f.discard("="); + char lowerbuf[500]; + char lowerbuf2[500]; + //oops, have to do this first. CTextfile uses a static buffer to return strings + Util::str2lowercase(lowerbuf2,token); + Util::str2lowercase(lowerbuf,f.readString()); + extraProps[lowerbuf2]=lowerbuf; + f.discard(";"); + } + + token=f.getToken(); + } + + if (type=="broadcast") + retval= new TRACKED CBroadcastTrigger(value,teamValue,keys,extraProps); + else if (type=="goal") + retval = new TRACKED CGoalTrigger(value,teamValue,keys,extraProps); + else if (type=="fullsearch") + retval = new TRACKED CFullSearchTrigger(value,teamValue,keys,extraProps); + else + g_pApp->fatalError("Invalid trigger type while parsing %s:\n\"%s\" is not a valid trigger type, please use \"broadcast\", \"goal\" or \"fullsearch\"",f.fileName().c_str(),type); + + return retval; +} + +//------------------------------------------------------------------------------------------------------ +// Function: CBroadcastTrigger::CBroadcastTrigger +// Purpose: Constructor for CBroadcastTrigger +// Input: value - the value of the trigger relative to other triggers +// teamValue - the teamValue of the trigger (not used) +// keys - strings to search for in the text of any broadcast event +//------------------------------------------------------------------------------------------------------ +CBroadcastTrigger::CBroadcastTrigger (int value, int teamValue, vector<string>& keys,map<string,string> extras) +:CCustomAwardTrigger(value,teamValue,extras) +{ + //this line works in win32, but not in G++... g++ doesn't seem to have vector::assign + //broadcastStrings.assign(keys.begin(),keys.end()); + + //make a new temp object, and assign it to broadcastStrings + broadcastStrings=vector<string>(keys); +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CBroadcastTrigger::matches +// Purpose: Determines if a given event is a broadcast and matches any of the keys +// Input: le - the event we're testing +// Output: Returns true if the given event triggers this trigger +//------------------------------------------------------------------------------------------------------ +bool CBroadcastTrigger::matches(const CLogEvent* le) +{ + if (le->getType() == CLogEvent::NAMED_BROADCAST)// || le->getType() == CLogEvent::ANON_BROADCAST) + { + //broadcastID is arg0 + string BroadID=le->getArgument(0)->getStringValue(); + vector<string>::iterator it; + + for (it=broadcastStrings.begin();it!=broadcastStrings.end();++it) + { + string s=*it; + if (BroadID==*it) + return true; + } + } + return false; +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CGoalTrigger::CGoalTrigger +// Purpose: Constructor for CGoalTrigger +// Input: value - the value of the trigger relative to other triggers +// teamValue - the teamValue of the trigger (not used) +// keys - the names of goals that will cause this trigger to trigger +//------------------------------------------------------------------------------------------------------ +CGoalTrigger::CGoalTrigger(int value, int teamValue, vector<string>& keys,map<string,string> extras) +:CCustomAwardTrigger(value,teamValue,extras) +{ + //this line works in win32, but not in G++... g++ doesn't seem to have vector::assign + //goalNames.assign(keys.begin(),keys.end()); + + //make a new temp object, and assign it to broadcastStrings + //does this introduce a memory leak? + + goalNames=vector<string>(keys); +} + +//------------------------------------------------------------------------------------------------------ +// Function: CGoalTrigger::matches +// Purpose: Determines if a given event is a goal activation and matches any of the keys +// Input: le - the event we're testing +// Output: Returns true if the given event triggers this trigger +//------------------------------------------------------------------------------------------------------ +bool CGoalTrigger::matches(const CLogEvent* le) +{ + + if (le->getType() == CLogEvent::NAMED_GOAL_ACTIVATE) + { + string n=le->getArgument(1)->getStringValue(); + vector<string>::iterator it; + + for (it=goalNames.begin();it!=goalNames.end();++it) + { + int diff=strnicmp(n.c_str(),(*it).c_str(),(*it).length()); + if (diff==0) + return true; + } + } + return false; +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CFullSearchTrigger::CFullSearchTrigger +// Purpose: Constructor for CFullSearchTrigger +// Input: value - the value of the trigger relative to other triggers +// teamValue - the teamValue of the trigger (not used) +// ks - the names of FullSearchs that will cause this trigger to trigger +//------------------------------------------------------------------------------------------------------ +CFullSearchTrigger::CFullSearchTrigger(int value, int teamValue, vector<string>& ks,map<string,string> extras) +:CCustomAwardTrigger(value,teamValue,extras) +{ + //this line works in win32, but not in G++... g++ doesn't seem to have vector::assign + //FullSearchNames.assign(keys.begin(),keys.end()); + + //make a new temp object, and assign it to broadcastStrings + winnerVar=extraProps["winnervar"]; + + keys=vector<string>(ks); +} + +bool killws(const char*& cs) +{ + bool retval=false; + while(isspace(*cs)) + { + retval=true; + cs++; + } + return retval; +} + + +#include <regex> +int regExprCompare(string sexpr,string scmp) +{ + regex expression(sexpr); + cmatch what; + if(query_match(scmp.c_str(), scmp.c_str() + strlen(scmp.c_str()), what, expression)) + { + //matched! + return 0; + } + else + return 1; + + +} + +bool CFullSearchTrigger::compare(string str_msg,string str_key,map<string,string>& varmatches) +{ + const char* msg=str_msg.c_str(); + const char* key=str_key.c_str(); + + bool match=true; + char varbuf[100]; + char cmpbuf[100]; + while (1) + { + if (!*msg) break; + if (!*key) break; + //get a variable. + if (*key=='%') + { + int i=0; + while(*key && *key!=' ') + { + varbuf[i++]=*(key++); + } + varbuf[i]=0; + if (winnerVar=="") + winnerVar=varbuf; + + killws(msg); + if (*msg=='\"') + { + msg++; + int i=0; + while (*msg && *msg!='\"') + { + cmpbuf[i++]=*msg++; + } + cmpbuf[i]=0; + msg++; //skip past last " + } + else + { + int i=0; + while (*msg!=' ') + { + cmpbuf[i++]=*msg++; + } + cmpbuf[i]=0; + } + + string matchexpr=extraProps[varbuf]; + if (matchexpr=="") + { + //if blank, match any quote delimited string or space delimited word + + varmatches.insert(pair<string,string>(varbuf,cmpbuf)); + } + else if (matchexpr.at(0)!='!' && matchexpr.at(1)!='!') + { + //do a normal string compare + if (stricmp(matchexpr.c_str(),cmpbuf)==0) + varmatches.insert(pair<string,string>(varbuf,cmpbuf)); + else + return false; + } + else + { + //in tfstats, reg expressions start with !! so skip past that + const char* rexpr=matchexpr.c_str()+2; + string test=rexpr; + if (regExprCompare(rexpr,cmpbuf)==0) + varmatches.insert(pair<string,string>(varbuf,cmpbuf)); + else + return false; + } + + + } + + bool movedptr1 = killws(msg); + bool movedptr2 = killws(key); + + if (!movedptr1 && !movedptr2) + { + if (!*msg) break; + + if (*msg!=*key) + { + match=false; + break; + } + msg++; + key++; + } + if (!*msg) break; + } + + return match; +} + + +//------------------------------------------------------------------------------------------------------ +// Function: CFullSearchTrigger::matches +// Purpose: +// Input: le - the event we're testing +// Output: Returns true if the given event triggers this trigger +//------------------------------------------------------------------------------------------------------ +bool CFullSearchTrigger::matches(const CLogEvent* le) +{ + //test against full text + //clear out the state from the last match attempt + map<string,string> varmatches; + bool match=compare(le->getFullMessage(),keys[0],varmatches); + +#ifdef _CUSTOMDEBUG +#ifdef _DEBUG + if (match) + { + map<string,string>::iterator it=varmatches.begin(); + for (it;it!=varmatches.end();++it) + { + debug_printf("matched %s with %s\n",it->first.c_str(),it->second.c_str()); + } + } +#endif +#endif + return match; +} + +#include "pid.h" +PID CFullSearchTrigger::plrIDFromEvent(const CLogEvent* ple) +{ +#ifdef WIN32 + if (winnerVar.compare(0,5,"%plr_")==0) +#else + if (winnerVar.at(0)=='%' && + winnerVar.at(1)=='p' && + winnerVar.at(2)=='l' && + winnerVar.at(3)=='r' && + winnerVar.at(4)=='_') +#endif + { + map<string,string> varmatches; + compare(ple->getFullMessage(),keys[0],varmatches); + string name=varmatches[winnerVar]; + int svrID=Util::string2svrID(name); + return pidMap[svrID]; + } + else + return -1; +} + + //this class does +string CFullSearchTrigger::getTrackString(const CLogEvent* ple) +{ + map<string,string> varmatches; + compare(ple->getFullMessage(),keys[0],varmatches); + return varmatches[winnerVar]; +}
\ No newline at end of file |