从新设计抽奖逻辑
This commit is contained in:
@@ -70,35 +70,47 @@ class PlayStartLogic
|
||||
throw new ApiException('奖池配置不存在');
|
||||
}
|
||||
|
||||
// 先按奖池权重抽出档位 T1-T5
|
||||
$tier = LotteryService::drawTierByWeights($config);
|
||||
|
||||
// 生成 5 个 1-6 的点数,计算总和 roll_number(即本局摇到的点数)
|
||||
$rollArray = $this->generateRollArray();
|
||||
$rollNumber = (int) array_sum($rollArray);
|
||||
|
||||
// 索引范围为 0~25 共 26 个格子
|
||||
$boardSize = 26;
|
||||
|
||||
// 1. 根据抽到的档位,在 tier 相等的数据中任选一条,其 id 为结束索引 target_index(从缓存读取)
|
||||
$tierRewards = DiceRewardConfig::getCachedByTier($tier);
|
||||
if (empty($tierRewards)) {
|
||||
Log::error("档位 {$tier} 无任何奖励配置");
|
||||
throw new ApiException('该档位暂无奖励配置');
|
||||
// 按玩家权重抽取档位;若该档位无奖励或该方向下均无可用路径则重新摇取档位
|
||||
$maxTierRetry = 10;
|
||||
$chosen = null;
|
||||
$startCandidates = [];
|
||||
$tier = null;
|
||||
for ($tierAttempt = 0; $tierAttempt < $maxTierRetry; $tierAttempt++) {
|
||||
$tier = LotteryService::drawTierByPlayerWeights($player);
|
||||
$tierRewards = DiceRewardConfig::getCachedByTier($tier);
|
||||
if (empty($tierRewards)) {
|
||||
Log::warning("档位 {$tier} 无任何奖励配置,重新摇取档位");
|
||||
continue;
|
||||
}
|
||||
$maxRewardRetry = count($tierRewards);
|
||||
for ($attempt = 0; $attempt < $maxRewardRetry; $attempt++) {
|
||||
$chosen = $tierRewards[array_rand($tierRewards)];
|
||||
$chosenId = (int) ($chosen['id'] ?? 0);
|
||||
if ($direction === 0) {
|
||||
$startCandidates = DiceRewardConfig::getCachedBySEndIndex($chosenId);
|
||||
} else {
|
||||
$startCandidates = DiceRewardConfig::getCachedByNEndIndex($chosenId);
|
||||
}
|
||||
if (!empty($startCandidates)) {
|
||||
break 2;
|
||||
}
|
||||
Log::warning("方向 {$direction} 下无 s_end_index/n_end_index={$chosenId} 的配置,重新摇取");
|
||||
}
|
||||
Log::warning("方向 {$direction} 下档位 {$tier} 所有奖励均无可用路径配置,重新摇取档位");
|
||||
}
|
||||
$chosen = $tierRewards[array_rand($tierRewards)];
|
||||
$targetIndex = (int) ($chosen['id'] ?? 0);
|
||||
$targetIndex = (($targetIndex % $boardSize) + $boardSize) % $boardSize;
|
||||
|
||||
// 2. 根据结果反推起始点 start_index(由 target_index 与方向反算)
|
||||
// 顺时针(direction=0): targetIndex = (startIndex + rollNumber) % 26 => startIndex = (targetIndex - rollNumber) % 26
|
||||
// 逆时针(direction=1): targetIndex = (startIndex - rollNumber) % 26 => startIndex = (targetIndex + rollNumber) % 26
|
||||
if ($direction === 0) {
|
||||
$startIndex = ($targetIndex - $rollNumber) % $boardSize;
|
||||
} else {
|
||||
$startIndex = ($targetIndex + $rollNumber) % $boardSize;
|
||||
if (empty($startCandidates)) {
|
||||
Log::error("方向 {$direction} 下多次摇取档位后仍无可用路径配置");
|
||||
throw new ApiException('该方向下暂无可用路径配置');
|
||||
}
|
||||
$startIndex = ($startIndex % $boardSize + $boardSize) % $boardSize;
|
||||
$chosenId = (int) ($chosen['id'] ?? 0);
|
||||
$startRecord = $startCandidates[array_rand($startCandidates)];
|
||||
|
||||
$startIndex = (int) ($startRecord['id'] ?? 0);
|
||||
$targetIndex = $direction === 0
|
||||
? (int) ($startRecord['s_end_index'] ?? 0)
|
||||
: (int) ($startRecord['n_end_index'] ?? 0);
|
||||
$rollNumber = (int) ($startRecord['grid_number'] ?? 0);
|
||||
$rollArray = $this->generateRollArrayFromSum($rollNumber);
|
||||
|
||||
Log::info(sprintf(
|
||||
'摇取点数 roll_number=%d, 方向=%d, start_index=%d, target_index=%d',
|
||||
@@ -112,7 +124,7 @@ class PlayStartLogic
|
||||
|
||||
$record = null;
|
||||
$configId = (int) $config->id;
|
||||
$rewardId = (int) ($chosen['id'] ?? 0);
|
||||
$rewardId = $chosenId;
|
||||
$configName = (string) ($config->name ?? '');
|
||||
$isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5';
|
||||
try {
|
||||
@@ -224,16 +236,30 @@ class PlayStartLogic
|
||||
if (isset($arr['roll_array']) && is_string($arr['roll_array'])) {
|
||||
$arr['roll_array'] = json_decode($arr['roll_array'], true) ?? [];
|
||||
}
|
||||
$arr['roll_number'] = is_array($arr['roll_array'] ?? null) ? array_sum($arr['roll_array']) : 0;
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/** 生成 5 个 1-6 的点数,roll_number 为其总和 */
|
||||
private function generateRollArray(): array
|
||||
/**
|
||||
* 根据摇取点数(5-30)生成 5 个色子数组,每个 1-6,总和为 $sum
|
||||
* @return int[] 如 [1,2,3,4,5]
|
||||
*/
|
||||
private function generateRollArrayFromSum(int $sum): array
|
||||
{
|
||||
$dice = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$dice[] = random_int(1, 6);
|
||||
$sum = max(5, min(30, $sum));
|
||||
$arr = [1, 1, 1, 1, 1];
|
||||
$remain = $sum - 5;
|
||||
for ($i = 0; $i < $remain; $i++) {
|
||||
$candidates = array_keys(array_filter($arr, function ($v) {
|
||||
return $v < 6;
|
||||
}));
|
||||
if (empty($candidates)) {
|
||||
break;
|
||||
}
|
||||
$idx = $candidates[array_rand($candidates)];
|
||||
$arr[$idx]++;
|
||||
}
|
||||
return $dice;
|
||||
shuffle($arr);
|
||||
return array_values($arr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user