Skip to content

Commit

Permalink
Easier to use and well defined schema for gamechangers
Browse files Browse the repository at this point in the history
  • Loading branch information
albert-wang committed Dec 10, 2024
1 parent 4c221cd commit 3005e2c
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 4 deletions.
75 changes: 73 additions & 2 deletions gamelink_single.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30304,7 +30304,8 @@ namespace gateway
std::function<void(const PollUpdate&)> OnComplete;
};

struct MatchPollConfiguration
template<typename T>
struct GenericMatchPollConfiguration
{
string Prompt;
std::vector<string> Options;
Expand All @@ -30318,7 +30319,7 @@ namespace gateway
int32_t Duration = 0;

// Arbitrary user data to send. Should be small.
nlohmann::json UserData;
T UserData;

// Called regularly as poll results are streamed in from the server
std::function<void(const MatchPollUpdate&)> OnUpdate;
Expand All @@ -30327,6 +30328,44 @@ namespace gateway
std::function<void(const MatchPollUpdate&)> OnComplete;
};

typedef GenericMatchPollConfiguration<nlohmann::json> MatchPollConfiguration;

struct GamechangerTier
{
string IncrementalText;
double IncrementalValue;

string EffectText;
double EffectValue;

// In seconds
int64_t TierDuration;

int64_t TierThreshold;

MUXY_GAMELINK_SERIALIZE_INTRUSIVE_6(GamechangerTier,
"incremental_effect_text", IncrementalText,
"incremental_effect_value", IncrementalValue,
"effect_text", EffectText,
"effect_value", EffectValue,
"tier_duration", TierDuration,
"tier_threshold", TierThreshold
);
};

struct GamechangerPollData
{
string Name;
std::vector<GamechangerTier> Tiers;

MUXY_GAMELINK_SERIALIZE_INTRUSIVE_2(GamechangerPollData,
"name", Name,
"tiers", Tiers
);
};

typedef GenericMatchPollConfiguration<GamechangerPollData> GamechangerMatchPollConfiguration;

enum class ActionCategory
{
Neutral = 0,
Expand Down Expand Up @@ -30509,9 +30548,41 @@ namespace gateway
void AddChannelsToMatch(const string& match, const string* start, const string* end);
void RemoveChannelsFromMatch(const string& match, const string* start, const string* end);

template<typename T>
void RunMatchPoll(const string& match, const GenericMatchPollConfiguration<T>& cfg)
{
MatchPollConfiguration proxy;
proxy.Prompt = cfg.Prompt;
proxy.Options = cfg.Options;
proxy.Mode = cfg.Mode;
proxy.Location = cfg.Location;
proxy.Duration = cfg.Duration;
proxy.UserData = cfg.UserData;
proxy.OnUpdate = cfg.OnUpdate;
proxy.OnComplete = cfg.OnComplete;

return RunMatchPoll(match, proxy);
}

void RunMatchPoll(const string& match, const MatchPollConfiguration& cfg);
void StopMatchPoll(const string& match);

template<typename T>
void RunMatchPollWithID(const string& match, const string& id, const GenericMatchPollConfiguration<T>& cfg)
{
MatchPollConfiguration proxy;
proxy.Prompt = cfg.Prompt;
proxy.Options = cfg.Options;
proxy.Mode = cfg.Mode;
proxy.Location = cfg.Location;
proxy.Duration = cfg.Duration;
proxy.UserData = cfg.UserData;
proxy.OnUpdate = cfg.OnUpdate;
proxy.OnComplete = cfg.OnComplete;

return RunMatchPollWithID(match, id, proxy);
}

void RunMatchPollWithID(const string& match, const string& id, const MatchPollConfiguration& cfg);
void StopMatchPollWithID(const string& match, const string& id);
private:
Expand Down
78 changes: 76 additions & 2 deletions include/gateway.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ namespace gateway
std::function<void(const PollUpdate&)> OnComplete;
};

struct MatchPollConfiguration
template<typename T>
struct GenericMatchPollConfiguration
{
string Prompt;
std::vector<string> Options;
Expand All @@ -136,7 +137,7 @@ namespace gateway
int32_t Duration = 0;

// Arbitrary user data to send. Should be small.
nlohmann::json UserData;
T UserData;

// Called regularly as poll results are streamed in from the server
std::function<void(const MatchPollUpdate&)> OnUpdate;
Expand All @@ -145,6 +146,47 @@ namespace gateway
std::function<void(const MatchPollUpdate&)> OnComplete;
};

typedef GenericMatchPollConfiguration<nlohmann::json> MatchPollConfiguration;

struct GamechangerTier
{
string IncrementalText;
double IncrementalValue;

string EffectText;
double EffectValue;

// In seconds
int64_t TierDuration;

int64_t TierThreshold;

MUXY_GAMELINK_SERIALIZE_INTRUSIVE_6(GamechangerTier,
"incremental_effect_text", IncrementalText,
"incremental_effect_value", IncrementalValue,
"effect_text", EffectText,
"effect_value", EffectValue,
"tier_duration", TierDuration,
"tier_threshold", TierThreshold
);
};

struct GamechangerPollData
{
string Name;
std::vector<GamechangerTier> Tiers;

// Shouldn't need to be changed, a marker to signal for special-case handling
string Type = string("gamechanger");

MUXY_GAMELINK_SERIALIZE_INTRUSIVE_3(GamechangerPollData,
"name", Name,
"type", Type,
"tiers", Tiers
);
};

typedef GenericMatchPollConfiguration<GamechangerPollData> GamechangerMatchPollConfiguration;

enum class ActionCategory
{
Expand Down Expand Up @@ -328,9 +370,41 @@ namespace gateway
void AddChannelsToMatch(const string& match, const string* start, const string* end);
void RemoveChannelsFromMatch(const string& match, const string* start, const string* end);

template<typename T>
void RunMatchPoll(const string& match, const GenericMatchPollConfiguration<T>& cfg)
{
MatchPollConfiguration proxy;
proxy.Prompt = cfg.Prompt;
proxy.Options = cfg.Options;
proxy.Mode = cfg.Mode;
proxy.Location = cfg.Location;
proxy.Duration = cfg.Duration;
proxy.UserData = cfg.UserData;
proxy.OnUpdate = cfg.OnUpdate;
proxy.OnComplete = cfg.OnComplete;

return RunMatchPoll(match, proxy);
}

void RunMatchPoll(const string& match, const MatchPollConfiguration& cfg);
void StopMatchPoll(const string& match);

template<typename T>
void RunMatchPollWithID(const string& match, const string& id, const GenericMatchPollConfiguration<T>& cfg)
{
MatchPollConfiguration proxy;
proxy.Prompt = cfg.Prompt;
proxy.Options = cfg.Options;
proxy.Mode = cfg.Mode;
proxy.Location = cfg.Location;
proxy.Duration = cfg.Duration;
proxy.UserData = cfg.UserData;
proxy.OnUpdate = cfg.OnUpdate;
proxy.OnComplete = cfg.OnComplete;

return RunMatchPollWithID(match, id, proxy);
}

void RunMatchPollWithID(const string& match, const string& id, const MatchPollConfiguration& cfg);
void StopMatchPollWithID(const string& match, const string& id);
private:
Expand Down
176 changes: 176 additions & 0 deletions test/gateway_matches.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#include "catch2/catch.hpp"
#include "util.h"

#include "gateway.h"


TEST_CASE("Create a gamechanger", "[gateway][matches]")
{
gateway::SDK sdk("This is a game");

gateway::GamechangerMatchPollConfiguration cfg;
cfg.Duration = 120;
cfg.Prompt = "Empower my snacks";
cfg.Options = {
"Empower",
};

cfg.Mode = gateway::PollMode::Chaos;
cfg.UserData.Name = "Delivery Budget";
cfg.UserData.Tiers = {
gateway::GamechangerTier{
.IncrementalText = "Spend $1 more",
.IncrementalValue = 1,

.EffectText = "Spend $10 more",
.EffectValue = 10,

.TierDuration = 120,
.TierThreshold = 0
},

gateway::GamechangerTier{
.EffectText = "Spend $100 more",
.EffectValue = 100,

.IncrementalText = "Spend $10 more",
.IncrementalValue = 10,

.TierDuration = 60,
.TierThreshold = 200
},

gateway::GamechangerTier{
.EffectText = "Spend $200 more",
.EffectValue = 200,

.IncrementalText = "Spend $20 more",
.IncrementalValue = 20,

.TierDuration = 30,
.TierThreshold = 400
},

gateway::GamechangerTier{
.EffectText = "Go for broke!!",
.EffectValue = 1000,

.IncrementalText = "Please no more :(",
.IncrementalValue = 5,

.TierDuration = 15,
.TierThreshold = 1000
},
};

sdk.RunMatchPoll("my-cool-match", cfg);
REQUIRE(sdk.HasPayloads());

validateSinglePayload(sdk, R"({
"action": "delete",
"params":{
"request_id": 65535,
"target": "match_poll"
},
"data": {
"id": "my-cool-match",
"poll_id": "default"
}
})");

const char* msg = R"({
"meta": {
"action": "nothing",
"request_id": 1
}
})";
sdk.ReceiveMessage(msg, strlen(msg));

validateSinglePayload(sdk, R"({
"action": "subscribe",
"data": {
"topic_id": "my-cool-match"
},
"params": {
"request_id": 65535,
"target": "match_poll"
}
})");

const char* msg2 = R"({
"meta": {
"action": "nothing",
"request_id": 2
}
})";
sdk.ReceiveMessage(msg2, strlen(msg2));

const char* expected = R"({
"action": "create",
"data": {
"id": "my-cool-match",
"poll": {
"config": {
"disabled": false,
"distinctOptionsPerUser": 258,
"endsAt": 0,
"endsIn": 120,
"startsAt": 0,
"startsIn": 0,
"totalVotesPerUser": 1024,
"userIDVoting": true,
"votesPerOption": 1024
},
"options": [
"Empower"
],
"poll_id": "default",
"prompt": "Empower my snacks",
"user_data": {
"name": "Delivery Budget",
"type": "gamechanger",
"tiers": [
{
"effect_text": "Spend $10 more",
"effect_value": 10.0,
"incremental_effect_text": "Spend $1 more",
"incremental_effect_value": 1.0,
"tier_duration": 120,
"tier_threshold": 0
},
{
"effect_text": "Spend $100 more",
"effect_value": 100.0,
"incremental_effect_text": "Spend $10 more",
"incremental_effect_value": 10.0,
"tier_duration": 60,
"tier_threshold": 200
},
{
"effect_text": "Spend $200 more",
"effect_value": 200.0,
"incremental_effect_text": "Spend $20 more",
"incremental_effect_value": 20.0,
"tier_duration": 30,
"tier_threshold": 400
},
{
"effect_text": "Go for broke!!",
"effect_value": 1000.0,
"incremental_effect_text": "Please no more :(",
"incremental_effect_value": 5.0,
"tier_duration": 15,
"tier_threshold": 1000
}
]
}
}
},
"params": {
"request_id": 65535,
"target": "match_poll"
}
})";

validateSinglePayload(sdk, expected);
}
Loading

0 comments on commit 3005e2c

Please sign in to comment.