+
+
+
+
+
+
{{ $t('page.weightTest.sectionPaid') }}
,
free_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record,
paid_s_count: 100,
- paid_n_count: 100
+ paid_n_count: 100,
+ kill_mode_enabled: false,
+ test_safety_line: 5000
})
const lotteryOptions = ref>([])
/** 付费抽奖券可选档位:name=default */
@@ -242,7 +259,9 @@
paid_n_count: form.paid_n_count,
free_s_count: 0,
free_n_count: 0,
- chain_free_mode: true
+ chain_free_mode: true,
+ kill_mode_enabled: form.kill_mode_enabled,
+ test_safety_line: form.test_safety_line
}
if (form.paid_lottery_config_id != null) {
payload.paid_lottery_config_id = form.paid_lottery_config_id
@@ -266,6 +285,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) {
diff --git a/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/index.vue b/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/index.vue
index a2b7cc5..070f26f 100644
--- a/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/index.vue
+++ b/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/index.vue
@@ -225,6 +225,12 @@
width: 120,
align: 'center'
},
+ {
+ prop: 'ante',
+ label: 'page.table.ante',
+ width: 90,
+ align: 'center'
+ },
{
prop: 'play_again_count',
label: 'page.table.playAgainCount',
diff --git a/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/modules/table-search.vue b/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/modules/table-search.vue
index d1d8c79..b45fa16 100644
--- a/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/modules/table-search.vue
+++ b/saiadmin-artd/src/views/plugin/dice/reward_config_record/index/modules/table-search.vue
@@ -8,6 +8,32 @@
@search="handleSearch"
@expand="handleExpand"
>
+
+
+
+
+
+
+
+
+
+
diff --git a/server/app/dice/controller/reward/DiceRewardController.php b/server/app/dice/controller/reward/DiceRewardController.php
index f0046b0..ea4d62e 100644
--- a/server/app/dice/controller/reward/DiceRewardController.php
+++ b/server/app/dice/controller/reward/DiceRewardController.php
@@ -85,6 +85,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:测试内启用杀分;当模拟玩家累计盈利达到 test_safety_line 后,付费抽奖切到 killScore
*/
#[Permission('一键测试权重', 'dice:reward:index:startWeightTest')]
public function startWeightTest(Request $request): Response
@@ -100,6 +101,8 @@ class DiceRewardController extends BaseController
'paid_tier_weights' => $post['paid_tier_weights'] ?? null,
'free_tier_weights' => $post['free_tier_weights'] ?? null,
'chain_free_mode' => $post['chain_free_mode'] ?? null,
+ 'kill_mode_enabled' => $post['kill_mode_enabled'] ?? null,
+ 'test_safety_line' => $post['test_safety_line'] ?? null,
];
$adminId = isset($this->adminInfo['id']) ? (int) $this->adminInfo['id'] : null;
try {
diff --git a/server/app/dice/controller/reward_config_record/DiceRewardConfigRecordController.php b/server/app/dice/controller/reward_config_record/DiceRewardConfigRecordController.php
index 8e3ea33..e6bbfd4 100644
--- a/server/app/dice/controller/reward_config_record/DiceRewardConfigRecordController.php
+++ b/server/app/dice/controller/reward_config_record/DiceRewardConfigRecordController.php
@@ -38,6 +38,8 @@ class DiceRewardConfigRecordController extends BaseController
public function index(Request $request): Response
{
$where = $request->more([
+ ['paid_planned_spins', ''],
+ ['ante', ''],
]);
$query = $this->logic->search($where);
$data = $this->logic->getList($query);
diff --git a/server/app/dice/logic/reward_config_record/DiceRewardConfigRecordLogic.php b/server/app/dice/logic/reward_config_record/DiceRewardConfigRecordLogic.php
index dba7339..006130a 100644
--- a/server/app/dice/logic/reward_config_record/DiceRewardConfigRecordLogic.php
+++ b/server/app/dice/logic/reward_config_record/DiceRewardConfigRecordLogic.php
@@ -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;
diff --git a/server/app/dice/logic/reward_config_record/WeightTestRunner.php b/server/app/dice/logic/reward_config_record/WeightTestRunner.php
index 1c46660..d83d4f3 100644
--- a/server/app/dice/logic/reward_config_record/WeightTestRunner.php
+++ b/server/app/dice/logic/reward_config_record/WeightTestRunner.php
@@ -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);
diff --git a/server/app/dice/model/reward_config_record/DiceRewardConfigRecord.php b/server/app/dice/model/reward_config_record/DiceRewardConfigRecord.php
index 6b2963d..0324580 100644
--- a/server/app/dice/model/reward_config_record/DiceRewardConfigRecord.php
+++ b/server/app/dice/model/reward_config_record/DiceRewardConfigRecord.php
@@ -30,6 +30,8 @@ use think\model\relation\HasMany;
* @property int $paid_s_count 付费抽奖顺时针次数
* @property int $paid_n_count 付费抽奖逆时针次数
* @property int $chain_free_mode 1=链式再来一次免费抽奖
+ * @property int $kill_mode_enabled 测试内杀分开关 1=开启
+ * @property int $test_safety_line 测试内安全线(模拟玩家累计盈利阈值)
* @property int $paid_planned_spins 计划付费抽奖次数(顺+逆)
* @property int $play_again_count 再来一次次数(T5触发次数)
* @property array|null $paid_tier_weights 付费自定义档位权重 T1-T5
@@ -68,6 +70,22 @@ class DiceRewardConfigRecord extends BaseModel
return $this->hasMany(DicePlayRecordTest::class, 'reward_config_record_id', 'id');
}
+ /** 计划付费抽奖次数(顺+逆) */
+ public function searchPaidPlannedSpinsAttr($query, $value): void
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('paid_planned_spins', '=', $value);
+ }
+ }
+
+ /** 底注/注数(dice_ante_config.mult) */
+ public function searchAnteAttr($query, $value): void
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('ante', '=', $value);
+ }
+ }
+
/**
* 根据关联的 DicePlayRecordTest 统计平台赚取平台币
* platform_profit = 关联的付费(lottery_type=0)付费金额求和(paid_amount) - 关联的 win_coin 求和