zenno/doc/fans: new data coverage and fix off-by-ones
ci/woodpecker/push/horsebot Pipeline was successful
ci/woodpecker/push/zenno Pipeline failed

This commit is contained in:
2026-10-18 19:31:05 -04:00
parent 75558f35ba
commit 16a5433594
2 changed files with 70 additions and 40 deletions
+19 -4
View File
@@ -1,3 +1,15 @@
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],
@@ -9,15 +21,15 @@ const margins = [
/**
* 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
* @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 > 3) {
if (finishOrder > 5) {
return 0;
}
const [, wb, lb] = margins.find(([m]) => margin < m)!;
const [, wb, lb] = margins.find(([m]) => margin <= m)!;
const b = finishOrder === 1 ? wb : lb;
return Math.floor(baseFans * b);
}
@@ -52,7 +64,10 @@ export function skillFans(baseFans: number, skillsActivated: number): number {
*/
export function gained(baseFans: number, marginFans: number, skillFans: number, fanBonus: number, itemBonus?: number): number {
const f = baseFans + marginFans + skillFans;
const d = Math.round(f * (1 + fanBonus / 100));
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));
}