diff --git a/server/app/dice/logic/reward_config_record/WeightTestRunner.php b/server/app/dice/logic/reward_config_record/WeightTestRunner.php index 9bbc2dd..df21c24 100644 --- a/server/app/dice/logic/reward_config_record/WeightTestRunner.php +++ b/server/app/dice/logic/reward_config_record/WeightTestRunner.php @@ -62,11 +62,6 @@ class WeightTestRunner return; } - $anteRandom = $this->isAnteRandomMode($record); - $ante = is_numeric($record->ante ?? null) ? intval($record->ante) : 1; - if (!$anteRandom && $ante <= 0) { - $ante = 1; - } $paidS = (int) ($record->paid_s_count ?? 0); $paidN = (int) ($record->paid_n_count ?? 0); $total = $paidS + $paidN; @@ -77,6 +72,12 @@ class WeightTestRunner $this->runDeptId = $this->resolveRunDeptId($recordId, $record); $deptId = $this->runDeptId; + + $anteRandom = $this->isAnteRandomMode($record); + $ante = is_numeric($record->ante ?? null) ? intval($record->ante) : 1; + if (!$anteRandom && $ante <= 0) { + $ante = $this->getMinAnteMult($deptId); + } DiceReward::setRequestDeptId($deptId); DiceRewardConfig::clearRequestInstance(); @@ -210,19 +211,22 @@ class WeightTestRunner $queue[] = ['paid', 1, $anteRandom ? 0 : $ante]; } $qi = 0; + $lastPaidPlayAnte = 0; while ($qi < count($queue)) { $item = $queue[$qi]; $isPaid = $item[0] === 'paid'; $dir = $item[1]; $playAnte = (int) $item[2]; + $playAnte = $this->resolvePlayAnteMult( + $deptId, + $playAnte, + $isPaid, + $anteRandom, + $ante, + $lastPaidPlayAnte + ); if ($isPaid) { - if ($anteRandom) { - $playAnte = $this->pickRandomAnteMult($deptId); - } elseif ($playAnte <= 0) { - $playAnte = $ante > 0 ? $ante : 1; - } - } elseif ($playAnte <= 0) { - $playAnte = $ante > 0 ? $ante : 1; + $lastPaidPlayAnte = $playAnte; } $lotteryType = $isPaid ? 0 : 1; @@ -273,29 +277,113 @@ class WeightTestRunner */ private function isAnteRandomMode(DiceRewardConfigRecord $record): bool { - $snap = $record->tier_weights_snapshot ?? null; - if (!is_array($snap)) { - return false; + $snap = $this->normalizeTierWeightsSnapshot($record->tier_weights_snapshot ?? null); + if (is_array($snap) && !empty($snap['ante_random'])) { + return true; } + // 创建随机测试时主表 ante 固定为 0;快照丢失 ante_random 时仍按随机模式执行 + $recordAnte = is_numeric($record->ante ?? null) ? (int) $record->ante : -1; - return !empty($snap['ante_random']); + return $recordAnte === 0; } /** - * 从当前渠道 dice_ante_config 中随机取一条 mult + * @param mixed $snap + * @return array|null + */ + private function normalizeTierWeightsSnapshot($snap): ?array + { + if (is_array($snap)) { + return $snap; + } + if (is_string($snap) && $snap !== '') { + $decoded = json_decode($snap, true); + + return is_array($decoded) ? $decoded : null; + } + + return null; + } + + /** + * 解析本局有效底注(dice_ante_config.mult),禁止写入 0 + */ + private function resolvePlayAnteMult( + int $deptId, + int $queuedAnte, + bool $isPaid, + bool $anteRandom, + int $recordAnte, + int $lastPaidPlayAnte + ): int { + if ($isPaid) { + if ($anteRandom) { + return $this->pickRandomAnteMult($deptId); + } + if ($queuedAnte > 0) { + return $queuedAnte; + } + if ($recordAnte > 0) { + return $recordAnte; + } + + return $this->getMinAnteMult($deptId); + } + + // 免费券(T5 链式):与触发付费局同底注,不得为 0 + if ($queuedAnte > 0) { + return $queuedAnte; + } + if ($lastPaidPlayAnte > 0) { + return $lastPaidPlayAnte; + } + if ($recordAnte > 0) { + return $recordAnte; + } + + return $this->getMinAnteMult($deptId); + } + + /** + * 当前渠道底注配置中最小正数 mult + */ + private function getMinAnteMult(int $deptId): int + { + $mults = $this->listPositiveAnteMults($deptId); + + return $mults !== [] ? $mults[0] : 1; + } + + /** + * @return list + */ + private function listPositiveAnteMults(int $deptId): array + { + $anteQuery = DiceAnteConfig::field('mult')->order('mult', 'asc'); + ConfigScopeEditHelper::applyDeptIdWhere($anteQuery, $deptId); + $rows = $anteQuery->select()->toArray(); + $mults = []; + foreach ($rows as $row) { + $mult = (int) ($row['mult'] ?? 0); + if ($mult > 0) { + $mults[] = $mult; + } + } + + return $mults; + } + + /** + * 从当前渠道 dice_ante_config 中随机取一条 mult(仅 mult>0) */ private function pickRandomAnteMult(int $deptId): int { - $anteQuery = DiceAnteConfig::field('id,mult')->order('mult', 'asc'); - ConfigScopeEditHelper::applyDeptIdWhere($anteQuery, $deptId); - $rows = $anteQuery->select()->toArray(); - if ($rows === []) { + $mults = $this->listPositiveAnteMults($deptId); + if ($mults === []) { return 1; } - $picked = $rows[random_int(0, count($rows) - 1)]; - $mult = (int) ($picked['mult'] ?? 0); - return $mult > 0 ? $mult : 1; + return $mults[random_int(0, count($mults) - 1)]; } /** @@ -303,8 +391,8 @@ class WeightTestRunner */ private function resolveTierWeightsSnapshot(DiceRewardConfigRecord $record, string $side): ?array { - $snap = $record->tier_weights_snapshot ?? null; - if (! is_array($snap)) { + $snap = $this->normalizeTierWeightsSnapshot($record->tier_weights_snapshot ?? null); + if ($snap === null) { return null; } $weights = $snap[$side] ?? null; @@ -399,6 +487,9 @@ class WeightTestRunner $out[$k] = $row[$k]; } } + if (array_key_exists('ante', $out) && (int) ($out['ante'] ?? 0) <= 0) { + $out['ante'] = $this->getMinAnteMult($bindDeptId > 0 ? $bindDeptId : $deptId); + } return $out; }