Files
webman-buildadmin/app/common/library/GameRewardWeightSeeder.php

173 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\common\library;
use support\think\Db;
use Throwable;
/**
* 根据档位奖励 JSON 生成 game_reward_weight 对照(先删后插)
*/
final class GameRewardWeightSeeder
{
private const LEOPARD = [5, 10, 15, 20, 25, 30];
/**
* @throws Throwable
*/
public static function syncFromTierRewardForm(int $gameChannelId, string $tierRewardFormJson): void
{
$decoded = json_decode($tierRewardFormJson, true);
if (!is_array($decoded) || count($decoded) !== 26) {
throw new \RuntimeException('档位奖励表单必须为 26 条且为合法 JSON');
}
$byGrid = [];
foreach ($decoded as $idx => $row) {
if (!is_array($row)) {
throw new \RuntimeException('档位奖励表单第' . strval($idx + 1) . '条格式错误');
}
$g = $row['grid_number'] ?? null;
if (!is_numeric($g)) {
throw new \RuntimeException('档位奖励表单第' . strval($idx + 1) . '条点数无效');
}
$gi = intval(strval($g));
if ($gi < 5 || $gi > 30) {
throw new \RuntimeException('档位奖励表单点数须在 530');
}
$byGrid[$gi] = $row;
}
$cells = [];
for ($i = 0; $i < 26; $i++) {
$g = 5 + $i;
if (!isset($byGrid[$g])) {
throw new \RuntimeException('档位奖励表单缺少点数 ' . strval($g));
}
$cells[$i] = self::normalizeCell($byGrid[$g], $i + 1);
}
self::assertLeopardOk($cells);
$batch = [];
for ($d = 5; $d <= 30; $d++) {
$start = $d - 5;
$endCw = ($start + $d) % 26;
$x = $start - $d;
$endCcw = $x >= 0 ? $x : 26 + $start - $d;
$batch[] = self::buildInsertRow($gameChannelId, 0, $d, $start, $endCw, $cells[$endCw]);
$batch[] = self::buildInsertRow($gameChannelId, 1, $d, $start, $endCcw, $cells[$endCcw]);
}
$now = time();
foreach ($batch as $k => $_) {
$batch[$k]['create_time'] = $now;
$batch[$k]['update_time'] = $now;
}
Db::startTrans();
try {
Db::name('game_reward_weight')->where('game_channel_id', $gameChannelId)->delete();
Db::name('game_reward_weight')->insertAll($batch);
Db::commit();
} catch (Throwable $e) {
Db::rollback();
$msg = $e->getMessage();
if (str_contains($msg, 'game_reward_weight') || str_contains($msg, "doesn't exist")) {
throw new \RuntimeException('写入失败:请确认已创建数据表 game_reward_weight 并已执行迁移。' . $msg);
}
throw $e;
}
}
/**
* @param list<array{ui_text: string, real_ev: float, tier: string, remark: string}> $cells
*/
private static function assertLeopardOk(array $cells): void
{
foreach (self::LEOPARD as $d) {
$start = $d - 5;
$endCw = ($start + $d) % 26;
$x = $start - $d;
$endCcw = $x >= 0 ? $x : 26 + $start - $d;
foreach ([$endCw, $endCcw] as $idx) {
$t = $cells[$idx]['tier'];
if ($t === 'T4' || $t === 'T5') {
throw new \RuntimeException(
'豹子点数 ' . strval($d) . ' 的落点不能为 T4/T5请先在档位表中调整后再生成权重对照'
);
}
}
}
}
/**
* @param array<string, mixed> $row
* @return array{ui_text: string, real_ev: float, tier: string, remark: string}
*/
private static function normalizeCell(array $row, int $rowNo): array
{
$ui = $row['ui_text'] ?? null;
$ev = $row['real_ev'] ?? null;
$tier = $row['tier'] ?? null;
if (!is_string($ui) || trim($ui) === '') {
throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条显示文本不能为空');
}
if ($ev === null || $ev === '' || !is_numeric($ev)) {
throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条实际中奖无效');
}
if (!is_string($tier) || !in_array($tier, ['T1', 'T2', 'T3', 'T4', 'T5'], true)) {
throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条档位无效');
}
$remark = $row['remark'] ?? '';
$remarkStr = is_string($remark) ? $remark : '';
return [
'ui_text' => $ui,
'real_ev' => floatval(strval($ev)),
'tier' => $tier,
'remark' => $remarkStr,
];
}
/**
* @param array{ui_text: string, real_ev: float, tier: string, remark: string} $cell
* @return array<string, int|float|string>
*/
private static function buildInsertRow(
int $gameChannelId,
int $direction,
int $gridNumber,
int $startIndex,
int $endIndex,
array $cell
): array {
return [
'game_channel_id' => $gameChannelId,
'direction' => $direction,
'grid_number' => $gridNumber,
'start_index' => $startIndex,
'end_index' => $endIndex,
'ui_text' => $cell['ui_text'],
'real_ev' => $cell['real_ev'],
'tier' => $cell['tier'],
'type' => self::tierToType($cell['tier']),
'remark' => $cell['remark'],
'weight' => 1,
];
}
private static function tierToType(string $tier): int
{
return match ($tier) {
'T1' => 3,
'T2' => 2,
'T3' => -1,
'T4' => -2,
'T5' => 1,
};
}
}