Skip to main content

Statistics

1. Overview

Statistics is a service that helps you to store and track player or global statistics. By default, Statistics is also a major data source of the Leaderboard service.

To read this chapter, you will learn the key mechanism and how to set up and use statistics.

2. Key Concepts

2.1 Stat

A Stat is essentially a data map to store statistical data. Each data item in it has the following key fields:

  • Key: This is a unique string used to identify the data item. What the key should be depends on your scenario. For example, you can set as the PlayerID to track the player's kill counts or set as the TeamID to track the team's score.
  • Value: The data item's value is a double type, with the default being 0.
  • Secondary Value: This is an optional data item value, also in double type and with a default of 0. It is used for multi-value sorting in the Leaderboard service. If you don't require multi-value sorting, you can ignore this field.
  • Tags: Tags can be added to the data item. This field is used to configure and construct sub-leaderboards in the Leaderboard service. You can also use it to store arbitrary strings to tag the data item.

You can update the data item in Stat with a specific aggregate type. The mechanism for this is outlined in the following table:

Aggregate TypeValueSecondary ValueTags
OverrideOverwriteOverwriteOverwrite
Sumthe sum of the new value and the existing oneOverwriteOverwrite
MaxOverwrite if the new value is higher than the existing oneOverwrite if the value is updatedOverwrite if the value updated
MinOverwrite if the new value is lower than the existing oneOverwrite if the value is updatedOverwrite if the value updated

2.2 Cycle

To keep track of statistics data within a specific time frame, you can use the Cycle feature. When you bind a Stat with a Cycle, the PGOS backend automatically updates the Cycle data whenever you update the Stat data. Once the cycle time frame ends, the data is reset, for example, allowing players to start a new competition. For instance, the game can track daily kill counts or the best game session score of the season.

There are different cycle types to choose from, including Daily, Weekly, Monthly, and Seasonal (custom-defined). You can determine the reset time clock for each cycle type. For Seasonal cycles, you can define the reset time clock for every period, such as 90 days for a game season lasting 90 days.

A Stat can be bound with multiple Cycles, and a Cycle can be bound with multiple Stats.

tip

Please note that data is updated into the Cycle after binding, and existing Stat data before binding is not transferred to the Cycle.

  • Stat not bound with Cycle: There is only a persistent data map in it, shown below chart:

    image-20230921171114283

  • Stat bound with Cycle: There is an extra cycle data map for every bound Cycle. Each cycle data is stored separately from the persistent data, shown below chart:

    image-20230921171139755

3. Manage on Portal

3.1 Stats

3.1.1 Add New Stat

Log in to the web portal, enter the console, and go to Statistics > Stat:

image-20230906171133759

Field description:

  • Stat Name: The name of the new stat. It can only contain letters, numbers, and underscores, and must start with a letter.
  • Min Value (optional): Minimum value for Stat item value. Enable and specify a limit value if there is a need to restrict the item minimum value.
  • Max Value (optional): Maximum value for Stat item value. Enable and specify a limit value if there is a need to restrict the item's maximum value.
  • Description (optional): The description of the stat.

If everything is ok then you will get a new stat:

image-20230906172448274

3.1.2 Edit Stat

If you want to edit a stat, click the Edit link button in the stat list:

image-20230906172814253

tip

Modifications to the Max limit and Min limit only affect subsequent update operations and will not change the existing data.

3.1.3 Delete Stat

If you want to remove a stat, click the Delete link button in the stat list:

image-20230906192931943

tip

Once a stat is deleted, its data can no longer be accessed through the PgosSDK or HTTP API.

3.1.4 Manage Stat Items

Click the stat name to start managing stat items:

image-20230906175254806

After the stat name clicking, you will see a recently updated item list:

image-20230922185421849

If you want to search for a specific item, input the item key and click the Search button:

If you want to search multiple items at the same time, enable the multi-keys checkbox, and input multiple item keys in the search box.

image-20230906195333551

If you want to add/update the stat item, click the Add/Update Data button:

image-20230906195853748

Fill in the fields and click the OK button, Then:

  • If the item key exists, the item will be updated.
  • If the item key does not exist, the item will be added.

3.2 Cycles

3.2.1 Add New Cycle

Log in to the web portal, enter the console, and go to Statistics > Cycles:

image-20230922192557336

Field description:

  • Name: The name of the new cycle. It can only contain letters, numbers, and underscores, and must start with a letter.
  • Type: The cycle type, which represents the data reset period, including Daily, Weekly, Monthly, and Seasonal (custom-defined).
  • Reset Time: The time indicates when to reset the cycle data.
  • Start Date Time: The time indicates when the cycle starts to work.
  • End Date Time: The time indicates when the cycle stops working.
  • Description (optional): The description of the cycle.

If everything is okay then you will get a new cycle:

image-20230922193429424

3.2.2 Edit Cycle

If you want to edit a cycle, click the Edit link button in the cycle list:

image-20230922193630418

3.2.3 Delete Cycle

If you want to remove a cycle, click the Delete link button in the cycle list:

image-20230922193801224

3.2.4 Bind Stat to Cycle

If you want a stat to have cycle data, you need to bind the stat to a cycle., click the Cycle Name to want to bind to in the cycle list:

image-20230922194422480

After the cycle name clicking, you will see a view below:

image-20230922194550144

Click the Bind Stat button, you can bind stats to the cycle:

image-20230922195138930

You can select the stats you want bind to the cycle. After that, the stats you selected will be in the bound stats list:

image-20230922195258186

If you want to unbind a stat from the cycle, click the Delete link button in the bound stats list:

image-20230922195735544

3.2.5 View Cycle Data

Once the stat is bound to a cycle, you will be able to simultaneously obtain the corresponding cycle data when updating the stat item data in the future. If you want to view the cycle data in the console, please enter the Manage Stat Items page, click the drop-down arrow next to the item key, then you can view the cycle data:

image-20230922200815960

4. Boundary Cases

When using Stat and Cycle, the following boundary cases may be encountered, please be aware of them.

4.1 Stat Min/Max Limitations

When configuring the min or max limit for stat, if the result of the value using the following aggregate types may exceed the min or max limit, PGOS will handle it as shown in the table below.

Aggregate TypeValue Result
OverrideValues greater than the max limit will be set to the max limit itself, while values less than the min limit will be set to the min limit itself.
SumIf the sum of values exceeds the max limit, the value will be set to the max limit itself. If the sum of values is less than the minimum limit, the value will be set to the min limit itself.
MaxWhen comparing the current value with a value greater than the max limit, the value will be set to the max limit itself.
MinWhen comparing the current value with a value less than the minimum limit, the value will be set to the min limit itself.

Let's take min: 0 max: 100 limitations for example:

Aggregate TypeOld ValueValue In RequestResult Value
Override75150100
Override75-1000
Sum7530100
Sum75-1000
Max75150100
Min75-1000

4.2 Cycle First Reset Period

Under certain circumstances, the first reset cycle of the Cycle may be shorter than the preset reset cycle. This can occur in the following examples:

Daily Cycle

Cycle TypeReset TimeStart Date
Daily10:002023-09-01 00:00:00

The first reset time will be 2023-09-01 10:00:00, which is 10 hours after the cycle starts instead of 24 hours. The Next reset time will be 2023-09-02 10:00:00, and so will the following ones.

Weekly Cycle

Cycle TypeReset TimeReset WeekdayStart Date
Weekly10:00Tuesday2023-01-01 00:00:00 (Let's assume this day is Monday)

The first reset time will be 2023-01-02 10:00 (which is Tuesday), the next reset time will be 2023-01-09 10:00 and so will the following ones.

Monthly Cycle

Cycle TypeReset TimeReset MonthdayStart Date
Monthly10:0052023-01-01 00:00:00

The first reset time will be 2023-01-05 10:00 (which is Tuesday), the next reset time will be 2023-02-05 10:00 and so will the following ones.

As you can see, in the above scenes, the first reset period is typically less than the period configured in the cycle type. If this situation occurs, please note that it is as expected.

4.3 Cycle Monthly Reset Boundary Case

When using the monthly cycle, if the reset day exceeds the maximum number of days in the current month, it will default to the last day of the month.

Cycle TypeReset TimeReset MonthdayStart Date
Monthly10:00312024-02-01 00:00:00

The first reset time will be 2024-02-28 10:00:00, which is the last day of that month.

5. Access via SDK

5.1 For Game Client

The game can query stat data on the game client through PgosSDK.

APIDescription
GetStatPersistentInfoQuery the persistent info of the specified stat item.
BatchGetStatPersistentInfoQuery item persistent info with specified stat names and keys in batches.
GetStatCycleInfoQuery the cycle info of the specified stat item for the current cycle round.
BatchGetStatCycleInfoQuery item cycle info with specified stat names and keys for the current cycle round in batches.
BatchGetStatCycleRoundInfoQuery the current round infos of cycles in batches.

5.1.1 GetStatPersistentInfo Client API

Query the persistent info of the specified stat item.

Interface prototype:

/**
* Query the persistent info of the specified stat item.
*
* @param Params Request structure for querying persistent info.
*/
void GetStatPersistentInfo(
const FGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FStatItem* Data)> Callback) const;

struct FGetStatPersistentInfoParams {
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FGetStatPersistentInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Statistics->GetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FStatItem* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.1.2 BatchGetStatPersistentInfo Client API

Query persistent info with specified stat names and keys in batches.

Interface prototype:

/**
* Query item persistent info with specified stat names and keys in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item persistent infos.
*/
void BatchGetStatPersistentInfo(
const FBatchGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data)> Callback) const;

struct FBatchGetStatPersistentInfoParams
{
/** Stat names. */
TArray<FString> stat_names;
/** Stat item keys. */
TArray<FString> keys;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatPersistentInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Statistics->BatchGetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.1.3 GetStatCycleInfo Client API

Query the cycle info of the specified stat item for the current cycle round.

Interface prototype:

/**
* Query the cycle info of the specified stat item for the current cycle round.
*
* @param Params Request structure for querying the cycle info.
*/
void GetStatCycleInfo(
const FGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FGetStatCycleInfoResult* Data)> Callback) const;

struct FGetStatCycleInfoParams
{
/** The stat name. */
FString stat_name;
/** The stat item key. */
FString key;
/** The stat cycle name. */
FString cycle_name;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FGetStatCycleInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Params.cycle_name = TEXT("Daily");
Statistics->GetStatCycleInfo(Params, [](const FPgosResult& Ret, const FGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.1.4 BatchGetStatCycleInfo Client API

Query item cycle info with specified stat names and keys for the current cycle round in batches.

Interface prototype:

/**
* Query cycle info with specified stat names and keys for the current cycle round in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item cycle infos.
*/
void BatchGetStatCycleInfo(
const FBatchGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleInfoParams
{
/** The stat names. */
TArray<FString> stat_names;
/** The stat item keys. */
TArray<FString> keys;
/** The stat cycle name. */
FString cycle_name;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Params.cycle_name = TEXT("Daily");
Statistics->BatchGetStatCycleInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.1.5 BatchGetStatCycleRoundInfo Client API

Query the current round infos of cycles in batches.

Interface prototype:

/**
* Query the current round infos of cycles in batches.
*
* @param Params Request structure for querying current round infos.
*/
void BatchGetStatCycleRoundInfo(
const FBatchGetStatCycleRoundInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleRoundInfoParams
{
/** The stat cycle names. */
TArray<FString> cycle_names;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleRoundInfoParams Params;
Params.cycle_names.Add(TEXT("Daily"));
Params.cycle_names.Add(TEXT("Weekly"));
Statistics->BatchGetStatCycleRoundInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleRoundInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2 For Game Server

The game can query and update stat data on the game server through PgosSDK.

APIDescription
GetStatPersistentInfoQuery the persistent info of the specified stat item.
BatchGetStatPersistentInfoQuery item persistent info with specified stat names and keys in batches.
GetStatCycleInfoQuery the cycle info of the specified stat item for the current cycle round.
BatchGetStatCycleInfoQuery item cycle info with specified stat names and keys for the current cycle round in batches.
UpdateStatItemUpdate the specified stat item.
BatchUpdateStatItemUpdate the stat items in batches.
BatchGetStatCycleRoundInfoQuery the current round infos of cycles in batches.

5.2.1 GetStatPersistentInfo Server API

Query the persistent info of the specified stat item.

Interface prototype:

/**
* Query the persistent info of the specified stat item.
*
* @param Params Request structure for querying persistent info.
*/
void GetStatPersistentInfo(
const FGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FStatItem* Data)> Callback) const;

struct FGetStatPersistentInfoParams {
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FGetStatPersistentInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Statistics->GetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FStatItem* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.2 BatchGetStatPersistentInfo Server API

Query persistent infos with specified stat names and keys in batches.

Interface prototype:

/**
* Query item persistent infos with specified stat names and keys in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item persistent infos.
*/
void BatchGetStatPersistentInfo(
const FBatchGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data)> Callback) const;

struct FBatchGetStatPersistentInfoParams
{
/** Stat names. */
TArray<FString> stat_names;
/** Stat item keys. */
TArray<FString> keys;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatPersistentInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Statistics->BatchGetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.3 GetStatCycleInfo Server API

Query the cycle info of the specified stat item for the current cycle round.

Interface prototype:

/**
* Query the cycle info of the specified stat item for the current cycle round.
*
* @param Params Request structure for querying the cycle info.
*/
void GetStatCycleInfo(
const FGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FGetStatCycleInfoResult* Data)> Callback) const;

struct FGetStatCycleInfoParams
{
/** The stat name. */
FString stat_name;
/** The stat item key. */
FString key;
/** The stat cycle name. */
FString cycle_name;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FGetStatCycleInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Params.cycle_name = TEXT("Daily");
Statistics->GetStatCycleInfo(Params, [](const FPgosResult& Ret, const FGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.4 BatchGetStatCycleInfo Server API

Query item cycle info with specified stat names and keys for the current cycle round in batches.

Interface prototype:

/**
* Query cycle infos with specified stat names and keys for the current cycle round in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item cycle infos.
*/
void BatchGetStatCycleInfo(
const FBatchGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleInfoParams
{
/** The stat names. */
TArray<FString> stat_names;
/** The stat item keys. */
TArray<FString> keys;
/** The stat cycle name. */
FString cycle_name;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Params.cycle_name = TEXT("Daily");
Statistics->BatchGetStatCycleInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.5 UpdateStatItem Server API

Interface prototype:

/**
* Update the specified stat item.
*
* @param Params Request structure for updating the specified stat item.
*/
void UpdateStatItem(
const FServerUpdateStatItemParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerStatItemAfterUpdate* Data)> Callback) const;

struct FServerUpdateStatItemParams
{
/** The stat item to update. */
FStatItem item;
};

struct FStatItem
{
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
/**
* The meaning of the value varies in different scenarios:
* 1. Get stat item persistent value: it is item persistent value.
* 2. Get stat item cycle value: it is item cycle value.
* 3. Update stat item value: it is the value to be aggregated into the stat item.
*/
double value = 0.0;
/** Stat item secondary value. It will overwrite the old one when updated. */
double secondary_value = 0.0;
/** Stat item tags. It will overwrite the old one when updated. */
TArray<FString> tags;
/** The method to aggregate. */
EAggregateType aggregate_type = EAggregateType::Overwrite;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FServerUpdateStatItemParams Params;
Params.item.stat_name = TEXT("EnemyKills");
Params.item.key = TEXT("p456792");
Params.item.value = 2;
Params.item.aggregate_type = EAggregateType::Sum;
Statistics->UpdateStatItem(Params, [](const FPgosResult& Ret, const FServerStatItemAfterUpdate* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("UpdateStatItem Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("UpdateStatItem Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.6 BatchUpdateStatItem Server API

Interface prototype:

/**
* Update the stat items in batches.
*
* @param Params Request structure for updating the stat items in batches.
*/
void BatchUpdateStatItem(
const FServerBatchUpdateStatItemParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchUpdateStatItemResult* Data)> Callback) const;

struct FServerBatchUpdateStatItemParams
{
/** The stat items to update. */
TArray<FStatItem> items;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FStatItem item1;
item1.stat_name = TEXT("EnemyKills");
item1.key = TEXT("p600001");
item1.value = 2;
item1.aggregate_type = EAggregateType::Sum;

FStatItem item2;
item2.stat_name = TEXT("EnemyKills");
item2.key = TEXT("p600002");
item2.value = 5;
item2.aggregate_type = EAggregateType::Sum;

FServerBatchUpdateStatItemParams Params;
Params.items.Add(item1);
Params.items.Add(item2);
Statistics->BatchUpdateStatItem(Params, [](const FPgosResult& Ret, const FServerBatchUpdateStatItemResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchUpdateStatItem Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchUpdateStatItem Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.2.7 BatchGetStatCycleRoundInfo Server API

Query the current round infos of cycles in batches.

Interface prototype:

/**
* Query the current round infos of cycles in batches.
*
* @param Params Request structure for querying current round infos.
*/
void BatchGetStatCycleRoundInfo(
const FBatchGetStatCycleRoundInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleRoundInfoParams
{
/** The stat cycle names. */
TArray<FString> cycle_names;
};

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleRoundInfoParams Params;
Params.cycle_names.Add(TEXT("Daily"));
Params.cycle_names.Add(TEXT("Weekly"));
Statistics->BatchGetStatCycleRoundInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleRoundInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5.3 Error Handling

Error CodeRelevant APIHandling Suggestion
kBackendStatItemMissingCriticalFieldsGetStatPersistentInfo Client API
BatchGetStatPersistentInfo Client API
GetStatCycleInfo Client API
BatchGetStatCycleInfo Client API
GetStatPersistentInfo Server API
BatchGetStatPersistentInfo Server API
GetStatCycleInfo Server API
BatchGetStatCycleInfo Server API
UpdateStatItem Server API
BatchUpdateStatItem Server API
Missing critical fields such as stat_name, key
kBackendStatKeysNoDataGetStatPersistentInfo Client API
BatchGetStatPersistentInfo Client API
GetStatCycleInfo Client API
BatchGetStatCycleInfo Client API
GetStatPersistentInfo Server API
BatchGetStatPersistentInfo Server API
GetStatCycleInfo Server API
BatchGetStatCycleInfo Server API
Found no data for specific stat and cycle
kSdkNetworkErrorAll Network APInetwork error, check error msg for detail.