From c0d5258aee754d95beb2f5b024f115f453166694 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Tue, 2 Jun 2026 17:04:55 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E5=A4=8D=E6=8A=BD=E5=A5=96=E6=A1=A3?= =?UTF-8?q?=E4=BD=8D=E4=B8=8D=E7=BB=9F=E4=B8=80=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../locales/langs/en/dice/reward_config.json | 18 ++++----- .../locales/langs/zh/dice/reward_config.json | 18 ++++----- .../plugin/dice/reward_config/index/index.vue | 14 +++---- .../utils/generateIndexByRules.ts | 40 +++++++++---------- server/app/api/logic/PlayStartLogic.php | 13 +++--- .../reward/DiceRewardController.php | 2 +- .../DicePlayerTicketRecord.php | 2 +- server/docs/ADMIN_GUIDE.md | 2 +- 8 files changed, 55 insertions(+), 54 deletions(-) diff --git a/saiadmin-artd/src/locales/langs/en/dice/reward_config.json b/saiadmin-artd/src/locales/langs/en/dice/reward_config.json index 31b3927..c04b493 100644 --- a/saiadmin-artd/src/locales/langs/en/dice/reward_config.json +++ b/saiadmin-artd/src/locales/langs/en/dice/reward_config.json @@ -8,7 +8,7 @@ "tabIndex": "Reward Index", "tabBigwin": "Big Win Weights", "tipIndex": "Dice points must be between 5 and 30 and unique in this table.", - "tierRecommendRules": "[Settlement vs tier] T1 (big prize): >2; T2 (small win): 2≥amount>1; T3 (rake): 1≥amount>0; T4 (try again): =0; T5 (penalty): 0>amount. Set recommended settlement per tier below. The Tier column is auto-calculated from settlement and cannot be edited manually.", + "tierRecommendRules": "[Settlement vs tier] T1 (big prize): >2; T2 (small win): 2≥amount>1; T3 (rake): 1≥amount>0; T4 (penalty): 0>amount; T5 (try again): =0. Set recommended settlement per tier below. The Tier column is auto-calculated from settlement and cannot be edited manually.", "tierRecommendRealEv": "Recommended settlement", "tierRecommendAutoMatch": "Auto-match tier when settlement changes", "tierRecommendApplyAmount": "Fill recommended amount for rows with tier set", @@ -17,8 +17,8 @@ "tierRecommendMatchTier": "Match all tiers from settlement", "tierRecommendMatchTierOk": "Matched tier for {n} row(s) from settlement", "tierRecommendMatchTierNone": "No rows to match", - "tierRecommendT4UiText": "再来一次", - "tierRecommendT4UiTextEn": "Once again", + "tierRecommendT5UiText": "再来一次", + "tierRecommendT5UiTextEn": "Once again", "colTierAutoHint": "Auto-matched from settlement", "tipBigwin": "Left to right: big-win points (read-only), display text, real EV, remark, weight (0~10000). Points 5 and 30 are fixed at 100%. This tab saves big-win weights only.", "colId": "Index (id)", @@ -52,7 +52,7 @@ "createRefPreviewClockwise": "Clockwise", "createRefPreviewCounterclockwise": "Counter-clockwise", "createRefPreviewTipUnchanged": "Dice points mapping is unchanged: weights in the preview are reused from current dice_reward; importing will not override existing weights.", - "createRefPreviewTipChanged": "Dice points mapping has changed: preview weights use the default value (1). After importing, adjust weights in the Dice Reward page if needed.", + "createRefPreviewTipChanged": "Dice points mapping has changed: preview weights use defaults (100 by default; sums 5/10/15/20/25/30 default to 1). After importing, adjust weights in the Dice Reward page if needed.", "createRefPreviewSkipped": "{n} dice point(s) are missing in the reward index and were skipped (please complete all 26 points from 5 to 30).", "createRefPreviewRefresh": "Refresh preview", "createRefPreviewImport": "Import", @@ -79,12 +79,12 @@ "infoNoBigwin": "No BIGWIN rows. Set tier to BIGWIN in the Reward Index tab first.", "btnRuleGenerate": "Generate by rules", "ruleGenerateTitle": "Generate reward index by rules", - "ruleGenerateRules": "[Generation logic (same as Create Reward Reference)]\n• 26 cells ordered by id ascending are positions 0–25; each row’s grid_number is 5–30 and unique.\n• Roll D (5–30): start at the cell whose grid_number equals D (start_index); clockwise landing = (start position + D) mod 26; counter-clockwise = start − D (if negative, +26).\n• Each reference row’s “dice points” column is the roll D; tier / real_ev / display text come from the config at the landing id.\n\n[Leopard rolls]\nFor rolls 5, 10, 15, 20, 25, 30, clockwise and counter-clockwise landing tiers must NOT be T4 or T5 (avoid leopard roll + try again / penalty).\n\n[Settlement vs tier]\nT1: >2; T2: 2≥amount>1; T3: 1≥amount>0; T4: =0; T5: 0>amount. Set recommended settlement per tier below.\n\n[Inputs in this dialog]\nCount: T1/T4/T5 are fixed; T2 is minimum. Clockwise and counter-clockwise weighted counts must each satisfy the entered values.\nSettlement standard: same tier uses the same value. T1–T3 and T5 use ui_text = settlement; T4 is fixed to \"再来一次\" / \"Once again\".", + "ruleGenerateRules": "[Generation logic (same as Create Reward Reference)]\n• 26 cells ordered by id ascending are positions 0–25; each row’s grid_number is 5–30 and unique.\n• Roll D (5–30): start at the cell whose grid_number equals D (start_index); clockwise landing = (start position + D) mod 26; counter-clockwise = start − D (if negative, +26).\n• Each reference row’s “dice points” column is the roll D; tier / real_ev / display text come from the config at the landing id.\n\n[Leopard rolls]\nFor rolls 5, 10, 15, 20, 25, 30, clockwise and counter-clockwise landing tiers must NOT be T4 or T5 (avoid leopard roll + penalty / try again).\n\n[Settlement vs tier]\nT1: >2; T2: 2≥amount>1; T3: 1≥amount>0; T4: 0>amount; T5: =0. Set recommended settlement per tier below.\n\n[Inputs in this dialog]\nCount: T1/T4/T5 are fixed; T2 is minimum. Clockwise and counter-clockwise weighted counts must each satisfy the entered values.\nSettlement standard: same tier uses the same value. T1–T4 use ui_text = settlement; T5 is fixed to \"再来一次\" / \"Once again\".", "ruleGenT1Row": "T1 (big prize)", "ruleGenT2Row": "T2 (small win / break-even)", "ruleGenT3RealEvOnly": "T3 (rake)", - "ruleGenT4Row": "T4 (try again)", - "ruleGenT5Row": "T5 (penalty)", + "ruleGenT4Row": "T4 (penalty)", + "ruleGenT5Row": "T5 (try again)", "ruleGenMinCount": "Min count", "ruleGenFixedCount": "Fixed count (CW & CCW)", "ruleGenRealEvStd": "real_ev standard", @@ -92,8 +92,8 @@ "ruleGenInvalidT1RealEv": "T1 (big prize) settlement must satisfy: value > 2", "ruleGenInvalidT2RealEv": "T2 (small win) settlement must satisfy: 1 < value ≤ 2", "ruleGenInvalidT3RealEv": "T3 (rake) settlement must satisfy: 0 < value ≤ 1", - "ruleGenInvalidT4RealEv": "T4 (try again) settlement must be 0", - "ruleGenInvalidT5RealEv": "T5 (penalty) settlement must satisfy: value < 0", + "ruleGenInvalidT4RealEv": "T4 (penalty) settlement must satisfy: value < 0", + "ruleGenInvalidT5RealEv": "T5 (try again) settlement must be 0", "ruleGenT1Min": "T1 fixed count (CW & CCW)", "ruleGenT2Min": "T2 min (CW & CCW)", "ruleGenT4Max": "T4 fixed count (CW & CCW)", diff --git a/saiadmin-artd/src/locales/langs/zh/dice/reward_config.json b/saiadmin-artd/src/locales/langs/zh/dice/reward_config.json index efb0793..a960361 100644 --- a/saiadmin-artd/src/locales/langs/zh/dice/reward_config.json +++ b/saiadmin-artd/src/locales/langs/zh/dice/reward_config.json @@ -8,7 +8,7 @@ "tabIndex": "奖励索引", "tabBigwin": "大奖权重", "tipIndex": "色子点数须在 5~30 之间且本表内不重复。", - "tierRecommendRules": "【结算金额与档位】【大奖】T1:结算金额>2;【小赚】T2:2>=结算金额>1;【抽水】T3:1>=结算金额>0;【再来一次】T4:结算金额=0;【惩罚】T5:0>结算金额。下方可为各档位填写推荐结算金额;表格中「所属档位」随结算金额自动计算,不可手动修改。", + "tierRecommendRules": "【结算金额与档位】【大奖】T1:结算金额>2;【小赚】T2:2>=结算金额>1;【抽水】T3:1>=结算金额>0;【惩罚】T4:0>结算金额;【再来一次】T5:结算金额=0。下方可为各档位填写推荐结算金额;表格中「所属档位」随结算金额自动计算,不可手动修改。", "tierRecommendRealEv": "推荐结算金额", "tierRecommendAutoMatch": "修改结算金额时自动匹配档位", "tierRecommendApplyAmount": "将推荐金额填入已选档位的行", @@ -17,8 +17,8 @@ "tierRecommendMatchTier": "按结算金额匹配全部档位", "tierRecommendMatchTierOk": "已根据结算金额为 {n} 行匹配档位", "tierRecommendMatchTierNone": "没有可匹配档位的行", - "tierRecommendT4UiText": "再来一次", - "tierRecommendT4UiTextEn": "Once again", + "tierRecommendT5UiText": "再来一次", + "tierRecommendT5UiTextEn": "Once again", "colTierAutoHint": "根据结算金额自动匹配", "tipBigwin": "从左至右:中大奖点数(不可改)、显示信息、实际中奖、备注、权重(0~10000)。点数 5、30 权重固定 100%。本表单独立提交,仅提交大奖权重。", "colId": "索引(id)", @@ -52,7 +52,7 @@ "createRefPreviewClockwise": "顺时针", "createRefPreviewCounterclockwise": "逆时针", "createRefPreviewTipUnchanged": "检测到色子点数映射未变化:预览中权重将复用当前奖励对照表(dice_reward)的权重;导入时不会覆盖现有权重。", - "createRefPreviewTipChanged": "检测到色子点数映射已变化:预览中权重将使用默认值(1);确认导入后可再到「奖励对照」页面调整权重。", + "createRefPreviewTipChanged": "检测到色子点数映射已变化:预览中权重将使用默认值(默认 100;点数和为 5/10/15/20/25/30 默认 1);确认导入后可再到「奖励对照」页面调整权重。", "createRefPreviewSkipped": "有 {n} 个点数在当前奖励索引中缺失,已跳过生成(请先补齐 5~30 共 26 个点数)。", "createRefPreviewRefresh": "刷新预览", "createRefPreviewImport": "确认导入", @@ -79,12 +79,12 @@ "infoNoBigwin": "暂无 BIGWIN 档位配置,请先在「奖励索引」中设置 tier 为 BIGWIN", "btnRuleGenerate": "按规则生成", "ruleGenerateTitle": "按规则生成奖励索引", - "ruleGenerateRules": "【生成逻辑(与创建奖励对照一致)】\n• 盘面 26 格按 id 升序为位置 0~25;每条配置的 grid_number 为 5~30 且不重复。\n• 摇取点数 D(5~30):起点为「grid_number=D」所在格位的 id(即 start_index),顺时针落点位置 = (起点位置 + D) mod 26,逆时针落点 = 起点位置 − D(若小于 0 则 +26)。\n• 对照表每条记录的「色子点数」列为摇取点数 D;档位、真实结算、显示文案取自落点格位对应 id 的配置。\n\n【豹子摇取点数】\n摇取点数为 5、10、15、20、25、30 时,其顺/逆时针落点档位不能为 T4、T5(避免对照表上出现豹子点数 + 再来一次/惩罚)。\n\n【结算金额 与 档位】\n【大奖】T1:>2;【小赚】T2:2>=金额>1;【抽水】T3:1>=金额>0;【再来一次】T4:=0;【惩罚】T5:0>金额。下方可为各档位填写推荐结算金额标准,生成时写入配置。\n\n【本弹窗输入】\n条数:T1/T4/T5「固定」;T2「不少于」——顺时针与逆时针的加权条数(每条摇取结果计一次)须分别满足所填数值;T1、T4 与 T5 分开填写。\n结算金额 标准:同档位各格使用同一数值。生成时 T1~T3、T5 的显示文本 = 结算金额;T4 固定为「再来一次」/「Once again」。备注仍区分完美回本/小赚等。", + "ruleGenerateRules": "【生成逻辑(与创建奖励对照一致)】\n• 盘面 26 格按 id 升序为位置 0~25;每条配置的 grid_number 为 5~30 且不重复。\n• 摇取点数 D(5~30):起点为「grid_number=D」所在格位的 id(即 start_index),顺时针落点位置 = (起点位置 + D) mod 26,逆时针落点 = 起点位置 − D(若小于 0 则 +26)。\n• 对照表每条记录的「色子点数」列为摇取点数 D;档位、真实结算、显示文案取自落点格位对应 id 的配置。\n\n【豹子摇取点数】\n摇取点数为 5、10、15、20、25、30 时,其顺/逆时针落点档位不能为 T4、T5(避免对照表上出现豹子点数 + 惩罚/再来一次)。\n\n【结算金额 与 档位】\n【大奖】T1:>2;【小赚】T2:2>=金额>1;【抽水】T3:1>=金额>0;【惩罚】T4:0>金额;【再来一次】T5:=0。下方可为各档位填写推荐结算金额标准,生成时写入配置。\n\n【本弹窗输入】\n条数:T1/T4/T5「固定」;T2「不少于」——顺时针与逆时针的加权条数(每条摇取结果计一次)须分别满足所填数值;T1、T4 与 T5 分开填写。\n结算金额 标准:同档位各格使用同一数值。生成时 T1~T4 的显示文本 = 结算金额;T5 固定为「再来一次」/「Once again」。备注仍区分完美回本/小赚等。", "ruleGenT1Row": "T1 大奖", "ruleGenT2Row": "T2 小赚/回本", "ruleGenT3RealEvOnly": "T3 抽水", - "ruleGenT4Row": "T4 再来一次", - "ruleGenT5Row": "T5 惩罚", + "ruleGenT4Row": "T4 惩罚", + "ruleGenT5Row": "T5 再来一次", "ruleGenMinCount": "最少条数", "ruleGenFixedCount": "固定条数(顺/逆)", "ruleGenRealEvStd": "结算金额", @@ -92,8 +92,8 @@ "ruleGenInvalidT1RealEv": "T1(大奖)结算金额须满足:值 > 2", "ruleGenInvalidT2RealEv": "T2(小赚)结算金额须满足:1 < 值 ≤ 2", "ruleGenInvalidT3RealEv": "T3(抽水)结算金额须满足:0 < 值 ≤ 1", - "ruleGenInvalidT4RealEv": "T4(再来一次)结算金额须为 0", - "ruleGenInvalidT5RealEv": "T5(惩罚)结算金额须满足:值 < 0", + "ruleGenInvalidT4RealEv": "T4(惩罚)结算金额须满足:值 < 0", + "ruleGenInvalidT5RealEv": "T5(再来一次)结算金额须为 0", "ruleGenT1Min": "T1 固定条数(顺/逆)", "ruleGenT2Min": "T2 最少条数(顺/逆)", "ruleGenT4Max": "T4 固定条数(顺/逆)", diff --git a/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue b/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue index 058fb55..adbfb24 100644 --- a/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue +++ b/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue @@ -29,7 +29,7 @@ {{ $t('page.configPage.tierRecommendRealEv') }} 2 * T2 小赚:2>=金额>1 * T3 抽水:1>=金额>0 - * T4 再来一次:=0 - * T5 惩罚:0>金额 + * T4 惩罚:0>金额 + * T5 再来一次:=0 */ export function inferTierFromRealEv(realEv: number): IndexTier | '' { if (!Number.isFinite(realEv)) { return '' } + if (realEv === 0) { + return 'T5' + } + if (realEv < 0) { + return 'T4' + } if (realEv > 2) { return 'T1' } @@ -83,12 +89,6 @@ export function inferTierFromRealEv(realEv: number): IndexTier | '' { if (realEv > 0 && realEv <= 1) { return 'T3' } - if (realEv === 0) { - return 'T4' - } - if (realEv < 0) { - return 'T5' - } return '' } @@ -105,10 +105,10 @@ export function validateTierRealEvStandards(s: TierRealEvStandards): string | nu if (!Number.isFinite(s.T3) || !(s.T3 > 0 && s.T3 <= 1)) { return 'ruleGenInvalidT3RealEv' } - if (!Number.isFinite(s.T4) || s.T4 !== 0) { + if (!Number.isFinite(s.T4) || !(s.T4 < 0)) { return 'ruleGenInvalidT4RealEv' } - if (!Number.isFinite(s.T5) || s.T5 >= 0) { + if (!Number.isFinite(s.T5) || s.T5 !== 0) { return 'ruleGenInvalidT5RealEv' } return null @@ -305,7 +305,7 @@ function uiTextByTierWhenStandards( tier: IndexTier, realEv: number ): { ui_text: string; ui_text_en: string } { - if (tier === 'T4') { + if (tier === 'T5') { return { ui_text: '再来一次', ui_text_en: 'Once again' } } const value = Number.isFinite(realEv) ? realEv.toFixed(2) : String(realEv) @@ -377,13 +377,13 @@ export function buildRowsFromTiers( const f = uiTextByTierWhenStandards(tier, real_ev) ui_text = f.ui_text ui_text_en = f.ui_text_en - remark = '再来一次' + remark = '惩罚' } else { real_ev = standards.T5 const f = uiTextByTierWhenStandards(tier, real_ev) ui_text = f.ui_text ui_text_en = f.ui_text_en - remark = '惩罚' + remark = '再来一次' } } else if (tier === 'T1') { real_ev = 101 + ((id * 17 + grid_number * 3) % 398) @@ -415,17 +415,17 @@ export function buildRowsFromTiers( ui_text_en = f.ui_text_en remark = '抽水' } else if (tier === 'T4') { - real_ev = 0 - ui_text = '再来一次' - ui_text_en = 'Once again' - remark = '再来一次' - } else { t4Seq++ real_ev = -101 - t4Seq * 15 const f = uiTextFromRealEv(real_ev) ui_text = f.ui_text ui_text_en = f.ui_text_en remark = '惩罚' + } else { + real_ev = 0 + ui_text = '再来一次' + ui_text_en = 'Once again' + remark = '再来一次' } rows.push({ id, diff --git a/server/app/api/logic/PlayStartLogic.php b/server/app/api/logic/PlayStartLogic.php index 4c538ff..6aa7b26 100644 --- a/server/app/api/logic/PlayStartLogic.php +++ b/server/app/api/logic/PlayStartLogic.php @@ -187,9 +187,9 @@ class PlayStartLogic $rollNumber = (int) ($chosen['grid_number'] ?? 0); $realEv = (float) ($chosen['real_ev'] ?? 0); // T5/再来一次:以奖励行 tier 为准,并以摇奖档位 $tier 兜底(与 reward_tier 展示一致,避免 dice_reward 行缺 tier 时不发券) - $isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5'; - if ($isTierT5 === false && (string) ($tier ?? '') === 'T5') { - $isTierT5 = true; + $isTierPlayAgain = (string) ($chosen['tier'] ?? '') === 'T5'; + if ($isTierPlayAgain === false && (string) ($tier ?? '') === 'T5') { + $isTierPlayAgain = true; } // 摇色子中奖:按 dice_reward_config.real_ev 直接结算(已乘 ante) $rewardWinCoin = round($realEv * $ante, 2); @@ -230,7 +230,7 @@ class PlayStartLogic // 中 BIGWIN 豹子:不走原奖励流程,不记录原奖励,不触发 T5 再来一次,仅发放豹子奖金 $rewardWinCoin = 0.0; $realEv = 0.0; - $isTierT5 = false; + $isTierPlayAgain = false; } else { $rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber); } @@ -276,7 +276,7 @@ class PlayStartLogic $startIndex, $targetIndex, $rollArray, - $isTierT5, + $isTierPlayAgain, $tier, &$record, &$settledWinCoin @@ -372,7 +372,7 @@ class PlayStartLogic // 若本局中奖档位为 T5,则额外赠送 1 次免费抽奖次数: // - 新结构:写入 free_ticket(ante=本局注数,count+1) // - 兼容旧结构:free_ticket_count +1 - if ($isTierT5) { + if ($isTierPlayAgain) { $ft = $p->free_ticket ?? null; $ftAnte = null; $ftCount = 0; @@ -654,6 +654,7 @@ class PlayStartLogic */ public function simulateOnePlay($config, int $direction, int $lotteryType = 0, int $ante = 1, ?array $customTierWeights = null, ?int $configDeptId = null): array { + $useKillMode = false; $rewardInstance = DiceReward::getCachedInstance($configDeptId); $byTierDirection = $rewardInstance['by_tier_direction'] ?? []; $maxTierRetry = 10; diff --git a/server/app/dice/controller/reward/DiceRewardController.php b/server/app/dice/controller/reward/DiceRewardController.php index e0e5fd8..8ff119e 100644 --- a/server/app/dice/controller/reward/DiceRewardController.php +++ b/server/app/dice/controller/reward/DiceRewardController.php @@ -95,7 +95,7 @@ class DiceRewardController extends BaseController * 一键测试权重:创建测试记录并启动单进程后台执行,写入 dice_play_record_test * 参数: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) + * chain_free_mode=1:仅按付费次数模拟;付费抽到再来一次/T4 则在队列中插入免费局(同底注、lottery_type=免费、paid_amount=0) * kill_mode_enabled=1:测试内启用杀分;当模拟玩家累计盈利达到 test_safety_line 后,付费抽奖切到 killScore */ #[Permission('一键测试权重', 'dice:reward:index:startWeightTest')] diff --git a/server/app/dice/model/player_ticket_record/DicePlayerTicketRecord.php b/server/app/dice/model/player_ticket_record/DicePlayerTicketRecord.php index f804a8d..daa285b 100644 --- a/server/app/dice/model/player_ticket_record/DicePlayerTicketRecord.php +++ b/server/app/dice/model/player_ticket_record/DicePlayerTicketRecord.php @@ -19,7 +19,7 @@ use think\model\relation\BelongsTo; * @property $player_id 玩家id * @property $admin_id 关联玩家所属管理员ID(DicePlayer.admin_id) * @property $use_coins 消耗硬币 - * @property $ante 底注/注数(历史购买记录默认为1;T5再来一次写入本次注数) + * @property $ante 底注/注数(历史购买记录默认为1;T4再来一次写入本次注数) * @property $total_ticket_count 总抽奖次数 * @property $paid_ticket_count 购买抽奖次数 * @property $free_ticket_count 赠送抽奖次数 diff --git a/server/docs/ADMIN_GUIDE.md b/server/docs/ADMIN_GUIDE.md index 138a071..a04c7ab 100644 --- a/server/docs/ADMIN_GUIDE.md +++ b/server/docs/ADMIN_GUIDE.md @@ -83,7 +83,7 @@ 其中地图的索引可以按照需求点击图中的按规则生成 -并且规则尽可能符合:结算金额>2 → T1;2>=结算金额>1 → T2;1>=结算金额>0 → T3;结算金额=0 → T4(再来一次);0>结算金额 → T5(惩罚) +并且规则尽可能符合:结算金额>2 → T1;2>=结算金额>1 → T2;1>=结算金额>0 → T3;0>结算金额 → T4(惩罚);结算金额=0 → T5(再来一次) ![image.png](/docs/picture/guide_16.png)