Lint: fix errors and remove unused variables
**Motivations:** - Ensure lint config is not degraded and fix all lint errors for pousse workflow. **Root causes:** - Unused variables kept with _ prefix instead of removed (_row, _questReward, _i). - getAnimalBlockOrigin had 5 parameters (max 4). - use of continue statement (no-continue rule). **Correctifs:** - ESLint config verified; no eslint-disable in codebase. - Removed unused variable _row (biome-rules); removed dead function _questReward (quests); removed unused map param _i (state.js). - getAnimalBlockOrigin refactored to 4 params (pos object instead of x, y). - Replaced continue with if (cell) block in normalizeLoadedCells (state.js). - JSDoc param names aligned with _height, _y (biome-rules). **Evolutions:** - (none) **Pages affectées:** - web/js/biome-rules.js - web/js/quests.js - web/js/state.js - web/js/placement.js
This commit is contained in:
@@ -11,24 +11,92 @@ export const INCIDENT_TYPES = ["thirst", "bin", "bench", "animalFar", "photo"];
|
||||
/** Emoji per incident type for bubble display. */
|
||||
export const INCIDENT_EMOJI = { thirst: "💧", bin: "🗑️", bench: "🪑", animalFar: "🦌", photo: "📷" };
|
||||
|
||||
/**
|
||||
* True when truck (egg or sale) is in progress.
|
||||
* @param {import("./types.js").GameState} state
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasTruckWait(state) {
|
||||
if (state.eggPurchaseTruck && state.eggPurchaseTruck.startAt) return true;
|
||||
if (state.truckSale && state.truckSale.startAt) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True when there are API sales as buyer undelivered with pending validation.
|
||||
* @param {import("./types.js").GameState} state
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasApiUndeliveredWait(state) {
|
||||
const api = state.salesFromApi;
|
||||
if (!api || !api.asBuyerUndelivered || api.asBuyerUndelivered.length === 0) return false;
|
||||
const nowMs = Date.now();
|
||||
for (const s of api.asBuyerUndelivered) {
|
||||
const validatedAtMs = s.validated_at ? new Date(s.validated_at).getTime() : 0;
|
||||
const pending = (s.status === "sold" || s.status === "validated") && validatedAtMs > nowMs;
|
||||
if (pending) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True when player is in a wait phase (truck moving, sale pending validation, etc.).
|
||||
* @param {import("./types.js").GameState} state
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isInWaitPhase(state) {
|
||||
if (state.eggPurchaseTruck && state.eggPurchaseTruck.startAt) return true;
|
||||
if (state.truckSale && state.truckSale.startAt) return true;
|
||||
const api = state.salesFromApi;
|
||||
if (api && api.asBuyerUndelivered && api.asBuyerUndelivered.length > 0) {
|
||||
const nowMs = Date.now();
|
||||
for (const s of api.asBuyerUndelivered) {
|
||||
const validatedAtMs = s.validated_at ? new Date(s.validated_at).getTime() : 0;
|
||||
const pending = (s.status === "sold" || s.status === "validated") && validatedAtMs > nowMs;
|
||||
if (pending) return true;
|
||||
return hasTruckWait(state) || hasApiUndeliveredWait(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expire timed-out incidents and apply penalty. Returns indices to remove from arrivals.
|
||||
* @param {import("./types.js").VisitorArrival[]} arrivals
|
||||
* @param {{ nowUnix: number, timeoutSec: number, penalty: number, stateRef: { attractivityBonusFromIncidents: number } }} opts
|
||||
* @returns {number[]}
|
||||
*/
|
||||
function expireIncidents(arrivals, opts) {
|
||||
const { nowUnix, timeoutSec, penalty, stateRef } = opts;
|
||||
const toRemove = [];
|
||||
for (let i = 0; i < arrivals.length; i++) {
|
||||
const v = arrivals[i];
|
||||
if (v.incidentType !== null && v.incidentType !== undefined) {
|
||||
if (nowUnix - (v.incidentSince ?? nowUnix) >= timeoutSec) {
|
||||
stateRef.attractivityBonusFromIncidents = (stateRef.attractivityBonusFromIncidents ?? 0) - penalty;
|
||||
toRemove.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn new incidents on visitors without one (by chance).
|
||||
* @param {import("./types.js").VisitorArrival[]} arrivals
|
||||
* @param {number} chance
|
||||
* @param {number} nowUnix
|
||||
*/
|
||||
function spawnIncidents(arrivals, chance, nowUnix) {
|
||||
for (let i = 0; i < arrivals.length; i++) {
|
||||
const v = arrivals[i];
|
||||
const hasNoIncident = v.incidentType === null || v.incidentType === undefined;
|
||||
if (hasNoIncident && Math.random() < chance) {
|
||||
v.incidentType = INCIDENT_TYPES[Math.floor(Math.random() * INCIDENT_TYPES.length)];
|
||||
v.incidentSince = nowUnix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{ baseChance: number, waitMult: number, timeoutSec: number, penalty: number }}
|
||||
*/
|
||||
function getIncidentConfig() {
|
||||
const cfg = GameConfig.Visitor;
|
||||
return {
|
||||
baseChance: cfg?.IncidentChanceBase ?? 0.002,
|
||||
waitMult: cfg?.IncidentChanceWaitMultiplier ?? 4,
|
||||
timeoutSec: cfg?.IncidentTimeoutSeconds ?? 45,
|
||||
penalty: cfg?.IncidentUnresolvedAttractivityPenalty ?? 0.2,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,30 +106,30 @@ export function isInWaitPhase(state) {
|
||||
*/
|
||||
export function tickVisitorIncidents(state, nowUnix) {
|
||||
const arrivals = state.visitorArrivals ?? [];
|
||||
const cfg = GameConfig.Visitor;
|
||||
const baseChance = cfg?.IncidentChanceBase ?? 0.002;
|
||||
const waitMult = cfg?.IncidentChanceWaitMultiplier ?? 4;
|
||||
const timeoutSec = cfg?.IncidentTimeoutSeconds ?? 45;
|
||||
const penalty = cfg?.IncidentUnresolvedAttractivityPenalty ?? 0.2;
|
||||
const { baseChance, waitMult, timeoutSec, penalty } = getIncidentConfig();
|
||||
const inWait = isInWaitPhase(state);
|
||||
const chance = inWait ? baseChance * waitMult : baseChance;
|
||||
const toRemove = [];
|
||||
|
||||
for (let i = 0; i < arrivals.length; i++) {
|
||||
const v = arrivals[i];
|
||||
if (v.incidentType !== null && v.incidentType !== undefined) {
|
||||
if (nowUnix - (v.incidentSince ?? nowUnix) >= timeoutSec) {
|
||||
state.attractivityBonusFromIncidents = (state.attractivityBonusFromIncidents ?? 0) - penalty;
|
||||
toRemove.push(i);
|
||||
}
|
||||
} else if (Math.random() < chance) {
|
||||
v.incidentType = INCIDENT_TYPES[Math.floor(Math.random() * INCIDENT_TYPES.length)];
|
||||
v.incidentSince = nowUnix;
|
||||
}
|
||||
}
|
||||
const toRemove = expireIncidents(arrivals, { nowUnix, timeoutSec, penalty, stateRef: state });
|
||||
for (let r = toRemove.length - 1; r >= 0; r--) {
|
||||
arrivals.splice(toRemove[r], 1);
|
||||
}
|
||||
spawnIncidents(arrivals, chance, nowUnix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply resolve bonus (coins + attractivity) to state. Mutates state and v.
|
||||
* @param {import("./types.js").GameState} state
|
||||
* @param {import("./types.js").VisitorArrival} v
|
||||
*/
|
||||
function applyResolveBonus(state, v) {
|
||||
const cfg = GameConfig.Visitor;
|
||||
const coinBonus = cfg?.IncidentResolveCoinBonus ?? 8;
|
||||
const attractivityBonus = cfg?.IncidentResolveAttractivityBonus ?? 0.15;
|
||||
state.coins += coinBonus;
|
||||
state.attractivityBonusFromIncidents = (state.attractivityBonusFromIncidents ?? 0) + attractivityBonus;
|
||||
if (state.stats) state.stats.coinsEarned = (state.stats.coinsEarned ?? 0) + coinBonus;
|
||||
delete v.incidentType;
|
||||
delete v.incidentSince;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,13 +142,6 @@ export function resolveIncident(state, visitorIndex) {
|
||||
const arrivals = state.visitorArrivals ?? [];
|
||||
const v = arrivals[visitorIndex];
|
||||
if (!v || (v.incidentType === null || v.incidentType === undefined)) return false;
|
||||
const cfg = GameConfig.Visitor;
|
||||
const coinBonus = cfg?.IncidentResolveCoinBonus ?? 8;
|
||||
const attractivityBonus = cfg?.IncidentResolveAttractivityBonus ?? 0.15;
|
||||
state.coins += coinBonus;
|
||||
state.attractivityBonusFromIncidents = (state.attractivityBonusFromIncidents ?? 0) + attractivityBonus;
|
||||
if (state.stats) state.stats.coinsEarned = (state.stats.coinsEarned ?? 0) + coinBonus;
|
||||
delete v.incidentType;
|
||||
delete v.incidentSince;
|
||||
applyResolveBonus(state, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user