diff --git a/saiadmin-artd/src/locales/langs/en/dice/reward.json b/saiadmin-artd/src/locales/langs/en/dice/reward.json index cf260da..c2ddc4d 100644 --- a/saiadmin-artd/src/locales/langs/en/dice/reward.json +++ b/saiadmin-artd/src/locales/langs/en/dice/reward.json @@ -54,14 +54,16 @@ "weightTest": { "title": "One-Click Weight Test", "alertTitle": "Bonus pool logic", - "alertBody": "Test mode is non-kill by default. When test kill mode is enabled, rules match production: compare default pool profit_amount to the safety line, with kill_enabled on and a killScore config present.", + "alertBody": "Kill switching is off by default. Enable “Test kill mode” below and set a test safety line (independent from the lottery pool config) to simulate kill triggers.", "chainModeHint": "Simulation: set paid spin counts only (CW/CCW). If a paid draw hits “play again” (or T5), the next draw is free with the same ante, lottery type free, paid amount 0. Free-draw tier odds are configured below (including chained free plays).", - "killModeHint": "When test kill mode is on: start from default pool profit_amount and accumulate each spin (paid: win_coin - paid_amount; free: win_coin). Once profit >= safety line and kill_enabled is on, subsequent paid draws use killScore; free draws still use the name=free pool.", - "labelKillModeEnabled": "Enable test kill mode", - "labelTestSafetyLine": "default safety line", - "killEnabledOn": "kill on", - "killEnabledOff": "kill off", - "poolProfitPrefix": "pool profit ", + "killModeHint": "When test kill mode is on: start from default pool profit_amount and accumulate each spin (paid: win_coin - paid_amount; free: win_coin). Once profit >= the test safety line below, subsequent paid draws use killScore; free draws still use the name=free pool.", + "killModePanelTitle": "Test kill mode", + "killModeSwitchOn": "On", + "killModeSwitchOff": "Off", + "labelTestSafetyLine": "Test safety line", + "testSafetyLineHint": "Used for this weight test only, independent from the pool config safety line. Use a lower value to observe kill switching quickly.", + "poolProfitRef": "Reference: default pool profit {profit}, pool config safety line {line}", + "killModeOffHint": "When off, all draws follow paid/free settings without kill switching.", "sectionPaid": "Paid draws", "sectionFreeAfterPlayAgain": "Free draw tier odds (after play-again)", "tierProbHintFreeChain": "When using custom tier odds: T1–T5 below apply when a free draw runs (tier roll; combined with dice_reward row weights).", diff --git a/saiadmin-artd/src/locales/langs/zh/dice/reward.json b/saiadmin-artd/src/locales/langs/zh/dice/reward.json index f04dfb7..c3d1f8f 100644 --- a/saiadmin-artd/src/locales/langs/zh/dice/reward.json +++ b/saiadmin-artd/src/locales/langs/zh/dice/reward.json @@ -54,14 +54,16 @@ "weightTest": { "title": "一键测试权重", "alertTitle": "彩金池逻辑说明", - "alertBody": "测试模式默认不启用杀分切换;开启「测试内杀分」后,判定规则与线上一致:以 default 彩金池累计盈利(profit_amount)对比安全线,且需 kill_enabled=开启、存在 killScore 配置。", + "alertBody": "测试模式默认不启用杀分切换;开启下方「测试内杀分」后,可单独设置测试安全线(与彩金池配置中的安全线无关),用于模拟杀分触发。", "chainModeHint": "模拟方式:只配置付费抽奖次数(顺/逆时针)。付费抽到「再来一次」或 T5 时,下一局自动为免费抽奖,底注与触发局相同,抽奖类型记为免费、付费金额记为 0。免费抽奖的档位概率由下方「免费抽奖」配置决定(含通过再来一次触发的后续免费局)。", - "killModeHint": "杀分开关开启后:从 default 奖池当前 profit_amount 起步,测试内逐局累加(付费=win_coin-paid_amount,免费=win_coin);当累计盈利 ≥ 安全线且 kill_enabled 开启时,后续付费抽奖切 killScore;免费抽奖仍走 name=free 奖池。", - "labelKillModeEnabled": "开启测试内杀分", - "labelTestSafetyLine": "default 安全线", - "killEnabledOn": "杀分已开启", - "killEnabledOff": "杀分已关闭", - "poolProfitPrefix": "当前池盈利 ", + "killModeHint": "杀分开关开启后:从 default 奖池当前 profit_amount 起步逐局累加(付费=win_coin-paid_amount,免费=win_coin);当累计盈利 ≥ 下方「测试安全线」时,后续付费抽奖切 killScore;免费抽奖仍走 name=free 奖池。", + "killModePanelTitle": "测试内杀分", + "killModeSwitchOn": "已开启", + "killModeSwitchOff": "已关闭", + "labelTestSafetyLine": "测试安全线", + "testSafetyLineHint": "仅用于本次权重测试,与彩金池配置页的安全线独立;可设较小值以便快速观察杀分切换效果。", + "poolProfitRef": "参考:当前 default 池盈利 {profit},彩金池配置安全线 {line}", + "killModeOffHint": "关闭时全程按付费/免费配置抽档,不模拟杀分切换。", "sectionPaid": "付费抽奖", "sectionFreeAfterPlayAgain": "免费抽奖(再来一次后的档位概率)", "tierProbHintFreeChain": "当使用自定义档位时:以下为「免费抽奖」时 T1~T5 的档位概率(仅在有免费局时参与摇档,与 dice_reward 格子权重共同决定结果)。", diff --git a/saiadmin-artd/src/views/plugin/dice/reward/index/modules/weight-test-dialog.vue b/saiadmin-artd/src/views/plugin/dice/reward/index/modules/weight-test-dialog.vue index 9b687fa..cdb8df6 100644 --- a/saiadmin-artd/src/views/plugin/dice/reward/index/modules/weight-test-dialog.vue +++ b/saiadmin-artd/src/views/plugin/dice/reward/index/modules/weight-test-dialog.vue @@ -20,7 +20,7 @@ - + - - - - - - - - + +
+
+
{{ $t('page.weightTest.killModePanelTitle') }}
+ +
+
+ + - - +
{{ $t('page.weightTest.testSafetyLineHint') }}
+
+ {{ $t('page.weightTest.poolProfitRef', { + profit: defaultPoolInfo.profit_amount, + line: defaultPoolInfo.safety_line + }) }} +
+
+
{{ $t('page.weightTest.killModeOffHint') }}
+
@@ -218,17 +240,8 @@ free_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record, paid_s_count: 100, paid_n_count: 100, - kill_mode_enabled: false - }) - const defaultPoolSafetyLineText = computed(() => { - const info = defaultPoolInfo.value - if (!info) { - return '-' - } - const killText = info.kill_enabled === 1 - ? t('page.weightTest.killEnabledOn') - : t('page.weightTest.killEnabledOff') - return `${info.safety_line}(${killText},${t('page.weightTest.poolProfitPrefix')}${info.profit_amount})` + kill_mode_enabled: false, + test_safety_line: 5000 }) const lotteryOptions = ref>([]) const paidLotteryOptions = computed(() => @@ -373,7 +386,7 @@ free_n_count: 0, chain_free_mode: true, kill_mode_enabled: form.kill_mode_enabled, - test_safety_line: defaultPoolInfo.value?.safety_line ?? 0 + test_safety_line: form.test_safety_line } if (form.paid_lottery_config_id != null) { payload.paid_lottery_config_id = form.paid_lottery_config_id @@ -402,6 +415,10 @@ ElMessage.warning(t('page.weightTest.warnPaidSpins')) return false } + if (form.kill_mode_enabled && (form.test_safety_line == null || form.test_safety_line < 0)) { + ElMessage.warning(t('page.weightTest.warnTestSafetyLine')) + return false + } const needPaidTier = form.paid_lottery_config_id == null const needFreeTier = form.free_lottery_config_id == null if (needPaidTier) { @@ -498,6 +515,54 @@ } } + .kill-mode-panel { + margin-bottom: 14px; + padding: 12px 14px; + border: 1px solid var(--el-border-color-lighter); + border-radius: var(--el-border-radius-base); + background: var(--el-fill-color-light); + } + + .kill-mode-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + } + + .kill-mode-title { + font-size: 13px; + font-weight: 600; + color: var(--el-text-color-primary); + line-height: 1.4; + } + + .kill-mode-body { + margin-top: 12px; + padding-top: 12px; + border-top: 1px dashed var(--el-border-color); + } + + .kill-safety-item { + margin-bottom: 8px; + :deep(.el-form-item__label) { + white-space: nowrap; + } + } + + .kill-mode-hint, + .kill-mode-off-hint, + .kill-mode-ref { + font-size: 12px; + line-height: 1.5; + color: var(--el-text-color-secondary); + } + + .kill-mode-ref { + margin-top: 4px; + color: var(--el-text-color-placeholder); + } + .section-row { margin-top: 4px; } diff --git a/server/app/dice/controller/reward/DiceRewardController.php b/server/app/dice/controller/reward/DiceRewardController.php index 3039d7d..f48ebcf 100644 --- a/server/app/dice/controller/reward/DiceRewardController.php +++ b/server/app/dice/controller/reward/DiceRewardController.php @@ -96,7 +96,7 @@ class DiceRewardController extends BaseController * 参数:lottery_config_id 可选;paid_tier_weights / free_tier_weights 自定义档位; * paid_s_count, paid_n_count * chain_free_mode=1:仅按付费次数模拟;付费抽到再来一次/T5 则在队列中插入免费局(同底注、lottery_type=免费、paid_amount=0) - * kill_mode_enabled=1:测试内启用杀分;规则与线上一致(default.profit_amount + safety_line + kill_enabled) + * kill_mode_enabled=1:测试内启用杀分;当模拟池盈利达到 test_safety_line 后,付费抽奖切到 killScore */ #[Permission('一键测试权重', 'dice:reward:index:startWeightTest')] public function startWeightTest(Request $request): Response diff --git a/server/app/dice/logic/reward_config_record/WeightTestRunner.php b/server/app/dice/logic/reward_config_record/WeightTestRunner.php index d40e048..568a860 100644 --- a/server/app/dice/logic/reward_config_record/WeightTestRunner.php +++ b/server/app/dice/logic/reward_config_record/WeightTestRunner.php @@ -17,7 +17,7 @@ use support\think\Db; * 一键测试权重:单进程后台执行模拟摇色子,写入 dice_play_record_test 并更新 dice_reward_config_record 进度 * 抽奖规则与 PlayStartLogic 一致: * - 付费未杀分:按模拟玩家档位权重抽档,lottery_config_id 记 default - * - 付费杀分:default.profit_amount + safety_line + kill_enabled 满足后切 killScore + * - 付费杀分:测试内杀分开启且模拟池盈利 >= test_safety_line 后切 killScore * - 免费券:name=free 奖池(无则 default),排除 5/30 豹子 */ class WeightTestRunner @@ -115,10 +115,12 @@ class WeightTestRunner DiceReward::clearRequestInstance(); $killModeEnabled = (int) ($record->kill_mode_enabled ?? 0) === 1; - $safetyLine = (int) ($configType0->safety_line ?? 0); - $dbKillEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1; + $testSafetyLine = (int) ($record->test_safety_line ?? 5000); + if ($testSafetyLine < 0) { + $testSafetyLine = 0; + } - // 彩金池累计盈利:与线上一致,从 default.profit_amount 起步并在测试内逐局累加 + // 彩金池累计盈利:从 default.profit_amount 起步并在测试内逐局累加,与杀分判定值一致 $poolProfitTotal = (float) ($configType0->profit_amount ?? 0); // 付费未杀分时的模拟玩家档位权重(自定义 > 快照 > 兜底奖池) @@ -145,8 +147,7 @@ class WeightTestRunner $paidPlayerWeights, $freeTierWeightsCustom, $killModeEnabled, - $safetyLine, - $dbKillEnabled, + $testSafetyLine, $poolProfitTotal, $resultCounts, $tierCounts, @@ -186,8 +187,7 @@ class WeightTestRunner ?array $paidPlayerWeights, ?array $freeTierWeightsCustom, bool $killModeEnabled, - int $safetyLine, - bool $dbKillEnabled, + int $testSafetyLine, float &$poolProfitTotal, array &$resultCounts, array &$tierCounts, @@ -211,8 +211,7 @@ class WeightTestRunner if ($isPaid) { $useKillForPaid = $killModeEnabled - && $dbKillEnabled - && $poolProfitTotal >= $safetyLine + && $poolProfitTotal >= $testSafetyLine && $killPoolConfig !== null; if ($useKillForPaid) { $cfg = $killPoolConfig;