Initial commit
**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
This commit is contained in:
178
web/js/main-bootstrap.js
Normal file
178
web/js/main-bootstrap.js
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user