zenno: section speed does not use base wit
Per analysis by Aya, only final wit is used for section speed. Fixes #40.
This commit is contained in:
+4
-10
@@ -504,14 +504,12 @@ export function baseTargetSpeed(
|
||||
/**
|
||||
* Calculate the range of section speed values for a horse in early or mid race.
|
||||
* @param raceLen Length of the race in meters
|
||||
* @param baseWit Base wit, after mood but before other modifiers
|
||||
* @param witStat Final wit stat, including strategy proficiency and skills
|
||||
* @param style Horse's running style
|
||||
* @param phase Phase of the current section
|
||||
*/
|
||||
export function sectionSpeed(
|
||||
raceLen: number,
|
||||
baseWit: number,
|
||||
witStat: number,
|
||||
style: RunningStyle,
|
||||
phase: Exclude<Phase, Phase.LateRace>,
|
||||
@@ -520,7 +518,6 @@ export function sectionSpeed(
|
||||
* Calculate the range of section speed values for a horse not spurting during late race.
|
||||
* @param raceLen Length of the race in meters
|
||||
* @param speedStat Final speed stat
|
||||
* @param baseWit Base wit, after mood but before other modifiers
|
||||
* @param witStat Final wit stat, including strategy proficiency and skills
|
||||
* @param style Horse's running style
|
||||
* @param distance Hores's distance proficiency aptitude
|
||||
@@ -529,7 +526,6 @@ export function sectionSpeed(
|
||||
export function sectionSpeed(
|
||||
raceLen: number,
|
||||
speedStat: number,
|
||||
baseWit: number,
|
||||
witStat: number,
|
||||
style: RunningStyle,
|
||||
distance: AptitudeLevel,
|
||||
@@ -537,16 +533,14 @@ export function sectionSpeed(
|
||||
): [number, number];
|
||||
export function sectionSpeed(
|
||||
raceLen: number,
|
||||
speedStatOrBaseWit: number,
|
||||
baseWitOrWitStat: number,
|
||||
speedStatOrWitStat: number,
|
||||
witStatOrStyle: number | RunningStyle,
|
||||
styleOrPhase: RunningStyle | Phase,
|
||||
distance?: AptitudeLevel,
|
||||
lateRace?: Phase.LateRace,
|
||||
): [number, number] {
|
||||
const speedStat = lateRace !== undefined ? speedStatOrBaseWit : 0;
|
||||
const baseWit = lateRace !== undefined ? baseWitOrWitStat : speedStatOrBaseWit;
|
||||
const witStat = lateRace !== undefined ? witStatOrStyle : baseWitOrWitStat;
|
||||
const speedStat = lateRace !== undefined ? speedStatOrWitStat : 0;
|
||||
const witStat = lateRace !== undefined ? witStatOrStyle : speedStatOrWitStat;
|
||||
const style = lateRace !== undefined ? (styleOrPhase as RunningStyle) : (witStatOrStyle as RunningStyle);
|
||||
const phase = lateRace !== undefined ? lateRace : (styleOrPhase as Phase);
|
||||
const base = baseSpeed(raceLen);
|
||||
@@ -555,7 +549,7 @@ export function sectionSpeed(
|
||||
phase === Phase.LateRace
|
||||
? (math.sqrt(500 * speedStat) as number) * distanceProficiencyMod[distance ?? AptitudeLevel.A] * 0.002
|
||||
: 0;
|
||||
const u = (witStat / 550000) * math.log10(baseWit * 0.1);
|
||||
const u = (witStat / 550000) * math.log10(witStat * 0.1);
|
||||
const l = u - 0.0065;
|
||||
return [baseTarget + late + base * l, baseTarget + late + base * u];
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
const uphillSlowPow = 800;
|
||||
const uphillFastPow = 1200;
|
||||
const uphillBaseSpeed = mean2(sectionSpeed(2500, 1200, 1200, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const uphillBaseSpeed = mean2(sectionSpeed(2500, 1200, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const uphillSlopes = [
|
||||
{ per: 2, len: 110 },
|
||||
{ per: 1.5, len: 200 },
|
||||
@@ -137,13 +137,13 @@
|
||||
|
||||
const secSpeedS = 1200;
|
||||
const secSpeedA = 1000;
|
||||
const secSpeedExample = $derived(sectionSpeed(raceLen, secSpeedS, secSpeedS * 1.1, RunningStyle.FrontRunner, Phase.EarlyRace));
|
||||
const secSpeedExample = $derived(sectionSpeed(raceLen, secSpeedS * 1.1, RunningStyle.FrontRunner, Phase.EarlyRace));
|
||||
const secSpeedInfo = $derived(secSpeedExample.map((x) => x.toFixed(2)).join(' to '));
|
||||
const secSpeedPassTime = $derived.by(() => {
|
||||
const sSecSpeed = mean2(sectionSpeed(raceLen, secSpeedS, secSpeedS * 1.1, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const sSecSpeed = mean2(sectionSpeed(raceLen, secSpeedS * 1.1, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const sMode = frontModeEnterChance(secSpeedS * 1.1);
|
||||
const sOvertakeSpeed = modemean(sSecSpeed, 1.05, sMode);
|
||||
const aSecSpeed = mean2(sectionSpeed(raceLen, secSpeedA, secSpeedA, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const aSecSpeed = mean2(sectionSpeed(raceLen, secSpeedA, RunningStyle.FrontRunner, Phase.MidRace));
|
||||
const aMode = frontModeEnterChance(secSpeedA);
|
||||
const aSpeedupSpeed = modemean(aSecSpeed, 1.04, aMode);
|
||||
const r = 2 / (sOvertakeSpeed - aSpeedupSpeed);
|
||||
@@ -183,35 +183,35 @@
|
||||
const secSpeedSeries: Array<ComputedAreas | null> = $derived([
|
||||
{
|
||||
label: 'Early Race',
|
||||
y1: (x) => sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[0],
|
||||
y2: (x) => sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[1],
|
||||
y1: (x) => sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[0],
|
||||
y2: (x) => sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[1],
|
||||
},
|
||||
{
|
||||
label: 'Mid Race',
|
||||
y1: (x) => sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[0],
|
||||
y2: (x) => sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[1],
|
||||
y1: (x) => sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[0],
|
||||
y2: (x) => sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[1],
|
||||
},
|
||||
secIsFront
|
||||
? {
|
||||
label: 'Early Race + Mean Speed-Up Mode',
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[0], 1.04, frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[1], 1.04, frontModeEnterChance(x)),
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[0], 1.04, frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[1], 1.04, frontModeEnterChance(x)),
|
||||
}
|
||||
: {
|
||||
label: 'Early Race + Mean Pace-Up Mode',
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[0], 1.04, paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.EarlyRace)[1], 1.04, paceUpEnterChance(x)),
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[0], 1.04, paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.EarlyRace)[1], 1.04, paceUpEnterChance(x)),
|
||||
},
|
||||
secIsFront
|
||||
? {
|
||||
label: 'Mid Race + Mean Speed-Up Mode',
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[0], 1.04, frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[1], 1.04, frontModeEnterChance(x)),
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[0], 1.04, frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[1], 1.04, frontModeEnterChance(x)),
|
||||
}
|
||||
: {
|
||||
label: 'Mid Race + Mean Pace-Up Mode',
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[0], 1.04, paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, x, secSpeedStyle, Phase.MidRace)[1], 1.04, paceUpEnterChance(x)),
|
||||
y1: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[0], 1.04, paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(sectionSpeed(raceLen, x, secSpeedStyle, Phase.MidRace)[1], 1.04, paceUpEnterChance(x)),
|
||||
},
|
||||
]);
|
||||
const fcSeries: ComputedSeries[] = $derived([
|
||||
@@ -649,10 +649,7 @@
|
||||
ref="https://docs.google.com/document/d/15VzW9W2tXBBTibBRbZ8IVpW6HaMX8H0RP03kq6Az7Xg/edit?tab=t.0#heading=h.xdha40q2176g"
|
||||
>Section Speed</Sec
|
||||
>
|
||||
<p>
|
||||
Each section, each horse gets a random modifier to target speed. The modifier's range is determined by the wit stat.
|
||||
(Curiously, the calculation uses both wit as modified by style proficiency and green skills as well as base wit.)
|
||||
</p>
|
||||
<p>Each section, each horse gets a random modifier to target speed. The modifier's range is determined by the wit stat.</p>
|
||||
<div class="mb-24 h-60 w-full md:mb-20 md:h-96">
|
||||
<StatChart
|
||||
class="mx-auto mb-12 h-full w-full max-w-3xl md:mb-10"
|
||||
|
||||
@@ -86,37 +86,35 @@
|
||||
const secSpeed: Array<ComputedAreas | null> = $derived([
|
||||
{
|
||||
label: 'Early Race',
|
||||
y1: (x) => race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[0],
|
||||
y2: (x) => race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[1],
|
||||
y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0],
|
||||
y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1],
|
||||
},
|
||||
{
|
||||
label: 'Mid Race',
|
||||
y1: (x) => race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[0],
|
||||
y2: (x) => race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[1],
|
||||
y1: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0],
|
||||
y2: (x) => race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1],
|
||||
},
|
||||
styleIsFront
|
||||
? {
|
||||
label: 'Early Race + Mean Speed-Up Mode',
|
||||
y1: (x) =>
|
||||
modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[0], 1.04, race.frontModeEnterChance(x)),
|
||||
y2: (x) =>
|
||||
modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[1], 1.04, race.frontModeEnterChance(x)),
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0], 1.04, race.frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1], 1.04, race.frontModeEnterChance(x)),
|
||||
}
|
||||
: {
|
||||
label: 'Early Race + Mean Pace-Up Mode',
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[0], 1.04, race.paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.EarlyRace)[1], 1.04, race.paceUpEnterChance(x)),
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[0], 1.04, race.paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.EarlyRace)[1], 1.04, race.paceUpEnterChance(x)),
|
||||
},
|
||||
styleIsFront
|
||||
? {
|
||||
label: 'Mid Race + Mean Speed-Up Mode',
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[0], 1.04, race.frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[1], 1.04, race.frontModeEnterChance(x)),
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0], 1.04, race.frontModeEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1], 1.04, race.frontModeEnterChance(x)),
|
||||
}
|
||||
: {
|
||||
label: 'Mid Race + Mean Pace-Up Mode',
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[0], 1.04, race.paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, x, style, race.Phase.MidRace)[1], 1.04, race.paceUpEnterChance(x)),
|
||||
y1: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[0], 1.04, race.paceUpEnterChance(x)),
|
||||
y2: (x) => modemean(race.sectionSpeed(raceLen, x, style, race.Phase.MidRace)[1], 1.04, race.paceUpEnterChance(x)),
|
||||
},
|
||||
]);
|
||||
const downhill: ComputedSeries[] = [
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
const damCarry = $derived(allowDAM && slope < 0 ? race.downhillAccelMod(slope) : 0);
|
||||
const carry = $derived(skillCarry + damCarry);
|
||||
const midSpeed = $derived.by(() => {
|
||||
const s = race.sectionSpeed(raceLen, baseWit, wit, style, race.Phase.MidRace) satisfies [number, number];
|
||||
const s = race.sectionSpeed(raceLen, wit, style, race.Phase.MidRace) satisfies [number, number];
|
||||
const u = slope > 0 ? race.uphillMod(power, slope) : 0;
|
||||
return [s[0] + u, s[1] + u] as const;
|
||||
});
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
}
|
||||
return [0, 0];
|
||||
});
|
||||
const earlyTarget = $derived(race.sectionSpeed(raceLen, baseWit, wit, style, race.Phase.EarlyRace));
|
||||
const earlyTarget = $derived(race.sectionSpeed(raceLen, wit, style, race.Phase.EarlyRace));
|
||||
const speeds: [number, number] = $derived([earlyTarget[0] + hillMod[0], earlyTarget[1] + hillMod[1]]);
|
||||
|
||||
const startInstant: accel.Instant = { t: 0, x: 0, v: 3 };
|
||||
|
||||
@@ -96,14 +96,8 @@
|
||||
|
||||
const distType = $derived(race.distance(raceLen));
|
||||
const phaseSpeed = $derived({
|
||||
[race.Phase.EarlyRace]: race.sectionSpeed(
|
||||
raceLen,
|
||||
baseStats[race.Stat.Wit],
|
||||
stats[race.Stat.Wit],
|
||||
style,
|
||||
race.Phase.EarlyRace,
|
||||
),
|
||||
[race.Phase.MidRace]: race.sectionSpeed(raceLen, baseStats[race.Stat.Wit], stats[race.Stat.Wit], style, race.Phase.MidRace),
|
||||
[race.Phase.EarlyRace]: race.sectionSpeed(raceLen, stats[race.Stat.Wit], style, race.Phase.EarlyRace),
|
||||
[race.Phase.MidRace]: race.sectionSpeed(raceLen, stats[race.Stat.Wit], style, race.Phase.MidRace),
|
||||
[race.Phase.LateRace]: [
|
||||
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
|
||||
race.spurtSpeed(stats[race.Stat.Speed], stats[race.Stat.Guts], style, distanceApt, raceLen),
|
||||
|
||||
Reference in New Issue
Block a user