summaryrefslogtreecommitdiff
path: root/utils/tfstats/timeindexedlist.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/tfstats/timeindexedlist.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/tfstats/timeindexedlist.h')
-rw-r--r--utils/tfstats/timeindexedlist.h346
1 files changed, 346 insertions, 0 deletions
diff --git a/utils/tfstats/timeindexedlist.h b/utils/tfstats/timeindexedlist.h
new file mode 100644
index 0000000..ec28ad6
--- /dev/null
+++ b/utils/tfstats/timeindexedlist.h
@@ -0,0 +1,346 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Interface AND implementation of CTimeIndexedList
+//
+// $Workfile: $
+// $Date: $
+//
+//------------------------------------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef TIMEINDEXEDLIST_H
+#define TIMEINDEXEDLIST_H
+#ifdef WIN32
+#pragma once
+#endif
+#include <list>
+#include "TFStatsApplication.h"
+#include "util.h"
+//------------------------------------------------------------------------------------------------------
+// Purpose: CTimedIndexedList is a list of elements indexed by time_t's.
+// the elements of the list are meant to represent a state that endures over time
+// and when it is switched to another state, that is represented by an element in this
+// list with the value of the new state at index t, where t is the time that the switch
+// occured.
+// in TFStats, this is used for player names and player classes
+//------------------------------------------------------------------------------------------------------
+template <class T>
+class CTimeIndexedList
+{
+public:
+ static time_t PENDING;
+ typedef struct{T data;time_t start; time_t end;} listtype;
+ typedef std::list<listtype>::iterator iterator;
+ typedef std::map<T,time_t>::iterator accumulatorIterator;
+ typedef std::map<T,time_t> accumulator;
+ typedef std::list<listtype> timelist;
+
+ timelist theList;
+ time_t endTime;
+ bool anythingAtTime(time_t);
+ T atTime(time_t,T errorvalue=T());
+ T favourite(T errorvalue=T());
+ CTimeIndexedList();
+ void add(time_t a,T b);
+ bool contains(const T& t);
+
+ accumulator accumulate();
+
+ time_t howLong(const T& t);
+ iterator begin();
+ iterator end();
+ int size();
+ int numDifferent();
+
+ void cut(time_t t);
+ void remove(T b);
+};
+template <class T>
+time_t CTimeIndexedList<T>::PENDING=-1;
+
+template <class T>
+CTimeIndexedList<T>::CTimeIndexedList()
+{
+
+ endTime=0;
+
+}
+
+//------------------------------------------------------------------------------------------------------
+// Function: CTimeIndexedList<T>::accumulate
+// Purpose:
+// Output: CTimeIndexedList<T>::accumulator
+//------------------------------------------------------------------------------------------------------
+template<class T>
+CTimeIndexedList<T>::accumulator CTimeIndexedList<T>::accumulate()
+{
+ CTimeIndexedList<T>::accumulator accum; //maps from a value of T, to the time that value was played
+
+/*
+ //iterate through for debugging purposes
+ {
+
+ CTimeIndexedList<T>::iterator it=theList.begin();
+ for (it;it!=theList.end();++it)
+ {
+ CTimeIndexedList<T>::listtype lt=*it;
+ }
+ }
+*/
+ CTimeIndexedList<T>::iterator it=theList.begin();
+ for (it;it!=theList.end();++it)
+ {
+ time_t start=it->start;
+ time_t end=it->end;
+ T& bucket=it->data;
+ if (end==PENDING)
+ {
+ end=endTime;
+ if (end==0)
+ {
+ g_pApp->fatalError("Time flow error, make sure your log file\n");
+ }
+ }
+ accum[bucket]+=(end-start);
+ }
+
+ return accum;
+}
+
+//------------------------------------------------------------------------------------------------------
+// Function: CTimeIndexedList<T>::add
+// Purpose:
+// Input: a -
+// b -
+//------------------------------------------------------------------------------------------------------
+template<class T>
+void CTimeIndexedList<T>::add(time_t a,T b)
+{
+ bool lastIsB=false;
+ bool firstElement=false;
+ listtype insertme;
+ insertme.data=b;
+ insertme.start=a;
+ insertme.end=PENDING;
+
+ if (!theList.empty())
+ {
+ //find the last element and fix up its end-time (if it's pending)
+ CTimeIndexedList<T>::iterator last=theList.end();
+ last--;
+ listtype lt=*last;
+
+ if (last->end==PENDING && last->data!=b)
+ last->end=insertme.start;
+ }
+
+ //add the new element!
+ theList.push_back(insertme);
+
+ if (a > endTime)
+ endTime=a;
+
+
+
+}
+//------------------------------------------------------------------------------------------------------
+// Function: CTimeIndexedList::atTime
+// Purpose: returns the element whose time index is the closest to and less than or
+// equal to the queried time
+// Input: tm - the time that is being queried
+// Output: T, the element
+//------------------------------------------------------------------------------------------------------
+template <class T>
+T CTimeIndexedList<T>::atTime(time_t tm,T errorvalue)
+{
+ CTimeIndexedList<T>::iterator it;
+ if (theList.empty())
+ return errorvalue;
+
+ //nothing exists here!
+ if (tm < theList.begin()->start)
+ return errorvalue;
+
+ for (it=theList.begin();it!=theList.end();++it)
+ {
+ time_t mark=it->start;
+ time_t markend=it->end;
+
+ if (tm >= mark && tm < markend)
+ return it->data;
+ if (tm >= mark && markend == PENDING)
+ return it->data;
+ }
+
+ return errorvalue;
+}
+
+//------------------------------------------------------------------------------------------------------
+// Function: CTimeIndexedList::favourite
+// Purpose: returns the element that spans the most time
+// Output: T, the element
+//------------------------------------------------------------------------------------------------------
+template <class T>
+T CTimeIndexedList<T>::favourite(T errorvalue)
+{
+ if (theList.empty())
+ return errorvalue;
+
+ CTimeIndexedList<T>::accumulator accum=accumulate();
+
+ //now scan that intermediate map, and determine the element with the longest duration
+ CTimeIndexedList<T>::accumulatorIterator accumiter=accum.begin();
+
+ time_t maxtime=0;
+ CTimeIndexedList<T>::accumulatorIterator fave=accumiter;
+
+ T t= fave->first;
+ for (accumiter;accumiter!=accum.end();++accumiter)
+ {
+ t= fave->first;
+ time_t clicksPlayed=accumiter->second;
+
+ if (clicksPlayed> maxtime)
+ {
+ maxtime=clicksPlayed;
+ fave=accumiter;
+ }
+ }
+
+ T ttt= fave->first;
+
+ return ttt;
+}
+
+//------------------------------------------------------------------------------------------------------
+// Function: CTimeIndexedList::contains
+// Purpose: returns true if the element is in the list
+// Input: t, the element value that we're querying
+// Output: Returns true if the element was in the list
+//------------------------------------------------------------------------------------------------------
+template <class T>
+bool CTimeIndexedList<T>::contains(const T& t)
+{
+ CTimeIndexedList<T>::iterator it=theList.begin();
+ for (it=theList.begin();it!=theList.end();++it)
+ {
+ if (it->data==t)
+ return true;
+ }
+ return false;
+}
+
+template <class T>
+time_t CTimeIndexedList<T>::howLong(const T& t)
+{
+ if (theList.begin()==theList.end())
+ return 0;
+
+ CTimeIndexedList<T>::accumulator accum=accumulate(); //maps from a value of T, to the time that value was played
+
+ return accum[t];
+}
+
+template <class T>
+CTimeIndexedList<T>::iterator CTimeIndexedList<T>::begin()
+{
+ return theList.begin();
+}
+
+template <class T>
+CTimeIndexedList<T>::iterator CTimeIndexedList<T>::end()
+{
+ return theList.end();
+}
+
+template <class T>
+int CTimeIndexedList<T>::size()
+{
+ return theList.size();
+}
+
+
+template <class T>
+int CTimeIndexedList<T>::numDifferent()
+{
+ if (theList.begin()==theList.end())
+ return 0;
+
+ //maps from a value of T, to the time that value was played
+ CTimeIndexedList<T>::accumulator accum=accumulate();
+
+ return accum.size();
+}
+
+
+template<class T>
+void CTimeIndexedList<T>::cut(time_t t)
+{
+ if (t > endTime)
+ endTime=t;
+ if (!theList.empty())
+ {
+ //find the last element and fix up its end-time (if it's pending)
+ CTimeIndexedList<T>::iterator last=theList.end();
+ last--;
+
+ if (last->end==PENDING)
+ last->end=t;
+ }
+}
+
+
+template<class T>
+void CTimeIndexedList<T>::remove(T b)
+{
+ CTimeIndexedList<T>::iterator it=theList.begin();
+
+ while(it!=theList.end())
+ {
+ if (it->data==b)
+ it=theList.erase(it);
+ else
+ ++it;
+ }
+}
+
+
+
+
+template <class T>
+bool CTimeIndexedList<T>::anythingAtTime(time_t tm)
+{
+/*
+ //iterate through for debugging purposes
+ {
+
+ CTimeIndexedList<T>::iterator it=theList.begin();
+ for (it;it!=theList.end();++it)
+ {
+ CTimeIndexedList<T>::listtype lt=*it;
+ }
+ }
+ */
+ CTimeIndexedList<T>::iterator it;
+ if (theList.empty())
+ return false;
+
+ //nothing exists here!
+ if (tm < theList.begin()->start)
+ return false;
+
+ for (it=theList.begin();it!=theList.end();++it)
+ {
+ time_t mark=it->start;
+ time_t markend=it->end;
+
+ if (tm >= mark && tm < markend)
+ return true;
+ }
+
+ return false;
+}
+
+#endif // TIMEINDEXEDLIST_H \ No newline at end of file