From c7955900ab9c35a4f3da1dc5eaa35b77b495e8ad Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:17:18 -0700 Subject: [PATCH] Add new user activity events --- interface/src/Application.cpp | 42 +++++++++++++++++++++++-- interface/src/Application.h | 2 ++ libraries/avatars/src/AvatarHashMap.cpp | 14 +++++++++ libraries/avatars/src/AvatarHashMap.h | 1 + 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8effefd6e..f2f265aae0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -435,7 +435,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - + DependencyManager::set(); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) DependencyManager::set(); @@ -1057,6 +1057,44 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } }); + // Add periodic checks to send user activity data + static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000; + static int SEND_FPS_INTERVAL_MS = 10000; + + // Periodically send fps as a user activity event + QTimer* sendFPSTimer = new QTimer(this); + sendFPSTimer->setInterval(SEND_FPS_INTERVAL_MS); + connect(sendFPSTimer, &QTimer::timeout, this, [this]() { + UserActivityLogger::getInstance().logAction("fps", { { "rate", _frameCounter.rate() } }); + }); + sendFPSTimer->start(); + + + // Periodically check for count of nearby avatars + static int lastCountOfNearbyAvatars = -1; + QTimer* checkNearbyAvatarsTimer = new QTimer(this); + checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); + connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() { + auto avatarManager = DependencyManager::get(); + int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), 10) - 1; + if (nearbyAvatars != lastCountOfNearbyAvatars) { + UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); + } + }); + + // Track user activity event when we receive a mute packet + auto onMutedByMixer = []() { + UserActivityLogger::getInstance().logAction("received_mute_packet"); + }; + connect(DependencyManager::get().data(), &AudioClient::mutedByMixer, this, onMutedByMixer); + + // Track when the address bar is opened + auto onAddressBarToggled = [this]() { + // Record time + UserActivityLogger::getInstance().logAction("opened_address_bar", { { "uptime_ms", _sessionRunTimer.elapsed() } }); + }; + connect(DependencyManager::get().data(), &DialogsManager::addressBarToggled, this, onAddressBarToggled); + // Make sure we don't time out during slow operations at startup updateHeartbeat(); @@ -4560,7 +4598,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); - scriptEngine->registerGlobalObject("UserActivityLogger", new UserActivityLoggerScriptingInterface()); + scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index a17250a58e..d728359ed1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -195,6 +195,8 @@ public: float getRenderResolutionScale() const; + qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); } + bool isAboutToQuit() const { return _aboutToQuit; } // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 9084fd837b..d153cfd977 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -44,6 +44,20 @@ bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range return false; } +int AvatarHashMap::numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters) { + auto hashCopy = getHashCopy(); + auto rangeMeters2 = rangeMeters * rangeMeters; + int count = 0; + for (const AvatarSharedPointer& sharedAvatar : hashCopy) { + glm::vec3 avatarPosition = sharedAvatar->getPosition(); + auto distance2 = glm::distance2(avatarPosition, position); + if (distance2 < rangeMeters2) { + ++count; + } + } + return count; +} + AvatarSharedPointer AvatarHashMap::newSharedAvatar() { return std::make_shared(); } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 5f58074427..9d3ebb60f5 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -39,6 +39,7 @@ public: Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID); virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) { return findAvatar(sessionID); } + int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); signals: void avatarAddedEvent(const QUuid& sessionUUID);