// Copyright (C) 2007 Id Software, Inc. // #ifndef __GAME_PROFICIENCY_STATSTRACKER_H__ #define __GAME_PROFICIENCY_STATSTRACKER_H__ #include "../../sdnet/SDNetStatsManager.h" enum statsRequestState_t { SR_EMPTY, SR_REQUESTING, SR_COMPLETED, SR_FAILED, }; typedef sdHandle< int, -1 > statHandle_t; class sdPlayerStatEntry { public: struct statValue_t { public: statValue_t( int value ) { data.i = value; type = sdNetStatKeyValue::SVT_INT; } statValue_t( float value ) { data.f = value; type = sdNetStatKeyValue::SVT_FLOAT; } int GetInt( void ) const { assert( type == sdNetStatKeyValue::SVT_INT ); return data.i; } float GetFloat( void ) const { assert( type == sdNetStatKeyValue::SVT_FLOAT ); return data.f; } sdNetStatKeyValue::statValueType GetType( void ) const { return type; } private: sdNetStatKeyValue::statValueType type; sdNetStatKeyValue::valueData_t data; }; sdPlayerStatEntry( sdNetStatKeyValue::statValueType _type ) : type( _type ) { ; } virtual ~sdPlayerStatEntry( void ) { ; } virtual void IncreaseValue( int playerIndex, const statValue_t& value ) = 0; virtual void Clear( int playerIndex ) = 0; virtual void Display( const char* name ) const = 0; virtual void Write( idFile* fp, int playerIndex, const char* name ) const = 0; virtual bool Write( sdNetStatKeyValList& kvList, int playerIndex, const char* name, bool failOnBlank ) const = 0; virtual void SetValue( int playerIndex, const statValue_t& value ) = 0; virtual statValue_t GetValue( int playerIndex ) = 0; virtual statValue_t GetDeltaValue( int playerIndex ) = 0; virtual void SaveBaseLine( int playerIndex ) = 0; sdNetStatKeyValue::statValueType GetType( void ) const { return type; } protected: sdNetStatKeyValue::statValueType type; }; class sdPlayerStatEntry_Integer : public sdPlayerStatEntry { public: sdPlayerStatEntry_Integer( sdNetStatKeyValue::statValueType _type ); virtual void IncreaseValue( int playerIndex, const statValue_t& value ); virtual void Clear( int playerIndex ); virtual void Display( const char* name ) const; virtual void Write( idFile* fp, int playerIndex, const char* name ) const; virtual bool Write( sdNetStatKeyValList& kvList, int playerIndex, const char* name, bool failOnBlank ) const; virtual void SetValue( int playerIndex, const statValue_t& value ); virtual statValue_t GetValue( int playerIndex ) { return statValue_t( values[ playerIndex ] ); } virtual statValue_t GetDeltaValue( int playerIndex ) { return statValue_t( values[ playerIndex ] - baseValues[ playerIndex ] ); } virtual void SaveBaseLine( int playerIndex ) { baseValues[ playerIndex ] = values[ playerIndex ]; } private: int values[ MAX_CLIENTS ]; int baseValues[ MAX_CLIENTS ]; }; class sdPlayerStatEntry_Float : public sdPlayerStatEntry { public: sdPlayerStatEntry_Float( sdNetStatKeyValue::statValueType _type ); virtual void IncreaseValue( int playerIndex, const statValue_t& value ); virtual void Clear( int playerIndex ); virtual void Display( const char* name ) const; virtual void Write( idFile* fp, int playerIndex, const char* name ) const; virtual bool Write( sdNetStatKeyValList& kvList, int playerIndex, const char* name, bool failOnBlank ) const; virtual void SetValue( int playerIndex, const statValue_t& value ); virtual statValue_t GetValue( int playerIndex ) { return statValue_t( values[ playerIndex ] ); } virtual statValue_t GetDeltaValue( int playerIndex ) { return statValue_t( values[ playerIndex ] - baseValues[ playerIndex ] ); } virtual void SaveBaseLine( int playerIndex ) { baseValues[ playerIndex ] = values[ playerIndex ]; } private: float values[ MAX_CLIENTS ]; float baseValues[ MAX_CLIENTS ]; }; class sdStatsTracker; class sdStatsCommand { public: virtual ~sdStatsCommand( void ) { ; } virtual bool Run( sdStatsTracker& tracker, const idCmdArgs& args ) = 0; virtual void CommandCompletion( sdStatsTracker& tracker, const idCmdArgs& args, argCompletionCallback_t callback ) { ; } }; class sdStatsCommand_Request : public sdStatsCommand { public: virtual ~sdStatsCommand_Request( void ) { ; } virtual bool Run( sdStatsTracker& tracker, const idCmdArgs& args ); }; class sdStatsCommand_Get : public sdStatsCommand { public: virtual ~sdStatsCommand_Get( void ) { ; } virtual bool Run( sdStatsTracker& tracker, const idCmdArgs& args ); }; class sdStatsCommand_Display : public sdStatsCommand { public: virtual ~sdStatsCommand_Display( void ) { ; } virtual bool Run( sdStatsTracker& tracker, const idCmdArgs& args ); virtual void CommandCompletion( sdStatsTracker& tracker, const idCmdArgs& args, argCompletionCallback_t callback ); }; class sdStatsCommand_ClearUserStats : public sdStatsCommand { public: virtual ~sdStatsCommand_ClearUserStats( void ) { ; } virtual bool Run( sdStatsTracker& tracker, const idCmdArgs& args ); }; class sdStatsTracker { public: struct lifeStatsData_t { public: lifeStatsData_t( void ) : oldValue( 0 ), newValue( 0 ) { ; } const char* GetName( void ) const; int index; sdPlayerStatEntry::statValue_t oldValue; sdPlayerStatEntry::statValue_t newValue; }; sdStatsTracker( void ); ~sdStatsTracker( void ); statHandle_t AllocStat( const char* name, sdNetStatKeyValue::statValueType type ); statHandle_t GetStat( const char* name ) const; sdPlayerStatEntry* GetStat( statHandle_t handle ) const; void DisplayStat( statHandle_t handle ) const; void Restore( int playerIndex ); void SetStatBaseLine( int playerIndex ); // Server void CancelStatsRequest( int playerIndex ); void AddStatsRequest( int playerIndex ); void AcknowledgeStatsReponse( int playerIndex ); // Client void OnServerStatsRequestMessage( const idBitMsg& msg ); void OnServerStatsRequestCancelled( void ); void OnServerStatsRequestCompleted( void ); void Clear( void ); void Clear( int playerIndex ); int GetNumStats( void ) const { return stats.Num(); } // Gordon: This is only really used internally, so i'm leaving it unsafe, please guard this if you decide to use it externally const char* GetStatName( statHandle_t handle ) const { return stats[ handle ]->GetName(); } void Write( int playerIndex, const char* name ); bool StartStatsRequest( bool globalOnly = false ); void UpdateStatsRequests( void ); statsRequestState_t GetLocalStatsRequestState( void ) const { return requestState; } const sdNetStatKeyValList& GetLocalStats( void ) const { return completeStats; } const idHashIndex& GetLocalStatsHash( void ) const { return completeStatsHash; } const sdNetStatKeyValue* GetLocalStat( const char* name ) const; const sdNetStatKeyValue* GetNetStat( const char* name ) const; const sdNetStatKeyValue* GetServerStat( const char* name ) const; void GetTopLifeStats( idList< const lifeStatsData_t* >& improved, idList< const lifeStatsData_t* >& unchanged, idList< const lifeStatsData_t* >& worse ) const; static void Init( void ); static void HandleCommand( const idCmdArgs& args ); static void CommandCompletion( const idCmdArgs& args, argCompletionCallback_t callback ); static void ClearLocalUserStats( sdNetUser* activeUser ); static void ReadLocalUserStats( sdNetUser* activeUser, sdNetStatKeyValList& list ); private: // Server void ProcessLocalStats( int playerIndex ); void ProcessRemoteStats( int playerIndex ); // Client void UpdateStatsRequest( void ); void OnServerStatsRequestMessage( const sdNetStatKeyValList& list ); void OnStatsRequestFinished( void ); void WriteLocalUserStats( sdNetUser* activeUser, int playerIndex ); sdNetStatKeyValue* GetLocalStat( const char* name ); lifeStatsData_t* GetLifeStatData( const char* name ); class sdStatEntry { public: sdStatEntry( const char* _name, sdPlayerStatEntry* _entry ) : name( _name ), entry( _entry ) { ; } ~sdStatEntry( void ) { delete entry; } void Clear( int playerIndex ) { entry->Clear( playerIndex ); } void Display( void ) const { entry->Display( name ); } void Write( idFile* fp, int playerIndex ) const { entry->Write( fp, playerIndex, name ); } bool Write( sdNetStatKeyValList& kvList, int playerIndex, bool failOnBlank = false ) const { return entry->Write( kvList, playerIndex, name, failOnBlank ); } sdPlayerStatEntry* GetEntry( void ) const { return entry; } const char* GetName( void ) const { return name; } private: sdPlayerStatEntry* entry; idStr name; }; sdNetTask* requestTask; bool requestedStatsValid; sdNetStatKeyValList requestedStats; // Stats from demonware idHashIndex requestedStatsHash; bool serverStatsValid; sdNetStatKeyValList serverStats; // Stats from server idHashIndex serverStatsHash; sdNetStatKeyValList completeStats; // Combined stats idHashIndex completeStatsHash; idList< lifeStatsData_t > lifeStatsData; idHashIndex lifeStatsDataHash; int playerRequestState[ MAX_CLIENTS ]; bool playerRequestWaiting[ MAX_CLIENTS ]; statsRequestState_t requestState; idList< sdStatEntry* > stats; idHashIndex statHash; static idHashMap< sdStatsCommand* > s_commands; }; typedef sdSingleton< sdStatsTracker > sdGlobalStatsTracker; #endif // __GAME_PROFICIENCY_STATSTRACKER_H__