Skip to content

Commit 6c3d93a

Browse files
committed
level event
1 parent b6c8168 commit 6c3d93a

File tree

16 files changed

+276
-35
lines changed

16 files changed

+276
-35
lines changed

include/GameAnalytics/GATypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ namespace gameanalytics
7373
LogVerbose = 4
7474
};
7575

76+
enum class EGALevelStatus
77+
{
78+
Abort = -1,
79+
Start = 0,
80+
Complete = 1,
81+
Failure = 2,
82+
};
83+
7684
using StringVector = std::vector<std::string>;
7785

7886
using LogHandler = std::function<void(std::string const&, EGALoggerMessageType)>;

include/GameAnalytics/GameAnalytics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ namespace gameanalytics
7777

7878
static void addErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& customFields = "", bool mergeFields = false);
7979

80+
static void addLevelEvent(EGALevelStatus status, int levelId, std::string const& levelName, int value = 0, std::string const& customFields);
81+
8082
// set calls can be changed at any time (pre- and post-initialize)
8183
// some calls only work after a configure is called (setCustomDimension)
8284
static void setEnabledInfoLog(bool flag);

source/gameanalytics/GAEvents.cpp

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,56 @@ namespace gameanalytics
473473
}
474474
}
475475

476+
void GAEvents::addLevelEvent(EGALevelStatus status, int id, std::string const& name, int value, const json& fields)
477+
{
478+
try
479+
{
480+
if(!state::GAState::isEventSubmissionEnabled())
481+
{
482+
return;
483+
}
484+
485+
if(!state::GAState::getInstance().updateLevelContext(status, id, name))
486+
{
487+
logging::GALogger::e("Invalid level");
488+
return;
489+
}
490+
491+
// Validate
492+
validators::ValidationResult validationResult = validators::GAValidator::validateLevelEvent(status, id, name);
493+
if (!validationResult.result)
494+
{
495+
http::GAHTTPApi& httpInstance = http::GAHTTPApi::getInstance();
496+
httpInstance.sendSdkErrorEvent(validationResult.category, validationResult.area, validationResult.action, validationResult.parameter, validationResult.reason, state::GAState::getGameKey(), state::GAState::getGameSecret());
497+
return;
498+
}
499+
500+
// Create empty eventData
501+
json eventData;
502+
eventData["category"] = GAEvents::CategoryLevel;
503+
eventData["status"] = levelStatusString(status);
504+
eventData["level_id"] = id;
505+
eventData["level_name"] = name;
506+
eventData["value"] = value;
507+
508+
json cleanedFields = state::GAState::getValidatedCustomFields(fields);
509+
getInstance().addCustomFieldsToEvent(eventData, cleanedFields);
510+
511+
// Add custom dimensions
512+
getInstance().addDimensionsToEvent(eventData);
513+
514+
// Log
515+
logging::GALogger::i("Add LEVEL event: %s", eventData.dump().c_str());
516+
517+
// Send to store
518+
getInstance().addEventToStore(eventData);
519+
}
520+
catch(std::exception& e)
521+
{
522+
logging::GALogger::e("addLevelEvent - Exception thrown: %s", e.what());
523+
}
524+
}
525+
476526
void GAEvents::processEventQueue()
477527
{
478528
processEvents("", true);
@@ -590,36 +640,7 @@ namespace gameanalytics
590640
http::EGAHTTPApiResponse responseEnum;
591641
http::GAHTTPApi& http = http::GAHTTPApi::getInstance();
592642

593-
#if USE_UWP && defined(USE_UWP_HTTP)
594-
std::pair<http::EGAHTTPApiResponse, std::string> pair;
595-
596-
try
597-
{
598-
pair = http->sendEventsInArray(payloadArray).get();
599-
}
600-
catch(Platform::COMException^ e)
601-
{
602-
pair = std::pair<http::EGAHTTPApiResponse, std::string>(http::NoResponse, "");
603-
}
604-
responseEnum = pair.first;
605-
606-
if(pair.second.size() > 0)
607-
{
608-
try
609-
{
610-
json d = json::parse(pair.second);
611-
dataDict.merge_patch(d);
612-
}
613-
catch(const json::exception& e)
614-
{
615-
logging::GALogger::d("processEvents -- JSON error: %s", e.what());
616-
logging::GALogger::d("%s", pair.second.c_str());
617-
}
618-
}
619-
#else
620643
responseEnum = http.sendEventsInArray(dataDict, payloadArray);
621-
#endif
622-
623644
if (responseEnum == http::Ok)
624645
{
625646
// Delete events

source/gameanalytics/GAEvents.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ namespace gameanalytics
2727
static void addProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, bool sendScore, const json& fields, bool mergeFields);
2828
static void addDesignEvent(std::string const& eventId, double value, bool sendValue, const json& fields, bool mergeFields);
2929
static void addErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& function, int32_t line, const json& fields, bool mergeFields, bool skipAddingFields = false);
30+
static void addLevelEvent(EGALevelStatus status, int id, std::string const& name, int value, const json& fields);
3031

3132
static void addSDKInitEvent();
3233
static void addHealthEvent();
3334

3435
static std::string progressionStatusString(EGAProgressionStatus progressionStatus);
3536
static std::string errorSeverityString(EGAErrorSeverity errorSeverity);
3637
static std::string resourceFlowTypeString(EGAResourceFlowType flowType);
38+
static std::string levelStatusString(EGALevelStatus lvlStatus);
3739

3840
static void processEvents(std::string const& category, bool performCleanUp);
3941

@@ -51,6 +53,7 @@ namespace gameanalytics
5153
static constexpr const char* CategoryError = "error";
5254
static constexpr const char* CategorySDKInit = "sdk_init";
5355
static constexpr const char* CategoryHealth = "health";
56+
static constexpr const char* CategoryLevel = "level";
5457
static constexpr int MaxEventCount = 500;
5558

5659
static constexpr std::chrono::milliseconds PROCESS_EVENTS_INTERVAL{8000};

source/gameanalytics/GAHTTPApi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace gameanalytics
5353
ProgressionEvent = 3,
5454
DesignEvent = 4,
5555
ErrorEvent = 5,
56+
LevelEvent = 6,
5657
InitHttp = 9,
5758
EventsHttp = 10,
5859
ProcessEvents = 11,

source/gameanalytics/GALogger.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ namespace gameanalytics
102102

103103
private:
104104

105-
static constexpr const char* tag = "GameAnalytics";
105+
static constexpr const char* TAG = "GameAnalytics";
106106
static GALogger& getInstance();
107107

108108
GALogger();

source/gameanalytics/GAState.cpp

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ namespace gameanalytics
2727

2828
namespace state
2929
{
30+
bool GAState::LevelContext::StartLevel(int32_t id, std::string const& name)
31+
{
32+
if(!IsInLevel() && id > 0)
33+
{
34+
levelId = id;
35+
levelName = name;
36+
37+
timer.reset();
38+
timer.start();
39+
40+
return true;
41+
}
42+
43+
return false;
44+
}
45+
46+
bool GAState::LevelContext::EndLevel()
47+
{
48+
if(IsInLevel())
49+
{
50+
levelId = INVALID_LVL;
51+
levelName = "";
52+
53+
return true;
54+
}
55+
56+
return false;
57+
}
58+
3059
GAState& GAState::getInstance()
3160
{
3261
static GAState instance;
@@ -305,7 +334,8 @@ namespace gameanalytics
305334
bool GAState::hasAvailableCustomDimensions02(std::string const& dimension2)
306335
{
307336
return utilities::GAUtilities::stringVectorContainsString(
308-
getInstance()._availableCustomDimensions02, dimension2);
337+
getInstance()._availableCustomDimensions02, dimension2
338+
);
309339
}
310340

311341
bool GAState::hasAvailableCustomDimensions03(std::string const& dimension3)
@@ -427,6 +457,13 @@ namespace gameanalytics
427457

428458
// ---- OPTIONAL ---- //
429459

460+
// level
461+
if(getInstance()._levelContext.IsInLevel())
462+
{
463+
out["level_name"] = getInstance()._levelContext.levelName;
464+
out["level_id"] = getInstance()._levelContext.levelId;
465+
}
466+
430467
// A/B testing
431468
utilities::addIfNotEmpty(out, "ab_id", getInstance()._abId);
432469
utilities::addIfNotEmpty(out, "ab_variant_id", getInstance()._abVariantId);
@@ -465,7 +502,7 @@ namespace gameanalytics
465502
out["device"] = device::GADevice::getDeviceModel();
466503
out["platform"] = device::GADevice::getBuildPlatform();
467504
out["connection_type"] = device::GADevice::getConnectionType();
468-
out["category"] = "sdk_error";
505+
out["category"] = CategorySdkError;
469506

470507
// ---- OPTIONAL ---- //
471508

@@ -1132,5 +1169,34 @@ namespace gameanalytics
11321169

11331170
return cleanedFields;
11341171
}
1172+
1173+
bool GAState::updateLevelContext(EGALevelStatus status, int id, std::string const& levelName)
1174+
{
1175+
switch(status)
1176+
{
1177+
case EGALevelStatus::Start:
1178+
{
1179+
if(_levelContext.IsInLevel())
1180+
{
1181+
1182+
}
1183+
1184+
return _levelContext.StartLevel(id, levelName);
1185+
}
1186+
1187+
case EGALevelStatus::Failure:
1188+
case EGALevelStatus::Complete:
1189+
case EGALevelStatus::Abort:
1190+
{
1191+
if(!_levelContext.IsInLevel())
1192+
{
1193+
logging::GALogger::w("No active level found. A level start event must be called before Failure/Complete/Abort events!");
1194+
return false;
1195+
}
1196+
1197+
return _levelContext.EndLevel();
1198+
}
1199+
}
1200+
}
11351201
}
11361202
}

source/gameanalytics/GAState.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,20 @@ namespace gameanalytics
150150
int64_t calculateSessionLength() const;
151151

152152
private:
153+
154+
struct LevelContext
155+
{
156+
static constexpr int32_t INVALID_LVL = -1;
157+
158+
int32_t levelId{INVALID_LVL};
159+
std::string levelName;
160+
utilities::Stopwatch timer;
161+
162+
inline bool IsInLevel() const { return levelId != INVALID_LVL; }
163+
164+
bool StartLevel(int32_t id, std::string const& name);
165+
bool EndLevel();
166+
};
153167

154168
GAState();
155169
~GAState();
@@ -185,6 +199,8 @@ namespace gameanalytics
185199

186200
void addErrorEvent(EGAErrorSeverity severity, std::string const& message);
187201

202+
bool updateLevelContext(EGALevelStatus status, int levelId, std::string const& levelName);
203+
188204
threading::GAThreading _gaThread;
189205
events::GAEvents _gaEvents;
190206
device::GADevice _gaDevice;
@@ -244,6 +260,8 @@ namespace gameanalytics
244260
bool _enableEventSubmission = true;
245261

246262
bool _enableIdTracking = true;
263+
264+
LevelContext _levelContext;
247265

248266
json _configurations;
249267
bool _remoteConfigsIsReady;

source/gameanalytics/GAStore.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ namespace gameanalytics
4444
executeQuerySync(sql, {}, 0, out);
4545
}
4646

47-
4847
void GAStore::executeQuerySync(std::string const& sql, StringVector const& parameters)
4948
{
5049
json d;

source/gameanalytics/GAThreading.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#pragma once
77

8-
98
#include <functional>
109
#include <atomic>
1110
#include <vector>

0 commit comments

Comments
 (0)