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

252 lines
6.6 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 Parseur UWP (Universal World Profile)
*
* Format standard : SAAHPGL-T
* Exemples : A788899-C B200400-A
*
* S = Astroport (A B C D E X)
* A = Taille (0A hex, 010)
* A = Atmosphère (0F hex, 015)
* H = Hydrographie (0A hex, 010)
* P = Population (0C hex, 012)
* G = Gouvernement (0F hex, 015)
* L = Niveau de loi(0J hex, 019)
* T = Niveau tech (0F hex, 015) — après le tiret
*/
import { TRADE_CODES } from './data/tradeTables.js';
/**
* Convertit un caractère de code UWP en valeur numérique.
* Utilise la base 16 pour les chiffres 09 et lettres AF.
* Pour le Niveau de loi : G=16, H=17, J=18 (pas de I).
*/
function uwpCharToInt(char) {
if (!char) return 0;
const c = char.toUpperCase();
if (c === 'G') return 16;
if (c === 'H') return 17;
if (c === 'J') return 18;
const n = parseInt(c, 16);
return isNaN(n) ? 0 : n;
}
/**
* Parse une chaîne UWP et retourne un objet avec tous les attributs.
* @param {string} uwp Ex. "A788899-C"
* @returns {{
* raw: string,
* valid: boolean,
* error: string|null,
* starport: string,
* size: number,
* atmosphere: number,
* hydrographics: number,
* population: number,
* government: number,
* lawLevel: number,
* techLevel: number,
* tradeCodes: string[],
* zone: string,
* }}
*/
export function parseUWP(uwp, zone = 'normal') {
const result = {
raw: uwp,
valid: false,
error: null,
starport: '',
size: 0,
atmosphere: 0,
hydrographics: 0,
population: 0,
government: 0,
lawLevel: 0,
techLevel: 0,
tradeCodes: [],
zone,
};
if (!uwp || typeof uwp !== 'string') {
result.error = 'UWP manquant';
return result;
}
// Normalise : retire espaces, met en majuscules
const s = uwp.trim().toUpperCase();
// Accepte SAAHPGL-T ou SAAHPGL (sans tech level)
const match = s.match(/^([ABCDEX])([0-9A-F])([0-9A-F])([0-9A])([0-9A-C])([0-9A-F])([0-9A-J])(?:-([0-9A-F]))?$/i);
if (!match) {
result.error = `Format UWP invalide : "${uwp}". Attendu : SAAHPGL-T (ex. A788899-C)`;
return result;
}
result.starport = match[1];
result.size = uwpCharToInt(match[2]);
result.atmosphere = uwpCharToInt(match[3]);
result.hydrographics = uwpCharToInt(match[4]);
result.population = uwpCharToInt(match[5]);
result.government = uwpCharToInt(match[6]);
result.lawLevel = uwpCharToInt(match[7]);
result.techLevel = match[8] ? uwpCharToInt(match[8]) : 0;
result.valid = true;
result.tradeCodes = deriveTradeCodes(result);
return result;
}
/**
* Dérive les codes commerciaux d'un monde à partir de ses attributs UWP.
* @param {object} w Objet retourné par parseUWP
* @returns {string[]}
*/
export function deriveTradeCodes(w) {
const codes = [];
// Ag Agricole : Atm 49, Hyd 48, Pop 57
if (w.atmosphere >= 4 && w.atmosphere <= 9 &&
w.hydrographics >= 4 && w.hydrographics <= 8 &&
w.population >= 5 && w.population <= 7) {
codes.push('Ag');
}
// As Astéroïdes : Taille 0, Atm 0, Hyd 0
if (w.size === 0 && w.atmosphere === 0 && w.hydrographics === 0) {
codes.push('As');
}
// Ba Stérile : Pop 0, Gov 0, Loi 0
if (w.population === 0 && w.government === 0 && w.lawLevel === 0) {
codes.push('Ba');
}
// De Désert : Atm 2+, Hyd 0
if (w.atmosphere >= 2 && w.hydrographics === 0) {
codes.push('De');
}
// Fl Océans fluides : Atm A (10)+, Hyd 1+
if (w.atmosphere >= 10 && w.hydrographics >= 1) {
codes.push('Fl');
}
// Ga Jardin : Taille 68, Atm 5 ou 6 ou 8, Hyd 57
if (w.size >= 6 && w.size <= 8 &&
[5, 6, 8].includes(w.atmosphere) &&
w.hydrographics >= 5 && w.hydrographics <= 7) {
codes.push('Ga');
}
// Hi Pop. élevée : Pop A (10)+
if (w.population >= 10) {
codes.push('Hi');
}
// Ht Haute tech : TL C (12)+
if (w.techLevel >= 12) {
codes.push('Ht');
}
// IC Calotte glaciaire : Atm 01, Hyd 1+
if (w.atmosphere <= 1 && w.hydrographics >= 1) {
codes.push('IC');
}
// In Industriel : Atm ∈ {0,1,2,4,7,9}, Pop 9+
if ([0, 1, 2, 4, 7, 9].includes(w.atmosphere) && w.population >= 9) {
codes.push('In');
}
// Lo Pop. basse : Pop 13
if (w.population >= 1 && w.population <= 3) {
codes.push('Lo');
}
// Lt Basse tech : TL ≤ 5
if (w.techLevel <= 5) {
codes.push('Lt');
}
// Na Non-Agricole : Atm 03, Hyd 03, Pop 6+
if (w.atmosphere <= 3 && w.hydrographics <= 3 && w.population >= 6) {
codes.push('Na');
}
// Ni Non-Industriel : Pop 46
if (w.population >= 4 && w.population <= 6) {
codes.push('Ni');
}
// Po Pauvre : Atm 25, Hyd 03
if (w.atmosphere >= 2 && w.atmosphere <= 5 && w.hydrographics <= 3) {
codes.push('Po');
}
// Ri Riche : Gov ∈ {4,5,6,10}, Pop 68, Atm ∈ {6,8}
if ([4, 5, 6, 10].includes(w.government) &&
w.population >= 6 && w.population <= 8 &&
[6, 8].includes(w.atmosphere)) {
codes.push('Ri');
}
// Wa Monde aquatique : Hyd A (10)
if (w.hydrographics === 10) {
codes.push('Wa');
}
// Va Vide : Atm 0
if (w.atmosphere === 0) {
codes.push('Va');
}
return codes;
}
/**
* Retourne le modificateur d'astroport pour les tables de trafic.
* @param {string} starport 'A'|'B'|'C'|'D'|'E'|'X'
* @param {string} table 'passenger'|'cargo'|'supplier'
* @returns {number}
*/
export function starportModifier(starport, table = 'passenger') {
if (table === 'supplier') {
return { A: 6, B: 4, C: 2, D: 0, E: 0, X: 0 }[starport] ?? 0;
}
// passenger & cargo
return { A: 2, B: 1, C: 0, D: 0, E: -1, X: -3 }[starport] ?? 0;
}
/**
* Retourne le modificateur de population pour les tables de trafic.
* @param {number} pop Valeur numérique de la population
* @param {string} table 'passenger'|'cargo'
* @returns {number}
*/
export function populationModifier(pop, table = 'passenger') {
if (table === 'cargo') {
if (pop <= 1) return -4;
if (pop >= 6 && pop <= 7) return 2;
if (pop >= 8) return 4;
return 0;
}
// passenger
if (pop <= 1) return -4;
if (pop >= 6 && pop <= 7) return 1;
if (pop >= 8) return 3;
return 0;
}
/**
* Retourne le modificateur de zone (Ambre/Rouge/Normal) pour les tables de trafic.
* @param {string} zone 'normal'|'amber'|'red'
* @param {string} table 'passenger'|'cargo'
* @returns {number}
*/
export function zoneModifier(zone, table = 'passenger') {
if (table === 'cargo') {
return { normal: 0, amber: -2, red: -6 }[zone] ?? 0;
}
return { normal: 0, amber: 1, red: -4 }[zone] ?? 0;
}