mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-06 13:19:31 -05:00
159 lines
3.9 KiB
TypeScript
159 lines
3.9 KiB
TypeScript
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
|
import {
|
|
weaponCategories,
|
|
weaponIdToBaseWeaponId,
|
|
weaponIdToType,
|
|
} from "~/modules/in-game-lists/weapon-ids";
|
|
import type {
|
|
ParamDefinition,
|
|
ParamValueWithHistory,
|
|
ParsedWeaponParams,
|
|
} from "../weapon-params-types";
|
|
|
|
export function parseParamKey(key: string): {
|
|
baseKey: string;
|
|
version: string | null;
|
|
} {
|
|
const atIndex = key.indexOf("@");
|
|
if (atIndex === -1) {
|
|
return { baseKey: key, version: null };
|
|
}
|
|
return {
|
|
baseKey: key.slice(0, atIndex),
|
|
version: key.slice(atIndex + 1),
|
|
};
|
|
}
|
|
|
|
export function parseWeaponParams(
|
|
weaponId: MainWeaponId,
|
|
rawParams: Record<string, Record<string, unknown>>,
|
|
versions: string[],
|
|
): ParsedWeaponParams {
|
|
const categories: Record<string, Record<string, ParamValueWithHistory>> = {};
|
|
|
|
for (const [categoryName, categoryParams] of Object.entries(rawParams)) {
|
|
if (
|
|
typeof categoryParams !== "object" ||
|
|
categoryParams === null ||
|
|
Object.keys(categoryParams).length === 0
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const parsedParams: Record<string, ParamValueWithHistory> = {};
|
|
const paramHistory: Record<
|
|
string,
|
|
{ current: number | string; versions: Map<string, number | string> }
|
|
> = {};
|
|
|
|
for (const [key, value] of Object.entries(categoryParams)) {
|
|
if (typeof value !== "number" && typeof value !== "string") {
|
|
continue;
|
|
}
|
|
|
|
const { baseKey, version } = parseParamKey(key);
|
|
|
|
if (!paramHistory[baseKey]) {
|
|
paramHistory[baseKey] = {
|
|
current: value,
|
|
versions: new Map(),
|
|
};
|
|
}
|
|
|
|
if (version === null) {
|
|
paramHistory[baseKey].current = value;
|
|
} else {
|
|
paramHistory[baseKey].versions.set(version, value);
|
|
}
|
|
}
|
|
|
|
for (const [baseKey, data] of Object.entries(paramHistory)) {
|
|
const history: Array<{ version: string; value: number | string }> = [];
|
|
|
|
for (const version of versions) {
|
|
const historicalValue = data.versions.get(version);
|
|
if (historicalValue !== undefined) {
|
|
history.push({ version, value: historicalValue });
|
|
}
|
|
}
|
|
|
|
parsedParams[baseKey] = {
|
|
current: data.current,
|
|
history,
|
|
};
|
|
}
|
|
|
|
if (Object.keys(parsedParams).length > 0) {
|
|
categories[categoryName] = parsedParams;
|
|
}
|
|
}
|
|
|
|
return { weaponId, categories };
|
|
}
|
|
|
|
export function collectAllParamKeys(
|
|
weaponParams: Record<string, ParsedWeaponParams>,
|
|
): ParamDefinition[] {
|
|
const seenKeys = new Set<string>();
|
|
const definitions: ParamDefinition[] = [];
|
|
|
|
for (const parsed of Object.values(weaponParams)) {
|
|
for (const [category, params] of Object.entries(parsed.categories)) {
|
|
for (const key of Object.keys(params)) {
|
|
const fullKey = `${category}.${key}`;
|
|
if (!seenKeys.has(fullKey)) {
|
|
seenKeys.add(fullKey);
|
|
definitions.push({ category, key, fullKey });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
definitions.sort((a, b) => {
|
|
if (a.category !== b.category) {
|
|
return a.category.localeCompare(b.category);
|
|
}
|
|
return a.key.localeCompare(b.key);
|
|
});
|
|
|
|
return definitions;
|
|
}
|
|
|
|
export function getWeaponCategory(weaponId: MainWeaponId) {
|
|
return weaponCategories.find((cat) =>
|
|
(cat.weaponIds as readonly number[]).includes(weaponId),
|
|
);
|
|
}
|
|
|
|
export function getCategoryWeaponIds(weaponId: MainWeaponId): MainWeaponId[] {
|
|
const category = getWeaponCategory(weaponId);
|
|
if (!category) {
|
|
return [weaponId];
|
|
}
|
|
|
|
const baseWeapons = (category.weaponIds as readonly MainWeaponId[]).filter(
|
|
(id) => weaponIdToType(id) === "BASE",
|
|
);
|
|
|
|
if (baseWeapons.includes(weaponId)) {
|
|
return baseWeapons;
|
|
}
|
|
|
|
const currentWeaponBaseId = weaponIdToBaseWeaponId(weaponId);
|
|
return [weaponId, ...baseWeapons.filter((id) => id !== currentWeaponBaseId)];
|
|
}
|
|
|
|
export function hasParamHistory(param: ParamValueWithHistory): boolean {
|
|
return param.history.length > 0;
|
|
}
|
|
|
|
export function formatParamValue(value: number | string): string {
|
|
if (typeof value === "number") {
|
|
if (Number.isInteger(value)) {
|
|
return String(value);
|
|
}
|
|
return value.toFixed(4).replace(/\.?0+$/, "");
|
|
}
|
|
return String(value);
|
|
}
|