优化中奖权重计算方式

This commit is contained in:
2026-03-12 17:17:00 +08:00
parent 064ce06393
commit 7e4ba86afa
25 changed files with 2344 additions and 403 deletions

View File

@@ -0,0 +1,139 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
namespace app\dice\model\reward;
use plugin\saiadmin\basic\think\BaseModel;
use support\think\Cache;
/**
* 奖励对照模型
*
* dice_reward 奖励对照表(主键 id 自增)
* 唯一约束 (direction, grid_number)保证每个点数、每个方向各一条end_index 关联 DiceRewardConfig.id
*
* @property $id 主键
* @property $tier 档位 T1-T5/BIGWIN
* @property $direction 方向:0=顺时针,1=逆时针
* @property $end_index 结束索引DiceRewardConfig.id
* @property $weight 权重 1-10000档位内按权重比抽取
* @property $grid_number 色子点数(摇取值)
* @property $start_index 起始索引(DiceRewardConfig.id)
* @property $ui_text 显示文本(来自config)
* @property $real_ev 实际中奖金额(来自config)
* @property $remark 备注(来自config)
* @property $type 奖励类型(来自config)
*/
class DiceReward extends BaseModel
{
/** 方向:顺时针 */
public const DIRECTION_CLOCKWISE = 0;
/** 方向:逆时针 */
public const DIRECTION_COUNTERCLOCKWISE = 1;
/** 缓存键:奖励对照实例 */
private const CACHE_KEY_INSTANCE = 'dice:reward:instance';
private const CACHE_TTL = 86400 * 30;
private static ?array $instance = null;
protected $table = 'dice_reward';
/** 主键 id 自增,唯一约束 (direction, grid_number) */
protected $pk = 'id';
/**
* 获取奖励对照实例(按档位+方向索引,用于抽奖与权重配比)
* @return array{list: array, by_tier_direction: array}
*/
public static function getCachedInstance(): array
{
if (self::$instance !== null) {
return self::$instance;
}
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
if ($instance !== null && is_array($instance)) {
self::$instance = $instance;
return $instance;
}
self::refreshCache();
$instance = Cache::get(self::CACHE_KEY_INSTANCE);
self::$instance = is_array($instance) ? $instance : self::buildEmptyInstance();
return self::$instance;
}
/**
* 按档位+方向取权重列表(用于抽奖:该档位该方向下 end_index => weight
* @return array<int, int> end_index => weight
*/
public static function getCachedByTierAndDirection(string $tier, int $direction): array
{
$inst = self::getCachedInstance();
$byTierDirection = $inst['by_tier_direction'] ?? [];
$list = $byTierDirection[$tier][$direction] ?? [];
$result = [];
foreach ($list as $row) {
$endIndex = isset($row['end_index']) ? (int) $row['end_index'] : 0;
$weight = isset($row['weight']) ? (int) $row['weight'] : 1;
$result[$endIndex] = $weight;
}
return $result;
}
/**
* 重新从数据库加载并写入缓存;修改/新增/删除后需调用以实例化
*/
public static function refreshCache(): void
{
$list = (new self())->order('tier')->order('direction')->order('end_index')->select()->toArray();
$byTierDirection = [];
foreach ($list as $row) {
$tier = isset($row['tier']) ? (string) $row['tier'] : '';
$direction = isset($row['direction']) ? (int) $row['direction'] : 0;
if ($tier !== '') {
if (!isset($byTierDirection[$tier])) {
$byTierDirection[$tier] = [0 => [], 1 => []];
}
if (!isset($byTierDirection[$tier][$direction])) {
$byTierDirection[$tier][$direction] = [];
}
$byTierDirection[$tier][$direction][] = $row;
}
}
self::$instance = [
'list' => $list,
'by_tier_direction' => $byTierDirection,
];
Cache::set(self::CACHE_KEY_INSTANCE, self::$instance, self::CACHE_TTL);
}
private static function buildEmptyInstance(): array
{
return [
'list' => [],
'by_tier_direction' => [],
];
}
public static function clearRequestInstance(): void
{
self::$instance = null;
}
public static function onAfterInsert($model): void
{
self::refreshCache();
}
public static function onAfterUpdate($model): void
{
self::refreshCache();
}
public static function onAfterDelete($model): void
{
self::refreshCache();
}
}