Applique .gitattributes sur tous les fichiers existants. Élimine les différences fantômes entre WSL et Windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.4 KiB
TypeScript
Executable File
81 lines
2.4 KiB
TypeScript
Executable File
import { BREEDING_RECIPES, RACE_GEN } from '@domain/value-objects/Race';
|
|
|
|
export interface ReapproInput {
|
|
target: string;
|
|
qty: number;
|
|
repro: Readonly<Record<string, number>>;
|
|
inverted: Readonly<Record<string, boolean>>;
|
|
}
|
|
|
|
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<string, { total: number; m: number; f: number }> = {};
|
|
needs[target] = { total: qty, m: 0, f: 0 };
|
|
const steps: ReapproStep[] = [];
|
|
const processed = new Set<string>();
|
|
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 };
|
|
}
|
|
}
|