118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
/** 档位权重固定键(与 GameConfig / GameUser JSON 一致) */
|
||
export const TIER_WEIGHT_KEYS = ['T1', 'T2', 'T3', 'T4', 'T5'] as const
|
||
|
||
/** 中大奖权重固定键 */
|
||
export const BIGWIN_WEIGHT_KEYS = ['5', '10', '15', '20', '25', '30'] as const
|
||
|
||
/** 默认大奖权重:点数 5、30 为豹子号必中,权重固定 10000 */
|
||
export function isBigwinDiceLockedKey(key: string): boolean {
|
||
return key === '5' || key === '30'
|
||
}
|
||
|
||
export type WeightRow = { key: string; val: string }
|
||
|
||
export function weightArrayToMap(arr: unknown): Record<string, string> {
|
||
const map: Record<string, string> = {}
|
||
if (!Array.isArray(arr)) {
|
||
return map
|
||
}
|
||
for (const item of arr) {
|
||
if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
|
||
for (const [k, v] of Object.entries(item)) {
|
||
map[k] = v === null || v === undefined ? '' : String(v)
|
||
}
|
||
}
|
||
}
|
||
return map
|
||
}
|
||
|
||
/** 解析 game_weight JSON 为键值映射(键为 T1 / 5 等) */
|
||
export function parseWeightJsonToMap(raw: unknown): Record<string, string> {
|
||
if (raw === null || raw === undefined || raw === '') {
|
||
return {}
|
||
}
|
||
if (typeof raw === 'string') {
|
||
const s = raw.trim()
|
||
if (!s || s === '[]') {
|
||
return {}
|
||
}
|
||
try {
|
||
const parsed = JSON.parse(s)
|
||
return weightArrayToMap(parsed)
|
||
} catch {
|
||
return {}
|
||
}
|
||
}
|
||
if (Array.isArray(raw)) {
|
||
return weightArrayToMap(raw)
|
||
}
|
||
return {}
|
||
}
|
||
|
||
export function fixedRowsFromKeys(keys: readonly string[], map: Record<string, string>): WeightRow[] {
|
||
const rows: WeightRow[] = []
|
||
for (const k of keys) {
|
||
rows.push({ key: k, val: map[k] ?? '' })
|
||
}
|
||
return rows
|
||
}
|
||
|
||
export function rowsToMap(rows: WeightRow[]): Record<string, string> {
|
||
const m: Record<string, string> = {}
|
||
for (const r of rows) {
|
||
m[r.key] = r.val
|
||
}
|
||
return m
|
||
}
|
||
|
||
export function jsonStringFromFixedKeys(keys: readonly string[], map: Record<string, string>): string {
|
||
const pairs: Record<string, string>[] = []
|
||
for (const k of keys) {
|
||
const one: Record<string, string> = {}
|
||
one[k] = map[k] ?? ''
|
||
pairs.push(one)
|
||
}
|
||
return JSON.stringify(pairs)
|
||
}
|
||
|
||
/**
|
||
* 统一配置标识:trim、去掉「 (说明)」「(说明)」「(说明)」等后缀、小写,避免下拉/接口返回不一致导致走错位校验(如误报每项≤10000)
|
||
*/
|
||
export function normalizeGameWeightConfigName(name: string | undefined): string {
|
||
if (name === undefined || name === null) {
|
||
return ''
|
||
}
|
||
let s = String(name).trim()
|
||
// 截到第一个半角/全角左括号之前(兼容 "key (说明)"、"key(说明)"、"key(说明)"、无前导空格)
|
||
const m = s.match(/^([^((]+)/u)
|
||
if (m) {
|
||
s = m[1].trim()
|
||
}
|
||
return s.toLowerCase()
|
||
}
|
||
|
||
/** 当前行是否为大奖骰子键 5~30(与 BIGWIN_WEIGHT_KEYS 一致) */
|
||
export function weightRowsMatchBigwinDiceKeys(rows: { key: string }[]): boolean {
|
||
const keys = rows
|
||
.map((r) => r.key.trim())
|
||
.filter((k) => k !== '')
|
||
.sort((a, b) => Number(a) - Number(b))
|
||
if (keys.length !== BIGWIN_WEIGHT_KEYS.length) {
|
||
return false
|
||
}
|
||
return BIGWIN_WEIGHT_KEYS.every((k, i) => keys[i] === k)
|
||
}
|
||
|
||
/** GameConfig 中按 name 判断是否使用固定键编辑 */
|
||
export function getFixedKeysForGameConfigName(name: string | undefined): readonly string[] | null {
|
||
const n = normalizeGameWeightConfigName(name)
|
||
/** 击杀分权重与档位权重同为 T1~T5;库中 JSON 为 [{"T1":"0"},...],非骰子点 5~30 */
|
||
if (n === 'default_tier_weight' || n === 'default_kill_score_weight') {
|
||
return TIER_WEIGHT_KEYS
|
||
}
|
||
if (n === 'default_bigwin_weight') {
|
||
return BIGWIN_WEIGHT_KEYS
|
||
}
|
||
return null
|
||
}
|