From 211da3c428da40c66684adf74fcb58cfcacd08e6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 11 Aug 2016 16:49:29 -0700 Subject: [PATCH 1/5] Add more user activity tracking data --- interface/src/Application.cpp | 21 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.cpp | 14 +++++++++++++ .../entities/src/EntityScriptingInterface.h | 12 +++++++++++ 3 files changed, 47 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3d519d1790..c4750c69df 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1145,10 +1145,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : static int SEND_STATS_INTERVAL_MS = 10000; static int NEARBY_AVATAR_RADIUS_METERS = 10; + static glm::vec3 lastAvatarPosition = getMyAvatar()->getPosition(); + static glm::mat4 lastHMDHeadPose = getHMDSensorPose(); + // Periodically send fps as a user activity event QTimer* sendStatsTimer = new QTimer(this); sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS); connect(sendStatsTimer, &QTimer::timeout, this, [this]() { + QJsonObject properties = {}; MemoryInfo memInfo; if (getMemoryInfo(memInfo)) { @@ -1190,6 +1194,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; + glm::vec3 avatarPosition = getMyAvatar()->getPosition(); + properties["avatar_has_moved"] = lastAvatarPosition != avatarPosition; + lastAvatarPosition = avatarPosition; + + auto entityScriptingInterface = DependencyManager::get(); + auto entityActivityTracking = entityScriptingInterface->getActivityTracking(); + entityScriptingInterface->resetActivityTracking(); + properties["added_entity"] = entityActivityTracking.hasAddedEntity; + properties["deleted_entity"] = entityActivityTracking.hasDeletedEntity; + properties["edited_entity"] = entityActivityTracking.hasEditedEntity; + + auto hmdHeadPose = getHMDSensorPose(); + properties["hmd_head_pose_changed"] = isHMDMode() && (hmdHeadPose != lastHMDHeadPose); + lastHMDHeadPose = hmdHeadPose; + + properties["hand_pose_changed"] = false; + UserActivityLogger::getInstance().logAction("stats", properties); }); sendStatsTimer->start(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 653b37c3bb..031847b3f3 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -40,6 +40,12 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType, getEntityPacketSender()->queueEditEntityMessage(packetType, _entityTree, entityID, properties); } +void EntityScriptingInterface::resetActivityTracking() { + _activityTracking.hasAddedEntity = false; + _activityTracking.hasDeletedEntity = false; + _activityTracking.hasEditedEntity = false; +} + bool EntityScriptingInterface::canAdjustLocks() { auto nodeList = DependencyManager::get(); return nodeList->isAllowedEditor(); @@ -130,6 +136,8 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, bool clientOnly) { + _activityTracking.hasAddedEntity = true; + EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); @@ -200,6 +208,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, bool dynamic, const glm::vec3& position, const glm::vec3& gravity) { + _activityTracking.hasAddedEntity = true; + EntityItemProperties properties; properties.setType(EntityTypes::Model); properties.setName(name); @@ -263,6 +273,8 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit } QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { + _activityTracking.hasEditedEntity = true; + EntityItemProperties properties = scriptSideProperties; auto dimensions = properties.getDimensions(); @@ -406,6 +418,8 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } void EntityScriptingInterface::deleteEntity(QUuid id) { + _activityTracking.hasDeletedEntity = true; + EntityItemID entityID(id); bool shouldDelete = true; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 5aa0f5907e..bde0974d7c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -65,6 +65,13 @@ class EntityScriptingInterface : public OctreeScriptingInterface, public Depende public: EntityScriptingInterface(bool bidOnSimulationOwnership); + class ActivityTracking { + public: + bool hasAddedEntity { false }; + bool hasDeletedEntity { false }; + bool hasEditedEntity { false }; + }; + EntityEditPacketSender* getEntityPacketSender() const { return (EntityEditPacketSender*)getPacketSender(); } virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; } virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } @@ -73,6 +80,9 @@ public: EntityTreePointer getEntityTree() { return _entityTree; } void setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine); float calculateCost(float mass, float oldVelocity, float newVelocity); + + void resetActivityTracking(); + ActivityTracking getActivityTracking() const { return _activityTracking; } public slots: // returns true if the DomainServer will allow this Node/Avatar to make changes @@ -226,6 +236,8 @@ private: float _currentAvatarEnergy = { FLT_MAX }; float getCurrentAvatarEnergy() { return _currentAvatarEnergy; } void setCurrentAvatarEnergy(float energy); + + ActivityTracking _activityTracking; float costMultiplier = { 0.01f }; float getCostMultiplier(); From 2598d27cf3d5d5a600f321cb4b9877aca6ba1f2e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 15 Aug 2016 10:29:19 -0700 Subject: [PATCH 2/5] Add hand_pose_changed implementation for stats --- interface/src/Application.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c4750c69df..a6484c6c9c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1147,6 +1147,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : static glm::vec3 lastAvatarPosition = getMyAvatar()->getPosition(); static glm::mat4 lastHMDHeadPose = getHMDSensorPose(); + static controller::Pose lastLeftHandPose = getMyAvatar()->getLeftHandPose(); + static controller::Pose lastRightHandPose = getMyAvatar()->getRightHandPose(); // Periodically send fps as a user activity event QTimer* sendStatsTimer = new QTimer(this); @@ -1209,7 +1211,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : properties["hmd_head_pose_changed"] = isHMDMode() && (hmdHeadPose != lastHMDHeadPose); lastHMDHeadPose = hmdHeadPose; - properties["hand_pose_changed"] = false; + auto leftHandPose = getMyAvatar()->getLeftHandPose(); + auto rightHandPose = getMyAvatar()->getRightHandPose(); + // controller::Pose considers two poses to be different if either are invalid. In our case, we actually + // want to consider the pose to be unchanged if it was invalid and still is invalid, so we check that first. + properties["hand_pose_changed"] = + (!(leftHandPose.valid || lastLeftHandPose.valid) && (leftHandPose != lastLeftHandPose)) + || (!(rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); + lastLeftHandPose = leftHandPose; + lastRightHandPose = rightHandPose; UserActivityLogger::getInstance().logAction("stats", properties); }); From fbe971e730b71343dbe254a547f129b9c6d90910 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 16 Aug 2016 17:46:21 -0700 Subject: [PATCH 3/5] Fix hand_pose_changed event --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a6484c6c9c..e352b841b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1216,8 +1216,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // controller::Pose considers two poses to be different if either are invalid. In our case, we actually // want to consider the pose to be unchanged if it was invalid and still is invalid, so we check that first. properties["hand_pose_changed"] = - (!(leftHandPose.valid || lastLeftHandPose.valid) && (leftHandPose != lastLeftHandPose)) - || (!(rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); + ((leftHandPose.valid || lastLeftHandPose.valid) && (leftHandPose != lastLeftHandPose)) + || ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); lastLeftHandPose = leftHandPose; lastRightHandPose = rightHandPose; From 25b9d756ca8965b1a0162f8edb92e41d0ac30955 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Aug 2016 16:54:04 -0700 Subject: [PATCH 4/5] Update entity edit tracking to track count rather than bool --- interface/src/Application.cpp | 6 +++--- .../entities/src/EntityScriptingInterface.cpp | 14 +++++++------- libraries/entities/src/EntityScriptingInterface.h | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e352b841b7..0876869554 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1203,9 +1203,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : auto entityScriptingInterface = DependencyManager::get(); auto entityActivityTracking = entityScriptingInterface->getActivityTracking(); entityScriptingInterface->resetActivityTracking(); - properties["added_entity"] = entityActivityTracking.hasAddedEntity; - properties["deleted_entity"] = entityActivityTracking.hasDeletedEntity; - properties["edited_entity"] = entityActivityTracking.hasEditedEntity; + properties["added_entity_cnt"] = entityActivityTracking.addedEntityCount; + properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount; + properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount; auto hmdHeadPose = getHMDSensorPose(); properties["hmd_head_pose_changed"] = isHMDMode() && (hmdHeadPose != lastHMDHeadPose); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 031847b3f3..c3dbd47600 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -41,9 +41,9 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType, } void EntityScriptingInterface::resetActivityTracking() { - _activityTracking.hasAddedEntity = false; - _activityTracking.hasDeletedEntity = false; - _activityTracking.hasEditedEntity = false; + _activityTracking.addedEntityCount = 0; + _activityTracking.deletedEntityCount = 0; + _activityTracking.editedEntityCount = 0; } bool EntityScriptingInterface::canAdjustLocks() { @@ -136,7 +136,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, bool clientOnly) { - _activityTracking.hasAddedEntity = true; + _activityTracking.addedEntityCount++; EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); @@ -208,7 +208,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, bool dynamic, const glm::vec3& position, const glm::vec3& gravity) { - _activityTracking.hasAddedEntity = true; + _activityTracking.addedEntityCount++; EntityItemProperties properties; properties.setType(EntityTypes::Model); @@ -273,7 +273,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit } QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { - _activityTracking.hasEditedEntity = true; + _activityTracking.editedEntityCount++; EntityItemProperties properties = scriptSideProperties; @@ -418,7 +418,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } void EntityScriptingInterface::deleteEntity(QUuid id) { - _activityTracking.hasDeletedEntity = true; + _activityTracking.deletedEntity++; EntityItemID entityID(id); bool shouldDelete = true; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index bde0974d7c..ce5b332b2a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -67,9 +67,9 @@ public: class ActivityTracking { public: - bool hasAddedEntity { false }; - bool hasDeletedEntity { false }; - bool hasEditedEntity { false }; + int addedEntityCount { 0 }; + int deletedEntityCount { 0 }; + int editedEntityCount { 0 }; }; EntityEditPacketSender* getEntityPacketSender() const { return (EntityEditPacketSender*)getPacketSender(); } From d46af500c195eb27b36e76174a989f10aa58f788 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 17 Aug 2016 17:00:56 -0700 Subject: [PATCH 5/5] Fix wrong property name in entity activity tracking --- libraries/entities/src/EntityScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c3dbd47600..2bff2a99de 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -418,7 +418,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } void EntityScriptingInterface::deleteEntity(QUuid id) { - _activityTracking.deletedEntity++; + _activityTracking.deletedEntityCount++; EntityItemID entityID(id); bool shouldDelete = true;