Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.9 KiB

  1. //====== Copyright � 1996-2006, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose: Uploads gamestats via the SteamWorks API. Server version.
  4. //
  5. //=============================================================================//
  6. #ifndef STEAMWORKS_GAMESTATS_SERVER_H
  7. #define STEAMWORKS_GAMESTATS_SERVER_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "steamworks_gamestats.h"
  12. //used to drive most of the game stat event handlers as well as track basic stats under the hood of CBaseGameStats
  13. class CSteamWorksGameStatsServer : public CSteamWorksGameStatsUploader
  14. {
  15. DECLARE_CLASS( CSteamWorksGameStatsServer, CSteamWorksGameStatsUploader )
  16. public:
  17. CSteamWorksGameStatsServer();
  18. void WriteSessionRow();
  19. protected:
  20. virtual EGameStatsAccountType GetGameStatsAccountType();
  21. // called before a row is committed, allows derived classes to add sessionIDs, etc.
  22. virtual void AddSessionIDsToTable( int iTableID );
  23. };
  24. CSteamWorksGameStatsServer& GetSteamWorksGameStatsServer();
  25. // Macros to ease the creation of SendData method for stats structs/classes
  26. #define BEGIN_STAT_TABLE( tableName ) \
  27. static const char* GetStatTableName( void ) { return tableName; } \
  28. void BuildGamestatDataTable( KeyValues* pKV ) \
  29. { \
  30. pKV->SetName( GetStatTableName() );
  31. #define REGISTER_STAT( varName ) \
  32. AddDataToKV(pKV, #varName, varName);
  33. #define REGISTER_STAT_NAMED( varName, dbName ) \
  34. AddDataToKV(pKV, dbName, varName);
  35. #define REGISTER_STAT_POSITION( varName ) \
  36. AddPositionDataToKV(pKV, #varName, varName);
  37. #define REGISTER_STAT_POSITION_NAMED( varName, dbName ) \
  38. AddPositionDataToKV(pKV, dbName, varName);
  39. #define REGISTER_STAT_ARRAY( varName ) \
  40. AddArrayDataToKV( pKV, #varName, varName, ARRAYSIZE( varName ) );
  41. #define REGISTER_STAT_ARRAY_NAMED( varName, dbName ) \
  42. AddArrayDataToKV( pKV, dbName, varName, ARRAYSIZE( varName ) );
  43. #define REGISTER_STAT_STRING( varName ) \
  44. AddStringDataToKV( pKV, #varName, varName );
  45. #define REGISTER_STAT_STRING_NAMED( varName, dbName ) \
  46. AddStringDataToKV( pKV, dbName, varName );
  47. #define AUTO_STAT_TABLE_KEY() \
  48. pKV->SetInt( "TimeSubmitted", GetUniqueIDForStatTable( *this ) );
  49. #define END_STAT_TABLE() \
  50. pKV->SetUint64( ::BaseStatData::m_bUseGlobalData ? "TimeSubmitted" : "SessionTime", ::BaseStatData::TimeSubmitted ); \
  51. GetSteamWorksGameStatsServer().AddStatsForUpload( pKV ); \
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Purpose: Templatized class for getting unique ID's for stat tables that need
  55. // to be submitted multiple times per-session.
  56. //-----------------------------------------------------------------------------
  57. template < typename T >
  58. class UniqueStatID_t
  59. {
  60. public:
  61. static unsigned GetNext( void )
  62. {
  63. return ++s_nLastID;
  64. }
  65. static void Reset( void )
  66. {
  67. s_nLastID = 0;
  68. }
  69. private:
  70. static unsigned s_nLastID;
  71. };
  72. template < typename T >
  73. unsigned UniqueStatID_t< T >::s_nLastID = 0;
  74. template < typename T >
  75. unsigned GetUniqueIDForStatTable( const T &table )
  76. {
  77. return UniqueStatID_t< T >::GetNext();
  78. }
  79. //=============================================================================
  80. //
  81. // An interface for tracking gamestats.
  82. //
  83. class IGameStatTracker
  84. {
  85. public:
  86. //-----------------------------------------------------------------------------
  87. // Templatized methods to track a per-mission stat.
  88. // The stat is copied, then deleted after it's sent to the SQL server.
  89. //-----------------------------------------------------------------------------
  90. template < typename T >
  91. void SubmitStat( T& stat )
  92. {
  93. // Make a copy of the stat. All of the stat lists require pointers,
  94. // so we need to protect against a stat allocated on the stack
  95. T* pT = new T();
  96. if( !pT )
  97. return;
  98. *pT = stat;
  99. SubmitStat( pT );
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Templatized methods to track a per-mission stat (by pointer)
  103. // The stat is deleted after it's sent to the SQL server
  104. //-----------------------------------------------------------------------------
  105. template < typename T >
  106. void SubmitStat( T* pStat )
  107. {
  108. // Get the static stat table for this type and add the stat to it
  109. GetStatTable<T>()->AddToTail( pStat );
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Add all stats to an existing key value file for submit.
  113. //-----------------------------------------------------------------------------
  114. virtual void SubmitGameStats( KeyValues *pKV ) = 0;
  115. //-----------------------------------------------------------------------------
  116. // Prints the memory usage of all of the stats being tracked
  117. //-----------------------------------------------------------------------------
  118. void PrintGamestatMemoryUsage( void );
  119. protected:
  120. //=============================================================================
  121. //
  122. // Used as a base interface to store a list of all templatized stat containers
  123. //
  124. class IStatContainer
  125. {
  126. public:
  127. virtual void SendData( KeyValues *pKV ) = 0;
  128. virtual void Clear( void ) = 0;
  129. virtual void PrintMemoryUsage( void ) = 0;
  130. };
  131. // Defines a list of stat containers.
  132. typedef CUtlVector< IStatContainer* > StatContainerList_t;
  133. //-----------------------------------------------------------------------------
  134. // Used to get a list of all stats containers being tracked by the deriving class
  135. //-----------------------------------------------------------------------------
  136. virtual StatContainerList_t* GetStatContainerList( void ) = 0;
  137. private:
  138. //=============================================================================
  139. //
  140. // Templatized list of stats submitted
  141. //
  142. template < typename T >
  143. class CGameStatList : public IStatContainer, public CUtlVector< T* >
  144. {
  145. public:
  146. //-----------------------------------------------------------------------------
  147. // Get data ready to send to the SQL server
  148. //-----------------------------------------------------------------------------
  149. virtual void SendData( KeyValues *pKV )
  150. {
  151. //ASSERT( pKV != NULL );
  152. // Duplicate the master KeyValue for each stat instance
  153. for( int i=0; i < this->m_Size; ++i )
  154. {
  155. // Make a copy of the master key value and build the stat table
  156. KeyValues *pKVCopy = this->operator [](i)->m_bUseGlobalData ? pKV->MakeCopy() : new KeyValues( "" );
  157. this->operator [](i)->BuildGamestatDataTable( pKVCopy );
  158. }
  159. // Reset unique ID counter for the stat type
  160. UniqueStatID_t< T >::Reset();
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Clear and delete every stat in this list
  164. //-----------------------------------------------------------------------------
  165. virtual void Clear( void )
  166. {
  167. this->Purge();
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Print out details about this lists memory usage
  171. //-----------------------------------------------------------------------------
  172. virtual void PrintMemoryUsage( void )
  173. {
  174. if( this->m_Size == 0 )
  175. return;
  176. // Compute the memory used as the size of type times the list count
  177. unsigned uMemoryUsed = this->m_Size * ( sizeof( T ) );
  178. Msg( " %d\tbytes used by %s table\n", uMemoryUsed, T::GetStatTableName() );
  179. }
  180. };
  181. //-----------------------------------------------------------------------------
  182. // Templatized method to get a single instance of a stat list per data type.
  183. //-----------------------------------------------------------------------------
  184. template < typename T >
  185. CGameStatList< T >* GetStatTable( void )
  186. {
  187. static CGameStatList< T > *s_vecOfType = 0;
  188. if( s_vecOfType == 0 )
  189. {
  190. s_vecOfType = new CGameStatList< T >();
  191. GetStatContainerList()->AddToTail( s_vecOfType );
  192. }
  193. return s_vecOfType;
  194. }
  195. };
  196. struct BaseStatData
  197. {
  198. BaseStatData( bool bUseGlobalData = true ) : m_bUseGlobalData( bUseGlobalData )
  199. {
  200. TimeSubmitted = GetSteamWorksGameStatsServer().GetTimeSinceEpoch();
  201. }
  202. bool m_bUseGlobalData;
  203. uint64 TimeSubmitted;
  204. };
  205. #endif // STEAMWORKS_GAMESTATS_SERVER_H