const placementPms = [1000, 400, 250, 150, 100, 90, 80, 70, 60, 50, 40, 30, 25, 20, 15, 10, 10, 10] as const; /** * Calculate base fans for a given placement in a race. * @param winBase Base fans for a win, as displayed in the race menu * @param finishOrder Placement of the trainee, with winner being 1 * @returns Base fans for the race and placement together */ export function baseFans(winBase: number, finishOrder: number): number { return Math.round(winBase * placementPms[finishOrder - 1] / 1000); } const margins = [ [0.75, 0.0, 0.09], [2.5, 0.02, 0.06], [4, 0.04, 0.04], [6, 0.06, 0.02], [Infinity, 0.09, 0.0], ] as const; /** * Calculate fans gained from a career race due to the margin of the finish. * @param baseFans Base fans from the race and finish order * @param finishOrder Placement of the trainee, with winner being 1 * @param margin Margin in lengths between the trainee and second if a win, or the winner and trainee if a loss * @returns Fans gained due to finish margin */ export function marginFans(baseFans: number, finishOrder: number, margin: number): number { if (finishOrder > 5) { return 0; } const [, wb, lb] = margins.find(([m]) => margin <= m)!; const b = finishOrder === 1 ? wb : lb; return Math.floor(baseFans * b); } const skills = [ [0, 0.0], [3, 0.02], [6, 0.03], [9, 0.05], [Infinity, 0.08], ] as const; /** * Calculate the fans gained from a career race due to skills activated. * @param baseFans Base fans from the race and finish order * @param skillsActivated Number of skills the trainee activated during the race * @returns Fans gained due to skill activations */ export function skillFans(baseFans: number, skillsActivated: number): number { const [, b] = skills.find(([n]) => skillsActivated <= n)!; return Math.floor(baseFans * b); } /** * Calculate fan gain from a career race. * @param baseFans Base fans from the race and finish order * @param marginFans Fans gained due to finish margin * @param skillFans Fans gained due to skill activations * @param fanBonus Total fan bonus from support cards * @param itemBonus Fan bonus from items (MANT glowsticks) * @returns Total fans gained */ export function gained(baseFans: number, marginFans: number, skillFans: number, fanBonus: number, itemBonus?: number): number { const f = baseFans + marginFans + skillFans; const s = Math.fround(f * Math.fround(1 + fanBonus / 100)); const p = Math.exp((4 - Math.floor(Math.log10(s))) * Math.LN10); // Add half a significant figure to account for precision. const d = Math.floor(Math.round(s * p + 5e-6) / p + 5e-6); const b = itemBonus ?? 0; return Math.floor(d * (1 + b / 100)); }