Skip to content

Commit b813b86

Browse files
committed
player progression event
1 parent be061a0 commit b813b86

File tree

7 files changed

+189
-54
lines changed

7 files changed

+189
-54
lines changed

source/gameanalytics/GAEvents.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,14 @@ namespace gameanalytics
724724
{
725725
json sessionEndEvent = json::parse(session["event"].get<std::string>());
726726

727+
std::string userId = sessionEndEvent["user_id"];
728+
729+
// workaround for server based implementation, we want to skip player events
730+
if(userId != state::GAState::getUserId())
731+
{
732+
continue;
733+
}
734+
727735
int64_t event_ts = utilities::getOptionalValue<int64_t>(sessionEndEvent, "client_ts", 0);
728736
int64_t start_ts = std::stoll(utilities::getOptionalValue<std::string>(session, "timestamp", "0"));
729737

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
3+
#include "GameAnalytics/GATypes.h"
4+
5+
namespace gameanalytics
6+
{
7+
8+
struct ProgressionTries
9+
{
10+
public:
11+
12+
inline void addOrUpdate(std::string const& s, int tries)
13+
{
14+
_tries[s] = tries;
15+
}
16+
17+
inline void remove(std::string const& s)
18+
{
19+
if (_tries.count(s))
20+
{
21+
_tries.erase(s);
22+
}
23+
}
24+
25+
inline int getTries(std::string const& s) const
26+
{
27+
if (_tries.count(s))
28+
{
29+
return _tries.at(s);
30+
}
31+
32+
return 0;
33+
}
34+
35+
inline int incrementTries(std::string const& s)
36+
{
37+
if (_tries.count(s))
38+
{
39+
_tries[s]++;
40+
}
41+
else
42+
{
43+
_tries[s] = 1;
44+
}
45+
46+
return _tries[s];
47+
}
48+
49+
private:
50+
51+
std::unordered_map<std::string, int> _tries;
52+
};
53+
}

source/gameanalytics/GAState.h

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,56 +21,12 @@
2121
#include "GAHTTPApi.h"
2222
#include "GADevice.h"
2323

24+
#include "GAProgressionTries.h"
25+
2426
namespace gameanalytics
2527
{
2628
namespace state
2729
{
28-
struct ProgressionTries
29-
{
30-
public:
31-
32-
inline void addOrUpdate(std::string const& s, int tries)
33-
{
34-
_tries[s] = tries;
35-
}
36-
37-
inline void remove(std::string const& s)
38-
{
39-
if (_tries.count(s))
40-
{
41-
_tries.erase(s);
42-
}
43-
}
44-
45-
inline int getTries(std::string const& s) const
46-
{
47-
if (_tries.count(s))
48-
{
49-
return _tries.at(s);
50-
}
51-
52-
return 0;
53-
}
54-
55-
inline int incrementTries(std::string const& s)
56-
{
57-
if (_tries.count(s))
58-
{
59-
_tries[s]++;
60-
}
61-
else
62-
{
63-
_tries[s] = 1;
64-
}
65-
66-
return _tries[s];
67-
}
68-
69-
private:
70-
71-
std::unordered_map<std::string, int> _tries;
72-
};
73-
7430
class GAState
7531
{
7632
friend class threading::GAThreading;

source/gameanalytics/Server/GAPlayer.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,18 @@ namespace gameanalytics
1414
device = "unknown";
1515
manufacturer = "unknown";
1616
platform = "windows";
17-
connectionType = "wifi";
17+
connectionType = "lan";
1818
}
1919

20-
Player::Player(std::string const& userId, std::string const& abId, std::string const& abVariantId)
20+
Player::Player(std::string const& userId, std::string const& externalId):
21+
_userId(userId),
22+
extUserId(externalId)
2123
{
22-
_userId = userId;
23-
_abId = abId;
24-
_abVariantId = abVariantId;
25-
2624
osVersion = "windows 10";
2725
device = "unknown";
2826
manufacturer = "unknown";
2927
platform = "windows";
30-
connectionType = "wifi";
28+
connectionType = "lan";
3129
}
3230

3331
Player::Player(std::string const& jsonData)

source/gameanalytics/Server/GAPlayer.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "GameAnalytics/GATypes.h"
44
#include "Server/GACustomFields.h"
5+
#include "GAProgressionTries.h"
56
#include <chrono>
67

78
namespace gameanalytics
@@ -47,11 +48,15 @@ namespace gameanalytics
4748
std::string manufacturer;
4849
std::string osVersion;
4950
std::string connectionType;
51+
std::string gpuModel;
52+
std::string cpuModel;
5053
CustomFields customFields;
54+
55+
ProgressionTries progressionTries;
5156

5257
Player();
5358
Player(std::string const& jsonData);
54-
Player(std::string const& userId, std::string const& abId, std::string const& abVariantId);
59+
Player(std::string const& userId, std::string const& extUserId);
5560

5661
std::string getUserId() const;
5762
std::string getABId() const;
@@ -103,8 +108,13 @@ namespace gameanalytics
103108

104109
struct PlayerCallbacks
105110
{
111+
// called when a new player joins the first session
106112
virtual void onNewPlayer(Player& player) = 0;
113+
114+
// called when a player starts a session (e.g: logs in)
107115
virtual void onPlayerJoin(Player& player) = 0;
116+
117+
// called when a player ends a session (e.g: logs off)
108118
virtual void onPlayerExit(Player& player) = 0;
109119
};
110120

source/gameanalytics/Server/GAServer.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,91 @@ namespace gameanalytics
384384
}
385385
}
386386

387+
void GameAnalyticsServer::addPlayerProgressionEventInternal(Player& player, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields)
388+
{
389+
try
390+
{
391+
if(!state::GAState::isEventSubmissionEnabled())
392+
{
393+
return;
394+
}
395+
396+
// Validate event params
397+
validators::ValidationResult validationResult;
398+
validators::GAValidator::validateProgressionEvent(progressionStatus, progression01, progression02, progression03, validationResult);
399+
if (!validationResult.result)
400+
{
401+
http::GAHTTPApi& httpInstance = http::GAHTTPApi::getInstance();
402+
httpInstance.sendSdkErrorEvent(validationResult.category, validationResult.area, validationResult.action, validationResult.parameter, validationResult.reason, state::GAState::getGameKey(), state::GAState::getGameSecret());
403+
return;
404+
}
405+
406+
// Create empty eventData
407+
json eventDict = PlayerDatabase::getPlayerAnnotations(player);
408+
409+
// Progression identifier
410+
std::string progressionIdentifier = progression01;
411+
412+
if(!progression02.empty())
413+
{
414+
progressionIdentifier += ':';
415+
progressionIdentifier += progression02;
416+
417+
if(!progression03.empty())
418+
{
419+
progressionIdentifier += ':';
420+
progressionIdentifier += progression03;
421+
}
422+
}
423+
424+
const std::string statusString = events::GAEvents::progressionStatusString(progressionStatus);
425+
426+
eventDict["category"] = events::GAEvents::CategoryProgression;
427+
eventDict["event_id"] = statusString + ':' + progressionIdentifier;
428+
429+
// Attempt
430+
int attempt_num = 0;
431+
432+
// Add score if specified and status is not start
433+
if (sendScore && progressionStatus != EGAProgressionStatus::Start)
434+
{
435+
eventDict["score"] = score;
436+
}
437+
438+
// Count attempts on each progression fail and persist
439+
if (progressionStatus == EGAProgressionStatus::Fail)
440+
{
441+
// Increment attempt number
442+
player.progressionTries.incrementTries(progressionIdentifier);
443+
}
444+
445+
// increment and add attempt_num on complete and delete persisted
446+
if (progressionStatus == EGAProgressionStatus::Complete)
447+
{
448+
// Increment attempt number
449+
player.progressionTries.incrementTries(progressionIdentifier);
450+
451+
// Add to event
452+
attempt_num = player.progressionTries.getTries(progressionIdentifier);
453+
eventDict["attempt_num"] = attempt_num;
454+
455+
// Clear
456+
state::GAState::clearProgressionTries(progressionIdentifier);
457+
}
458+
459+
// Log
460+
logging::GALogger::i("Add PROGRESSION event: {status:%s, progression01:%s, progression02:%s, progression03:%s, score:%d, attempt:%d, fields:%s}",
461+
statusString.c_str(), progression01.c_str(), progression02.c_str(), progression03.c_str(), score, attempt_num, customFields.c_str());
462+
463+
// Send to store
464+
events::GAEvents::getInstance().addEventToStore(eventDict);
465+
}
466+
catch(std::exception& e)
467+
{
468+
logging::GALogger::e("addProgressionEvent - Exception thrown: %s", e.what());
469+
}
470+
}
471+
387472
void GameAnalyticsServer::addPlayerDesignEvent(Player& player, std::string const& eventId, double value, std::string const& customFields)
388473
{
389474
threading::GAThreading::performTaskOnGAThread(
@@ -424,6 +509,16 @@ namespace gameanalytics
424509
);
425510
}
426511

512+
void GameAnalyticsServer::addPlayerProgressionEvent(Player& player, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields)
513+
{
514+
threading::GAThreading::performTaskOnGAThread(
515+
[this, &player, progressionStatus, progression01, progression02, progression03, sendScore, score, customFields]()
516+
{
517+
addPlayerProgressionEventInternal(player, progressionStatus, progression01, progression02, progression03, sendScore, score, customFields);
518+
}
519+
);
520+
}
521+
427522
void GameAnalyticsServer::addPlayerDesignEvent(std::string const& userId, std::string const& eventId, double value, std::string const& customFields)
428523
{
429524
if(isExistingPlayer(userId))
@@ -471,4 +566,16 @@ namespace gameanalytics
471566
logging::GALogger::w("Invalid user id: %s", userId.c_str());
472567
}
473568
}
569+
570+
void GameAnalyticsServer::addPlayerProgressionEvent(std::string const& userId, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields)
571+
{
572+
if(isExistingPlayer(userId))
573+
{
574+
return addPlayerProgressionEvent(getPlayer(userId), progressionStatus, progression01, progression02, progression03, sendScore, score, customFields);
575+
}
576+
else
577+
{
578+
logging::GALogger::w("Invalid user id: %s", userId.c_str());
579+
}
580+
}
474581
}

source/gameanalytics/Server/GAServer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace gameanalytics
1818
void addPlayerBusinessEventInternal(Player& player, std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& customFields = "");
1919
void addPlayerResourceEventInternal(Player& player, EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& customFields = "");
2020
void addPlayerErrorEventInternal(Player& player, EGAErrorSeverity severity, std::string const& message, std::string const& customFields = "");
21+
void addPlayerProgressionEventInternal(Player& player, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields = "");
2122

2223
public:
2324

@@ -42,11 +43,13 @@ namespace gameanalytics
4243
void addPlayerBusinessEvent(Player& player, std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& customFields = "");
4344
void addPlayerResourceEvent(Player& player, EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& customFields = "");
4445
void addPlayerErrorEvent(Player& player, EGAErrorSeverity severity, std::string const& message, std::string const& customFields = "");
46+
void addPlayerProgressionEvent(Player& player, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields = "");
4547

4648
void addPlayerDesignEvent(std::string const& userId, std::string const& eventId, double value = 0.0, std::string const& customFields = "");
4749
void addPlayerBusinessEvent(std::string const& userId, std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& customFields = "");
4850
void addPlayerResourceEvent(std::string const& userId, EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& customFields = "");
4951
void addPlayerErrorEvent(std::string const& userId, EGAErrorSeverity severity, std::string const& message, std::string const& customFields = "");
52+
void addPlayerProgressionEvent(std::string const& userId, EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, std::string const& customFields = "");
5053
};
5154

5255
} // namespace gameanalytics

0 commit comments

Comments
 (0)