import { BREEDING_RECIPES, RACE_GEN } from '@domain/value-objects/Race'; export interface ReapproInput { target: string; qty: number; repro: Readonly>; inverted: Readonly>; } export interface ReapproStep { race: string; gen: number; qty: number; couples: number; parentA: string; parentB: string; repro: number; } export interface Gen1Need { name: string; total: number; m: number; f: number; } export interface ReapproResult { steps: readonly ReapproStep[]; gen1Needs: readonly Gen1Need[]; totalGen1: number; } export class ReapproCalculator { compute(input: ReapproInput): ReapproResult { const { target, qty, repro, inverted } = input; if (!target || !BREEDING_RECIPES[target]) return { steps: [], gen1Needs: [], totalGen1: 0 }; const needs: Record = {}; needs[target] = { total: qty, m: 0, f: 0 }; const steps: ReapproStep[] = []; const processed = new Set(); const targetGen = RACE_GEN[target] ?? 2; for (let gen = targetGen; gen >= 2; gen--) { const racesAtGen = Object.keys(needs).filter( r => !processed.has(r) && (RACE_GEN[r] ?? 0) === gen && !!BREEDING_RECIPES[r] ); for (const race of racesAtGen) { const Q = needs[race]!.total; if (Q <= 0) { processed.add(race); continue; } const R = repro[race] ?? 0; const couplesReal = (2 * R >= Q) ? Math.ceil(Q / 2) : (R > 0 ? Q - R : Q); const isInv = inverted[race] ?? false; const [rawA, rawB] = BREEDING_RECIPES[race]!; const a = isInv ? rawB : rawA; const b = isInv ? rawA : rawB; if (!needs[a]) needs[a] = { total: 0, m: 0, f: 0 }; if (!needs[b]) needs[b] = { total: 0, m: 0, f: 0 }; needs[a]!.total += couplesReal; needs[a]!.m += couplesReal; needs[b]!.total += couplesReal; needs[b]!.f += couplesReal; steps.push({ race, gen, qty: Q, couples: couplesReal, parentA: a, parentB: b, repro: R }); processed.add(race); } } const gen1Needs: Gen1Need[] = Object.entries(needs) .filter(([n]) => !BREEDING_RECIPES[n] && needs[n]!.total > 0) .sort((a, b) => b[1].total - a[1].total) .map(([name, d]) => ({ name, total: d.total, m: d.m, f: d.f })); const totalGen1 = gen1Needs.reduce((s, n) => s + n.total, 0); return { steps, gen1Needs, totalGen1 }; } }