sokko-g/website/src/features/games/loaders.js
Shinuwa 895fec2b40
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
structure refacto & file documentation
2026-07-25 17:51:53 +02:00

127 lines
4.3 KiB
JavaScript

// Rôle : charge et normalise les données publiques des jeux.
export const INITIAL_MHWILDS_STATE = {
loaded: false,
loading: false,
error: "",
translations: {},
monsters: [],
endemic: [],
lists: [],
filterOptions: { monsters: [], endemic: [] },
filterOptionKeys: { monsters: "", endemic: "" }
};
export const INITIAL_DIABLO4_STATE = {
loaded: false,
loading: false,
error: "",
affixes: [],
filterOptions: { affixes: [] },
categoryMap: {},
filterOptionKeys: { affixes: "" }
};
export async function loadMhwildsData() {
const [monstersResponse, endemicResponse, listIndexResponse, translationsResponse] = await Promise.all([
fetch("/data/mhwilds/monsters.json"),
fetch("/data/mhwilds/endemic_life.json"),
fetch("/data/mhwilds/lists/index.json"),
fetch("/data/mhwilds/i18n/fr.json")
]);
if (!monstersResponse.ok || !endemicResponse.ok || !listIndexResponse.ok || !translationsResponse.ok) {
throw new Error("Impossible de charger les données Monster Hunter Wilds.");
}
const [monstersJson, endemicJson, listIndexJson, translations] = await Promise.all([
monstersResponse.json(),
endemicResponse.json(),
listIndexResponse.json(),
translationsResponse.json()
]);
const lists = await loadGameLists("mhwilds", listIndexJson);
const monsterFilterKey = Object.keys(monstersJson).find((key) => key !== "monsters") || "";
const endemicFilterKey = Object.keys(endemicJson).find((key) => key !== "endemicLife" && key !== "aquaticLife") || "";
return {
loaded: true,
loading: false,
error: "",
translations,
monsters: monstersJson.monsters || [],
endemic: [...(endemicJson.endemicLife || []), ...(endemicJson.aquaticLife || [])],
lists,
filterOptions: {
monsters: monstersJson[monsterFilterKey] || [],
endemic: endemicJson[endemicFilterKey] || []
},
filterOptionKeys: {
monsters: monsterFilterKey,
endemic: endemicFilterKey
}
};
}
async function loadGameLists(gameId, indexPayload) {
const entries = Array.isArray(indexPayload?.lists) ? indexPayload.lists : [];
const results = await Promise.all(entries.map(async (entry) => {
const response = await fetch(`/data/${gameId}/lists/${entry.file}`);
if (!response.ok) throw new Error(`Impossible de charger la liste ${entry.file}.`);
const payload = await response.json();
return normalizeGameListFile(entry, payload);
}));
return results;
}
function normalizeGameListFile(entry, payload) {
const id = String(entry?.id || entry?.file || "").replace(/\.json$/i, "");
const categories = Object.entries(payload || {}).filter(([, items]) => Array.isArray(items)).map(([categoryId, items]) => ({
id: categoryId,
title: formatListTitle(categoryId),
items: Array.isArray(items) ? items.map(normalizeGameListItem).filter((item) => item.name) : []
})).filter((category) => category.items.length);
return {
id,
title: payload?.titre || entry?.title || formatListTitle(id),
file: entry?.file || `${id}.json`,
categories,
itemCount: categories.reduce((count, category) => count + category.items.length, 0)
};
}
function normalizeGameListItem(item) {
const hasQuantity = item?.quantite !== undefined || item?.quantity !== undefined;
const quantity = Number.parseInt(item?.quantite ?? item?.quantity ?? 1, 10);
return {
name: String(item?.nom || item?.name || item?.label || "").trim(),
description: String(item?.description || item?.quete || item?.quest || item?.source || "").trim(),
quantity: Number.isFinite(quantity) ? quantity : 1,
hasQuantity
};
}
function formatListTitle(value) {
return String(value || "")
.replace(/_/g, " ")
.replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
}
export async function loadDiablo4Data() {
const response = await fetch("/data/diablo4/affixes_types.json");
if (!response.ok) throw new Error("Impossible de charger les données Diablo IV.");
const payload = await response.json();
const filterKey = Object.keys(payload).find((key) => key !== "affixes") || "";
const categories = payload[filterKey] || [];
return {
loaded: true,
loading: false,
error: "",
affixes: payload.affixes || [],
filterOptions: { affixes: categories },
categoryMap: Object.fromEntries(categories.map((category) => [category.id, category])),
filterOptionKeys: { affixes: filterKey }
};
}