[色子游戏]玩家钱包流水记录-优化抽奖逻辑根据结果推断起始位置
This commit is contained in:
@@ -12,6 +12,7 @@ use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
|
||||
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
|
||||
use app\dice\model\reward_config\DiceRewardConfig;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use support\Log;
|
||||
use support\think\Cache;
|
||||
use support\think\Db;
|
||||
|
||||
@@ -69,19 +70,49 @@ class PlayStartLogic
|
||||
throw new ApiException('奖池配置不存在');
|
||||
}
|
||||
|
||||
// 先按奖池权重抽出档位 T1-T5
|
||||
$tier = LotteryService::drawTierByWeights($config);
|
||||
$rewards = DiceRewardConfig::where('tier', $tier)->select();
|
||||
if ($rewards->isEmpty()) {
|
||||
|
||||
// 生成 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::where('tier', $tier)->select()->toArray();
|
||||
if (empty($tierRewards)) {
|
||||
Log::error("档位 {$tier} 无任何奖励配置");
|
||||
throw new ApiException('该档位暂无奖励配置');
|
||||
}
|
||||
$rewardList = $rewards->all();
|
||||
$reward = $rewardList[array_rand($rewardList)];
|
||||
$chosen = $tierRewards[array_rand($tierRewards)];
|
||||
$reward = DiceRewardConfig::find($chosen['id']);
|
||||
if (!$reward) {
|
||||
throw new ApiException('奖励配置不存在');
|
||||
}
|
||||
$targetIndex = (int) $reward->id;
|
||||
$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;
|
||||
}
|
||||
$startIndex = ($startIndex % $boardSize + $boardSize) % $boardSize;
|
||||
|
||||
Log::info(sprintf(
|
||||
'摇取点数 roll_number=%d, 方向=%d, start_index=%d, target_index=%d',
|
||||
$rollNumber,
|
||||
$direction,
|
||||
$startIndex,
|
||||
$targetIndex
|
||||
));
|
||||
$realEv = (float) $reward->real_ev;
|
||||
$winCoin = 100 + $realEv; // 赢取平台币 = 100 + DiceRewardConfig.real_ev
|
||||
$gridNumber = (int) $reward->grid_number;
|
||||
$startIndex = (int) Cache::get(LotteryService::getStartIndexKey($playerId), 0);
|
||||
$targetIndex = (int) $reward->id;
|
||||
$rollArray = $this->generateRollArray($gridNumber);
|
||||
|
||||
$record = null;
|
||||
$configId = (int) $config->id;
|
||||
@@ -162,8 +193,6 @@ class PlayStartLogic
|
||||
'wallet_after' => $coinAfter,
|
||||
'remark' => '抽奖|play_record_id=' . $record->id,
|
||||
]);
|
||||
|
||||
Cache::set(LotteryService::getStartIndexKey($playerId), $targetIndex, 86400 * 30);
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
if ($record === null) {
|
||||
@@ -202,23 +231,13 @@ class PlayStartLogic
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/** 生成 5 个 1-6 的点数,和为 grid_number(5~30),严格不超范围 */
|
||||
private function generateRollArray(int $gridNumber): array
|
||||
/** 生成 5 个 1-6 的点数,roll_number 为其总和 */
|
||||
private function generateRollArray(): array
|
||||
{
|
||||
$minSum = 5;
|
||||
$maxSum = 30;
|
||||
$n = max($minSum, min($maxSum, $gridNumber));
|
||||
$dice = [1, 1, 1, 1, 1];
|
||||
$remain = $n - 5;
|
||||
while ($remain > 0) {
|
||||
$i = array_rand($dice);
|
||||
if ($dice[$i] < 6) {
|
||||
$add = min($remain, 6 - $dice[$i]);
|
||||
$dice[$i] += $add;
|
||||
$remain -= $add;
|
||||
}
|
||||
$dice = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$dice[] = random_int(1, 6);
|
||||
}
|
||||
shuffle($dice);
|
||||
return $dice;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user