RTP test is a tool to calculate real game RTP thought the simulation of millions attempts (place bet/ spin / buy and play game) with calculation of random winnings, gathering in game data and get end result in RTP value with high accuracy. During the RTP test, your selected version of Server Game Function will be duplicated and deployed with specific parameters for making hard load tests. Each test will be divided into cycles with some amount of attempts (ex: 5 million bets test will be divided on 5K cycles with 1K bet place attempts each). Server Game Function need to receive test start message, provide game calculation simulation with no real bet place and winning paying.
public async Task<MessageResult> HandleMessage(ParseResult parseResult)
{
if (parseResult.IsSuccess)
{
switch (parseResult.MessageName)
{
...
case FireballConstants.MessagesNames.RTP_START:
return await StartTest(parseResult.MessageObject.ToObject<RTPStart<MyGameState>>());
...
}
}
...
}
public async Task<RTPWinResult> CalculateRandomWin(long betAmount)
{
// get random value
var random = await _fireball.Random.GetRandomDouble(0, 1);
if (random < 0.05f)
{
// Big win result
return new RTPWinResult()
{
WinType = "Spin",
WinSymbol = "Big Win",
BetAmount = betAmount,
WinAmount = 20 * betAmount,
};
}
else if (random < 0.3f)
{
// Low win result
return new RTPWinResult()
{
WinType = "Spin",
WinSymbol = "Low Win",
BetAmount = betAmount,
WinAmount = 2 * betAmount,
};
}
// lose result
return new RTPWinResult()
{
WinType = "Spin",
WinSymbol = "Lose",
BetAmount = betAmount,
WinAmount = 0,
};
}
public async Task<MessageResult> StartTest(RTPStart testStart)
{
// create list for win results
var winResults = new List<RTPWinResult>();
for (int i = 0; i < testStart.AttemptNumber; i++)
{
// calculate random win result
var attemptResult = await CalculateRandomWin(testStart.BetAmount);
winResults.Add(attemptResult);
}
// create new test result and set
var testResult = new RTPResult<MyGameState>();
testResult.TestId = testStart.TestId;
testResult.CycleId = testStart.CycleId;
testResult.Results = winResults;
// send current test cycle result to fireball and initiate next test cycle
return await _fireball.Tester.SendRTPResult(testResult);
}
// custom game state
public class MyGameState
{
// ingame data
public bool IsGameOver;
public int SercetsUnlock;
...
// test statistic
public int LowWinsNumber;
public int BigWinsNumber;
}
public async Task<MessageResult> StartTest(RTPStart<MyGameState> testStart)
{
// get start game state
var gameState = testStart.GameState;
// create list for win results
var winResults = new List<RTPWinResult>();
for (int i = 0; i < testStart.AttemptNumber; i++)
{
// calculate random win result
var attemptResult = await CalculateRandomWin(testStart.BetAmount);
winResults.Add(attemptResult);
// update game state
gameState.LowWinsNumber += attemptResult.WinSymbol == "Low Win" ? 1 : 0;
gameState.BigWinsNumber += attemptResult.WinSymbol == "Big Win" ? 1 : 0;
}
// create new test result and set
var testResult = new RTPResult<MyGameState>();
// set updated game state
testResult.GameState = gameState;
...
}
public async Task<MessageResult> StartTest(RTPStart<MyGameState> testStart)
{
// get custom settings dictionary
Dictionary<string, object> settings = testStart.CustomSettings;
...
}