一键测试权重-新增安全线杀分机制,保证测试数据合理

This commit is contained in:
2026-03-27 17:50:11 +08:00
parent 2f05ac0cd9
commit afd6113927
13 changed files with 140 additions and 45 deletions

View File

@@ -270,6 +270,11 @@ class DiceRewardConfigRecordLogic extends BaseLogic
$paidS = isset($params['paid_s_count']) ? (int) $params['paid_s_count'] : 0;
$paidN = isset($params['paid_n_count']) ? (int) $params['paid_n_count'] : 0;
$chainFreeMode = !empty($params['chain_free_mode']);
$killModeEnabled = !empty($params['kill_mode_enabled']);
$testSafetyLine = isset($params['test_safety_line']) ? (int) $params['test_safety_line'] : 5000;
if ($testSafetyLine < 0) {
throw new ApiException('test_safety_line must be greater than or equal to 0');
}
foreach ([$paidS, $paidN] as $c) {
if ($c !== 0 && !in_array($c, $allowed, true)) {
@@ -398,6 +403,8 @@ class DiceRewardConfigRecordLogic extends BaseLogic
$record = new DiceRewardConfigRecord();
$plannedPaidSpins = $paidS + $paidN;
$record->chain_free_mode = $chainFreeMode ? 1 : 0;
$record->kill_mode_enabled = $killModeEnabled ? 1 : 0;
$record->test_safety_line = $testSafetyLine;
$record->paid_planned_spins = $plannedPaidSpins;
// 总抽奖次数与 test_count 仅在任务成功结束时写入(见 WeightTestRunner::markSuccess
$record->test_count = 0;

View File

@@ -14,7 +14,7 @@ use support\think\Db;
/**
* 一键测试权重:单进程后台执行模拟摇色子,写入 dice_play_record_test 并更新 dice_reward_config_record 进度
* 抽奖逻辑与 PlayStartLogic 一致:使用 name=default 的安全线、杀分开关;盈利<安全线时付费用玩家权重、免费用 killScore盈利>=安全线且杀分开启时付费/免费均用 killScore
* 支持测试内杀分:当模拟玩家累计盈利达到安全线后,付费抽奖切换到 killScore
*/
class WeightTestRunner
{
@@ -41,8 +41,7 @@ class WeightTestRunner
];
/**
* 执行指定测试记录:按付费/免费、顺/逆方向交替模拟(付费顺→付费逆→免费顺→免费逆),每 10 条写入一次测试表并更新进度
* 使用与 playStart 相同的彩金池逻辑name=default 的安全线/kill_enabled付费用 paid_tier_weights玩家权重或 killScore免费用 killScore
* 执行指定测试记录:按付费次数模拟,若命中 T5 则链式插入免费局(同方向同底注)
* @param int $recordId dice_reward_config_record.id
*/
public function run(int $recordId): void
@@ -68,8 +67,6 @@ class WeightTestRunner
$this->markFailed($recordId, '彩金池配置 name=default 不存在');
return;
}
$safetyLine = (int) ($configType0->safety_line ?? 0);
$killEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1;
$paidTierWeightsCustom = (is_array($record->paid_tier_weights ?? null) && $record->paid_tier_weights !== [])
? $record->paid_tier_weights
@@ -103,8 +100,14 @@ class WeightTestRunner
DiceRewardConfig::clearRequestInstance();
DiceReward::clearRequestInstance();
// 彩金池累计盈利:用于判断是否触发杀分(不再依赖单个玩家累计盈利)
$poolProfitTotal = floatval($configType0->profit_amount ?? 0);
$killModeEnabled = (int) ($record->kill_mode_enabled ?? 0) === 1;
$testSafetyLine = (int) ($record->test_safety_line ?? 5000);
if ($testSafetyLine < 0) {
$testSafetyLine = 0;
}
// 测试内“玩家累计盈利”:用于控制付费局是否切换杀分
$playerProfitTotal = 0.0;
$playLogic = new PlayStartLogic();
$resultCounts = [];
@@ -121,13 +124,12 @@ class WeightTestRunner
$ante,
$paidPoolConfig,
$freePoolConfig,
$configType1,
$paidTierWeightsCustom,
$freeTierWeightsCustom,
$configType0,
$configType1,
$safetyLine,
$killEnabled,
$poolProfitTotal,
$killModeEnabled,
$testSafetyLine,
$playerProfitTotal,
$resultCounts,
$tierCounts,
$buffer,
@@ -157,13 +159,12 @@ class WeightTestRunner
int $ante,
$paidPoolConfig,
$freePoolConfig,
$killPoolConfig,
?array $paidTierWeightsCustom,
?array $freeTierWeightsCustom,
$configType0,
$configType1,
int $safetyLine,
bool $killEnabled,
float &$poolProfitTotal,
bool $killModeEnabled,
int $testSafetyLine,
float &$playerProfitTotal,
array &$resultCounts,
array &$tierCounts,
array &$buffer,
@@ -185,17 +186,23 @@ class WeightTestRunner
$lotteryType = $isPaid ? 0 : 1;
if ($isPaid) {
$usePoolWeights = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
$cfg = $usePoolWeights ? $configType1 : $paidPoolConfig;
$customWeights = $usePoolWeights ? null : $paidTierWeightsCustom;
$useKillForPaid = $killModeEnabled && $playerProfitTotal >= $testSafetyLine && $killPoolConfig !== null;
if ($useKillForPaid) {
$cfg = $killPoolConfig;
$customWeights = null;
} else {
$cfg = $paidPoolConfig;
$customWeights = $paidTierWeightsCustom;
}
} else {
$useKillMode = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
$cfg = $useKillMode ? $configType1 : $freePoolConfig;
$customWeights = $useKillMode ? null : $freeTierWeightsCustom;
$cfg = $freePoolConfig;
$customWeights = $freeTierWeightsCustom;
}
$row = $playLogic->simulateOnePlay($cfg, $dir, $lotteryType, $playAnte, $customWeights);
$this->accumulateProfitForDefault($row, $lotteryType, $cfg, $configType0, $poolProfitTotal);
$winCoin = (float) ($row['win_coin'] ?? 0);
$paidAmount = (float) ($row['paid_amount'] ?? 0);
$playerProfitTotal += $winCoin - $paidAmount;
$this->aggregate($row, $resultCounts, $tierCounts);
$buffer[] = $this->rowForInsert($row, $recordId);
$done++;
@@ -210,23 +217,6 @@ class WeightTestRunner
}
}
/**
* 累加彩金池累计盈利,用于触发杀分,与 PlayStartLogic 一致
* @param int $lotteryType 0=付费券1=免费券
* @param object $usedConfig 本次使用的奖池配置(仅用于校验非空)
* @param object $configType0 name=default 的彩金池
* @param float $playerProfitTotal 实际为“彩金池累计盈利”滚动值
*/
private function accumulateProfitForDefault(array $row, int $lotteryType, $usedConfig, $configType0, float &$playerProfitTotal): void
{
if (($lotteryType !== 0 && $lotteryType !== 1) || $usedConfig === null || $configType0 === null || !isset($row['win_coin'])) {
return;
}
$winCoin = (float) $row['win_coin'];
$paidAmount = (float) ($row['paid_amount'] ?? 0);
$playerProfitTotal += $lotteryType === 0 ? ($winCoin - $paidAmount) : $winCoin;
}
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
{
$grid = (int) ($row['roll_number_for_count'] ?? $row['roll_number'] ?? 0);