/* * Copyright (c) 2014, Oculus VR, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ /// \file StatisticsHistory.h /// \brief Input numerical values over time. Get sum, average, highest, lowest, standard deviation on recent or all-time values #include "NativeFeatureIncludes.hpp" #if _RAKNET_SUPPORT_StatisticsHistory==1 #ifndef __STATISTICS_HISTORY_H #define __STATISTICS_HISTORY_H #include "PluginInterface2.hpp" #include "RakMemoryOverride.hpp" #include "NativeTypes.hpp" #include "DS_List.hpp" #include "RakNetTypes.hpp" #include "DS_OrderedList.hpp" #include "RakString.hpp" #include "DS_Queue.hpp" #include "DS_Hash.hpp" #include namespace RakNet { /// Forward declarations class RakPeerInterface; // Type used to track values. If needed, change to double and recompile typedef double SHValueType; #define SH_TYPE_MAX DBL_MAX /// \brief Input numerical values over time. Get sum, average, highest, lowest, standard deviation on recent or all-time values class RAK_DLL_EXPORT StatisticsHistory { public: // GetInstance() and DestroyInstance(instance*) STATIC_FACTORY_DECLARATIONS(StatisticsHistory) enum SHErrorCode { SH_OK, SH_UKNOWN_OBJECT, SH_UKNOWN_KEY, SH_INVALID_PARAMETER, }; enum SHSortOperation { SH_DO_NOT_SORT, SH_SORT_BY_RECENT_SUM_ASCENDING, SH_SORT_BY_RECENT_SUM_DESCENDING, SH_SORT_BY_LONG_TERM_SUM_ASCENDING, SH_SORT_BY_LONG_TERM_SUM_DESCENDING, SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING, SH_SORT_BY_RECENT_SUM_OF_SQUARES_DESCENDING, SH_SORT_BY_RECENT_AVERAGE_ASCENDING, SH_SORT_BY_RECENT_AVERAGE_DESCENDING, SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING, SH_SORT_BY_LONG_TERM_AVERAGE_DESCENDING, SH_SORT_BY_RECENT_HIGHEST_ASCENDING, SH_SORT_BY_RECENT_HIGHEST_DESCENDING, SH_SORT_BY_RECENT_LOWEST_ASCENDING, SH_SORT_BY_RECENT_LOWEST_DESCENDING, SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING, SH_SORT_BY_LONG_TERM_HIGHEST_DESCENDING, SH_SORT_BY_LONG_TERM_LOWEST_ASCENDING, SH_SORT_BY_LONG_TERM_LOWEST_DESCENDING, }; enum SHDataCategory { /// Insert values from one set into the other set, in time order /// Values at the same time end up in the final set twice /// Use when you have additional data points to add to a graph DC_DISCRETE, /// Add values from one set to values from the other set, at corresponding times /// If value at time t does not exist in the other set, linearly extrapolate value for other set based on nearest two data points /// longTerm* values are unknown using this method /// Use to add two graphs together DC_CONTINUOUS }; struct TimeAndValue; struct TimeAndValueQueue; struct TrackedObjectData { TrackedObjectData(); TrackedObjectData(uint64_t _objectId, int _objectType, void *_userData); uint64_t objectId; int objectType; void *userData; }; StatisticsHistory(); virtual ~StatisticsHistory(); void SetDefaultTimeToTrack(Time defaultTimeToTrack); Time GetDefaultTimeToTrack(void) const; bool AddObject(TrackedObjectData tod); bool RemoveObject(uint64_t objectId, void **userData); void RemoveObjectAtIndex(unsigned int index); void Clear(void); unsigned int GetObjectCount(void) const; StatisticsHistory::TrackedObjectData * GetObjectAtIndex(unsigned int index) const; unsigned int GetObjectIndex(uint64_t objectId) const; bool AddValueByObjectID(uint64_t objectId, RakString key, SHValueType val, Time curTime, bool combineEqualTimes); void AddValueByIndex(unsigned int index, RakString key, SHValueType val, Time curTime, bool combineEqualTimes); SHErrorCode GetHistoryForKey(uint64_t objectId, RakString key, TimeAndValueQueue **values, Time curTime) const; bool GetHistorySorted(uint64_t objectId, SHSortOperation sortType, DataStructures::List &values) const; void MergeAllObjectsOnKey(RakString key, TimeAndValueQueue *tavqOutput, SHDataCategory dataCategory) const; void GetUniqueKeyList(DataStructures::List &keys); struct TimeAndValue { Time time; SHValueType val; }; struct TimeAndValueQueue { TimeAndValueQueue(); ~TimeAndValueQueue(); DataStructures::Queue values; Time timeToTrackValues; RakString key; SHValueType recentSum; SHValueType recentSumOfSquares; SHValueType longTermSum; SHValueType longTermCount; SHValueType longTermLowest; SHValueType longTermHighest; void SetTimeToTrackValues(Time t); Time GetTimeToTrackValues(void) const; SHValueType GetRecentSum(void) const; SHValueType GetRecentSumOfSquares(void) const; SHValueType GetLongTermSum(void) const; SHValueType GetRecentAverage(void) const; SHValueType GetRecentLowest(void) const; SHValueType GetRecentHighest(void) const; SHValueType GetRecentStandardDeviation(void) const; SHValueType GetLongTermAverage(void) const; SHValueType GetLongTermLowest(void) const; SHValueType GetLongTermHighest(void) const; SHValueType GetSumSinceTime(Time t) const; Time GetTimeRange(void) const; // Merge two sets to output static void MergeSets( const TimeAndValueQueue *lhs, SHDataCategory lhsDataCategory, const TimeAndValueQueue *rhs, SHDataCategory rhsDataCategory, TimeAndValueQueue *output ); // Shrink or expand a sample set to the approximate number given // DC_DISCRETE will produce a histogram (sum) while DC_CONTINUOUS will produce an average void ResizeSampleSet( int approximateSamples, DataStructures::Queue &blendedSamples, SHDataCategory dataCategory, Time timeClipStart=0, Time timeClipEnd=0 ); // Clear out all values void Clear(void); TimeAndValueQueue& operator = ( const TimeAndValueQueue& input ); /// \internal void CullExpiredValues(Time curTime); /// \internal static SHValueType Interpolate(TimeAndValue t1, TimeAndValue t2, Time time); /// \internal SHValueType sortValue; }; protected: struct TrackedObject; public: static int TrackedObjectComp( const uint64_t &key, TrackedObject* const &data ); protected: struct TrackedObject { TrackedObject(); ~TrackedObject(); TrackedObjectData trackedObjectData; DataStructures::Hash dataQueues; }; DataStructures::OrderedList objects; Time timeToTrack; }; /// \brief Input numerical values over time. Get sum, average, highest, lowest, standard deviation on recent or all-time values /// \ingroup PLUGINS_GROUP class RAK_DLL_EXPORT StatisticsHistoryPlugin : public PluginInterface2 { public: // GetInstance() and DestroyInstance(instance*) STATIC_FACTORY_DECLARATIONS(StatisticsHistoryPlugin) StatisticsHistory statistics; StatisticsHistoryPlugin(); virtual ~StatisticsHistoryPlugin(); void SetTrackConnections(bool _addNewConnections, int newConnectionsObjectType, bool _removeLostConnections); protected: virtual void Update(void); virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ); virtual void OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming); // Too slow // virtual bool UsesReliabilityLayer(void) const {return true;} // virtual void OnDirectSocketSend(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress); // virtual void OnDirectSocketReceive(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress); bool addNewConnections; bool removeLostConnections; int newConnectionsObjectType; }; } // namespace RakNet #endif // __STATISTICS_HISTORY_H #endif // _RAKNET_SUPPORT_*