**Motivations:** - Initialisation du versionning git pour le projet **Root causes:** - N/A (Nouveau projet) **Correctifs:** - N/A **Evolutions:** - Structure initiale du projet - Ajout du .gitignore **Pages affectées:** - Tous les fichiers
179 lines
6.1 KiB
JavaScript
179 lines
6.1 KiB
JavaScript
/**
|
|
* Bootstrap helpers: load state from API or show register/connect UI.
|
|
*/
|
|
|
|
import { defaultState, normalizeZooWeights } from "./state.js";
|
|
import { refreshOffers, getPlayerZooWeights } from "./conveyor.js";
|
|
import { ensureBotState } from "./bot-zoo.js";
|
|
import { loadZoos, loadMyZoo, register, createMyZoo } from "./api-client.js";
|
|
import { getOrCreateKeyPair } from "./auth-client.js";
|
|
|
|
/**
|
|
* @param {import("./types.js").GameState} gameState
|
|
* @param {{ zoosData: { worldZoos?: Array<unknown> }, playerZooId?: string, playerName?: string, playerX?: number, playerY?: number }} opts
|
|
* @returns {void}
|
|
*/
|
|
export function applyWorldZoos(gameState, opts) {
|
|
const { zoosData, playerZooId, playerName, playerX, playerY } = opts;
|
|
const playerWeights = getPlayerZooWeights(gameState);
|
|
const playerEntry = {
|
|
id: "player",
|
|
name: playerName || "Mon zoo",
|
|
x: playerX ?? 25,
|
|
y: playerY ?? 50,
|
|
animalWeights: playerWeights,
|
|
};
|
|
const others = (zoosData.worldZoos || [])
|
|
.filter((z) => z.id !== playerZooId)
|
|
.map((z) => ({
|
|
...z,
|
|
animalWeights: normalizeZooWeights(z.animalWeights),
|
|
botState: z.game_state ?? undefined,
|
|
}));
|
|
others.forEach((zoo) => ensureBotState(zoo, false));
|
|
gameState.worldZoos = [playerEntry, ...others];
|
|
}
|
|
|
|
/**
|
|
* @returns {Promise<import("./types.js").GameState>}
|
|
*/
|
|
export function bootstrapNoKeys() {
|
|
const s = defaultState();
|
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
refreshOffers(s, nowUnix);
|
|
return Promise.resolve(s);
|
|
}
|
|
|
|
/**
|
|
* @param {{ worldZoos?: Array<unknown> }} zoosData
|
|
* @param {HTMLElement} rootEl
|
|
* @param {(zooId: string) => void} setMyZooId
|
|
* @returns {Promise<import("./types.js").GameState>}
|
|
*/
|
|
export function bootstrapShowRegisterPanel(zoosData, rootEl, setMyZooId) {
|
|
return new Promise((resolve) => {
|
|
rootEl.innerHTML = "<div class=\"boot-panel\"><h1>Construis un zoo</h1><p>Créer un compte (pseudo, pas de mot de passe)</p><input id=\"boot-pseudo\" type=\"text\" placeholder=\"Pseudo\" maxlength=\"32\" /><button id=\"boot-submit\">Créer</button><p id=\"boot-err\" class=\"boot-err\"></p></div>";
|
|
const errEl = document.getElementById("boot-err");
|
|
document.getElementById("boot-submit").addEventListener("click", async () => {
|
|
const pseudo = document.getElementById("boot-pseudo").value.trim();
|
|
if (pseudo.length < 2) {
|
|
errEl.textContent = "Pseudo min. 2 caractères";
|
|
return;
|
|
}
|
|
errEl.textContent = "";
|
|
try {
|
|
await register(pseudo);
|
|
const s = defaultState();
|
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
refreshOffers(s, nowUnix);
|
|
const created = await createMyZoo(pseudo, s);
|
|
setMyZooId(created.zooId);
|
|
applyWorldZoos(s, { zoosData, playerZooId: created.zooId, playerName: created.name, playerX: created.x, playerY: created.y });
|
|
s.myZooId = created.zooId;
|
|
s.playerName = created.name;
|
|
s.playerX = created.x;
|
|
s.playerY = created.y;
|
|
resolve(s);
|
|
} catch (e) {
|
|
errEl.textContent = e.message || "Erreur";
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {{ worldZoos?: Array<unknown> }} zoosData
|
|
* @returns {Promise<import("./types.js").GameState>}
|
|
*/
|
|
export async function bootstrapMe404(zoosData) {
|
|
const s = defaultState();
|
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
refreshOffers(s, nowUnix);
|
|
const created = await createMyZoo("Mon zoo", s);
|
|
const myZooId = created.zooId;
|
|
applyWorldZoos(s, { zoosData, playerZooId: myZooId, playerName: created.name, playerX: created.x, playerY: created.y });
|
|
s.myZooId = myZooId;
|
|
s.playerName = created.name;
|
|
s.playerX = created.x;
|
|
s.playerY = created.y;
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @param {{ game_state: import("./types.js").GameState; zooId: string; name: string; x: number; y: number }} me
|
|
* @param {{ worldZoos?: Array<unknown> }} zoosData
|
|
* @returns {import("./types.js").GameState}
|
|
*/
|
|
export function bootstrapMeWithGameState(me, zoosData) {
|
|
const s = me.game_state;
|
|
const myZooId = me.zooId;
|
|
s.myZooId = myZooId;
|
|
s.playerName = me.name;
|
|
s.playerX = me.x;
|
|
s.playerY = me.y;
|
|
if (s.coins < 100) s.coins = 200;
|
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
if (s.conveyorOffers === null || s.conveyorOffers === undefined || s.conveyorOffers.length === 0) {
|
|
refreshOffers(s, nowUnix);
|
|
}
|
|
applyWorldZoos(s, { zoosData, playerZooId: myZooId, playerName: me.name, playerX: me.x, playerY: me.y });
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @param {{ name?: string }} me
|
|
* @param {{ worldZoos?: Array<unknown> }} zoosData
|
|
* @returns {Promise<import("./types.js").GameState>}
|
|
*/
|
|
export async function bootstrapMeCreateZoo(me, zoosData) {
|
|
const s = defaultState();
|
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
refreshOffers(s, nowUnix);
|
|
const created = await createMyZoo(me.name || "Mon zoo", s);
|
|
const myZooId = created.zooId;
|
|
applyWorldZoos(s, { zoosData, playerZooId: myZooId, playerName: created.name, playerX: created.x, playerY: created.y });
|
|
s.myZooId = myZooId;
|
|
s.playerName = created.name;
|
|
s.playerX = created.x;
|
|
s.playerY = created.y;
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @param {(zooId: string) => void} setMyZooId
|
|
* @param {HTMLElement} rootEl
|
|
* @returns {Promise<import("./types.js").GameState>}
|
|
*/
|
|
export async function bootstrapFromApi(setMyZooId, rootEl) {
|
|
const keys = await getOrCreateKeyPair();
|
|
if (!keys) {
|
|
return bootstrapNoKeys();
|
|
}
|
|
let zoosData = { worldZoos: [], mapWidth: 100, mapHeight: 100 };
|
|
try {
|
|
zoosData = await loadZoos();
|
|
} catch (e) {
|
|
console.warn("loadZoos failed", e);
|
|
}
|
|
const meRes = await loadMyZoo().catch((e) => {
|
|
console.warn("loadMyZoo failed", e);
|
|
return { status: 401 };
|
|
});
|
|
if (meRes.status === 401) {
|
|
return bootstrapShowRegisterPanel(zoosData, rootEl, setMyZooId);
|
|
}
|
|
if (meRes.status === 404) {
|
|
const s = await bootstrapMe404(zoosData);
|
|
setMyZooId(s.myZooId ?? "player");
|
|
return s;
|
|
}
|
|
const me = meRes.data;
|
|
if (me.game_state && typeof me.game_state === "object") {
|
|
setMyZooId(me.zooId);
|
|
return bootstrapMeWithGameState(me, zoosData);
|
|
}
|
|
const s = await bootstrapMeCreateZoo(me, zoosData);
|
|
setMyZooId(s.myZooId ?? "player");
|
|
return s;
|
|
}
|