Files
shoot-miniprograms/src/utils/matchAdapter.js
T

122 lines
3.9 KiB
JavaScript

// 比赛数据适配器:统一接口返回和比赛服 websocket 的字段结构。
// 页面继续使用原来的 camelCase 数据,后端可以返回 snake_case 或新的 matchInfo 包装结构。
export const MATCH_STATUS_BY_TEXT = {
MATCH_STATUS_READY: 0,
MATCH_STATUS_STARTED: 1,
MATCH_STATUS_END: 2,
MATCH_STATUS_TIMEOUT: 3,
MATCH_STATUS_UNEXPECTEDLY: 4,
};
export function pickField(source, camelKey, snakeKey) {
return source?.[camelKey] ?? source?.[snakeKey];
}
export function normalizeId(value) {
if (value === undefined || value === null || value === "") return "";
return String(value);
}
function toCamelKey(key) {
return key.replace(/_([a-z0-9])/g, (_, character) => character.toUpperCase());
}
export function normalizePlainObject(value) {
if (Array.isArray(value)) return value.map(normalizePlainObject);
if (!value || typeof value !== "object") return value;
return Object.keys(value).reduce((result, key) => {
result[toCamelKey(key)] = normalizePlainObject(value[key]);
return result;
}, {});
}
function normalizeMapValues(map = {}) {
return Object.keys(map || {}).reduce((result, key) => {
result[key] = normalizePlainObject(map[key]);
return result;
}, {});
}
function normalizeShootListMap(map = {}) {
return Object.keys(map || {}).reduce((result, key) => {
const value = map[key];
const items = Array.isArray(value)
? value
: Array.isArray(value?.items)
? value.items
: [];
result[key] = items.map(normalizePlainObject);
return result;
}, {});
}
function normalizeRound(round = {}) {
const normalized = normalizePlainObject(round);
normalized.shoots = normalizeShootListMap(round.shoots || normalized.shoots);
normalized.scores = normalizeMapValues(round.scores || normalized.scores);
return normalized;
}
export function normalizeMatchInfo(matchInfo = {}) {
if (!matchInfo || typeof matchInfo !== "object") return matchInfo;
const normalized = normalizePlainObject(matchInfo);
const statusText = normalized.statusText || matchInfo.status_text;
if (
(normalized.status === undefined ||
normalized.status === null ||
normalized.status === "") &&
MATCH_STATUS_BY_TEXT[statusText] !== undefined
) {
normalized.status = MATCH_STATUS_BY_TEXT[statusText];
}
if (matchInfo.teams || normalized.teams) {
normalized.teams = normalizeMapValues(matchInfo.teams || normalized.teams);
}
if (Array.isArray(matchInfo.rounds || normalized.rounds)) {
normalized.rounds = (matchInfo.rounds || normalized.rounds).map(normalizeRound);
}
if (matchInfo.current || normalized.current) {
normalized.current = normalizePlainObject(matchInfo.current || normalized.current);
}
if (matchInfo.next || normalized.next) {
normalized.next = normalizePlainObject(matchInfo.next || normalized.next);
}
if (matchInfo.shoot_data || normalized.shootData) {
normalized.shootData = normalizePlainObject(matchInfo.shoot_data || normalized.shootData);
}
if (Array.isArray(matchInfo.result_list || normalized.resultList)) {
normalized.resultList = (matchInfo.result_list || normalized.resultList).map(
normalizePlainObject
);
}
return normalized;
}
export function normalizeBattleApiResult(result) {
if (!result || typeof result !== "object") return result;
// request 通常已经解出顶层 data;这里额外兼容未解包和旧版扁平结构。
const resultData = result.data && typeof result.data === "object" ? result.data : null;
const payload =
resultData && (resultData.matchInfo || resultData.match_info)
? resultData
: result;
const matchInfo = payload.matchInfo || payload.match_info || payload;
const normalized = normalizeMatchInfo(matchInfo);
const serverAddr =
payload.serverAddr ||
payload.server_addr ||
matchInfo.serverAddr ||
matchInfo.server_addr ||
normalized.serverAddr;
if (serverAddr) normalized.serverAddr = serverAddr;
return normalized;
}