Files
mgt2-compendium-amiral-denisov/scripts/travellerMapApi.js

132 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* MGT2 Commerce Client API Traveller Map
*
* Documentation : https://travellermap.com/doc/api
*
* Deux fonctions exportées :
* searchWorlds(query) → [{name, sector, hex, uwp, zone}]
* fetchWorldDetail(sector, hex) → {uwp, zone} (zone: 'normal'|'amber'|'red')
*/
const BASE_URL = 'https://travellermap.com';
/** Convertit la zone Traveller Map ('A', 'R', '') vers notre convention. */
function normalizeZone(z) {
if (z === 'A') return 'amber';
if (z === 'R') return 'red';
return 'normal';
}
/**
* Recherche des mondes par nom via l'API Traveller Map.
*
* @param {string} query Nom partiel ou complet (ex. "Regina")
* @returns {Promise<Array<{name:string, sector:string, hex:string, uwp:string}>>}
* Tableau de résultats (uniquement les mondes, pas secteurs/subsecteurs).
* Vide si erreur réseau.
*/
export async function searchWorlds(query) {
if (!query || query.trim().length < 2) return [];
const url = `${BASE_URL}/api/search?q=${encodeURIComponent(query.trim())}`;
let data;
try {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
data = await resp.json();
} catch (err) {
console.warn('MGT2 Commerce | Traveller Map search error:', err);
return [];
}
const items = data?.Results?.Items ?? [];
return items
.filter(item => item.World) // garder uniquement les mondes
.map(item => {
const w = item.World;
// Formatter le code hex sur 4 chiffres (HexX→XX, HexY→YY)
const hex = String(w.HexX).padStart(2, '0') + String(w.HexY).padStart(2, '0');
return {
name: w.Name,
sector: w.Sector,
hex,
uwp: w.Uwp ?? '',
};
});
}
/**
* Récupère les coordonnées absolues d'un monde en parsecs.
* Utilise l'endpoint /api/coordinates.
*
* @param {string} sector Nom du secteur (ex. "Spinward Marches")
* @param {string} hex Code hex 4 chiffres (ex. "1910")
* @returns {Promise<{x:number, y:number}|null>}
*/
export async function fetchWorldCoordinates(sector, hex) {
const url = `${BASE_URL}/api/coordinates?sector=${encodeURIComponent(sector)}&hex=${encodeURIComponent(hex)}`;
try {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
if (data?.x == null || data?.y == null) return null;
return { x: data.x, y: data.y };
} catch (err) {
console.warn('MGT2 Commerce | Traveller Map coordinates error:', err);
return null;
}
}
/**
* Calcule la distance en parsecs entre deux mondes à partir de leurs
* coordonnées absolues (retournées par fetchWorldCoordinates).
* Utilise la formule de distance en coordonnées cubiques pour grille hexagonale.
*
* Dans le système Traveller Map : les colonnes impaires (hx impair) sont
* décalées vers le bas. En coordonnées API, hx impair ↔ x pair.
* Conversion offset→cube : q=x, r=y⌈x/2⌉, s=qr.
* Distance = max(|Δq|, |Δr|, |Δs|).
*
* @param {{x:number,y:number}} c1
* @param {{x:number,y:number}} c2
* @returns {number} Distance en parsecs (entier, minimum 1)
*/
export function calcParsecs(c1, c2) {
const q1 = c1.x, r1 = c1.y - Math.ceil(c1.x / 2);
const q2 = c2.x, r2 = c2.y - Math.ceil(c2.x / 2);
const dq = q2 - q1, dr = r2 - r1, ds = -dq - dr;
return Math.max(1, Math.max(Math.abs(dq), Math.abs(dr), Math.abs(ds)));
}
/**
* Récupère les détails d'un monde pour obtenir la zone de voyage.
* Utilise l'endpoint /data/{sector}/{hex} (jump=0).
*
* @param {string} sector Nom du secteur (ex. "Spinward Marches")
* @param {string} hex Code hex 4 chiffres (ex. "1910")
* @returns {Promise<{uwp:string, zone:string}>}
*/
export async function fetchWorldDetail(sector, hex) {
const url = `${BASE_URL}/data/${encodeURIComponent(sector)}/${hex}`;
let data;
try {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
data = await resp.json();
} catch (err) {
console.warn('MGT2 Commerce | Traveller Map detail error:', err);
return null;
}
const world = data?.Worlds?.[0];
if (!world) return null;
return {
uwp: world.UWP ?? '',
zone: normalizeZone(world.Zone ?? ''),
};
}