[色子游戏]抽奖记录(测试权重)-优化
[API]记录抽奖券DicePlayerTicketRecord
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
"direction": "Direction",
|
"direction": "Direction",
|
||||||
"isBigWin": "Is Big Win",
|
"isBigWin": "Is Big Win",
|
||||||
"winCoin": "Win Coin",
|
"winCoin": "Win Coin",
|
||||||
|
"paidAmount": "Paid Amount",
|
||||||
|
"ante": "Ante",
|
||||||
"rewardTier": "Reward Tier",
|
"rewardTier": "Reward Tier",
|
||||||
"rollNumber": "Roll Number",
|
"rollNumber": "Roll Number",
|
||||||
"paid": "Paid",
|
"paid": "Paid",
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"lotteryPoolConfig": "Lottery Pool Config",
|
"lotteryPoolConfig": "Lottery Pool Config",
|
||||||
"drawType": "Draw Type",
|
"drawType": "Draw Type",
|
||||||
"isBigWin": "Is Big Win",
|
"isBigWin": "Is Big Win",
|
||||||
|
"paidAmount": "Paid Amount",
|
||||||
|
"ante": "Ante",
|
||||||
"winCoin": "Win Coin",
|
"winCoin": "Win Coin",
|
||||||
"superWinCoin": "Super Win Coin",
|
"superWinCoin": "Super Win Coin",
|
||||||
"rewardWinCoin": "Reward Win Coin",
|
"rewardWinCoin": "Reward Win Coin",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"search": {
|
"search": {
|
||||||
"player": "Player",
|
"player": "Player",
|
||||||
"useCoins": "Use Coins",
|
"useCoins": "Use Coins",
|
||||||
|
"ante": "Ante",
|
||||||
"totalDrawCount": "Total Draw Count",
|
"totalDrawCount": "Total Draw Count",
|
||||||
"paidDrawCount": "Paid Draw Count",
|
"paidDrawCount": "Paid Draw Count",
|
||||||
"freeDrawCount": "Free Draw Count",
|
"freeDrawCount": "Free Draw Count",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"id": "ID",
|
"id": "ID",
|
||||||
"playerUsername": "Player Username",
|
"playerUsername": "Player Username",
|
||||||
"useCoins": "Use Coins",
|
"useCoins": "Use Coins",
|
||||||
|
"ante": "Ante",
|
||||||
"totalDrawCount": "Total Draw Count",
|
"totalDrawCount": "Total Draw Count",
|
||||||
"paidDrawCount": "Paid Draw Count",
|
"paidDrawCount": "Paid Draw Count",
|
||||||
"freeDrawCount": "Free Draw Count",
|
"freeDrawCount": "Free Draw Count",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
"stepFree": "Free ticket",
|
"stepFree": "Free ticket",
|
||||||
"labelLotteryTypePaid": "Test pool type",
|
"labelLotteryTypePaid": "Test pool type",
|
||||||
"labelLotteryTypeFree": "Test pool type",
|
"labelLotteryTypeFree": "Test pool type",
|
||||||
|
"labelAnte": "Ante",
|
||||||
"placeholderPaidPool": "Leave empty for custom tier odds below (default: default)",
|
"placeholderPaidPool": "Leave empty for custom tier odds below (default: default)",
|
||||||
"placeholderFreePool": "Leave empty for custom tier odds below (default: killScore)",
|
"placeholderFreePool": "Leave empty for custom tier odds below (default: killScore)",
|
||||||
"tierProbHint": "Custom tier odds (T1–T5), each 0–100%, sum of five must not exceed 100%",
|
"tierProbHint": "Custom tier odds (T1–T5), each 0–100%, sum of five must not exceed 100%",
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
"btnNext": "Next",
|
"btnNext": "Next",
|
||||||
"btnStart": "Start test",
|
"btnStart": "Start test",
|
||||||
"btnCancel": "Cancel",
|
"btnCancel": "Cancel",
|
||||||
|
"warnAnte": "Ante must be greater than 0",
|
||||||
"warnTotalSpins": "At least one of paid/free direction spin counts must be greater than 0",
|
"warnTotalSpins": "At least one of paid/free direction spin counts must be greater than 0",
|
||||||
"warnPaidTierSumPositive": "When no paid pool is selected, T1–T5 odds sum must be greater than 0",
|
"warnPaidTierSumPositive": "When no paid pool is selected, T1–T5 odds sum must be greater than 0",
|
||||||
"warnPaidTierSumMax": "Paid T1–T5 odds sum cannot exceed 100%",
|
"warnPaidTierSumMax": "Paid T1–T5 odds sum cannot exceed 100%",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"platformProfit": "Platform Profit",
|
"platformProfit": "Platform Profit",
|
||||||
"totalDrawCount": "Total Draw Count",
|
"totalDrawCount": "Total Draw Count",
|
||||||
"createdBy": "Created By",
|
"createdBy": "Created By",
|
||||||
|
"remark": "Remark",
|
||||||
"createTime": "Create Time",
|
"createTime": "Create Time",
|
||||||
"statusFail": "Failed",
|
"statusFail": "Failed",
|
||||||
"statusDone": "Done",
|
"statusDone": "Done",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"placeholderLotteryPool": "请选择彩金池配置",
|
"placeholderLotteryPool": "请选择彩金池配置",
|
||||||
"drawType": "抽奖类型",
|
"drawType": "抽奖类型",
|
||||||
"paid": "付费",
|
"paid": "付费",
|
||||||
"free": "赠送",
|
"free": "免费",
|
||||||
"isBigWin": "是否中大奖",
|
"isBigWin": "是否中大奖",
|
||||||
"noBigWin": "无",
|
"noBigWin": "无",
|
||||||
"bigWin": "中大奖",
|
"bigWin": "中大奖",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"nameFuzzy": "名称模糊",
|
"nameFuzzy": "名称模糊",
|
||||||
"uiTextFuzzy": "前端显示文本模糊",
|
"uiTextFuzzy": "前端显示文本模糊",
|
||||||
"paid": "付费",
|
"paid": "付费",
|
||||||
"free": "赠送",
|
"free": "免费",
|
||||||
"noBigWin": "无",
|
"noBigWin": "无",
|
||||||
"bigWin": "中大奖",
|
"bigWin": "中大奖",
|
||||||
"clockwise": "顺时针",
|
"clockwise": "顺时针",
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
"direction": "方向",
|
"direction": "方向",
|
||||||
"isBigWin": "是否中大奖",
|
"isBigWin": "是否中大奖",
|
||||||
"winCoin": "赢取平台币",
|
"winCoin": "赢取平台币",
|
||||||
|
"paidAmount": "付费金额",
|
||||||
|
"ante": "底注",
|
||||||
"rewardTier": "奖励档位",
|
"rewardTier": "奖励档位",
|
||||||
"rollNumber": "摇取点数和",
|
"rollNumber": "摇取点数和",
|
||||||
"paid": "付费",
|
"paid": "付费",
|
||||||
"free": "赠送",
|
"free": "免费",
|
||||||
"clockwise": "顺时针",
|
"clockwise": "顺时针",
|
||||||
"anticlockwise": "逆时针",
|
"anticlockwise": "逆时针",
|
||||||
"noBigWin": "无",
|
"noBigWin": "无",
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"lotteryPoolConfig": "彩金池配置",
|
"lotteryPoolConfig": "彩金池配置",
|
||||||
"drawType": "抽奖类型",
|
"drawType": "抽奖类型",
|
||||||
"isBigWin": "是否中大奖",
|
"isBigWin": "是否中大奖",
|
||||||
|
"paidAmount": "付费金额",
|
||||||
|
"ante": "底注",
|
||||||
"winCoin": "赢取平台币",
|
"winCoin": "赢取平台币",
|
||||||
"superWinCoin": "中大奖平台币",
|
"superWinCoin": "中大奖平台币",
|
||||||
"rewardWinCoin": "摇色子中奖平台币",
|
"rewardWinCoin": "摇色子中奖平台币",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"search": {
|
"search": {
|
||||||
"player": "玩家",
|
"player": "玩家",
|
||||||
"useCoins": "消耗硬币",
|
"useCoins": "消耗硬币",
|
||||||
|
"ante": "底注",
|
||||||
"totalDrawCount": "总抽奖次数",
|
"totalDrawCount": "总抽奖次数",
|
||||||
"paidDrawCount": "购买抽奖次数",
|
"paidDrawCount": "购买抽奖次数",
|
||||||
"freeDrawCount": "赠送抽奖次数",
|
"freeDrawCount": "赠送抽奖次数",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"id": "ID",
|
"id": "ID",
|
||||||
"playerUsername": "玩家用户名",
|
"playerUsername": "玩家用户名",
|
||||||
"useCoins": "消耗硬币",
|
"useCoins": "消耗硬币",
|
||||||
|
"ante": "底注",
|
||||||
"totalDrawCount": "总抽奖次数",
|
"totalDrawCount": "总抽奖次数",
|
||||||
"paidDrawCount": "购买抽奖次数",
|
"paidDrawCount": "购买抽奖次数",
|
||||||
"freeDrawCount": "赠送抽奖次数",
|
"freeDrawCount": "赠送抽奖次数",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
"stepFree": "免费抽奖券",
|
"stepFree": "免费抽奖券",
|
||||||
"labelLotteryTypePaid": "测试数据档位类型",
|
"labelLotteryTypePaid": "测试数据档位类型",
|
||||||
"labelLotteryTypeFree": "测试数据档位类型",
|
"labelLotteryTypeFree": "测试数据档位类型",
|
||||||
|
"labelAnte": "底注 ante",
|
||||||
"placeholderPaidPool": "不选则下方自定义档位概率(默认 default)",
|
"placeholderPaidPool": "不选则下方自定义档位概率(默认 default)",
|
||||||
"placeholderFreePool": "不选则下方自定义档位概率(默认 killScore)",
|
"placeholderFreePool": "不选则下方自定义档位概率(默认 killScore)",
|
||||||
"tierProbHint": "自定义档位概率(T1~T5),每档 0-100%,五档之和不能超过 100%",
|
"tierProbHint": "自定义档位概率(T1~T5),每档 0-100%,五档之和不能超过 100%",
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
"btnNext": "下一步",
|
"btnNext": "下一步",
|
||||||
"btnStart": "开始测试",
|
"btnStart": "开始测试",
|
||||||
"btnCancel": "取消",
|
"btnCancel": "取消",
|
||||||
|
"warnAnte": "底注 ante 必须大于 0",
|
||||||
"warnTotalSpins": "付费或免费至少一种方向次数之和大于 0",
|
"warnTotalSpins": "付费或免费至少一种方向次数之和大于 0",
|
||||||
"warnPaidTierSumPositive": "付费未选奖池时,T1~T5 档位概率之和需大于 0",
|
"warnPaidTierSumPositive": "付费未选奖池时,T1~T5 档位概率之和需大于 0",
|
||||||
"warnPaidTierSumMax": "付费档位概率 T1~T5 之和不能超过 100%",
|
"warnPaidTierSumMax": "付费档位概率 T1~T5 之和不能超过 100%",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"platformProfit": "平台赚取金额",
|
"platformProfit": "平台赚取金额",
|
||||||
"totalDrawCount": "总抽奖次数",
|
"totalDrawCount": "总抽奖次数",
|
||||||
"createdBy": "创建管理员",
|
"createdBy": "创建管理员",
|
||||||
|
"remark": "备注",
|
||||||
"createTime": "创建时间",
|
"createTime": "创建时间",
|
||||||
"statusFail": "失败",
|
"statusFail": "失败",
|
||||||
"statusDone": "完成",
|
"statusDone": "完成",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export default {
|
|||||||
* 可选 lottery_config_id;不选则传 paid_tier_weights / free_tier_weights(T1-T5)
|
* 可选 lottery_config_id;不选则传 paid_tier_weights / free_tier_weights(T1-T5)
|
||||||
*/
|
*/
|
||||||
startWeightTest(params: {
|
startWeightTest(params: {
|
||||||
|
ante?: number
|
||||||
lottery_config_id?: number
|
lottery_config_id?: number
|
||||||
paid_lottery_config_id?: number
|
paid_lottery_config_id?: number
|
||||||
free_lottery_config_id?: number
|
free_lottery_config_id?: number
|
||||||
|
|||||||
@@ -58,19 +58,37 @@
|
|||||||
<!-- 抽奖类型 -->
|
<!-- 抽奖类型 -->
|
||||||
<template #lottery_type="{ row }">
|
<template #lottery_type="{ row }">
|
||||||
<ElTag size="small" :type="row.lottery_type === 0 ? 'warning' : 'success'">
|
<ElTag size="small" :type="row.lottery_type === 0 ? 'warning' : 'success'">
|
||||||
{{ row.lottery_type === 0 ? t('page.search.paid') : row.lottery_type === 1 ? t('page.search.free') : '-' }}
|
{{
|
||||||
|
row.lottery_type === 0
|
||||||
|
? t('page.search.paid')
|
||||||
|
: row.lottery_type === 1
|
||||||
|
? t('page.search.free')
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
</ElTag>
|
</ElTag>
|
||||||
</template>
|
</template>
|
||||||
<!-- 是否中大奖 -->
|
<!-- 是否中大奖 -->
|
||||||
<template #is_win="{ row }">
|
<template #is_win="{ row }">
|
||||||
<ElTag size="small" :type="row.is_win === 1 ? 'success' : 'info'">
|
<ElTag size="small" :type="row.is_win === 1 ? 'success' : 'info'">
|
||||||
{{ row.is_win === 0 ? t('page.search.noBigWin') : row.is_win === 1 ? t('page.search.bigWin') : '-' }}
|
{{
|
||||||
|
row.is_win === 0
|
||||||
|
? t('page.search.noBigWin')
|
||||||
|
: row.is_win === 1
|
||||||
|
? t('page.search.bigWin')
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
</ElTag>
|
</ElTag>
|
||||||
</template>
|
</template>
|
||||||
<!-- 方向 -->
|
<!-- 方向 -->
|
||||||
<template #direction="{ row }">
|
<template #direction="{ row }">
|
||||||
<ElTag size="small" :type="row.direction === 0 ? 'primary' : 'warning'">
|
<ElTag size="small" :type="row.direction === 0 ? 'primary' : 'warning'">
|
||||||
{{ row.direction === 0 ? t('page.search.clockwise') : row.direction === 1 ? t('page.search.anticlockwise') : '-' }}
|
{{
|
||||||
|
row.direction === 0
|
||||||
|
? t('page.search.clockwise')
|
||||||
|
: row.direction === 1
|
||||||
|
? t('page.search.anticlockwise')
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
</ElTag>
|
</ElTag>
|
||||||
</template>
|
</template>
|
||||||
<!-- 摇取点数 -->
|
<!-- 摇取点数 -->
|
||||||
@@ -132,6 +150,8 @@
|
|||||||
lottery_type: undefined,
|
lottery_type: undefined,
|
||||||
direction: undefined,
|
direction: undefined,
|
||||||
is_win: undefined,
|
is_win: undefined,
|
||||||
|
paid_amount: undefined,
|
||||||
|
ante: undefined,
|
||||||
win_coin_min: undefined,
|
win_coin_min: undefined,
|
||||||
win_coin_max: undefined,
|
win_coin_max: undefined,
|
||||||
reward_tier: undefined,
|
reward_tier: undefined,
|
||||||
@@ -208,9 +228,16 @@
|
|||||||
columnsFactory: () => [
|
columnsFactory: () => [
|
||||||
{ type: 'selection' },
|
{ type: 'selection' },
|
||||||
{ prop: 'id', label: 'page.table.id', width: 80 },
|
{ prop: 'id', label: 'page.table.id', width: 80 },
|
||||||
{ prop: 'lottery_config_id', label: 'page.table.lotteryPoolConfig', width: 120, useSlot: true },
|
{
|
||||||
|
prop: 'lottery_config_id',
|
||||||
|
label: 'page.table.lotteryPoolConfig',
|
||||||
|
width: 120,
|
||||||
|
useSlot: true
|
||||||
|
},
|
||||||
{ prop: 'lottery_type', label: 'page.table.drawType', width: 100, useSlot: true },
|
{ prop: 'lottery_type', label: 'page.table.drawType', width: 100, useSlot: true },
|
||||||
{ prop: 'is_win', label: 'page.table.isBigWin', width: 100, useSlot: true },
|
{ prop: 'is_win', label: 'page.table.isBigWin', width: 100, useSlot: true },
|
||||||
|
{ prop: 'paid_amount', label: 'page.table.paidAmount', width: 130 },
|
||||||
|
{ prop: 'ante', label: 'page.table.ante', width: 90 },
|
||||||
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110 },
|
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110 },
|
||||||
{ prop: 'super_win_coin', label: 'page.table.superWinCoin', width: 120 },
|
{ prop: 'super_win_coin', label: 'page.table.superWinCoin', width: 120 },
|
||||||
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140 },
|
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140 },
|
||||||
@@ -222,7 +249,13 @@
|
|||||||
{ prop: 'reward_config_id', label: 'page.table.rewardConfig', width: 100, useSlot: true },
|
{ prop: 'reward_config_id', label: 'page.table.rewardConfig', width: 100, useSlot: true },
|
||||||
{ prop: 'status', label: 'page.table.status', width: 80, useSlot: true },
|
{ prop: 'status', label: 'page.table.status', width: 80, useSlot: true },
|
||||||
{ prop: 'create_time', label: 'page.table.createTime', width: 170 },
|
{ prop: 'create_time', label: 'page.table.createTime', width: 170 },
|
||||||
{ prop: 'operation', label: 'table.actions.operation', width: 100, fixed: 'right', useSlot: true }
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: 'table.actions.operation',
|
||||||
|
width: 100,
|
||||||
|
fixed: 'right',
|
||||||
|
useSlot: true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,6 +28,24 @@
|
|||||||
<el-option :label="$t('page.search.anticlockwise')" :value="1" />
|
<el-option :label="$t('page.search.anticlockwise')" :value="1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('page.search.ante')" prop="ante">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.ante"
|
||||||
|
:placeholder="$t('table.searchBar.all')"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('page.search.paidAmount')" prop="paid_amount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.paid_amount"
|
||||||
|
:placeholder="$t('table.searchBar.all')"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('page.search.isBigWin')" prop="is_win">
|
<el-form-item :label="$t('page.search.isBigWin')" prop="is_win">
|
||||||
<el-select v-model="formData.is_win" :placeholder="$t('form.placeholderSelect')" clearable style="width: 100%">
|
<el-select v-model="formData.is_win" :placeholder="$t('form.placeholderSelect')" clearable style="width: 100%">
|
||||||
<el-option :label="$t('page.search.noBigWin')" :value="0" />
|
<el-option :label="$t('page.search.noBigWin')" :value="0" />
|
||||||
@@ -153,6 +171,8 @@
|
|||||||
lottery_config_id: null,
|
lottery_config_id: null,
|
||||||
lottery_type: null,
|
lottery_type: null,
|
||||||
is_win: null,
|
is_win: null,
|
||||||
|
ante: 1,
|
||||||
|
paid_amount: 0,
|
||||||
win_coin: 0,
|
win_coin: 0,
|
||||||
direction: null,
|
direction: null,
|
||||||
reward_tier: undefined as string | undefined,
|
reward_tier: undefined as string | undefined,
|
||||||
|
|||||||
@@ -32,6 +32,28 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col v-bind="setSpan(6)">
|
||||||
|
<el-form-item :label="$t('page.search.paidAmount')" prop="paid_amount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.paid_amount"
|
||||||
|
:placeholder="$t('table.searchBar.all')"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col v-bind="setSpan(6)">
|
||||||
|
<el-form-item :label="$t('page.search.ante')" prop="ante">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.ante"
|
||||||
|
:placeholder="$t('table.searchBar.all')"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col v-bind="setSpan(6)">
|
<el-col v-bind="setSpan(6)">
|
||||||
<el-form-item :label="$t('page.search.winCoin')" prop="win_coin_min">
|
<el-form-item :label="$t('page.search.winCoin')" prop="win_coin_min">
|
||||||
<div class="range-wrap">
|
<div class="range-wrap">
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
username: undefined,
|
username: undefined,
|
||||||
use_coins_min: undefined,
|
use_coins_min: undefined,
|
||||||
use_coins_max: undefined,
|
use_coins_max: undefined,
|
||||||
|
ante: undefined,
|
||||||
total_ticket_count_min: undefined,
|
total_ticket_count_min: undefined,
|
||||||
total_ticket_count_max: undefined,
|
total_ticket_count_max: undefined,
|
||||||
paid_ticket_count_min: undefined,
|
paid_ticket_count_min: undefined,
|
||||||
@@ -136,6 +137,7 @@
|
|||||||
formatter: (row: Record<string, any>) => usernameFormatter(row)
|
formatter: (row: Record<string, any>) => usernameFormatter(row)
|
||||||
},
|
},
|
||||||
{ prop: 'use_coins', label: 'page.table.useCoins', align: 'center' },
|
{ prop: 'use_coins', label: 'page.table.useCoins', align: 'center' },
|
||||||
|
{ prop: 'ante', label: 'page.table.ante', align: 'center' },
|
||||||
{ prop: 'total_ticket_count', label: 'page.table.totalDrawCount', align: 'center' },
|
{ prop: 'total_ticket_count', label: 'page.table.totalDrawCount', align: 'center' },
|
||||||
{ prop: 'paid_ticket_count', label: 'page.table.paidDrawCount', align: 'center' },
|
{ prop: 'paid_ticket_count', label: 'page.table.paidDrawCount', align: 'center' },
|
||||||
{ prop: 'free_ticket_count', label: 'page.table.freeDrawCount', align: 'center' },
|
{ prop: 'free_ticket_count', label: 'page.table.freeDrawCount', align: 'center' },
|
||||||
|
|||||||
@@ -34,6 +34,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col v-bind="setSpan(6)">
|
||||||
|
<el-form-item :label="$t('page.search.ante')" prop="ante">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.ante"
|
||||||
|
:placeholder="$t('table.searchBar.all')"
|
||||||
|
:min="1"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col v-bind="setSpan(6)">
|
<el-col v-bind="setSpan(6)">
|
||||||
<el-form-item :label="$t('page.search.totalDrawCount')" prop="total_ticket_count_min">
|
<el-form-item :label="$t('page.search.totalDrawCount')" prop="total_ticket_count_min">
|
||||||
<div class="range-wrap">
|
<div class="range-wrap">
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
{{ $t('page.weightTest.alertBody') }}
|
{{ $t('page.weightTest.alertBody') }}
|
||||||
</ElAlert>
|
</ElAlert>
|
||||||
<ElForm ref="formRef" :model="form" label-width="140px">
|
<ElForm ref="formRef" :model="form" label-width="140px">
|
||||||
|
<ElFormItem :label="$t('page.weightTest.labelAnte')" prop="ante" required>
|
||||||
|
<ElInputNumber v-model="form.ante" :min="1" :step="1" style="width: 100%" />
|
||||||
|
</ElFormItem>
|
||||||
<ElSteps :active="currentStep" finish-status="success" simple class="steps-wrap">
|
<ElSteps :active="currentStep" finish-status="success" simple class="steps-wrap">
|
||||||
<ElStep :title="$t('page.weightTest.stepPaid')" />
|
<ElStep :title="$t('page.weightTest.stepPaid')" />
|
||||||
<ElStep :title="$t('page.weightTest.stepFree')" />
|
<ElStep :title="$t('page.weightTest.stepFree')" />
|
||||||
@@ -187,6 +190,7 @@
|
|||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const currentStep = ref(0)
|
const currentStep = ref(0)
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
|
ante: 1,
|
||||||
paid_lottery_config_id: undefined as number | undefined,
|
paid_lottery_config_id: undefined as number | undefined,
|
||||||
free_lottery_config_id: undefined as number | undefined,
|
free_lottery_config_id: undefined as number | undefined,
|
||||||
paid_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record<string, number>,
|
paid_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record<string, number>,
|
||||||
@@ -270,6 +274,7 @@
|
|||||||
|
|
||||||
function buildPayload() {
|
function buildPayload() {
|
||||||
const payload: Record<string, unknown> = {
|
const payload: Record<string, unknown> = {
|
||||||
|
ante: form.ante,
|
||||||
paid_s_count: form.paid_s_count,
|
paid_s_count: form.paid_s_count,
|
||||||
paid_n_count: form.paid_n_count,
|
paid_n_count: form.paid_n_count,
|
||||||
free_s_count: form.free_s_count,
|
free_s_count: form.free_s_count,
|
||||||
@@ -289,6 +294,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function validateForm(): boolean {
|
function validateForm(): boolean {
|
||||||
|
if (form.ante == null || form.ante <= 0) {
|
||||||
|
ElMessage.warning(t('page.weightTest.warnAnte'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (form.paid_s_count + form.paid_n_count + form.free_s_count + form.free_n_count <= 0) {
|
if (form.paid_s_count + form.paid_n_count + form.free_s_count + form.free_n_count <= 0) {
|
||||||
ElMessage.warning(t('page.weightTest.warnTotalSpins'))
|
ElMessage.warning(t('page.weightTest.warnTotalSpins'))
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -214,6 +214,13 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
showOverflowTooltip: true
|
showOverflowTooltip: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'remark',
|
||||||
|
label: 'page.table.remark',
|
||||||
|
width: 220,
|
||||||
|
align: 'center',
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
{ prop: 'create_time', label: 'page.table.createTime', width: 170, align: 'center' },
|
{ prop: 'create_time', label: 'page.table.createTime', width: 170, align: 'center' },
|
||||||
{
|
{
|
||||||
prop: 'operation',
|
prop: 'operation',
|
||||||
|
|||||||
@@ -284,6 +284,21 @@ class PlayStartLogic
|
|||||||
$p->free_ticket_count = max(0, (int) $p->free_ticket_count - 1);
|
$p->free_ticket_count = max(0, (int) $p->free_ticket_count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录每次游玩:写入抽奖券记录(用于后台“抽奖券记录”追踪付费/免费游玩与消耗)
|
||||||
|
$isPaidPlay = $ticketType === self::LOTTERY_TYPE_PAID;
|
||||||
|
$paidCnt = $isPaidPlay ? 1 : 0;
|
||||||
|
$freeCnt = $isPaidPlay ? 0 : 1;
|
||||||
|
DicePlayerTicketRecord::create([
|
||||||
|
'player_id' => $playerId,
|
||||||
|
'admin_id' => $adminId,
|
||||||
|
'use_coins' => $paidAmount,
|
||||||
|
'ante' => $ante,
|
||||||
|
'total_ticket_count' => $paidCnt + $freeCnt,
|
||||||
|
'paid_ticket_count' => $paidCnt,
|
||||||
|
'free_ticket_count' => $freeCnt,
|
||||||
|
'remark' => ($isPaidPlay ? '付费游玩' : '免费游玩') . '|play_record_id=' . $record->id,
|
||||||
|
]);
|
||||||
|
|
||||||
// 若本局中奖档位为 T5,则额外赠送 1 次免费抽奖次数(总次数也 +1),并记录抽奖券获取记录
|
// 若本局中奖档位为 T5,则额外赠送 1 次免费抽奖次数(总次数也 +1),并记录抽奖券获取记录
|
||||||
if ($isTierT5) {
|
if ($isTierT5) {
|
||||||
$p->free_ticket_count = (int) $p->free_ticket_count + 1;
|
$p->free_ticket_count = (int) $p->free_ticket_count + 1;
|
||||||
@@ -509,10 +524,11 @@ class PlayStartLogic
|
|||||||
* @param \app\dice\model\lottery_pool_config\DiceLotteryPoolConfig|null $config 奖池配置,自定义档位时可为 null
|
* @param \app\dice\model\lottery_pool_config\DiceLotteryPoolConfig|null $config 奖池配置,自定义档位时可为 null
|
||||||
* @param int $direction 0=顺时针 1=逆时针
|
* @param int $direction 0=顺时针 1=逆时针
|
||||||
* @param int $lotteryType 0=付费 1=免费
|
* @param int $lotteryType 0=付费 1=免费
|
||||||
|
* @param int $ante 底注/注数(dice_ante_config.mult)
|
||||||
* @param array|null $customTierWeights 自定义档位权重 ['T1'=>x, 'T2'=>x, ...],非空时忽略 config 的档位权重
|
* @param array|null $customTierWeights 自定义档位权重 ['T1'=>x, 'T2'=>x, ...],非空时忽略 config 的档位权重
|
||||||
* @return array 可直接用于 DicePlayRecordTest::create 的字段 + tier(用于统计档位概率)
|
* @return array 可直接用于 DicePlayRecordTest::create 的字段 + tier(用于统计档位概率)
|
||||||
*/
|
*/
|
||||||
public function simulateOnePlay($config, int $direction, int $lotteryType = 0, ?array $customTierWeights = null): array
|
public function simulateOnePlay($config, int $direction, int $lotteryType = 0, int $ante = 1, ?array $customTierWeights = null): array
|
||||||
{
|
{
|
||||||
$rewardInstance = DiceReward::getCachedInstance();
|
$rewardInstance = DiceReward::getCachedInstance();
|
||||||
$byTierDirection = $rewardInstance['by_tier_direction'] ?? [];
|
$byTierDirection = $rewardInstance['by_tier_direction'] ?? [];
|
||||||
@@ -558,8 +574,8 @@ class PlayStartLogic
|
|||||||
$targetIndex = (int) ($chosen['end_index'] ?? 0);
|
$targetIndex = (int) ($chosen['end_index'] ?? 0);
|
||||||
$rollNumber = (int) ($chosen['grid_number'] ?? 0);
|
$rollNumber = (int) ($chosen['grid_number'] ?? 0);
|
||||||
$realEv = (float) ($chosen['real_ev'] ?? 0);
|
$realEv = (float) ($chosen['real_ev'] ?? 0);
|
||||||
$isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5';
|
// 玩家始终增加:(100 + real_ev) * ante
|
||||||
$rewardWinCoin = $isTierT5 ? $realEv : (100 + $realEv);
|
$rewardWinCoin = (self::UNIT_COST + $realEv) * $ante;
|
||||||
|
|
||||||
$superWinCoin = 0;
|
$superWinCoin = 0;
|
||||||
$isWin = 0;
|
$isWin = 0;
|
||||||
@@ -588,8 +604,11 @@ class PlayStartLogic
|
|||||||
if ($doSuperWin) {
|
if ($doSuperWin) {
|
||||||
$rollArray = $this->getSuperWinRollArray($rollNumber);
|
$rollArray = $this->getSuperWinRollArray($rollNumber);
|
||||||
$isWin = 1;
|
$isWin = 1;
|
||||||
$superWinCoin = $bigWinRealEv > 0 ? $bigWinRealEv : self::SUPER_WIN_BONUS;
|
$bigWinEv = $bigWinRealEv > 0 ? $bigWinRealEv : self::SUPER_WIN_BONUS;
|
||||||
|
$superWinCoin = (self::UNIT_COST + $bigWinEv) * $ante;
|
||||||
$rewardWinCoin = 0;
|
$rewardWinCoin = 0;
|
||||||
|
// 中豹子时不走原奖励流程
|
||||||
|
$realEv = 0.0;
|
||||||
} else {
|
} else {
|
||||||
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
|
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
|
||||||
}
|
}
|
||||||
@@ -603,6 +622,7 @@ class PlayStartLogic
|
|||||||
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
|
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
|
||||||
$configName = $config !== null ? (string) ($config->name ?? '') : '自定义';
|
$configName = $config !== null ? (string) ($config->name ?? '') : '自定义';
|
||||||
$costRealEv = $realEv + ($isWin === 1 ? $bigWinRealEv : 0.0);
|
$costRealEv = $realEv + ($isWin === 1 ? $bigWinRealEv : 0.0);
|
||||||
|
$paidAmount = $lotteryType === 0 ? ($ante * self::UNIT_COST) : 0;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'player_id' => 0,
|
'player_id' => 0,
|
||||||
@@ -611,9 +631,11 @@ class PlayStartLogic
|
|||||||
'lottery_type' => $lotteryType,
|
'lottery_type' => $lotteryType,
|
||||||
'is_win' => $isWin,
|
'is_win' => $isWin,
|
||||||
'win_coin' => $winCoin,
|
'win_coin' => $winCoin,
|
||||||
|
'ante' => $ante,
|
||||||
|
'paid_amount' => $paidAmount,
|
||||||
'super_win_coin' => $superWinCoin,
|
'super_win_coin' => $superWinCoin,
|
||||||
'reward_win_coin' => $rewardWinCoin,
|
'reward_win_coin' => $rewardWinCoin,
|
||||||
'use_coins' => 0,
|
'use_coins' => $paidAmount,
|
||||||
'direction' => $direction,
|
'direction' => $direction,
|
||||||
'reward_config_id' => $rewardId,
|
'reward_config_id' => $rewardId,
|
||||||
'start_index' => $startIndex,
|
'start_index' => $startIndex,
|
||||||
|
|||||||
@@ -43,18 +43,20 @@ class DicePlayRecordTestController extends BaseController
|
|||||||
['is_win', ''],
|
['is_win', ''],
|
||||||
['win_coin_min', ''],
|
['win_coin_min', ''],
|
||||||
['win_coin_max', ''],
|
['win_coin_max', ''],
|
||||||
|
['paid_amount', ''],
|
||||||
|
['ante', ''],
|
||||||
['reward_tier', ''],
|
['reward_tier', ''],
|
||||||
['roll_number', ''],
|
['roll_number', ''],
|
||||||
]);
|
]);
|
||||||
$query = $this->logic->search($where);
|
$query = $this->logic->search($where);
|
||||||
$query->with(['diceLotteryPoolConfig', 'diceRewardConfig']);
|
$query->with(['diceLotteryPoolConfig', 'diceRewardConfig']);
|
||||||
|
|
||||||
// 按当前筛选条件统计:平台总盈利 = 付费抽奖(lottery_type=0)次数×100 - 玩家总收益(win_coin 求和)
|
// 按当前筛选条件统计:平台总盈利 = 付费金额(paid_amount 求和) - 玩家总收益(win_coin 求和)
|
||||||
$sumQuery = clone $query;
|
$sumQuery = clone $query;
|
||||||
$playerTotalWin = (float) $sumQuery->sum('win_coin');
|
$playerTotalWin = (float) $sumQuery->sum('win_coin');
|
||||||
$paidCountQuery = clone $query;
|
$paidAmountQuery = clone $query;
|
||||||
$paidCount = (int) $paidCountQuery->where('lottery_type', 0)->count();
|
$paidAmount = (float) $paidAmountQuery->where('lottery_type', 0)->sum('paid_amount');
|
||||||
$totalWinCoin = $paidCount * 100 - $playerTotalWin;
|
$totalWinCoin = $paidAmount - $playerTotalWin;
|
||||||
|
|
||||||
$data = $this->logic->getList($query);
|
$data = $this->logic->getList($query);
|
||||||
$data['total_win_coin'] = $totalWinCoin;
|
$data['total_win_coin'] = $totalWinCoin;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class DicePlayerTicketRecordController extends BaseController
|
|||||||
['username', ''],
|
['username', ''],
|
||||||
['use_coins_min', ''],
|
['use_coins_min', ''],
|
||||||
['use_coins_max', ''],
|
['use_coins_max', ''],
|
||||||
|
['ante', ''],
|
||||||
['total_ticket_count_min', ''],
|
['total_ticket_count_min', ''],
|
||||||
['total_ticket_count_max', ''],
|
['total_ticket_count_max', ''],
|
||||||
['paid_ticket_count_min', ''],
|
['paid_ticket_count_min', ''],
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ class DiceRewardController extends BaseController
|
|||||||
{
|
{
|
||||||
$post = is_array($request->post()) ? $request->post() : [];
|
$post = is_array($request->post()) ? $request->post() : [];
|
||||||
$params = [
|
$params = [
|
||||||
|
'ante' => $post['ante'] ?? null,
|
||||||
'lottery_config_id' => $post['lottery_config_id'] ?? null,
|
'lottery_config_id' => $post['lottery_config_id'] ?? null,
|
||||||
'paid_lottery_config_id' => $post['paid_lottery_config_id'] ?? null,
|
'paid_lottery_config_id' => $post['paid_lottery_config_id'] ?? null,
|
||||||
'free_lottery_config_id' => $post['free_lottery_config_id'] ?? null,
|
'free_lottery_config_id' => $post['free_lottery_config_id'] ?? null,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
namespace app\dice\logic\reward_config_record;
|
namespace app\dice\logic\reward_config_record;
|
||||||
|
|
||||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||||
|
use app\dice\model\ante_config\DiceAnteConfig;
|
||||||
use app\dice\model\reward\DiceReward;
|
use app\dice\model\reward\DiceReward;
|
||||||
use app\dice\model\reward\DiceRewardConfig;
|
use app\dice\model\reward\DiceRewardConfig;
|
||||||
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
||||||
@@ -250,6 +251,15 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
|||||||
$adminId = $adminIdOrFreeS !== null && $adminIdOrFreeS !== '' ? (int) $adminIdOrFreeS : null;
|
$adminId = $adminIdOrFreeS !== null && $adminIdOrFreeS !== '' ? (int) $adminIdOrFreeS : null;
|
||||||
}
|
}
|
||||||
$allowed = [100, 500, 1000, 5000];
|
$allowed = [100, 500, 1000, 5000];
|
||||||
|
$ante = isset($params['ante']) ? intval($params['ante']) : 1;
|
||||||
|
if ($ante <= 0) {
|
||||||
|
throw new ApiException('ante must be greater than 0');
|
||||||
|
}
|
||||||
|
$anteExists = DiceAnteConfig::where('mult', $ante)->count();
|
||||||
|
if ($anteExists <= 0) {
|
||||||
|
throw new ApiException('ante not allowed: ' . $ante);
|
||||||
|
}
|
||||||
|
|
||||||
$lotteryConfigId = isset($params['lottery_config_id']) ? (int) $params['lottery_config_id'] : 0;
|
$lotteryConfigId = isset($params['lottery_config_id']) ? (int) $params['lottery_config_id'] : 0;
|
||||||
$paidConfigId = isset($params['paid_lottery_config_id']) ? (int) $params['paid_lottery_config_id'] : 0;
|
$paidConfigId = isset($params['paid_lottery_config_id']) ? (int) $params['paid_lottery_config_id'] : 0;
|
||||||
$freeConfigId = isset($params['free_lottery_config_id']) ? (int) $params['free_lottery_config_id'] : 0;
|
$freeConfigId = isset($params['free_lottery_config_id']) ? (int) $params['free_lottery_config_id'] : 0;
|
||||||
@@ -407,6 +417,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
|||||||
$record->result_counts = [];
|
$record->result_counts = [];
|
||||||
$record->tier_counts = null;
|
$record->tier_counts = null;
|
||||||
$record->bigwin_weight = $bigwinWeights ?: null;
|
$record->bigwin_weight = $bigwinWeights ?: null;
|
||||||
|
$record->ante = $ante;
|
||||||
$record->admin_id = $adminId;
|
$record->admin_id = $adminId;
|
||||||
$record->create_time = date('Y-m-d H:i:s');
|
$record->create_time = date('Y-m-d H:i:s');
|
||||||
$record->save();
|
$record->save();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class WeightTestRunner
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ante = is_numeric($record->ante ?? null) ? intval($record->ante) : 1;
|
||||||
$paidS = (int) ($record->paid_s_count ?? 0);
|
$paidS = (int) ($record->paid_s_count ?? 0);
|
||||||
$paidN = (int) ($record->paid_n_count ?? 0);
|
$paidN = (int) ($record->paid_n_count ?? 0);
|
||||||
$freeS = (int) ($record->free_s_count ?? 0);
|
$freeS = (int) ($record->free_s_count ?? 0);
|
||||||
@@ -60,28 +61,40 @@ class WeightTestRunner
|
|||||||
$safetyLine = (int) ($configType0->safety_line ?? 0);
|
$safetyLine = (int) ($configType0->safety_line ?? 0);
|
||||||
$killEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1;
|
$killEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1;
|
||||||
|
|
||||||
$paidTierWeights = (is_array($record->paid_tier_weights ?? null) && $record->paid_tier_weights !== [])
|
$paidTierWeightsCustom = (is_array($record->paid_tier_weights ?? null) && $record->paid_tier_weights !== [])
|
||||||
? $record->paid_tier_weights
|
? $record->paid_tier_weights
|
||||||
: [
|
: null;
|
||||||
'T1' => (int) ($configType0->t1_weight ?? 0),
|
$freeTierWeightsCustom = (is_array($record->free_tier_weights ?? null) && $record->free_tier_weights !== [])
|
||||||
'T2' => (int) ($configType0->t2_weight ?? 0),
|
? $record->free_tier_weights
|
||||||
'T3' => (int) ($configType0->t3_weight ?? 0),
|
: null;
|
||||||
'T4' => (int) ($configType0->t4_weight ?? 0),
|
|
||||||
'T5' => (int) ($configType0->t5_weight ?? 0),
|
$paidPoolConfigId = (int) ($record->paid_lottery_config_id ?? 0);
|
||||||
];
|
$freePoolConfigId = (int) ($record->free_lottery_config_id ?? 0);
|
||||||
if (array_sum($paidTierWeights) <= 0) {
|
|
||||||
$this->markFailed($recordId, '需提供 paid_tier_weights(玩家权重,盈利未达安全线时付费抽奖使用)或选择 default 奖池');
|
$paidPoolConfig = $paidPoolConfigId > 0 ? DiceLotteryPoolConfig::find($paidPoolConfigId) : $configType0;
|
||||||
return;
|
if (!$paidPoolConfig) {
|
||||||
|
$paidPoolConfig = $configType0;
|
||||||
|
}
|
||||||
|
$freePoolConfig = $freePoolConfigId > 0 ? DiceLotteryPoolConfig::find($freePoolConfigId) : $configType1;
|
||||||
|
if (!$freePoolConfig) {
|
||||||
|
$freePoolConfig = $configType0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$freeConfig = $configType1 !== null ? $configType1 : $configType0;
|
if ($paidTierWeightsCustom !== null && array_sum($paidTierWeightsCustom) <= 0) {
|
||||||
|
$this->markFailed($recordId, 'paid_tier_weights(玩家权重)之和必须大于 0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($freeTierWeightsCustom !== null && array_sum($freeTierWeightsCustom) <= 0) {
|
||||||
|
$this->markFailed($recordId, 'free_tier_weights(免费玩家权重)之和必须大于 0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 每次测试开始前清空进程内静态缓存,强制从共享缓存读取最新 BIGWIN/奖励配置,与数据库一致
|
// 每次测试开始前清空进程内静态缓存,强制从共享缓存读取最新 BIGWIN/奖励配置,与数据库一致
|
||||||
DiceRewardConfig::clearRequestInstance();
|
DiceRewardConfig::clearRequestInstance();
|
||||||
DiceReward::clearRequestInstance();
|
DiceReward::clearRequestInstance();
|
||||||
|
|
||||||
// 彩金池累计盈利:用于判断是否触发杀分(不再依赖单个玩家累计盈利)
|
// 彩金池累计盈利:用于判断是否触发杀分(不再依赖单个玩家累计盈利)
|
||||||
$poolProfitTotal = $configType0->profit_amount ?? 0;
|
$poolProfitTotal = floatval($configType0->profit_amount ?? 0);
|
||||||
|
|
||||||
$playLogic = new PlayStartLogic();
|
$playLogic = new PlayStartLogic();
|
||||||
$resultCounts = [];
|
$resultCounts = [];
|
||||||
@@ -92,9 +105,9 @@ class WeightTestRunner
|
|||||||
try {
|
try {
|
||||||
for ($i = 0; $i < $paidS; $i++) {
|
for ($i = 0; $i < $paidS; $i++) {
|
||||||
$usePoolWeights = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
$usePoolWeights = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
||||||
$paidConfig = $usePoolWeights ? $configType1 : $configType0;
|
$paidConfig = $usePoolWeights ? $configType1 : $paidPoolConfig;
|
||||||
$customWeights = $usePoolWeights ? null : $paidTierWeights;
|
$customWeights = $usePoolWeights ? null : $paidTierWeightsCustom;
|
||||||
$row = $playLogic->simulateOnePlay($paidConfig, 0, 0, $customWeights);
|
$row = $playLogic->simulateOnePlay($paidConfig, 0, 0, $ante, $customWeights);
|
||||||
$this->accumulateProfitForDefault($row, 0, $paidConfig, $configType0, $poolProfitTotal);
|
$this->accumulateProfitForDefault($row, 0, $paidConfig, $configType0, $poolProfitTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
@@ -103,9 +116,9 @@ class WeightTestRunner
|
|||||||
}
|
}
|
||||||
for ($i = 0; $i < $paidN; $i++) {
|
for ($i = 0; $i < $paidN; $i++) {
|
||||||
$usePoolWeights = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
$usePoolWeights = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
||||||
$paidConfig = $usePoolWeights ? $configType1 : $configType0;
|
$paidConfig = $usePoolWeights ? $configType1 : $paidPoolConfig;
|
||||||
$customWeights = $usePoolWeights ? null : $paidTierWeights;
|
$customWeights = $usePoolWeights ? null : $paidTierWeightsCustom;
|
||||||
$row = $playLogic->simulateOnePlay($paidConfig, 1, 0, $customWeights);
|
$row = $playLogic->simulateOnePlay($paidConfig, 1, 0, $ante, $customWeights);
|
||||||
$this->accumulateProfitForDefault($row, 0, $paidConfig, $configType0, $poolProfitTotal);
|
$this->accumulateProfitForDefault($row, 0, $paidConfig, $configType0, $poolProfitTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
@@ -113,7 +126,10 @@ class WeightTestRunner
|
|||||||
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $freeS; $i++) {
|
for ($i = 0; $i < $freeS; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($freeConfig, 0, 1, null);
|
$useKillMode = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
||||||
|
$freeConfig = $useKillMode ? $configType1 : $freePoolConfig;
|
||||||
|
$customWeights = $useKillMode ? null : $freeTierWeightsCustom;
|
||||||
|
$row = $playLogic->simulateOnePlay($freeConfig, 0, 1, $ante, $customWeights);
|
||||||
$this->accumulateProfitForDefault($row, 1, $freeConfig, $configType0, $poolProfitTotal);
|
$this->accumulateProfitForDefault($row, 1, $freeConfig, $configType0, $poolProfitTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
@@ -121,7 +137,10 @@ class WeightTestRunner
|
|||||||
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $freeN; $i++) {
|
for ($i = 0; $i < $freeN; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($freeConfig, 1, 1, null);
|
$useKillMode = $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null;
|
||||||
|
$freeConfig = $useKillMode ? $configType1 : $freePoolConfig;
|
||||||
|
$customWeights = $useKillMode ? null : $freeTierWeightsCustom;
|
||||||
|
$row = $playLogic->simulateOnePlay($freeConfig, 1, 1, $ante, $customWeights);
|
||||||
$this->accumulateProfitForDefault($row, 1, $freeConfig, $configType0, $poolProfitTotal);
|
$this->accumulateProfitForDefault($row, 1, $freeConfig, $configType0, $poolProfitTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
@@ -153,7 +172,8 @@ class WeightTestRunner
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$winCoin = (float) $row['win_coin'];
|
$winCoin = (float) $row['win_coin'];
|
||||||
$playerProfitTotal += $lotteryType === 0 ? ($winCoin - 100.0) : $winCoin;
|
$paidAmount = (float) ($row['paid_amount'] ?? 0);
|
||||||
|
$playerProfitTotal += $lotteryType === 0 ? ($winCoin - $paidAmount) : $winCoin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
|
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
|
||||||
@@ -176,6 +196,7 @@ class WeightTestRunner
|
|||||||
$keys = [
|
$keys = [
|
||||||
'player_id', 'admin_id', 'lottery_config_id', 'lottery_type', 'is_win', 'win_coin',
|
'player_id', 'admin_id', 'lottery_config_id', 'lottery_type', 'is_win', 'win_coin',
|
||||||
'super_win_coin', 'reward_win_coin', 'use_coins', 'direction', 'reward_config_id',
|
'super_win_coin', 'reward_win_coin', 'use_coins', 'direction', 'reward_config_id',
|
||||||
|
'ante', 'paid_amount',
|
||||||
'start_index', 'target_index', 'roll_array', 'roll_number', 'lottery_name', 'status',
|
'start_index', 'target_index', 'roll_array', 'roll_number', 'lottery_name', 'status',
|
||||||
];
|
];
|
||||||
foreach ($keys as $k) {
|
foreach ($keys as $k) {
|
||||||
@@ -219,7 +240,7 @@ class WeightTestRunner
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记测试成功并记录平台总盈利 platform_profit
|
* 标记测试成功并记录平台总盈利 platform_profit
|
||||||
* 通过关联 DicePlayRecordTest(reward_config_record_id)统计:付费(lottery_type=0)次数×100 - win_coin 求和
|
* 通过关联 DicePlayRecordTest(reward_config_record_id)统计:付费金额 paid_amount 求和 - win_coin 求和
|
||||||
*/
|
*/
|
||||||
private function markSuccess(int $recordId, array $resultCounts, array $tierCounts): void
|
private function markSuccess(int $recordId, array $resultCounts, array $tierCounts): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ use think\model\relation\BelongsTo;
|
|||||||
*
|
*
|
||||||
* @property $id ID
|
* @property $id ID
|
||||||
* @property $lottery_config_id 彩金池配置id
|
* @property $lottery_config_id 彩金池配置id
|
||||||
* @property $lottery_type 抽奖类型:0=付费,1=赠送
|
* @property $lottery_type 抽奖类型:0=付费,1=免费
|
||||||
* @property $is_win 中大奖:0=无,1=中奖
|
* @property $is_win 中大奖:0=无,1=中奖
|
||||||
* @property $win_coin 赢取平台币
|
* @property $win_coin 赢取平台币
|
||||||
|
* @property int|null $ante 底注/注数(dice_ante_config.mult)
|
||||||
|
* @property int|null $paid_amount 付费金额(付费局=ante*100,免费局=0)
|
||||||
* @property $direction 方向:0=顺时针,1=逆时针
|
* @property $direction 方向:0=顺时针,1=逆时针
|
||||||
* @property $reward_config_id 奖励配置id
|
* @property $reward_config_id 奖励配置id
|
||||||
* @property $create_time 创建时间
|
* @property $create_time 创建时间
|
||||||
@@ -77,7 +79,7 @@ class DicePlayRecordTest extends BaseModel
|
|||||||
return $this->belongsTo(DiceRewardConfigRecord::class, 'reward_config_record_id', 'id');
|
return $this->belongsTo(DiceRewardConfigRecord::class, 'reward_config_record_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 抽奖类型 0=付费 1=赠送 */
|
/** 抽奖类型 0=付费 1=免费 */
|
||||||
public function searchLotteryTypeAttr($query, $value)
|
public function searchLotteryTypeAttr($query, $value)
|
||||||
{
|
{
|
||||||
if ($value !== '' && $value !== null) {
|
if ($value !== '' && $value !== null) {
|
||||||
@@ -117,6 +119,22 @@ class DicePlayRecordTest extends BaseModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 付费金额(付费局=ante*100,免费局=0) */
|
||||||
|
public function searchPaidAmountAttr($query, $value)
|
||||||
|
{
|
||||||
|
if ($value !== '' && $value !== null) {
|
||||||
|
$query->where('paid_amount', '=', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 底注/注数(dice_ante_config.mult) */
|
||||||
|
public function searchAnteAttr($query, $value)
|
||||||
|
{
|
||||||
|
if ($value !== '' && $value !== null) {
|
||||||
|
$query->where('ante', '=', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 中奖档位(按 reward_config_id 对应 DiceRewardConfig.tier) */
|
/** 中奖档位(按 reward_config_id 对应 DiceRewardConfig.tier) */
|
||||||
public function searchRewardTierAttr($query, $value)
|
public function searchRewardTierAttr($query, $value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -144,4 +144,12 @@ class DicePlayerTicketRecord extends BaseModel
|
|||||||
$query->where('create_time', '<=', $value);
|
$query->where('create_time', '<=', $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 底注/注数(ante) */
|
||||||
|
public function searchAnteAttr($query, $value)
|
||||||
|
{
|
||||||
|
if ($value !== '' && $value !== null) {
|
||||||
|
$query->where('ante', '=', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use think\model\relation\HasMany;
|
|||||||
* @property int $over_play_count 已完成次数
|
* @property int $over_play_count 已完成次数
|
||||||
* @property int $status 状态 -1失败 0进行中 1成功
|
* @property int $status 状态 -1失败 0进行中 1成功
|
||||||
* @property string|null $remark 失败时记录原因
|
* @property string|null $remark 失败时记录原因
|
||||||
|
* @property int|null $ante 底注/注数(dice_ante_config.mult)
|
||||||
* @property int $s_count 顺时针模拟次数(兼容旧数据)
|
* @property int $s_count 顺时针模拟次数(兼容旧数据)
|
||||||
* @property int $n_count 逆时针模拟次数(兼容旧数据)
|
* @property int $n_count 逆时针模拟次数(兼容旧数据)
|
||||||
* @property int $paid_s_count 付费抽奖顺时针次数
|
* @property int $paid_s_count 付费抽奖顺时针次数
|
||||||
@@ -70,18 +71,18 @@ class DiceRewardConfigRecord extends BaseModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据关联的 DicePlayRecordTest 统计平台赚取平台币
|
* 根据关联的 DicePlayRecordTest 统计平台赚取平台币
|
||||||
* platform_profit = 关联的付费(lottery_type=0)抽取次数 × 100 - 关联的 win_coin 求和
|
* platform_profit = 关联的付费(lottery_type=0)付费金额求和(paid_amount) - 关联的 win_coin 求和
|
||||||
* @param int $recordId dice_reward_config_record.id
|
* @param int $recordId dice_reward_config_record.id
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public static function computePlatformProfitFromRelated(int $recordId): float
|
public static function computePlatformProfitFromRelated(int $recordId): float
|
||||||
{
|
{
|
||||||
$paidCount = DicePlayRecordTest::where('reward_config_record_id', $recordId)
|
$paidAmount = (float) DicePlayRecordTest::where('reward_config_record_id', $recordId)
|
||||||
->where('lottery_type', 0)
|
->where('lottery_type', 0)
|
||||||
->count();
|
->sum('paid_amount');
|
||||||
$sumWinCoin = (float) DicePlayRecordTest::where('reward_config_record_id', $recordId)
|
$sumWinCoin = (float) DicePlayRecordTest::where('reward_config_record_id', $recordId)
|
||||||
->sum('win_coin');
|
->sum('win_coin');
|
||||||
return round($paidCount * 100 - $sumWinCoin, 2);
|
return round($paidAmount - $sumWinCoin, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DicePlayRecordTestValidate extends BaseValidate
|
|||||||
*/
|
*/
|
||||||
protected $message = [
|
protected $message = [
|
||||||
'lottery_config_id' => '彩金池配置id必须填写',
|
'lottery_config_id' => '彩金池配置id必须填写',
|
||||||
'lottery_type' => '抽奖类型:0=付费,1=赠送必须填写',
|
'lottery_type' => '抽奖类型:0=付费,1=免费必须填写',
|
||||||
'is_win' => '中大奖:0=无,1=中奖必须填写',
|
'is_win' => '中大奖:0=无,1=中奖必须填写',
|
||||||
'direction' => '方向:0=顺时针,1=逆时针必须填写',
|
'direction' => '方向:0=顺时针,1=逆时针必须填写',
|
||||||
'reward_config_id' => '奖励配置id必须填写',
|
'reward_config_id' => '奖励配置id必须填写',
|
||||||
|
|||||||
Reference in New Issue
Block a user