88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import {
|
|
LEGACY_RANK_DATA_TYPES,
|
|
RANK_DATA_TYPES,
|
|
rankDataMetaKey,
|
|
type LegacyRankDataType,
|
|
type RankDataType,
|
|
} from '@sammo-ts/common';
|
|
|
|
export interface RankedGeneralState {
|
|
id: number;
|
|
nationId: number;
|
|
experience: number;
|
|
dedication: number;
|
|
meta: unknown;
|
|
}
|
|
|
|
export interface PersistedRankRow {
|
|
generalId: number;
|
|
nationId: number;
|
|
type: RankDataType;
|
|
value: number;
|
|
}
|
|
|
|
const asRecord = (value: unknown): Record<string, unknown> =>
|
|
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
? { ...(value as Record<string, unknown>) }
|
|
: {};
|
|
const toLegacyDatabaseInt = (value: number): number => {
|
|
if (!Number.isFinite(value)) {
|
|
return 0;
|
|
}
|
|
return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
|
|
};
|
|
|
|
const readMetaNumber = (meta: Record<string, unknown>, key: string): number => {
|
|
const value = meta[key];
|
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
return toLegacyDatabaseInt(value);
|
|
}
|
|
if (typeof value === 'string') {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? toLegacyDatabaseInt(parsed) : 0;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
export const rankMetaKey = rankDataMetaKey;
|
|
|
|
export const buildPersistedRankRows = (general: RankedGeneralState): PersistedRankRow[] => {
|
|
const meta = asRecord(general.meta);
|
|
return RANK_DATA_TYPES.map((type) => {
|
|
const value =
|
|
type === 'experience'
|
|
? toLegacyDatabaseInt(general.experience)
|
|
: type === 'dedication'
|
|
? toLegacyDatabaseInt(general.dedication)
|
|
: readMetaNumber(meta, rankMetaKey(type));
|
|
return {
|
|
generalId: general.id,
|
|
nationId: general.nationId,
|
|
type,
|
|
value,
|
|
};
|
|
});
|
|
};
|
|
|
|
export const buildLegacyComparableRankRows = (
|
|
general: RankedGeneralState
|
|
): Array<PersistedRankRow & { type: LegacyRankDataType }> => {
|
|
const legacyTypes = new Set<RankDataType>(LEGACY_RANK_DATA_TYPES);
|
|
return buildPersistedRankRows(general).filter(
|
|
(row): row is PersistedRankRow & { type: LegacyRankDataType } => legacyTypes.has(row.type)
|
|
);
|
|
};
|
|
|
|
export const applyPersistedRankRowsToMeta = (
|
|
rawMeta: Record<string, unknown>,
|
|
rows: ReadonlyArray<{ type: string; value: number }>
|
|
): void => {
|
|
const supportedTypes = new Set<string>(RANK_DATA_TYPES);
|
|
for (const row of rows) {
|
|
if (row.type === 'experience' || row.type === 'dedication' || !supportedTypes.has(row.type)) {
|
|
continue;
|
|
}
|
|
rawMeta[rankMetaKey(row.type as RankDataType)] = row.value;
|
|
}
|
|
};
|