[色子游戏]玩家抽奖记录测试数据

This commit is contained in:
2026-03-12 19:21:10 +08:00
parent 7e4ba86afa
commit cc7e2d9a1a
21 changed files with 1712 additions and 4 deletions

View File

@@ -427,4 +427,98 @@ class PlayStartLogic
}
return $this->generateRollArrayFromSum($sum);
}
/**
* 模拟一局抽奖(不写库、不扣玩家),用于权重测试写入 dice_play_record_test
* @param \app\dice\model\lottery_pool_config\DiceLotteryPoolConfig $config 奖池配置
* @param int $direction 0=顺时针 1=逆时针
* @return array 可直接用于 DicePlayRecordTest::create 的字段 + tier用于统计档位概率
*/
public function simulateOnePlay($config, int $direction): array
{
$rewardInstance = DiceReward::getCachedInstance();
$byTierDirection = $rewardInstance['by_tier_direction'] ?? [];
$maxTierRetry = 10;
$chosen = null;
$tier = null;
for ($tierAttempt = 0; $tierAttempt < $maxTierRetry; $tierAttempt++) {
$tier = LotteryService::drawTierByWeights($config);
$tierRewards = $byTierDirection[$tier][$direction] ?? [];
if (empty($tierRewards)) {
continue;
}
try {
$chosen = self::drawRewardByWeight($tierRewards);
} catch (\RuntimeException $e) {
if ($e->getMessage() === self::EXCEPTION_WEIGHT_ALL_ZERO) {
continue;
}
throw $e;
}
break;
}
if ($chosen === null) {
throw new \RuntimeException('模拟抽奖:无可用奖励配置');
}
$startIndex = (int) ($chosen['start_index'] ?? 0);
$targetIndex = (int) ($chosen['end_index'] ?? 0);
$rollNumber = (int) ($chosen['grid_number'] ?? 0);
$realEv = (float) ($chosen['real_ev'] ?? 0);
$isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5';
$rewardWinCoin = $isTierT5 ? $realEv : (100 + $realEv);
$superWinCoin = 0;
$isWin = 0;
if (in_array($rollNumber, self::SUPER_WIN_GRID_NUMBERS, true)) {
$bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
$alwaysSuperWin = in_array($rollNumber, self::SUPER_WIN_ALWAYS_GRID_NUMBERS, true);
$doSuperWin = $alwaysSuperWin;
if (!$doSuperWin) {
$bigWinWeight = 10000;
if ($bigWinConfig !== null && isset($bigWinConfig['weight'])) {
$bigWinWeight = min(10000, max(0, (int) $bigWinConfig['weight']));
}
$roll = (random_int(0, PHP_INT_MAX - 1) / (float) PHP_INT_MAX);
$doSuperWin = $bigWinWeight > 0 && $roll < ($bigWinWeight / 10000.0);
}
if ($doSuperWin) {
$rollArray = $this->getSuperWinRollArray($rollNumber);
$isWin = 1;
$superWinCoin = ($bigWinConfig['real_ev'] ?? 0) > 0 ? (float) ($bigWinConfig['real_ev'] ?? 0) : self::SUPER_WIN_BONUS;
$rewardWinCoin = 0;
} else {
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
}
} else {
$rollArray = $this->generateRollArrayFromSum($rollNumber);
}
$winCoin = $superWinCoin + $rewardWinCoin;
$configId = (int) $config->id;
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
$configName = (string) ($config->name ?? '');
return [
'player_id' => 0,
'admin_id' => 0,
'lottery_config_id' => $configId,
'lottery_type' => self::LOTTERY_TYPE_PAID,
'is_win' => $isWin,
'win_coin' => $winCoin,
'super_win_coin' => $superWinCoin,
'reward_win_coin' => $rewardWinCoin,
'use_coins' => 0,
'direction' => $direction,
'reward_config_id' => $rewardId,
'start_index' => $startIndex,
'target_index' => $targetIndex,
'roll_array' => json_encode($rollArray),
'roll_number' => array_sum($rollArray),
'lottery_name' => $configName,
'status' => self::RECORD_STATUS_SUCCESS,
'tier' => $tier,
'roll_number_for_count' => $rollNumber,
];
}
}